diff --git a/DEPS b/DEPS index cf8f2cc6..52f271488c 100644 --- a/DEPS +++ b/DEPS
@@ -306,19 +306,19 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': '25029d94751c6df826cee247c0d57890c2cedbaa', + 'src_internal_revision': '523a084bc51377f455f0e042222acbc522a95165', # 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': 'c653705482bc2a85d42e19cb441ce5e250d81e39', + 'skia_revision': 'd503bc9c6e46b399fe7f89057c21b7c393ccd845', # 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': 'fb8803a8ccd3ccbca07e40deb509505b665af175', + 'v8_revision': 'ee50bc8415cbf6756bfa4cb078155e498c89a4f7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'e784b1ec822888844ec60abcf50d169f0347f6cf', + 'angle_revision': 'cb7d3cc206d6a4165c0012d78387b714b55a0556', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -326,7 +326,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': 'aad37f1a2976c5379b8a2aba60a330d7aba55164', + 'pdfium_revision': '64571d5d1f1eb7e91b7237b37d7bffecebb77981', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -381,7 +381,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'd80f7d1ae4c6c010ecc8e660588f33f5768cb177', + 'catapult_revision': '99cae5876c51001792d8225f77579eb537188490', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. @@ -401,7 +401,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'cb3c970179dfea108e67796c202f519068d1d48f', + 'devtools_frontend_revision': 'f12c052fc715d18e765fe3f78fdb3584a14baf4b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -429,7 +429,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. - 'quiche_revision': 'bccc7cc648236d93d8cd4f07c82d7a15a6218bf6', + 'quiche_revision': 'bb4f68479fd8fa4738339cdcc5782b04b985b72b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -825,7 +825,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '2c1a38e990de645f3a7871f5e3f44558d9d0ad17', + '2d0a791e87f12aa439b145774e2efe96e6d82225', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1203,7 +1203,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '1cdf05204cf5365bcb63fd8b306750b054be5c73', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'd5d8b1bb4ddbde9f4752ca8ae28543a31b64e211', 'condition': 'checkout_src_internal', }, @@ -1808,7 +1808,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@d8fc43000b3e5e924679432724228bf75695ca27', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@52f57acdf69e747b0cea3c458a6ec6467dcb6d8a', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', @@ -1960,7 +1960,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/eche_app/app', - 'version': 'cj6U89uuybmhL60Yo05WMPs4iRpeWzw1AKnPZYs1jrwC', + 'version': 'DnPrMxwYi3z-CBmheuwa4UpmeI5g0AUOWlPLCPDLbA4C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3995,7 +3995,7 @@ 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - 'f4aea18550bf707b1d06d65028e7e9edcae7d2c1', + '1f827a8c547d3157e40bbed7e375469c1585d5f7', 'condition': 'checkout_src_internal', },
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 503aed5..c08f638c 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2833,6 +2833,8 @@ "wm/window_restore/pine_contents_view.h", "wm/window_restore/pine_context_menu_model.cc", "wm/window_restore/pine_context_menu_model.h", + "wm/window_restore/pine_controller.cc", + "wm/window_restore/pine_controller.h", "wm/window_restore/window_restore_controller.cc", "wm/window_restore/window_restore_controller.h", "wm/window_restore/window_restore_util.cc",
diff --git a/ash/accelerators/debug_commands.cc b/ash/accelerators/debug_commands.cc index c5ab008e..7625b5c 100644 --- a/ash/accelerators/debug_commands.cc +++ b/ash/accelerators/debug_commands.cc
@@ -38,7 +38,7 @@ #include "ash/wallpaper/wallpaper_controller_impl.h" #include "ash/wm/float/float_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" -#include "ash/wm/window_restore/window_restore_controller.h" +#include "ash/wm/window_restore/pine_controller.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" #include "base/command_line.h" @@ -254,7 +254,7 @@ void HandleShowInformedRestore() { if (features::IsForestFeatureEnabled()) { Shell::Get() - ->window_restore_controller() + ->pine_controller() ->MaybeStartPineOverviewSessionDevAccelerator(); } }
diff --git a/ash/birch/birch_model_unittest.cc b/ash/birch/birch_model_unittest.cc index 6a6e854..418687b 100644 --- a/ash/birch/birch_model_unittest.cc +++ b/ash/birch/birch_model_unittest.cc
@@ -144,9 +144,17 @@ EXPECT_THAT(consumer.items_ready_responses(), testing::ElementsAre("0", "1")); } +// TODO(https://crbug.com/324963992): Fix `BirchModel*Test.DataFetchTimeout` +// for debug builds. +#if defined(NDEBUG) +#define MAYBE_DataFetchTimeout DataFetchTimeout +#else +#define MAYBE_DataFetchTimeout DISABLED_DataFetchTimeout +#endif + // Test that consumer is notified when waiting a set amount of time after // requesting birch data. -TEST_F(BirchModelTest, DataFetchTimeout) { +TEST_F(BirchModelTest, MAYBE_DataFetchTimeout) { BirchModel* model = Shell::Get()->birch_model(); TestModelConsumer consumer; EXPECT_TRUE(model); @@ -195,7 +203,7 @@ EXPECT_FALSE(model->IsDataFresh()); } -TEST_F(BirchModelWithoutWeatherTest, DataFetchTimeout) { +TEST_F(BirchModelWithoutWeatherTest, MAYBE_DataFetchTimeout) { BirchModel* model = Shell::Get()->birch_model(); TestModelConsumer consumer; EXPECT_TRUE(model);
diff --git a/ash/components/arc/arc_features.cc b/ash/components/arc/arc_features.cc index b437e3e..b0d82d65 100644 --- a/ash/components/arc/arc_features.cc +++ b/ash/components/arc/arc_features.cc
@@ -224,7 +224,7 @@ // Settings page. BASE_FEATURE(kPerAppLanguage, "PerAppLanguage", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Controls ARC picture-in-picture feature. If this is enabled, then Android // will control which apps can enter PIP. If this is disabled, then ARC PIP
diff --git a/ash/events/peripheral_customization_event_rewriter.cc b/ash/events/peripheral_customization_event_rewriter.cc index 3589d69..cdac91a4 100644 --- a/ash/events/peripheral_customization_event_rewriter.cc +++ b/ash/events/peripheral_customization_event_rewriter.cc
@@ -164,6 +164,7 @@ case mojom::CustomizationRestriction::kAllowAlphabetKeyEventRewrites: case mojom::CustomizationRestriction:: kAllowAlphabetOrNumberKeyEventRewrites: + case mojom::CustomizationRestriction::kAllowTabEventRewrites: return false; case mojom::CustomizationRestriction::kAllowHorizontalScrollWheelRewrites: case mojom::CustomizationRestriction::kAllowCustomizations: @@ -769,6 +770,8 @@ kAllowAlphabetOrNumberKeyEventRewrites: return IsAlphaKeyboardCode(key_event.key_code()) || IsNumberKeyboardCode(key_event.key_code()); + case mojom::CustomizationRestriction::kAllowTabEventRewrites: + return key_event.key_code() == ui::VKEY_TAB; case mojom::CustomizationRestriction::kDisallowCustomizations: case mojom::CustomizationRestriction::kDisableKeyEventRewrites: case mojom::CustomizationRestriction::kAllowHorizontalScrollWheelRewrites:
diff --git a/ash/game_dashboard/game_dashboard_main_menu_view.cc b/ash/game_dashboard/game_dashboard_main_menu_view.cc index d8cfe1ad..f2eed00 100644 --- a/ash/game_dashboard/game_dashboard_main_menu_view.cc +++ b/ash/game_dashboard/game_dashboard_main_menu_view.cc
@@ -51,7 +51,9 @@ #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/bubble/bubble_border.h" +#include "ui/views/controls/button/button.h" #include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/view.h" #include "ui/views/view_class_properties.h" @@ -77,6 +79,11 @@ /*upper_right=*/kDetailRowCornerRadius, /*lower_right=*/2.0f, /*lower_left=*/2.0f); +constexpr gfx::RoundedCornersF kScreenSizeRowCorners = + gfx::RoundedCornersF(/*upper_left=*/2.0f, + /*upper_right=*/2.0f, + /*lower_right=*/kDetailRowCornerRadius, + /*lower_left=*/kDetailRowCornerRadius); // For setup button pulse animation. constexpr int kSetupPulseExtraHalfSize = 32; @@ -131,56 +138,52 @@ return game_dashboard_utils::IsFlagSet(flags, ArcGameControlsFlag::kEnabled); } -} // namespace +// Helper function to configure the feature row button designs and return the +// layout manager. +views::BoxLayout* ConfigureFeatureRowLayout(views::Button* button, + const gfx::RoundedCornersF& corners, + bool enabled) { + auto* layout = button->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, + /*inside_border_insets=*/gfx::Insets::VH(16, 16))); + layout->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::kCenter); + button->SetNotifyEnterExitOnChild(true); + button->SetEnabled(enabled); + button->SetBackground(views::CreateThemedRoundedRectBackground( + enabled ? cros_tokens::kCrosSysSystemOnBase + : cros_tokens::kCrosSysDisabledContainer, + corners)); + + // Set up highlight ink drop and focus ring. + views::HighlightPathGenerator::Install( + button, std::make_unique<views::RoundRectHighlightPathGenerator>( + gfx::Insets(), corners)); + StyleUtil::SetUpInkDropForButton(button, gfx::Insets(), + /*highlight_on_hover=*/false, + /*highlight_on_focus=*/true); + auto* focus_ring = views::FocusRing::Get(button); + focus_ring->SetHaloInset(-4); + focus_ring->SetHaloThickness(2); + + return layout; +} // ----------------------------------------------------------------------------- -// GameDashboardMainMenuView::GameControlsDetailsRow: +// FeatureHeader: -// Game Controls details row includes feature icon, title and sub-title, set up -// button or switch button with drill in arrow icon. -// If there is no Game Controls set up, it shows as: -// +------------------------------------------------+ -// | |icon| |title| |set_up button||| -// | |sub-title| | -// +------------------------------------------------+ -// Otherwise, it shows as: -// +------------------------------------------------+ -// | |icon| |title| |switch| |drill in arrow|| -// | |sub-title| | -// +------------------------------------------------+ -class GameDashboardMainMenuView::GameControlsDetailsRow : public views::Button { - METADATA_HEADER(GameControlsDetailsRow, views::Button) +// `FeatureHeader` includes icon, title and sub-title. +// +---------------------+ +// | |icon| |title| | +// | |sub-title| | +// +---------------------+ +class FeatureHeader : public views::View { + METADATA_HEADER(FeatureHeader, views::View) public: - GameControlsDetailsRow(GameDashboardMainMenuView* main_menu) - : Button(base::BindRepeating(&GameControlsDetailsRow::OnButtonPressed, - base::Unretained(this))), - main_menu_(main_menu) { - CacheAppName(); - SetID(VIEW_ID_GD_CONTROLS_DETAILS_ROW); - - const auto flags = - game_dashboard_utils::GetGameControlsFlag(GetGameWindow()); - CHECK(flags); - - const bool is_available = game_dashboard_utils::IsFlagSet( - *flags, ArcGameControlsFlag::kAvailable); - SetEnabled(is_available); - - const auto title = l10n_util::GetStringUTF16( - IDS_ASH_GAME_DASHBOARD_CONTROLS_TILE_BUTTON_TITLE); - SetAccessibleName(title); - SetTooltipText(title); - SetBackground(views::CreateThemedRoundedRectBackground( - is_available ? cros_tokens::kCrosSysSystemOnBase - : cros_tokens::kCrosSysDisabledContainer, - kGCDetailRowCorners)); - SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(16, 16))); - - views::HighlightPathGenerator::Install( - this, std::make_unique<views::RoundRectHighlightPathGenerator>( - gfx::Insets(), kGCDetailRowCorners)); - + FeatureHeader(bool is_enabled, + const gfx::VectorIcon& icon, + const std::u16string& title) { auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>()); layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); @@ -189,17 +192,17 @@ auto* icon_container = AddChildView(std::make_unique<views::View>()); icon_container->SetLayoutManager(std::make_unique<views::FillLayout>()); icon_container->SetBackground(views::CreateThemedRoundedRectBackground( - is_available ? cros_tokens::kCrosSysSystemOnBase - : cros_tokens::kCrosSysDisabledContainer, + is_enabled ? cros_tokens::kCrosSysSystemOnBase + : cros_tokens::kCrosSysDisabledContainer, /*radius=*/12.0f)); icon_container->SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(6, 6))); icon_container->SetProperty(views::kMarginsKey, gfx::Insets::TLBR(0, 0, 0, 16)); icon_container->AddChildView( std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon( - kGdGameControlsIcon, - is_available ? cros_tokens::kCrosSysOnSurface - : cros_tokens::kCrosSysDisabled, + icon, + is_enabled ? cros_tokens::kCrosSysOnSurface + : cros_tokens::kCrosSysDisabled, /*icon_size=*/20))); // Add title and sub-title. @@ -215,7 +218,7 @@ auto* feature_title = tag_container->AddChildView(std::make_unique<views::Label>(title)); feature_title->SetAutoColorReadabilityEnabled(false); - feature_title->SetEnabledColorId(is_available + feature_title->SetEnabledColorId(is_enabled ? cros_tokens::kCrosSysOnSurface : cros_tokens::kCrosSysDisabled); feature_title->SetFontList( @@ -226,16 +229,150 @@ // Add sub-title. sub_title_ = tag_container->AddChildView(bubble_utils::CreateLabel( TypographyToken::kCrosAnnotation2, u"", - is_available ? cros_tokens::kCrosSysOnSurfaceVariant - : cros_tokens::kCrosSysDisabled)); + is_enabled ? cros_tokens::kCrosSysOnSurfaceVariant + : cros_tokens::kCrosSysDisabled)); sub_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); sub_title_->SetMultiLine(true); + } + + FeatureHeader(const FeatureHeader&) = delete; + FeatureHeader& operator=(const FeatureHeader) = delete; + ~FeatureHeader() override = default; + + void UpdateSubtitle(const std::u16string& text) { + // For multiline label, if the fixed width is not set, the preferred size is + // re-calcuated based on previous label size as available size instead of + // its real available size when changing the text. For `sub_title_`, it + // takes the whole width of its parent's width as fixed width after layout. + if (!sub_title_->GetFixedWidth()) { + if (int width = sub_title_->parent()->size().width(); width != 0) { + sub_title_->SizeToFit(width); + } + } + sub_title_->SetText(text); + } + + private: + raw_ptr<views::Label> sub_title_ = nullptr; +}; + +BEGIN_METADATA(FeatureHeader, views::View) +END_METADATA + +// ----------------------------------------------------------------------------- +// ScreenSizeRow: + +// ScreenSizeRow includes `FeatureHeader` and right arrow icon. +// +------------------------------------------------+ +// | |feature header| |>| | +// +------------------------------------------------+ +class ScreenSizeRow : public views::Button { + METADATA_HEADER(ScreenSizeRow, views::View) + + public: + ScreenSizeRow(PressedCallback callback, + ResizeCompatMode resize_mode, + ArcResizeLockType resize_lock_type) + : views::Button(std::move(callback)) { + SetID(VIEW_ID_GD_SCREEN_SIZE_TILE); + + bool enabled = false; + int tooltip = 0; + switch (resize_lock_type) { + case ArcResizeLockType::RESIZE_DISABLED_TOGGLABLE: + case ArcResizeLockType::RESIZE_ENABLED_TOGGLABLE: + enabled = true; + break; + case ArcResizeLockType::RESIZE_DISABLED_NONTOGGLABLE: + enabled = false; + tooltip = + IDS_ASH_ARC_APP_COMPAT_DISABLED_COMPAT_MODE_BUTTON_TOOLTIP_PHONE; + break; + case ArcResizeLockType::NONE: + enabled = false; + break; + } + + const std::u16string title = l10n_util::GetStringUTF16( + IDS_ASH_GAME_DASHBOARD_SCREEN_SIZE_SETTINGS_TITLE); + SetAccessibleName(title); + SetTooltipText(tooltip ? l10n_util::GetStringUTF16(tooltip) : title); + + auto* layout = + ConfigureFeatureRowLayout(this, kScreenSizeRowCorners, enabled); + // Add header. + auto* header = AddChildView(std::make_unique<FeatureHeader>( + enabled, compat_mode_util::GetIcon(resize_mode), title)); + layout->SetFlexForView(header, /*flex=*/1); + header->UpdateSubtitle(compat_mode_util::GetText(resize_mode)); + // Add arrow icon. + AddChildView( + std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon( + kQuickSettingsRightArrowIcon, + enabled ? cros_tokens::kCrosSysOnSurface + : cros_tokens::kCrosSysDisabled))); + } + + ScreenSizeRow(const ScreenSizeRow&) = delete; + ScreenSizeRow& operator=(const ScreenSizeRow) = delete; + ~ScreenSizeRow() override = default; +}; + +BEGIN_METADATA(ScreenSizeRow, views::Button) +END_METADATA + +} // namespace + +// ----------------------------------------------------------------------------- +// GameDashboardMainMenuView::GameControlsDetailsRow: + +// `GameControlsDetailsRow` includes `FeatureHeader`, set up button or switch +// button with drill in arrow icon. If there is no Game Controls set up, it +// shows as: +// +------------------------------------------------+ +// | |feature header| |set_up button|| +// +------------------------------------------------+ +// Otherwise, it shows as: +// +------------------------------------------------+ +// | |feature header| |switch| |drill in arrow|| +// +------------------------------------------------+ +class GameDashboardMainMenuView::GameControlsDetailsRow : public views::Button { + METADATA_HEADER(GameControlsDetailsRow, views::Button) + + public: + GameControlsDetailsRow(GameDashboardMainMenuView* main_menu) + : views::Button( + base::BindRepeating(&GameControlsDetailsRow::OnButtonPressed, + base::Unretained(this))), + main_menu_(main_menu) { + CacheAppName(); + SetID(VIEW_ID_GD_CONTROLS_DETAILS_ROW); + + const auto flags = + game_dashboard_utils::GetGameControlsFlag(GetGameWindow()); + CHECK(flags); + + const auto title = l10n_util::GetStringUTF16( + IDS_ASH_GAME_DASHBOARD_CONTROLS_TILE_BUTTON_TITLE); + SetAccessibleName(title); + SetTooltipText(title); + + const bool is_available = game_dashboard_utils::IsFlagSet( + *flags, ArcGameControlsFlag::kAvailable); + auto* layout = + ConfigureFeatureRowLayout(this, kGCDetailRowCorners, is_available); + + // Add header. + header_ = AddChildView(std::make_unique<FeatureHeader>( + /*is_enabled=*/is_available, kGdGameControlsIcon, title)); + // Flex `header_` to fill the empty space. + layout->SetFlexForView(header_, /*flex=*/1); // Add setup button, or feature switch and drill-in arrow. if (!is_available || game_dashboard_utils::IsFlagSet(*flags, ArcGameControlsFlag::kEmpty)) { // Add setup button. - sub_title_->SetText(l10n_util::GetStringUTF16( + header_->UpdateSubtitle(l10n_util::GetStringUTF16( IDS_ASH_GAME_DASHBOARD_GC_SET_UP_SUB_TITLE)); setup_button_ = AddChildView(std::make_unique<PillButton>( base::BindRepeating(&GameControlsDetailsRow::OnSetUpButtonPressed, @@ -319,8 +456,13 @@ is_feature_enabled ? IDS_ASH_GAME_DASHBOARD_GC_DETAILS_SUB_TITLE_ON_TEMPLATE : IDS_ASH_GAME_DASHBOARD_GC_DETAILS_SUB_TITLE_OFF_TEMPLATE; - sub_title_->SetText( + header_->UpdateSubtitle( l10n_util::GetStringFUTF16(string_id, base::UTF8ToUTF16(app_name_))); + + // In case the sub-title turns to two lines from one line. + if (GetWidget()) { + main_menu_->SizeToContents(); + } } void CacheAppName() { @@ -342,27 +484,9 @@ aura::Window* GetGameWindow() { return main_menu_->context_->game_window(); } - // views::View: - void OnThemeChanged() override { - views::View::OnThemeChanged(); - - // Set up highlight and focus ring for the whole row. - StyleUtil::SetUpInkDropForButton( - /*button=*/this, gfx::Insets(), /*highlight_on_hover=*/true, - /*highlight_on_focus=*/true, /*background_color=*/ - GetColorProvider()->GetColor(cros_tokens::kCrosSysHoverOnSubtle)); - - // `StyleUtil::SetUpInkDropForButton()` reinstalls the focus ring, so it - // needs to set the focus ring size after calling - // `StyleUtil::SetUpInkDropForButton()`. - auto* focus_ring = views::FocusRing::Get(this); - focus_ring->SetHaloInset(-4); - focus_ring->SetHaloThickness(2); - } - const raw_ptr<GameDashboardMainMenuView> main_menu_; - raw_ptr<views::Label> sub_title_ = nullptr; + raw_ptr<FeatureHeader> header_ = nullptr; raw_ptr<PillButton> setup_button_ = nullptr; raw_ptr<Switch> feature_switch_ = nullptr; @@ -401,7 +525,7 @@ /*between_child_spacing=*/16)); AddShortcutTilesRow(); - AddFeatureDetailsRows(); + MaybeAddArcFeatureRows(); AddUtilityClusterRow(); SizeToPreferredSize(); @@ -544,7 +668,11 @@ /*sub_label=*/std::nullopt)); } -void GameDashboardMainMenuView::AddFeatureDetailsRows() { +void GameDashboardMainMenuView::MaybeAddArcFeatureRows() { + if (!IsArcWindow(context_->game_window())) { + return; + } + auto* feature_details_container = AddChildView(std::make_unique<views::View>()); feature_details_container->SetLayoutManager( @@ -553,15 +681,8 @@ /*inside_border_insets=*/gfx::Insets(), /*between_child_spacing=*/2)); - // Set the container's corner radius. - feature_details_container->SetPaintToLayer(); - auto* container_layer = feature_details_container->layer(); - container_layer->SetFillsBoundsOpaquely(false); - container_layer->SetRoundedCornerRadius( - gfx::RoundedCornersF(kDetailRowCornerRadius)); - - MaybeAddGameControlsDetailsRow(feature_details_container); - MaybeAddScreenSizeSettingsRow(feature_details_container); + AddGameControlsDetailsRow(feature_details_container); + AddScreenSizeSettingsRow(feature_details_container); } void GameDashboardMainMenuView::MaybeAddGameControlsTile( @@ -588,52 +709,23 @@ game_controls_tile_->SetSubLabelVisibility(true); } -void GameDashboardMainMenuView::MaybeAddGameControlsDetailsRow( +void GameDashboardMainMenuView::AddGameControlsDetailsRow( views::View* container) { - if (IsArcWindow(context_->game_window())) { - game_controls_details_ = - container->AddChildView(std::make_unique<GameControlsDetailsRow>(this)); - } + DCHECK(IsArcWindow(context_->game_window())); + game_controls_details_ = + container->AddChildView(std::make_unique<GameControlsDetailsRow>(this)); } -void GameDashboardMainMenuView::MaybeAddScreenSizeSettingsRow( +void GameDashboardMainMenuView::AddScreenSizeSettingsRow( views::View* container) { aura::Window* game_window = context_->game_window(); - if (!IsArcWindow(game_window)) { - return; - } - - const auto resize_mode = compat_mode_util::PredictCurrentMode(game_window); - auto* screen_size_row = container->AddChildView(CreateFeatureTile( + DCHECK(IsArcWindow(game_window)); + container->AddChildView(std::make_unique<ScreenSizeRow>( base::BindRepeating( &GameDashboardMainMenuView::OnScreenSizeSettingsButtonPressed, base::Unretained(this)), - /*is_togglable=*/false, FeatureTile::TileType::kPrimary, - VIEW_ID_GD_SCREEN_SIZE_TILE, - /*icon=*/compat_mode_util::GetIcon(resize_mode), - l10n_util::GetStringUTF16( - IDS_ASH_GAME_DASHBOARD_SCREEN_SIZE_SETTINGS_TITLE), - /*sub_label=*/compat_mode_util::GetText(resize_mode))); - - const ArcResizeLockType resize_lock_type = - game_window->GetProperty(kArcResizeLockTypeKey); - switch (resize_lock_type) { - case ArcResizeLockType::RESIZE_DISABLED_TOGGLABLE: - case ArcResizeLockType::RESIZE_ENABLED_TOGGLABLE: - screen_size_row->SetEnabled(true); - // TODO(b/303351905): Investigate why drill in arrow isn't placed in - // correct location. - screen_size_row->CreateDecorativeDrillInArrow(); - break; - case ArcResizeLockType::RESIZE_DISABLED_NONTOGGLABLE: - screen_size_row->SetEnabled(false); - screen_size_row->SetTooltipText(l10n_util::GetStringUTF16( - IDS_ASH_ARC_APP_COMPAT_DISABLED_COMPAT_MODE_BUTTON_TOOLTIP_PHONE)); - break; - case ArcResizeLockType::NONE: - screen_size_row->SetEnabled(false); - break; - } + /*resize_mode=*/compat_mode_util::PredictCurrentMode(game_window), + /*resize_lock_type=*/game_window->GetProperty(kArcResizeLockTypeKey))); } void GameDashboardMainMenuView::AddUtilityClusterRow() {
diff --git a/ash/game_dashboard/game_dashboard_main_menu_view.h b/ash/game_dashboard/game_dashboard_main_menu_view.h index 0e5fed6..fe5e0ccd 100644 --- a/ash/game_dashboard/game_dashboard_main_menu_view.h +++ b/ash/game_dashboard/game_dashboard_main_menu_view.h
@@ -82,18 +82,18 @@ // Adds feature details rows, for example, including Game Controls or window // size. - void AddFeatureDetailsRows(); + void MaybeAddArcFeatureRows(); // Adds Game Controls feature tile in `container` if it is the ARC game window // and Game Controls is available. void MaybeAddGameControlsTile(views::View* container); // Adds menu controls row for Game Controls. - void MaybeAddGameControlsDetailsRow(views::View* container); + void AddGameControlsDetailsRow(views::View* container); // Adds a row to access a settings page controlling the screen size if the // given game window is an ARC app. - void MaybeAddScreenSizeSettingsRow(views::View* container); + void AddScreenSizeSettingsRow(views::View* container); // Adds the dashboard cluster (containing feedback, settings, and help // buttons) to the Game Controls tile view.
diff --git a/ash/glanceables/glanceables_metrics.cc b/ash/glanceables/glanceables_metrics.cc index d6d8887de..f814fd6 100644 --- a/ash/glanceables/glanceables_metrics.cc +++ b/ash/glanceables/glanceables_metrics.cc
@@ -24,11 +24,40 @@ constexpr char kTimeManagementClassroomPrefix[] = "Ash.Glanceables.TimeManagement.Classroom"; -void RecordTasksUserAction() { +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class TasksUserAction { + kActiveTaskListChanged = 0, + kTaskMarkedComplete = 1, + kTaskMarkedIncomplete = 2, + kAddTaskStarted = 3, + kModifyTaskStarted = 4, + kHeaderButtonClicked = 5, + kAddNewTaskButtonClicked = 6, + kFooterButtonClicked = 7, + kEditInGoogleTasksButtonClicked = 8, + kMaxValue = kEditInGoogleTasksButtonClicked +}; + +void RecordTasksUserAction(TasksUserAction action) { + base::UmaHistogramEnumeration( + base::JoinString({kTimeManagementTaskPrefix, "UserAction"}, "."), action); base::RecordAction(base::UserMetricsAction("Glanceables_Tasks_UserAction")); } -void RecordClassroomUserAction() { +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class ClassroomUserAction { + kAssignmentListSelected = 0, + kHeaderIconPressed = 1, + kStudentAssignmentPressed = 2, + kMaxValue = kStudentAssignmentPressed, +}; + +void RecordClassroomUserAction(ClassroomUserAction action) { + base::UmaHistogramEnumeration( + base::JoinString({kTimeManagementClassroomPrefix, "UserAction"}, "."), + action); base::RecordAction( base::UserMetricsAction("Glanceables_Classroom_UserAction")); } @@ -38,13 +67,14 @@ namespace ash { void RecordActiveTaskListChanged() { - RecordTasksUserAction(); + RecordTasksUserAction(TasksUserAction::kActiveTaskListChanged); base::RecordAction( base::UserMetricsAction("Glanceables_Tasks_ActiveTaskListChanged")); } void RecordTaskMarkedAsCompleted(bool complete) { - RecordTasksUserAction(); + RecordTasksUserAction(complete ? TasksUserAction::kTaskMarkedComplete + : TasksUserAction::kTaskMarkedIncomplete); if (complete) { base::RecordAction( @@ -56,7 +86,7 @@ } void RecordUserStartedAddingTask() { - RecordTasksUserAction(); + RecordTasksUserAction(TasksUserAction::kAddTaskStarted); base::RecordAction( base::UserMetricsAction("Glanceables_Tasks_AddTaskStarted")); @@ -83,7 +113,7 @@ } void RecordUserModifyingTask() { - RecordTasksUserAction(); + RecordTasksUserAction(TasksUserAction::kModifyTaskStarted); base::RecordAction( base::UserMetricsAction("Glanceables_Tasks_ModifyTaskStarted")); @@ -95,22 +125,25 @@ } void RecordTasksLaunchSource(TasksLaunchSource source) { - RecordTasksUserAction(); switch (source) { case TasksLaunchSource::kHeaderButton: + RecordTasksUserAction(TasksUserAction::kHeaderButtonClicked); base::RecordAction(base::UserMetricsAction( "Glanceables_Tasks_LaunchTasksApp_HeaderButton")); break; case TasksLaunchSource::kAddNewTaskButton: + RecordTasksUserAction(TasksUserAction::kAddNewTaskButtonClicked); base::RecordAction(base::UserMetricsAction( "Glanceables_Tasks_LaunchTasksApp_AddNewTaskButton")); break; case TasksLaunchSource::kFooterButton: + RecordTasksUserAction(TasksUserAction::kFooterButtonClicked); base::RecordAction(base::UserMetricsAction( "Glanceables_Tasks_LaunchTasksApp_FooterButton")); break; case TasksLaunchSource::kEditInGoogleTasksButton: + RecordTasksUserAction(TasksUserAction::kEditInGoogleTasksButtonClicked); base::RecordAction(base::UserMetricsAction( "Glanceables_Tasks_LaunchTasksApp_EditInGoogleTasksButton")); break; @@ -261,7 +294,7 @@ } void RecordStudentAssignmentPressed(bool default_list) { - RecordClassroomUserAction(); + RecordClassroomUserAction(ClassroomUserAction::kStudentAssignmentPressed); base::RecordAction( base::UserMetricsAction("Glanceables_Classroom_AssignmentPressed")); @@ -273,14 +306,14 @@ } void RecordClassroomHeaderIconPressed() { - RecordClassroomUserAction(); + RecordClassroomUserAction(ClassroomUserAction::kHeaderIconPressed); base::RecordAction( base::UserMetricsAction("Glanceables_Classroom_HeaderIconPressed")); } void RecordStudentAssignmentListSelected(StudentAssignmentsListType list_type) { - RecordClassroomUserAction(); + RecordClassroomUserAction(ClassroomUserAction::kAssignmentListSelected); base::UmaHistogramEnumeration( "Ash.Glanceables.Classroom.Student.ListSelected", list_type);
diff --git a/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc b/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc index 8244460..30cb13b 100644 --- a/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc +++ b/ash/glanceables/tasks/glanceables_tasks_view_unittest.cc
@@ -18,6 +18,7 @@ #include "ash/test/ash_test_base.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h" #include "base/types/cxx23_to_underlying.h" @@ -167,6 +168,7 @@ } TEST_F(GlanceablesTasksViewTest, ShowsProgressBarWhileAddingTask) { + base::HistogramTester histogram_tester; tasks_client()->set_paused(true); // Initially progress bar is hidden. @@ -184,9 +186,13 @@ // After replying to pending callbacks, the progress bar should become hidden. EXPECT_EQ(tasks_client()->RunPendingAddTaskCallbacks(), 1u); EXPECT_FALSE(GetProgressBar()->GetVisible()); + + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 3, 1); } TEST_F(GlanceablesTasksViewTest, ShowsProgressBarWhileEditingTask) { + base::HistogramTester histogram_tester; tasks_client()->set_paused(true); // Initially progress bar is hidden. @@ -211,6 +217,9 @@ // After replying to pending callbacks, the progress bar should become hidden. EXPECT_EQ(tasks_client()->RunPendingUpdateTaskCallbacks(), 1u); EXPECT_FALSE(GetProgressBar()->GetVisible()); + + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 4, 1); } TEST_F(GlanceablesTasksViewTest, OnlyShowsFooterIfAtLeast100Tasks) { @@ -235,6 +244,7 @@ } TEST_F(GlanceablesTasksViewTest, SupportsEditingRightAfterAdding) { + base::HistogramTester histogram_tester; tasks_client()->set_paused(true); // Add a task. @@ -263,6 +273,13 @@ // Verify executed callbacks number. EXPECT_EQ(tasks_client()->RunPendingAddTaskCallbacks(), 0u); EXPECT_EQ(tasks_client()->RunPendingUpdateTaskCallbacks(), 1u); + + histogram_tester.ExpectTotalCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 2); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 3, 1); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 4, 1); } TEST_F(GlanceablesTasksViewTest, AllowsPressingAddNewTaskButtonWhileAdding) { @@ -453,6 +470,7 @@ } TEST_F(GlanceablesTasksViewTest, ShowTasksWebUIFromEditInBrowserView) { + base::HistogramTester histogram_tester; base::UserActionTester user_actions; const auto* const title_label = views::AsViewClass<views::Label>( GetTaskItemsContainerView()->children()[0]->GetViewByID( @@ -470,6 +488,12 @@ GestureTapOn(edit_in_browser_button); EXPECT_EQ(1, user_actions.GetActionCount( "Glanceables_Tasks_LaunchTasksApp_EditInGoogleTasksButton")); + histogram_tester.ExpectTotalCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 2); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 4, 1); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 8, 1); // Simulate that the widget is hidden safely after opening a browser window. view()->GetWidget()->Hide();
diff --git a/ash/picker/picker_controller.cc b/ash/picker/picker_controller.cc index 46123204..abc872b 100644 --- a/ash/picker/picker_controller.cc +++ b/ash/picker/picker_controller.cc
@@ -146,10 +146,10 @@ u"Matching links", {{ PickerSearchResult::BrowsingHistory( - GURL("http://www.foo.com"), + GURL("http://www.foo.com"), u"Foo", ui::ImageModel::FromVectorIcon(kPlaceholderIcon)), PickerSearchResult::BrowsingHistory( - GURL("http://crbug.com"), + GURL("http://crbug.com"), u"Crbug", ui::ImageModel::FromVectorIcon(kPlaceholderIcon)), }}); } @@ -172,8 +172,7 @@ } // namespace -PickerController::PickerController() - : should_paint_(MatchPickerFeatureKeyHash() == PickerFeatureKeyType::kDev) { +PickerController::PickerController() { asset_fetcher_ = std::make_unique<PickerAssetFetcherImpl>(base::BindRepeating( &PickerController::DownloadGifToString, weak_ptr_factory_.GetWeakPtr())); if (auto* manager = ash::input_method::InputMethodManager::Get()) { @@ -263,10 +262,6 @@ input_method, ResultToInsertMediaData(result), kInsertMediaTimeout); } -bool PickerController::ShouldPaint() { - return should_paint_; -} - PickerAssetFetcher* PickerController::GetAssetFetcher() { return asset_fetcher_.get(); }
diff --git a/ash/picker/picker_controller.h b/ash/picker/picker_controller.h index e2743260..13ffb99 100644 --- a/ash/picker/picker_controller.h +++ b/ash/picker/picker_controller.h
@@ -68,7 +68,6 @@ std::optional<PickerCategory> category, SearchResultsCallback callback) override; void InsertResultOnNextFocus(const PickerSearchResult& result) override; - bool ShouldPaint() override; PickerAssetFetcher* GetAssetFetcher() override; // ash::input_method::ImeKeyboard::Observer: @@ -87,7 +86,6 @@ raw_ptr<PickerClient> client_ = nullptr; views::UniqueWidgetPtr widget_; - bool should_paint_ = false; std::unique_ptr<PickerAssetFetcher> asset_fetcher_; std::unique_ptr<PickerInsertMediaRequest> insert_media_request_;
diff --git a/ash/picker/picker_controller_unittest.cc b/ash/picker/picker_controller_unittest.cc index 2fc98ce..8899fc2 100644 --- a/ash/picker/picker_controller_unittest.cc +++ b/ash/picker/picker_controller_unittest.cc
@@ -175,7 +175,7 @@ Shell::GetPrimaryRootWindow()->GetHost()->GetInputMethod(); controller.InsertResultOnNextFocus(PickerSearchResult::BrowsingHistory( - GURL("http://foo.com"), ui::ImageModel{})); + GURL("http://foo.com"), u"Foo", ui::ImageModel{})); controller.widget_for_testing()->CloseNow(); ui::FakeTextInputClient input_field(input_method, {.type = ui::TEXT_INPUT_TYPE_TEXT});
diff --git a/ash/picker/views/picker_contents_view.cc b/ash/picker/views/picker_contents_view.cc index a66297c..ee3df259 100644 --- a/ash/picker/views/picker_contents_view.cc +++ b/ash/picker/views/picker_contents_view.cc
@@ -16,6 +16,7 @@ #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/compositor/layer.h" #include "ui/gfx/geometry/insets.h" +#include "ui/views/border.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/scrollbar/scroll_bar.h" #include "ui/views/layout/fill_layout.h" @@ -28,6 +29,8 @@ constexpr int kScrollViewGradientHeight = 16; +constexpr auto kScrollViewContentsBorderInsets = gfx::Insets::TLBR(0, 0, 8, 0); + gfx::Insets GetPickerScrollBarInsets(PickerView::PickerLayoutType layout_type) { switch (layout_type) { case PickerView::PickerLayoutType::kResultsBelowSearchField: @@ -88,6 +91,8 @@ auto page_container = std::make_unique<views::FlexLayoutView>(); page_container->SetOrientation(views::LayoutOrientation::kVertical); page_container->SetCrossAxisAlignment(views::LayoutAlignment::kStretch); + page_container->SetBorder( + views::CreateEmptyBorder(kScrollViewContentsBorderInsets)); page_container_ = scroll_view->SetContents(std::move(page_container)); }
diff --git a/ash/picker/views/picker_search_results_view.cc b/ash/picker/views/picker_search_results_view.cc index 77cf1e88..d9f8ef0 100644 --- a/ash/picker/views/picker_search_results_view.cc +++ b/ash/picker/views/picker_search_results_view.cc
@@ -113,7 +113,8 @@ [&](const PickerSearchResult::BrowsingHistoryData& data) { auto item_view = std::make_unique<PickerItemView>( std::move(select_result_callback)); - item_view->SetPrimaryText(base::UTF8ToUTF16(data.url.spec())); + item_view->SetPrimaryText(data.title); + item_view->SetSecondaryText(base::UTF8ToUTF16(data.url.spec())); item_view->SetLeadingIcon(data.icon); section_view->AddListItem(std::move(item_view)); },
diff --git a/ash/picker/views/picker_view.cc b/ash/picker/views/picker_view.cc index 28d52f04..b5bd0ea8 100644 --- a/ash/picker/views/picker_view.cc +++ b/ash/picker/views/picker_view.cc
@@ -53,6 +53,11 @@ constexpr ui::ColorId kBackgroundColor = cros_tokens::kCrosSysSystemBaseElevated; +// Padding to separate the Picker window from the caret. +constexpr gfx::Outsets kPaddingAroundCaret(4); +// Padding to separate the Picker window from the screen edge. +constexpr gfx::Insets kPaddingFromScreenEdge(16); + std::unique_ptr<views::BubbleBorder> CreateBorder() { auto border = std::make_unique<views::BubbleBorder>( views::BubbleBorder::NONE, views::BubbleBorder::NO_SHADOW); @@ -74,10 +79,14 @@ gfx::Rect GetPickerAnchorBounds(const gfx::Rect& caret_bounds, const gfx::Point& cursor_point, const gfx::Rect& focused_window_bounds) { - return caret_bounds != gfx::Rect() && - focused_window_bounds.Contains(caret_bounds) - ? caret_bounds - : gfx::Rect(cursor_point, gfx::Size()); + if (caret_bounds != gfx::Rect() && + focused_window_bounds.Contains(caret_bounds)) { + gfx::Rect anchor_rect = caret_bounds; + anchor_rect.Outset(kPaddingAroundCaret); + return anchor_rect; + } else { + return gfx::Rect(cursor_point, gfx::Size()); + } } // Gets the preferred layout to use given `anchor_bounds` in screen coordinates. @@ -102,9 +111,10 @@ PickerView::PickerLayoutType layout_type, const gfx::Size& picker_view_size, int picker_view_search_field_vertical_offset) { - const gfx::Rect screen_work_area = display::Screen::GetScreen() - ->GetDisplayMatching(anchor_bounds) - .work_area(); + gfx::Rect screen_work_area = display::Screen::GetScreen() + ->GetDisplayMatching(anchor_bounds) + .work_area(); + screen_work_area.Inset(kPaddingFromScreenEdge); gfx::Rect picker_view_bounds(picker_view_size); if (anchor_bounds.right() + picker_view_size.width() <= screen_work_area.right()) { @@ -220,12 +230,6 @@ return true; } -void PickerView::PaintChildren(const views::PaintInfo& paint_info) { - if (delegate_->ShouldPaint()) { - views::View::PaintChildren(paint_info); - } -} - std::unique_ptr<views::NonClientFrameView> PickerView::CreateNonClientFrameView( views::Widget* widget) { auto frame =
diff --git a/ash/picker/views/picker_view.h b/ash/picker/views/picker_view.h index 3e9538a..97a2462 100644 --- a/ash/picker/views/picker_view.h +++ b/ash/picker/views/picker_view.h
@@ -69,7 +69,6 @@ // views::WidgetDelegateView: bool AcceleratorPressed(const ui::Accelerator& accelerator) override; - void PaintChildren(const views::PaintInfo& paint_info) override; std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView( views::Widget* widget) override; void AddedToWidget() override;
diff --git a/ash/picker/views/picker_view_delegate.h b/ash/picker/views/picker_view_delegate.h index a13c0e20..a63408a 100644 --- a/ash/picker/views/picker_view_delegate.h +++ b/ash/picker/views/picker_view_delegate.h
@@ -45,10 +45,6 @@ // the result is dropped silently. virtual void InsertResultOnNextFocus(const PickerSearchResult& result) = 0; - // Whether the view should paint. Certain test scenarios do not need - // painting, so it is better to skip painting. - virtual bool ShouldPaint() = 0; - virtual PickerAssetFetcher* GetAssetFetcher() = 0; };
diff --git a/ash/picker/views/picker_view_unittest.cc b/ash/picker/views/picker_view_unittest.cc index c9bf7f1..b35eb88 100644 --- a/ash/picker/views/picker_view_unittest.cc +++ b/ash/picker/views/picker_view_unittest.cc
@@ -96,8 +96,6 @@ last_inserted_result_ = result; } - bool ShouldPaint() override { return true; } - PickerAssetFetcher* GetAssetFetcher() override { return &asset_fetcher_; } std::optional<PickerSearchResult> last_inserted_result() const { @@ -401,7 +399,7 @@ .work_area() .Contains(view->GetBoundsInScreen())); // Should be to the right of the caret. - EXPECT_GE(view->GetBoundsInScreen().x(), kDefaultCaretBounds.right()); + EXPECT_GT(view->GetBoundsInScreen().x(), kDefaultCaretBounds.right()); // Center of the search field should be vertically aligned with the caret. EXPECT_EQ(view->search_field_view_for_testing() .GetBoundsInScreen() @@ -425,7 +423,7 @@ // Should be entirely on screen. EXPECT_TRUE(screen_work_area.Contains(view->GetBoundsInScreen())); // Should be to the right of the caret. - EXPECT_GE(view->GetBoundsInScreen().x(), caret_bounds.right()); + EXPECT_GT(view->GetBoundsInScreen().x(), caret_bounds.right()); // Center of the search field should be vertically aligned with the caret. EXPECT_EQ(view->search_field_view_for_testing() .GetBoundsInScreen() @@ -449,7 +447,7 @@ // Should be entirely on screen. EXPECT_TRUE(screen_work_area.Contains(view->GetBoundsInScreen())); // Should be to the right of the caret. - EXPECT_GE(view->GetBoundsInScreen().x(), caret_bounds.right()); + EXPECT_GT(view->GetBoundsInScreen().x(), caret_bounds.right()); // Center of the search field should be vertically aligned with the caret. EXPECT_EQ(view->search_field_view_for_testing() .GetBoundsInScreen() @@ -473,7 +471,7 @@ // Should be entirely on screen. EXPECT_TRUE(screen_work_area.Contains(view->GetBoundsInScreen())); // Should be below the caret. - EXPECT_GE(view->GetBoundsInScreen().y(), caret_bounds.bottom()); + EXPECT_GT(view->GetBoundsInScreen().y(), caret_bounds.bottom()); } TEST_F(PickerViewTest, BoundsAboveCaretForCaretNearBottomRightOfScreen) { @@ -491,7 +489,7 @@ // Should be entirely on screen. EXPECT_TRUE(screen_work_area.Contains(view->GetBoundsInScreen())); // Should be above the caret. - EXPECT_LE(view->GetBoundsInScreen().bottom(), caret_bounds.y()); + EXPECT_LT(view->GetBoundsInScreen().bottom(), caret_bounds.y()); } TEST_F(PickerViewTest, BoundsAlignedWithCursorForEmptyCaretBounds) {
diff --git a/ash/public/cpp/external_arc/BUILD.gn b/ash/public/cpp/external_arc/BUILD.gn index 34c6933f..6f6845101 100644 --- a/ash/public/cpp/external_arc/BUILD.gn +++ b/ash/public/cpp/external_arc/BUILD.gn
@@ -93,6 +93,7 @@ "//testing/gmock", "//ui/aura:test_support", "//ui/base:test_support", + "//ui/compositor:test_support", "//ui/events:test_support", "//ui/message_center:test_support", "//ui/views:test_support",
diff --git a/ash/public/cpp/external_arc/message_center/DEPS b/ash/public/cpp/external_arc/message_center/DEPS index 2afa256..eac8a73 100644 --- a/ash/public/cpp/external_arc/message_center/DEPS +++ b/ash/public/cpp/external_arc/message_center/DEPS
@@ -5,6 +5,7 @@ "+ash/components/arc/session/mojo_channel.h", "+ash/system/message_center/message_center_constants.h" "+ash/system/message_center/message_view_factory.h", + "+ash/system/notification_center/message_center_utils.h", "+components/arc/metrics/arc_metrics_constants.h", "+components/arc/test/connection_holder_util.h", "+components/arc/test/fake_notifications_instance.h",
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc index ea88cfc..6589d642 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc +++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
@@ -425,10 +425,10 @@ // of the hosting widget's focus chain. It could only be created when both // are present. Further, if we are being destroyed (|item_| is null), don't // create the control buttons. - if (!surface_ || !GetWidget() || !item_) + if (!surface_ || !GetWidget() || !item_ || control_buttons_view_.parent()) { return; + } - DCHECK(!control_buttons_view_.parent()); DCHECK(!floating_control_buttons_widget_); views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); @@ -554,6 +554,23 @@ UpdateMask(false /* force_update */); } +void ArcNotificationContentView::EnsureSurfaceAttached() { + if (!surface_ || surface_->IsAttached()) { + return; + } + AttachSurface(); +} + +void ArcNotificationContentView::EnsureSurfaceDetached() { + if (!GetWidget()) { + return; + } + + if (surface_ && surface_->IsAttached()) { + surface_->Detach(); + } +} + void ArcNotificationContentView::ShowCopiedSurface() { if (!surface_) return;
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h index 6650712f..16e93bf3 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h +++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.h
@@ -65,6 +65,8 @@ void OnContainerAnimationStarted(); void OnContainerAnimationEnded(); void ActivateWidget(bool activate); + void EnsureSurfaceAttached(); + void EnsureSurfaceDetached(); bool slide_in_progress() const { return slide_in_progress_; }
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_view.cc b/ash/public/cpp/external_arc/message_center/arc_notification_view.cc index 21796f61..b96ca3b2 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_view.cc +++ b/ash/public/cpp/external_arc/message_center/arc_notification_view.cc
@@ -6,11 +6,15 @@ #include <algorithm> +#include "ash/constants/ash_features.h" #include "ash/public/cpp/external_arc/message_center/arc_notification_content_view.h" #include "ash/public/cpp/external_arc/message_center/arc_notification_item.h" #include "ash/public/cpp/message_center/arc_notification_constants.h" #include "ash/public/cpp/style/color_provider.h" +#include "ash/style/typography.h" #include "ash/system/notification_center/message_center_constants.h" +#include "ash/system/notification_center/message_center_utils.h" +#include "ash/system/notification_center/notification_grouping_controller.h" #include "base/time/time.h" #include "chromeos/constants/chromeos_features.h" #include "third_party/skia/include/core/SkColor.h" @@ -26,11 +30,12 @@ #include "ui/compositor/layer.h" #include "ui/gfx/geometry/size.h" #include "ui/message_center/public/cpp/message_center_constants.h" -#include "ui/message_center/views/notification_background_painter.h" -#include "ui/message_center/views/notification_control_buttons_view.h" +#include "ui/message_center/views/notification_view_base.h" +#include "ui/views/animation/animation_builder.h" #include "ui/views/background.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/image_view.h" +#include "ui/views/controls/label.h" #include "ui/views/view_utils.h" DEFINE_UI_CLASS_PROPERTY_TYPE(ash::ArcNotificationView*) @@ -40,6 +45,32 @@ // Android side. constexpr base::TimeDelta kArcNotificationAnimationDuration = base::Milliseconds(360); + +// Create a view containing the title and message for the notification in a +// single line. This is used when a grouped child notification is in a +// collapsed parent notification. +views::Builder<views::BoxLayoutView> CreateCollapsedSummaryBuilder( + const message_center::Notification& notification) { + return views::Builder<views::BoxLayoutView>() + .SetID( + message_center::NotificationViewBase::ViewId::kCollapsedSummaryView) + .SetInsideBorderInsets(ash::kGroupedCollapsedSummaryInsets) + .SetBetweenChildSpacing(ash::kGroupedCollapsedSummaryLabelSpacing) + .SetOrientation(views::BoxLayout::Orientation::kHorizontal) + .SetVisible(false) + .AddChild(views::Builder<views::Label>() + .SetText(notification.title()) + .SetFontList( + ash::TypographyProvider::Get()->ResolveTypographyToken( + ash::TypographyToken::kCrosButton2))) + .AddChild(views::Builder<views::Label>() + .SetText(notification.message()) + .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT) + .SetTextStyle(views::style::STYLE_SECONDARY) + .SetFontList( + ash::TypographyProvider::Get()->ResolveTypographyToken( + ash::TypographyToken::kCrosBody2))); +} } // namespace namespace ash { @@ -71,6 +102,13 @@ AddChildView(content_view_.get()); + AddChildView(CreateCollapsedSummaryBuilder(notification) + .CopyAddressTo(&collapsed_summary_view_) + .Build()); + + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical, gfx::Insets())); + if (shown_in_popup) { layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma); layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality); @@ -116,6 +154,7 @@ void ArcNotificationView::UpdateWithNotification( const message_center::Notification& notification) { message_center::MessageView::UpdateWithNotification(notification); + is_group_child_ = notification.group_child(); content_view_->Update(notification); } @@ -148,8 +187,13 @@ } void ArcNotificationView::GetAccessibleNodeData(ui::AXNodeData* node_data) { - // This data is never used since this view is never focused when the content - // view is focusable. + if (content_view_->IsFocusable()) { + // This data is never used since this view is never focused when the content + // view is focusable. + return; + } + CHECK(features::IsRenderArcNotificationsByChromeEnabled()); + message_center::MessageView::GetAccessibleNodeData(node_data); } message_center::NotificationControlButtonsView* @@ -221,19 +265,129 @@ return kArcNotificationAnimationDuration; } +void ArcNotificationView::SetGroupedChildExpanded(bool expanded) { + if (!collapsed_summary_view_) { + return; + } + CHECK(features::IsRenderArcNotificationsByChromeEnabled()); + + collapsed_summary_view_->SetVisible(!expanded); + content_view_->SetVisible(expanded); + if (expanded) { + content_view_->EnsureSurfaceAttached(); + } else { + content_view_->EnsureSurfaceDetached(); + } +} + +void ArcNotificationView::AnimateGroupedChildExpandedCollapse(bool expanded) { + if (!collapsed_summary_view_) { + return; + } + CHECK(features::IsRenderArcNotificationsByChromeEnabled()); + + message_center_utils::InitLayerForAnimations(collapsed_summary_view_); + message_center_utils::InitLayerForAnimations(content_view_); + // Fade out `collapsed_summary_view_`, then fade in `content_view_` in + // expanded state and vice versa in collapsed state. + if (expanded) { + message_center_utils::FadeOutView( + collapsed_summary_view_, + base::BindRepeating( + [](base::WeakPtr<ash::ArcNotificationView> parent, + views::View* collapsed_summary_view) { + if (parent) { + collapsed_summary_view->layer()->SetOpacity(1.0f); + collapsed_summary_view->SetVisible(false); + } + }, + weak_factory_.GetWeakPtr(), collapsed_summary_view_), + 0, kCollapsedSummaryViewAnimationDurationMs, gfx::Tween::LINEAR, + "Arc.NotificationView.CollapsedSummaryView.FadeOut." + "AnimationSmoothness"); + message_center_utils::FadeInView( + content_view_, kCollapsedSummaryViewAnimationDurationMs, + kChildMainViewFadeInAnimationDurationMs, gfx::Tween::LINEAR, + "Arc.NotificationView.ContentView.FadeIn.AnimationSmoothness"); + return; + } + + message_center_utils::FadeOutView( + content_view_, + base::BindRepeating( + [](base::WeakPtr<ash::ArcNotificationView> parent, + views::View* content_view) { + if (parent) { + content_view->layer()->SetOpacity(1.0f); + content_view->SetVisible(false); + } + }, + weak_factory_.GetWeakPtr(), content_view_), + 0, kChildMainViewFadeOutAnimationDurationMs, gfx::Tween::LINEAR, + "Arc.NotificationView.ContentView.FadeOut.AnimationSmoothness"); + message_center_utils::FadeInView( + collapsed_summary_view_, kChildMainViewFadeOutAnimationDurationMs, + kCollapsedSummaryViewAnimationDurationMs, gfx::Tween::LINEAR, + "Arc.NotificationView.CollapsedSummaryView.FadeIn.AnimationSmoothness"); +} + +void ArcNotificationView::AnimateSingleToGroup( + const std::string& notification_id, + std::string parent_id) { + if (!collapsed_summary_view_) { + return; + } + CHECK(features::IsRenderArcNotificationsByChromeEnabled()); + + auto on_animation_ended = base::BindOnce( + [](base::WeakPtr<ash::ArcNotificationView> parent, + const std::string& notification_id, std::string parent_id) { + if (!parent) { + return; + } + + auto* parent_notification = + message_center::MessageCenter::Get()->FindNotificationById( + parent_id); + auto* child_notification = + message_center::MessageCenter::Get()->FindNotificationById( + notification_id); + // The child and parent notifications are not guaranteed to exist. + // If they were deleted avoid the animation cleanup. + if (!parent_notification || !child_notification) { + return; + } + + auto* grouping_controller = + message_center_utils::GetGroupingControllerForNotificationView( + parent.get()); + if (grouping_controller) { + grouping_controller + ->ConvertFromSingleToGroupNotificationAfterAnimation( + notification_id, parent_id, parent_notification); + } + parent->DeprecatedLayoutImmediately(); + }, + weak_factory_.GetWeakPtr(), notification_id, parent_id); + + std::pair<base::OnceClosure, base::OnceClosure> split = + base::SplitOnceCallback(std::move(on_animation_ended)); + + views::AnimationBuilder() + .SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET) + .OnEnded(std::move(split.first)) + .OnAborted(std::move(split.second)) + .Once() + .SetDuration( + base::Milliseconds(kConvertFromSingleToGroupFadeOutDurationMs)); +} + void ArcNotificationView::OnSlideChanged(bool in_progress) { MessageView::OnSlideChanged(in_progress); content_view_->OnSlideChanged(in_progress); } -gfx::Size ArcNotificationView::CalculatePreferredSize() const { - const gfx::Insets insets = GetInsets(); - const int contents_width = kNotificationInMessageCenterWidth; - const int contents_height = content_view_->GetHeightForWidth(contents_width); - return gfx::Size(contents_width + insets.width(), - contents_height + insets.height()); -} - void ArcNotificationView::Layout(PassKey) { // Setting the bounds before calling the parent to prevent double Layout. content_view_->SetBoundsRect(GetContentsBounds());
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_view.h b/ash/public/cpp/external_arc/message_center/arc_notification_view.h index 3437d85f..ac0b807a7 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_view.h +++ b/ash/public/cpp/external_arc/message_center/arc_notification_view.h
@@ -64,12 +64,15 @@ void UpdateBackgroundPainter() override; base::TimeDelta GetBoundsAnimationDuration( const message_center::Notification&) const override; + void AnimateGroupedChildExpandedCollapse(bool expanded) override; + void AnimateSingleToGroup(const std::string& notification_id, + std::string parent_id) override; + void SetGroupedChildExpanded(bool expanded) override; // views::SlideOutControllerDelegate: void OnSlideChanged(bool in_progress) override; // Overridden from views::View: - gfx::Size CalculatePreferredSize() const override; void Layout(PassKey) override; bool HasFocus() const override; void RequestFocus() override; @@ -100,7 +103,11 @@ const bool shown_in_popup_; - const bool is_group_child_; + bool is_group_child_; + + raw_ptr<views::View> collapsed_summary_view_ = nullptr; + + base::WeakPtrFactory<ArcNotificationView> weak_factory_{this}; }; } // namespace ash
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc b/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc index 95d2309..c2070e8f 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc +++ b/ash/public/cpp/external_arc/message_center/arc_notification_view_unittest.cc
@@ -19,6 +19,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/ime/dummy_text_input_client.h" @@ -27,6 +28,8 @@ #include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/compositor/test/layer_animation_stopped_waiter.h" +#include "ui/compositor/test/test_utils.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/test/event_generator.h" @@ -193,6 +196,13 @@ ArcNotificationContentView* content_view() { return notification_view_->content_view_; } + + views::View* collapsed_summary_view() { + return notification_view_->collapsed_summary_view_; + } + + bool IsGroupChild() { return notification_view_->is_group_child_; } + views::Widget* widget() { return notification_view_->GetWidget(); } ArcNotificationView* notification_view() { return notification_view_; } @@ -373,19 +383,19 @@ // Default size. gfx::Size size = notification_view()->GetPreferredSize(); size.Enlarge(0, -notification_view()->GetInsets().height()); - EXPECT_EQ("344x100", size.ToString()); + EXPECT_EQ("100x100", size.ToString()); // Allow small notifications. content_view()->SetPreferredSize(gfx::Size(10, 10)); size = notification_view()->GetPreferredSize(); size.Enlarge(0, -notification_view()->GetInsets().height()); - EXPECT_EQ("344x10", size.ToString()); + EXPECT_EQ("10x10", size.ToString()); // The long notification. content_view()->SetPreferredSize(gfx::Size(1000, 1000)); size = notification_view()->GetPreferredSize(); size.Enlarge(0, -notification_view()->GetInsets().height()); - EXPECT_EQ("344x1000", size.ToString()); + EXPECT_EQ("1000x1000", size.ToString()); } class NotificationGestureUpdateTest : public ArcNotificationViewTest { @@ -418,4 +428,101 @@ EXPECT_TRUE(IsPopupRemovedAfterIdle(kDefaultNotificationId)); } +class ArcNotificationViewRenderByChromeEnabledTest + : public ArcNotificationViewTest { + public: + ArcNotificationViewRenderByChromeEnabledTest() = default; + + ArcNotificationViewRenderByChromeEnabledTest( + const ArcNotificationViewRenderByChromeEnabledTest&) = delete; + ArcNotificationViewRenderByChromeEnabledTest& operator=( + const ArcNotificationViewRenderByChromeEnabledTest&) = delete; + + ~ArcNotificationViewRenderByChromeEnabledTest() override = default; + + // Overridden from ViewsTestBase: + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + ash::features::kRenderArcNotificationsByChrome); + + ArcNotificationViewTest::SetUp(); + } + + // Check that smoothness should be recorded after an animation is performed on + // a particular view. + // This is copied from + // ash/system/notification_center/views/ash_notification_view_unittest.cc. + void CheckSmoothnessRecorded(base::HistogramTester& histograms, + views::View* view, + const char* animation_histogram_name, + int data_point_count = 1) { + ui::Compositor* compositor = view->layer()->GetCompositor(); + + ui::LayerAnimationStoppedWaiter animation_waiter; + animation_waiter.Wait(view->layer()); + + // Force frames and wait for all throughput trackers to be gone to allow + // animation throughput data to be passed from cc to ui. + while (compositor->has_throughput_trackers_for_testing()) { + compositor->ScheduleFullRedraw(); + std::ignore = ui::WaitForNextFrameToBePresented(compositor, + base::Milliseconds(500)); + } + + // Smoothness should be recorded. + histograms.ExpectTotalCount(animation_histogram_name, data_point_count); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// TODO(b/324991437)): the test is disabled due to recent flaky results. +TEST_F(ArcNotificationViewRenderByChromeEnabledTest, + DISABLED_AnimateGroupedChildExpandedCollapseChanged) { + // Enable animations. + ui::ScopedAnimationDurationScaleMode duration( + ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); + + std::unique_ptr<Notification> notification = CreateSimpleNotification(); + notification->SetGroupChild(); + UpdateNotificationViews(*notification); + EXPECT_TRUE(IsGroupChild()); + EXPECT_NE(nullptr, collapsed_summary_view()); + + // Expected histogram logged when expanding/collapsing. + notification_view()->AnimateGroupedChildExpandedCollapse(true); + + base::HistogramTester tester_; + CheckSmoothnessRecorded( + tester_, collapsed_summary_view(), + "Arc.NotificationView.CollapsedSummaryView.FadeOut.AnimationSmoothness"); + + // Expected behavior in collapsed state. + notification_view()->AnimateGroupedChildExpandedCollapse(false); + + CheckSmoothnessRecorded( + tester_, collapsed_summary_view(), + "Arc.NotificationView.CollapsedSummaryView.FadeIn.AnimationSmoothness"); +} + +TEST_F(ArcNotificationViewRenderByChromeEnabledTest, + GroupedChildExpandStateChanged) { + std::unique_ptr<Notification> notification = CreateSimpleNotification(); + notification->SetGroupChild(); + UpdateNotificationViews(*notification); + EXPECT_TRUE(IsGroupChild()); + EXPECT_NE(nullptr, collapsed_summary_view()); + + // Expected behavior in expanded state. + notification_view()->SetGroupedChildExpanded(true); + EXPECT_TRUE(content_view()->GetVisible()); + EXPECT_FALSE(collapsed_summary_view()->GetVisible()); + + // Expected behavior in collapsed state. + notification_view()->SetGroupedChildExpanded(false); + EXPECT_FALSE(content_view()->GetVisible()); + EXPECT_TRUE(collapsed_summary_view()->GetVisible()); +} + } // namespace ash
diff --git a/ash/public/cpp/input_device_settings_controller.h b/ash/public/cpp/input_device_settings_controller.h index 3b92a187..172f183 100644 --- a/ash/public/cpp/input_device_settings_controller.h +++ b/ash/public/cpp/input_device_settings_controller.h
@@ -65,6 +65,10 @@ virtual void OnCustomizablePenButtonPressed( const mojom::GraphicsTablet& mouse, const mojom::Button& button) {} + + virtual void OnCustomizableMouseObservingStarted( + const mojom::Mouse& mouse) {} + virtual void OnCustomizableMouseObservingStopped() {} }; static InputDeviceSettingsController* Get();
diff --git a/ash/public/cpp/picker/picker_search_result.cc b/ash/public/cpp/picker/picker_search_result.cc index 9c081270..3f7f9d84 100644 --- a/ash/public/cpp/picker/picker_search_result.cc +++ b/ash/public/cpp/picker/picker_search_result.cc
@@ -65,9 +65,10 @@ } PickerSearchResult PickerSearchResult::BrowsingHistory(const GURL& url, + std::u16string title, ui::ImageModel icon) { - return PickerSearchResult( - BrowsingHistoryData{.url = url, .icon = std::move(icon)}); + return PickerSearchResult(BrowsingHistoryData{ + .url = url, .title = std::move(title), .icon = std::move(icon)}); } bool PickerSearchResult::operator==(const PickerSearchResult&) const = default;
diff --git a/ash/public/cpp/picker/picker_search_result.h b/ash/public/cpp/picker/picker_search_result.h index fbf168f..1a56526a 100644 --- a/ash/public/cpp/picker/picker_search_result.h +++ b/ash/public/cpp/picker/picker_search_result.h
@@ -58,6 +58,7 @@ struct BrowsingHistoryData { GURL url; + std::u16string title; ui::ImageModel icon; bool operator==(const BrowsingHistoryData&) const; @@ -75,6 +76,7 @@ ~PickerSearchResult(); static PickerSearchResult BrowsingHistory(const GURL& url, + std::u16string title, ui::ImageModel icon); static PickerSearchResult Text(std::u16string_view text); static PickerSearchResult Emoji(std::u16string_view emoji);
diff --git a/ash/public/mojom/input_device_settings.mojom b/ash/public/mojom/input_device_settings.mojom index 1f948b9c..9fd6213 100644 --- a/ash/public/mojom/input_device_settings.mojom +++ b/ash/public/mojom/input_device_settings.mojom
@@ -407,4 +407,6 @@ // Allow horizontal scroll wheel as well as normal mouse buttons. Identical to // kDisableKeyEventRewrites but permits horizontal scroll wheel buttons. kAllowHorizontalScrollWheelRewrites = 5, + // Allow tab events in addition to normal mouse events to be rewritten. + kAllowTabEventRewrites = 6, };
diff --git a/ash/shell.cc b/ash/shell.cc index bbc68e8..f846d7b 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -229,6 +229,7 @@ #include "ash/wm/window_animations.h" #include "ash/wm/window_cycle/window_cycle_controller.h" #include "ash/wm/window_properties.h" +#include "ash/wm/window_restore/pine_controller.h" #include "ash/wm/window_restore/window_restore_controller.h" #include "ash/wm/window_util.h" #include "ash/wm/wm_shadow_controller_delegate.h" @@ -974,6 +975,7 @@ backlights_forced_off_setter_.reset(); float_controller_.reset(); + pine_controller_.reset(); pip_controller_.reset(); screen_pinning_controller_.reset(); @@ -1746,6 +1748,9 @@ projector_controller_ = std::make_unique<ProjectorControllerImpl>(); float_controller_ = std::make_unique<FloatController>(); + if (features::IsForestFeatureEnabled()) { + pine_controller_ = std::make_unique<PineController>(); + } pip_controller_ = std::make_unique<PipController>(); multitask_menu_nudge_delegate_ =
diff --git a/ash/shell.h b/ash/shell.h index c4e4bda7..b757654 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -152,7 +152,6 @@ class EventClientImpl; class EventRewriterControllerImpl; class EventTransformationHandler; -class WindowRestoreController; class FirmwareUpdateManager; class FirmwareUpdateNotificationController; class FloatController; @@ -187,7 +186,6 @@ class LoginUnlockThroughputRecorder; class MediaNotificationProvider; class TabClusterUIController; -class TabletModeController; class MediaControllerImpl; class MessageCenterAshImpl; class MessageCenterController; @@ -209,6 +207,7 @@ class PeripheralBatteryNotifier; class PersistentWindowController; class PickerController; +class PineController; class PipController; class PolicyRecommendationRestorer; class PostLoginGlanceablesMetricsRecorder; @@ -252,6 +251,7 @@ class SystemSoundsDelegate; class SystemTrayModel; class SystemTrayNotifier; +class TabletModeController; class ToastManagerImpl; class ToplevelWindowEventHandler; class ClipboardHistoryControllerImpl; @@ -264,6 +264,7 @@ class WallpaperControllerImpl; class WindowBoundsTracker; class WindowCycleController; +class WindowRestoreController; class WindowTilingController; class WindowTreeHostManager; class WmModeController; @@ -667,6 +668,7 @@ return peripheral_battery_listener_.get(); } PickerController* picker_controller() { return picker_controller_.get(); } + PineController* pine_controller() { return pine_controller_.get(); } PipController* pip_controller() { return pip_controller_.get(); } PolicyRecommendationRestorer* policy_recommendation_restorer() { return policy_recommendation_restorer_.get(); @@ -1078,6 +1080,7 @@ feature_discover_reporter_; std::unique_ptr<AshColorProvider> ash_color_provider_; std::unique_ptr<NightLightControllerImpl> night_light_controller_; + std::unique_ptr<PineController> pine_controller_; std::unique_ptr<PipController> pip_controller_; std::unique_ptr<PrivacyScreenController> privacy_screen_controller_; std::unique_ptr<PolicyRecommendationRestorer> policy_recommendation_restorer_;
diff --git a/ash/system/input_device_settings/input_device_duplicate_id_finder.cc b/ash/system/input_device_settings/input_device_duplicate_id_finder.cc index df7311c3..ff37600 100644 --- a/ash/system/input_device_settings/input_device_duplicate_id_finder.cc +++ b/ash/system/input_device_settings/input_device_duplicate_id_finder.cc
@@ -13,10 +13,8 @@ template <typename T> void UpdateList( const std::vector<T>& devices, - base::flat_map<InputDeviceDuplicateIdFinder::VidPidIdentifier, - base::flat_set<int>>& duplicate_ids_map, - base::flat_map<int, InputDeviceDuplicateIdFinder::VidPidIdentifier>& - vid_pid_map) { + base::flat_map<VendorProductId, base::flat_set<int>>& duplicate_ids_map, + base::flat_map<int, VendorProductId>& vid_pid_map) { for (const auto& device : devices) { duplicate_ids_map[{device.vendor_id, device.product_id}].insert(device.id); vid_pid_map[device.id] = {device.vendor_id, device.product_id}; @@ -25,14 +23,6 @@ } // namespace -bool operator<(const InputDeviceDuplicateIdFinder::VidPidIdentifier& lhs, - const InputDeviceDuplicateIdFinder::VidPidIdentifier& rhs) { - if (lhs.vendor_id != rhs.vendor_id) { - return lhs.vendor_id < rhs.vendor_id; - } - return lhs.product_id < rhs.product_id; -} - InputDeviceDuplicateIdFinder::InputDeviceDuplicateIdFinder() { ui::DeviceDataManager::GetInstance()->AddObserver(this); } @@ -55,6 +45,26 @@ return &dedupes_iter->second; } +const base::flat_set<int>* InputDeviceDuplicateIdFinder::GetDuplicateDeviceIds( + const VendorProductId& vid_pid) const { + auto dedupes_iter = duplicate_ids_map_.find(vid_pid); + if (dedupes_iter == duplicate_ids_map_.end()) { + return nullptr; + } + + return &dedupes_iter->second; +} + +std::optional<VendorProductId> +InputDeviceDuplicateIdFinder::GetVendorProductIdForDevice(int id) const { + auto vid_pid_iter = vid_pid_map_.find(id); + if (vid_pid_iter == vid_pid_map_.end()) { + return std::nullopt; + } + + return vid_pid_iter->second; +} + void InputDeviceDuplicateIdFinder::OnInputDeviceConfigurationChanged( uint8_t input_device_type) { duplicate_ids_map_.clear(); @@ -67,6 +77,8 @@ RefreshTouchscreens(); RefreshGraphicsTablets(); RefreshUncategorized(); + + NotifyObservers(); } void InputDeviceDuplicateIdFinder::OnDeviceListsComplete() { @@ -80,6 +92,8 @@ RefreshTouchscreens(); RefreshGraphicsTablets(); RefreshUncategorized(); + + NotifyObservers(); } void InputDeviceDuplicateIdFinder::RefreshKeyboards() { @@ -117,4 +131,18 @@ duplicate_ids_map_, vid_pid_map_); } +void InputDeviceDuplicateIdFinder::NotifyObservers() { + for (auto& observer : observers_) { + observer.OnDuplicateDevicesUpdated(); + } +} + +void InputDeviceDuplicateIdFinder::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void InputDeviceDuplicateIdFinder::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + } // namespace ash
diff --git a/ash/system/input_device_settings/input_device_duplicate_id_finder.h b/ash/system/input_device_settings/input_device_duplicate_id_finder.h index 0bdad28..b0f40e3 100644 --- a/ash/system/input_device_settings/input_device_duplicate_id_finder.h +++ b/ash/system/input_device_settings/input_device_duplicate_id_finder.h
@@ -6,8 +6,11 @@ #define ASH_SYSTEM_INPUT_DEVICE_SETTINGS_INPUT_DEVICE_DUPLICATE_ID_FINDER_H_ #include "ash/ash_export.h" +#include "ash/system/input_device_settings/input_device_settings_utils.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/observer_list.h" +#include "base/observer_list_types.h" #include "ui/events/devices/input_device_event_observer.h" namespace ash { @@ -17,11 +20,9 @@ class ASH_EXPORT InputDeviceDuplicateIdFinder : public ui::InputDeviceEventObserver { public: - struct VidPidIdentifier { - uint16_t vendor_id, product_id; - - friend bool operator<(const VidPidIdentifier& lhs, - const VidPidIdentifier& rhs); + class Observer : public base::CheckedObserver { + public: + virtual void OnDuplicateDevicesUpdated() {} }; InputDeviceDuplicateIdFinder(); @@ -36,6 +37,12 @@ // Gets the set of duplicate device ids for the given `device_id`. const base::flat_set<int>* GetDuplicateDeviceIds(int id) const; + const base::flat_set<int>* GetDuplicateDeviceIds( + const VendorProductId& vid_pid) const; + std::optional<VendorProductId> GetVendorProductIdForDevice(int id) const; + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); private: void RefreshKeyboards(); @@ -46,11 +53,15 @@ void RefreshGraphicsTablets(); void RefreshUncategorized(); + void NotifyObservers(); + // Contains the list of device ids that map back to the given VID/PID // Identifier. - base::flat_map<VidPidIdentifier, base::flat_set<int>> duplicate_ids_map_; + base::flat_map<VendorProductId, base::flat_set<int>> duplicate_ids_map_; // Maps from id -> VID/PID identifier to make searching quicker. - base::flat_map<int, VidPidIdentifier> vid_pid_map_; + base::flat_map<int, VendorProductId> vid_pid_map_; + + base::ObserverList<Observer> observers_; }; } // namespace ash
diff --git a/ash/system/input_device_settings/input_device_duplicate_id_finder_unittest.cc b/ash/system/input_device_settings/input_device_duplicate_id_finder_unittest.cc index 5c8dc1c5..b2562b2 100644 --- a/ash/system/input_device_settings/input_device_duplicate_id_finder_unittest.cc +++ b/ash/system/input_device_settings/input_device_duplicate_id_finder_unittest.cc
@@ -4,6 +4,8 @@ #include "ash/system/input_device_settings/input_device_duplicate_id_finder.h" +#include <memory> + #include "ash/test/ash_test_base.h" #include "ui/events/devices/device_data_manager_test_api.h" #include "ui/events/devices/input_device.h" @@ -21,6 +23,17 @@ base::FilePath(), vendor, product, 0); } +class TestObserver : public InputDeviceDuplicateIdFinder::Observer { + public: + // InputDeviceDuplicateIdFinder::Observer: + void OnDuplicateDevicesUpdated() override { num_times_updated_++; } + + int num_times_updated() { return num_times_updated_; } + + private: + int num_times_updated_ = 0; +}; + } // namespace class InputDeviceDuplicateIdFinderTest : public AshTestBase { @@ -37,15 +50,20 @@ AshTestBase::SetUp(); // Duplicate ID finder should be created after the test base is setup. duplicate_id_finder_ = std::make_unique<InputDeviceDuplicateIdFinder>(); + observer_ = std::make_unique<TestObserver>(); + duplicate_id_finder_->AddObserver(observer_.get()); } void TearDown() override { + duplicate_id_finder_->RemoveObserver(observer_.get()); + observer_.reset(); duplicate_id_finder_.reset(); AshTestBase::TearDown(); } protected: std::unique_ptr<InputDeviceDuplicateIdFinder> duplicate_id_finder_; + std::unique_ptr<TestObserver> observer_; }; TEST_F(InputDeviceDuplicateIdFinderTest, DuplicateIdFinding) { @@ -63,13 +81,18 @@ ui::DeviceDataManagerTestApi().SetMouseDevices( {duplicate_1_1, duplicate_2_1, duplicate_3_1}); + EXPECT_EQ(1, observer_->num_times_updated()); ui::DeviceDataManagerTestApi().SetGraphicsTabletDevices( {duplicate_1_2, duplicate_2_2, duplicate_3_2}); + EXPECT_EQ(2, observer_->num_times_updated()); ui::DeviceDataManagerTestApi().SetUncategorizedDevices({duplicate_1_3}); + EXPECT_EQ(3, observer_->num_times_updated()); ui::DeviceDataManagerTestApi().SetKeyboardDevices( {ui::KeyboardDevice(duplicate_2_3)}); + EXPECT_EQ(4, observer_->num_times_updated()); ui::DeviceDataManagerTestApi().SetTouchpadDevices( {ui::TouchpadDevice(duplicate_3_3)}); + EXPECT_EQ(5, observer_->num_times_updated()); { auto* duplicate_group =
diff --git a/ash/system/input_device_settings/input_device_settings_controller_impl.cc b/ash/system/input_device_settings/input_device_settings_controller_impl.cc index 8ce3767..023d6ac 100644 --- a/ash/system/input_device_settings/input_device_settings_controller_impl.cc +++ b/ash/system/input_device_settings/input_device_settings_controller_impl.cc
@@ -1804,6 +1804,9 @@ rewriter->StartObservingMouse(duplicate_id, mouse->customization_restriction); } + for (auto& observer : observers_) { + observer.OnCustomizableMouseObservingStarted(*mouse); + } return; } @@ -1830,6 +1833,10 @@ ->peripheral_customization_event_rewriter(); CHECK(rewriter); rewriter->StopObserving(); + + for (auto& observer : observers_) { + observer.OnCustomizableMouseObservingStopped(); + } } void InputDeviceSettingsControllerImpl::OnMouseButtonPressed(
diff --git a/ash/system/input_device_settings/input_device_settings_controller_unittest.cc b/ash/system/input_device_settings/input_device_settings_controller_unittest.cc index b745f9a8..0e95cf82 100644 --- a/ash/system/input_device_settings/input_device_settings_controller_unittest.cc +++ b/ash/system/input_device_settings/input_device_settings_controller_unittest.cc
@@ -387,6 +387,14 @@ num_pen_buttons_pressed_++; } + void OnCustomizableMouseObservingStarted(const mojom::Mouse& mouse) override { + num_mouse_observing_started_++; + } + + void OnCustomizableMouseObservingStopped() override { + num_mouse_observing_stopped_++; + } + uint32_t num_keyboards_connected() { return num_keyboards_connected_; } uint32_t num_graphics_tablets_connected() { return num_graphics_tablets_connected_; @@ -407,6 +415,12 @@ uint32_t num_mouse_buttons_pressed() { return num_mouse_buttons_pressed_; } uint32_t num_pen_buttons_pressed() { return num_pen_buttons_pressed_; } uint32_t num_tablet_buttons_pressed() { return num_tablet_buttons_pressed_; } + uint32_t num_mouse_observing_started() { + return num_mouse_observing_started_; + } + uint32_t num_mouse_observing_stopped() { + return num_mouse_observing_stopped_; + } private: uint32_t num_keyboards_connected_ = 0; @@ -419,6 +433,8 @@ uint32_t num_mouse_buttons_pressed_ = 0; uint32_t num_tablet_buttons_pressed_ = 0; uint32_t num_pen_buttons_pressed_ = 0; + uint32_t num_mouse_observing_started_ = 0; + uint32_t num_mouse_observing_stopped_ = 0; }; class InputDeviceSettingsControllerTest : public NoSessionAshTestBase { @@ -1314,10 +1330,12 @@ controller_->StartObservingButtons(kSampleMouseUsb.id); ASSERT_EQ(1u, rewriter->mice_to_observe().size()); EXPECT_TRUE(rewriter->mice_to_observe().contains(kSampleMouseUsb.id)); + EXPECT_EQ(1u, observer_->num_mouse_observing_started()); controller_->StopObservingButtons(); ASSERT_EQ(0u, rewriter->mice_to_observe().size()); ASSERT_EQ(0u, rewriter->graphics_tablets_to_observe().size()); + EXPECT_EQ(1u, observer_->num_mouse_observing_stopped()); controller_->StartObservingButtons(kSampleGraphicsTablet.id); ASSERT_EQ(1u, rewriter->graphics_tablets_to_observe().size());
diff --git a/ash/system/input_device_settings/input_device_settings_metadata.cc b/ash/system/input_device_settings/input_device_settings_metadata.cc index 8c81a33..d3ba1749 100644 --- a/ash/system/input_device_settings/input_device_settings_metadata.cc +++ b/ash/system/input_device_settings/input_device_settings_metadata.cc
@@ -54,6 +54,10 @@ {{0x046d, 0xb037}, {mojom::CustomizationRestriction::kDisableKeyEventRewrites, mojom::MouseButtonConfig::kFiveKey}}, + // Logitech MX Master 2S (Bluetooth) + {{0x046d, 0xb019}, + {mojom::CustomizationRestriction::kAllowTabEventRewrites, + mojom::MouseButtonConfig::kNoConfig}}, }); return *mouse_metadata_list; }
diff --git a/ash/system/input_device_settings/input_device_settings_utils.cc b/ash/system/input_device_settings/input_device_settings_utils.cc index 2e93e78..ab5177e 100644 --- a/ash/system/input_device_settings/input_device_settings_utils.cc +++ b/ash/system/input_device_settings/input_device_settings_utils.cc
@@ -106,6 +106,11 @@ return false; case mojom::CustomizationRestriction::kAllowHorizontalScrollWheelRewrites: return remapping.button->is_vkey(); + case mojom::CustomizationRestriction::kAllowTabEventRewrites: + if (remapping.button->is_customizable_button()) { + return false; + } + return remapping.button->get_vkey() != ui::VKEY_TAB; } }
diff --git a/ash/system/notification_center/message_center_utils.h b/ash/system/notification_center/message_center_utils.h index a6b3573d..e2a609f 100644 --- a/ash/system/notification_center/message_center_utils.h +++ b/ash/system/notification_center/message_center_utils.h
@@ -70,28 +70,30 @@ // Gets the grouping controller for the provided notification view. Each display // has it's own `NotificationGroupingController` so we need to look up the // display for the provide view first. -NotificationGroupingController* GetGroupingControllerForNotificationView( - views::View* notification_view); +NotificationGroupingController* ASH_EXPORT +GetGroupingControllerForNotificationView(views::View* notification_view); // Utils for animation within a notification view. // Initializes the layer for the specified `view` for animations. -void InitLayerForAnimations(views::View* view); +void ASH_EXPORT InitLayerForAnimations(views::View* view); // Fade in animation using AnimationBuilder. -void FadeInView(views::View* view, - int delay_in_ms, - int duration_in_ms, - gfx::Tween::Type tween_type = gfx::Tween::LINEAR, - const std::string& animation_histogram_name = std::string()); +void ASH_EXPORT +FadeInView(views::View* view, + int delay_in_ms, + int duration_in_ms, + gfx::Tween::Type tween_type = gfx::Tween::LINEAR, + const std::string& animation_histogram_name = std::string()); // Fade out animation using AnimationBuilder. -void FadeOutView(views::View* view, - base::OnceClosure on_animation_ended, - int delay_in_ms, - int duration_in_ms, - gfx::Tween::Type tween_type = gfx::Tween::LINEAR, - const std::string& animation_histogram_name = std::string()); +void ASH_EXPORT +FadeOutView(views::View* view, + base::OnceClosure on_animation_ended, + int delay_in_ms, + int duration_in_ms, + gfx::Tween::Type tween_type = gfx::Tween::LINEAR, + const std::string& animation_histogram_name = std::string()); // Slide out animation using AnimationBuilder. void SlideOutView(views::View* view,
diff --git a/ash/system/notification_center/views/ash_notification_view.cc b/ash/system/notification_center/views/ash_notification_view.cc index 986d5ee5..12edbe2 100644 --- a/ash/system/notification_center/views/ash_notification_view.cc +++ b/ash/system/notification_center/views/ash_notification_view.cc
@@ -1858,7 +1858,17 @@ if (needs_layout()) { DeprecatedLayoutImmediately(); } - DCHECK(!needs_layout()); + auto* notification = + message_center::MessageCenter::Get()->FindNotificationById( + notification_id()); + + // When the notification is ArcNotification and not group parent, the view + // is rendered in Android then attached to message center. Ash does not + // directly control the layout so we should not check `needs_layout()`. + if (message_center_utils::IsAshNotification(notification) && + !notification->group_parent()) { + DCHECK(!needs_layout()); + } expand_button_->AnimateExpandCollapse(); }
diff --git a/ash/system/unified/classroom_bubble_view_unittest.cc b/ash/system/unified/classroom_bubble_view_unittest.cc index fd88371..2ab6e13f 100644 --- a/ash/system/unified/classroom_bubble_view_unittest.cc +++ b/ash/system/unified/classroom_bubble_view_unittest.cc
@@ -405,6 +405,7 @@ TEST_F(ClassroomBubbleStudentViewTest, OpensClassroomUrlForListItem) { base::UserActionTester user_actions; + base::HistogramTester histogram_tester; EXPECT_CALL(classroom_client_, GetCompletedStudentAssignments(_)) .WillOnce([](GlanceablesClassroomClient::GetAssignmentsCallback cb) { std::move(cb).Run(/*success=*/true, CreateAssignments(1)); @@ -424,6 +425,14 @@ EXPECT_EQ(1, user_actions.GetActionCount( "Glanceables_Classroom_AssignmentPressed")); + histogram_tester.ExpectTotalCount( + "Ash.Glanceables.TimeManagement.Classroom.UserAction", 2); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Classroom.UserAction", 0, + /*expected_bucket_count=*/1); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Classroom.UserAction", 2, + /*expected_bucket_count=*/1); } TEST_F(ClassroomBubbleStudentViewTest, ShowsProgressBar) { @@ -445,6 +454,7 @@ TEST_F(ClassroomBubbleStudentViewTest, ClickHeaderIconButton) { base::UserActionTester user_actions; + base::HistogramTester histogram_tester; LeftClickOn(GetHeaderIcon()); EXPECT_EQ(new_window_delegate_.GetLastOpenedUrl(), @@ -452,6 +462,9 @@ EXPECT_EQ(1, user_actions.GetActionCount( "Glanceables_Classroom_HeaderIconPressed")); + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Classroom.UserAction", 1, + /*expected_bucket_count=*/1); } TEST_F(ClassroomBubbleStudentViewTest, ClickItemViewUserAction) { @@ -481,6 +494,14 @@ histogram_tester.ExpectUniqueSample( "Ash.Glanceables.Classroom.Student.ListSelected", 3, /*expected_bucket_count=*/1); + histogram_tester.ExpectTotalCount( + "Ash.Glanceables.TimeManagement.Classroom.UserAction", 3); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Classroom.UserAction", 0, + /*expected_bucket_count=*/1); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Classroom.UserAction", 2, + /*expected_bucket_count=*/2); } TEST_F(ClassroomBubbleStudentViewTest, ShowErrorMessageBubble) {
diff --git a/ash/system/unified/tasks_bubble_view_unittest.cc b/ash/system/unified/tasks_bubble_view_unittest.cc index dc94500..9f4d0ed 100644 --- a/ash/system/unified/tasks_bubble_view_unittest.cc +++ b/ash/system/unified/tasks_bubble_view_unittest.cc
@@ -18,6 +18,7 @@ #include "ash/test/ash_test_base.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h" #include "base/types/cxx23_to_underlying.h" @@ -131,6 +132,7 @@ }; TEST_F(TasksBubbleViewTest, ShowTasksComboModel) { + base::HistogramTester histogram_tester; EXPECT_FALSE(IsMenuRunning()); EXPECT_TRUE(GetComboBoxView()->GetVisible()); @@ -194,10 +196,13 @@ GetComboBoxView()->MenuItemAtIndex(0)->GetBoundsInScreen())); EXPECT_TRUE(GetComboBoxView()->MenuView()->GetBoundsInScreen().Intersects( GetComboBoxView()->MenuItemAtIndex(5)->GetBoundsInScreen())); + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 0, 3); } TEST_F(TasksBubbleViewTest, MarkTaskAsComplete) { base::UserActionTester user_actions; + base::HistogramTester histogram_tester; EXPECT_EQ(GetTaskItemsContainerView()->children().size(), 2u); auto* const task_view = views::AsViewClass<GlanceablesTaskView>( @@ -231,10 +236,18 @@ EXPECT_EQ(0, tasks_client()->completed_task_count()); tasks_client()->OnGlanceablesBubbleClosed(); EXPECT_EQ(1, tasks_client()->completed_task_count()); + + histogram_tester.ExpectTotalCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 3); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 1, 2); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 2, 1); } TEST_F(TasksBubbleViewTest, ShowTasksWebUIFromFooterView) { base::UserActionTester user_actions; + base::HistogramTester histogram_tester; const auto* const see_all_button = views::AsViewClass<views::LabelButton>(GetListFooterView()->GetViewByID( base::to_underlying(GlanceablesViewId::kListFooterSeeAllButton))); @@ -245,10 +258,13 @@ "Glanceables_Tasks_LaunchTasksApp_FooterButton")); EXPECT_EQ(0, user_actions.GetActionCount( "Glanceables_Tasks_ActiveTaskListChanged")); + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 7, 1); } TEST_F(TasksBubbleViewTest, ShowTasksWebUIFromAddNewButton) { base::UserActionTester user_actions; + base::HistogramTester histogram_tester; ASSERT_EQ(GetComboBoxView()->GetTextForRow(2), u"Task List 3 Title (empty)"); MenuSelectionAt(2); @@ -265,9 +281,16 @@ 1, user_actions.GetActionCount("Glanceables_Tasks_AddTaskButtonShown")); EXPECT_EQ(1, user_actions.GetActionCount( "Glanceables_Tasks_ActiveTaskListChanged")); + histogram_tester.ExpectTotalCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 2); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 0, 1); + histogram_tester.ExpectBucketCount( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 6, 1); } TEST_F(TasksBubbleViewTest, ShowTasksWebUIFromHeaderView) { + base::HistogramTester histogram_tester; base::UserActionTester user_actions; const auto* const header_icon_button = GetHeaderIconView(); GestureTapOn(header_icon_button); @@ -277,10 +300,13 @@ "Glanceables_Tasks_LaunchTasksApp_HeaderButton")); EXPECT_EQ(0, user_actions.GetActionCount( "Glanceables_Tasks_ActiveTaskListChanged")); + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 5, 1); } TEST_F(TasksBubbleViewTest, ShowsAndHidesAddNewButton) { base::UserActionTester user_actions; + base::HistogramTester histogram_tester; // Shows items from the first / default task list. EXPECT_TRUE(GetTaskItemsContainerView()->GetVisible()); @@ -297,9 +323,13 @@ EXPECT_FALSE(GetListFooterView()->GetVisible()); EXPECT_EQ( 1, user_actions.GetActionCount("Glanceables_Tasks_AddTaskButtonShown")); + + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 0, 1); } TEST_F(TasksBubbleViewTest, ShowsProgressBarWhileLoadingTasks) { + base::HistogramTester histogram_tester; ASSERT_TRUE(GetProgressBar()); ASSERT_TRUE(GetComboBoxView()); @@ -315,6 +345,8 @@ // After replying to pending callbacks, the progress bar should become hidden. EXPECT_EQ(tasks_client()->RunPendingGetTasksCallbacks(), 1u); EXPECT_FALSE(GetProgressBar()->GetVisible()); + histogram_tester.ExpectUniqueSample( + "Ash.Glanceables.TimeManagement.Tasks.UserAction", 0, 1); } } // namespace ash
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_actions.ts b/ash/webui/common/resources/sea_pen/sea_pen_actions.ts index 41b5707..f811677 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_actions.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_actions.ts
@@ -29,7 +29,6 @@ SET_RECENT_SEA_PEN_IMAGES = 'set_recent_sea_pen_images', SET_RECENT_SEA_PEN_IMAGE_DATA = 'set_recent_sea_pen_image_data', SET_SELECTED_RECENT_SEA_PEN_IMAGE = 'set_selected_recent_sea_pen_image', - SET_SEA_PEN_ATTRIBUTION = 'set_sea_pen_attribution', SET_SHOULD_SHOW_SEA_PEN_TERMS_OF_SERVICE_DIALOG = 'set_should_show_sea_pen_terms_of_service_dialog', } @@ -40,8 +39,8 @@ ClearSeaPenThumbnailsAction|EndSelectRecentSeaPenImageAction| SetThumbnailResponseStatusCodeAction|SetSeaPenThumbnailsAction| SetRecentSeaPenImagesAction|SetRecentSeaPenImageDataAction| - SetSelectedRecentSeaPenImageAction|SetSeaPenAttributionAction| - BeginSelectSeaPenThumbnailAction|EndSelectSeaPenThumbnailAction| + SetSelectedRecentSeaPenImageAction|BeginSelectSeaPenThumbnailAction| + EndSelectSeaPenThumbnailAction| SetShouldShowSeaPenTermsOfServiceDialogAction; export interface BeginSearchSeaPenThumbnailsAction extends Action { @@ -199,17 +198,6 @@ }; } -/** Sets the attribution for recent Sea Pen image. */ -export interface SetSeaPenAttributionAction extends Action { - name: SeaPenActionName.SET_SEA_PEN_ATTRIBUTION; -} - -export function setSeaPenAttributionAction(): SetSeaPenAttributionAction { - return { - name: SeaPenActionName.SET_SEA_PEN_ATTRIBUTION, - }; -} - /** Sets the Sea Pen thumbnail response status code. */ export interface SetThumbnailResponseStatusCodeAction extends Action { name: SeaPenActionName.SET_THUMBNAIL_RESPONSE_STATUS_CODE;
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts b/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts index 96dea1e..103eda5 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts
@@ -84,35 +84,18 @@ case SeaPenActionName.BEGIN_LOAD_SELECTED_RECENT_SEA_PEN_IMAGE: return { ...state, - selected: { - attribution: true, - image: true, - }, + currentSelected: true, }; case SeaPenActionName.BEGIN_SELECT_SEA_PEN_THUMBNAIL: return { ...state, + currentSelected: true, setImage: state.setImage + 1, - selected: { - attribution: true, - image: true, - }, }; case SeaPenActionName.SET_SELECTED_RECENT_SEA_PEN_IMAGE: return { ...state, - selected: { - ...state.selected, - image: false, - }, - }; - case SeaPenActionName.SET_SEA_PEN_ATTRIBUTION: - return { - ...state, - selected: { - ...state.selected, - attribution: false, - }, + currentSelected: false, }; default: return state;
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_state.ts b/ash/webui/common/resources/sea_pen/sea_pen_state.ts index a55ca32..d103b44 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_state.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_state.ts
@@ -11,10 +11,7 @@ recentImageData: Record<FilePath['path'], boolean>; recentImages: boolean; thumbnails: boolean; - selected: { - attribution: boolean, - image: boolean, - }; + currentSelected: boolean; setImage: number; } @@ -35,10 +32,7 @@ recentImages: false, recentImageData: {}, thumbnails: false, - selected: { - attribution: false, - image: false, - }, + currentSelected: false, setImage: 0, }, recentImageData: {},
diff --git a/ash/webui/personalization_app/resources/js/sea_pen_store_adapter.ts b/ash/webui/personalization_app/resources/js/sea_pen_store_adapter.ts index 845b5f67..4e8f4cb6 100644 --- a/ash/webui/personalization_app/resources/js/sea_pen_store_adapter.ts +++ b/ash/webui/personalization_app/resources/js/sea_pen_store_adapter.ts
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {SeaPenActions} from 'chrome://resources/ash/common/sea_pen/sea_pen_actions.js'; +import {SeaPenActionName, SeaPenActions} from 'chrome://resources/ash/common/sea_pen/sea_pen_actions.js'; import {SeaPenState} from 'chrome://resources/ash/common/sea_pen/sea_pen_state.js'; import {SeaPenStoreInterface, setSeaPenStore} from 'chrome://resources/ash/common/sea_pen/sea_pen_store.js'; import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; import {DeferredAction, StoreObserver} from 'chrome://resources/js/store.js'; +import {beginLoadSelectedImageAction} from './personalization_app.js'; import {PersonalizationState} from './personalization_state.js'; import {PersonalizationStore} from './personalization_store.js'; @@ -71,7 +72,19 @@ } dispatch(action: SeaPenActions|null) { - return PersonalizationStore.getInstance().dispatch(action); + const store = PersonalizationStore.getInstance(); + this.beginBatchUpdate(); + // Dispatch additional actions to set proper wallpaper state when necessary. + switch (action?.name) { + // Dispatch action to set wallpaper loading state to true when Sea Pen + // image is selected. + case SeaPenActionName.BEGIN_SELECT_SEA_PEN_THUMBNAIL: + case SeaPenActionName.BEGIN_LOAD_SELECTED_RECENT_SEA_PEN_IMAGE: + store.dispatch(beginLoadSelectedImageAction()); + break; + } + store.dispatch(action); + store.endBatchUpdate(); } onStateChanged({wallpaper: {seaPen}}: PersonalizationState) {
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_observer.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_observer.ts index 7d58ad0a..ae96171a 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_observer.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_observer.ts
@@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {setSeaPenAttributionAction, setSelectedRecentSeaPenImageAction} from 'chrome://resources/ash/common/sea_pen/sea_pen_actions.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {setSelectedRecentSeaPenImageAction} from 'chrome://resources/ash/common/sea_pen/sea_pen_actions.js'; import {CurrentAttribution, CurrentWallpaper, WallpaperObserverInterface, WallpaperObserverReceiver, WallpaperProviderInterface, WallpaperType} from '../../personalization_app.mojom-webui.js'; import {PersonalizationStore} from '../personalization_store.js'; @@ -60,17 +59,6 @@ onAttributionChanged(attribution: CurrentAttribution|null) { const store = PersonalizationStore.getInstance(); store.dispatch(setAttributionAction(attribution)); - // Set the Sea Pen wallpaper attribution loading state completed if it is - // loading. - if (store.data.wallpaper.seaPen.loading.selected.attribution) { - // Sea Pen currentSelected state should have been set before the - // attribution is notified, and match with the attribution key. - assert(attribution, 'attribution should be available'); - assert( - store.data.wallpaper.seaPen.currentSelected === attribution!.key, - 'attribution key should match currentSelected'); - store.dispatch(setSeaPenAttributionAction()); - } } onWallpaperChanged(currentWallpaper: CurrentWallpaper|null) {
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts index 2217b2aa..54e6e99 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.ts
@@ -204,16 +204,14 @@ this.watch('error_', state => state.error); this.watch('attribution_', state => state.wallpaper.attribution); this.watch('image_', state => state.wallpaper.currentSelected); - this.watch('isLoading_', state => { - const isWallpaperLoading = state.wallpaper.loading.setImage > 0 || - state.wallpaper.loading.selected.image || - state.wallpaper.loading.selected.attribution || - state.wallpaper.loading.refreshWallpaper; - const isSeaPenLoading = state.wallpaper.seaPen.loading.setImage > 0 || - state.wallpaper.seaPen.loading.selected.image || - state.wallpaper.seaPen.loading.selected.attribution; - return isWallpaperLoading || isSeaPenLoading; - }); + this.watch( + 'isLoading_', + state => state.wallpaper.loading.setImage > 0 || + state.wallpaper.loading.selected.image || + state.wallpaper.loading.selected.attribution || + state.wallpaper.loading.refreshWallpaper || + state.wallpaper.seaPen.loading.currentSelected || + state.wallpaper.seaPen.loading.setImage > 0); this.watch('dailyRefreshState_', state => state.wallpaper.dailyRefresh); this.watch( 'imagesByCollectionId_', state => state.wallpaper.backdrop.images);
diff --git a/ash/webui/print_preview_cros/BUILD.gn b/ash/webui/print_preview_cros/BUILD.gn new file mode 100644 index 0000000..8fd6ae4 --- /dev/null +++ b/ash/webui/print_preview_cros/BUILD.gn
@@ -0,0 +1,37 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chromeos/ui_mode.gni") + +assert(is_chromeos_ash, "Print Preview CrOS is ash-chrome only") + +static_library("print_preview_cros") { + sources = [ + "print_preview_cros_ui.cc", + "print_preview_cros_ui.h", + ] + + deps = [ + ":url_constants", + "//ash/constants:constants", + "//ash/webui/common:chrome_os_webui_config", + "//ash/webui/common:trusted_types_util", + "//ash/webui/print_preview_cros/resources:resources", + "//ash/webui/web_applications", + "//chromeos/strings/", + "//content/public/browser", + "//ui/base", + "//ui/resources", + "//ui/web_dialogs:web_dialogs", + "//ui/webui", + ] +} + +# Separating out constants to be used test support. +source_set("url_constants") { + sources = [ + "url_constants.cc", + "url_constants.h", + ] +}
diff --git a/ash/webui/print_preview_cros/DIR_METADATA b/ash/webui/print_preview_cros/DIR_METADATA new file mode 100644 index 0000000..ebfefd1 --- /dev/null +++ b/ash/webui/print_preview_cros/DIR_METADATA
@@ -0,0 +1,4 @@ +# ChromeOS > Software > System Services > Peripherals > Printing +buganizer { + component_id: 1131981 +} \ No newline at end of file
diff --git a/ash/webui/print_preview_cros/OWNERS b/ash/webui/print_preview_cros/OWNERS new file mode 100644 index 0000000..149a448 --- /dev/null +++ b/ash/webui/print_preview_cros/OWNERS
@@ -0,0 +1,7 @@ +# Primary OWNERS +gavinwill@chromium.org +jimmyxgong@chromium.org +ashleydp@google.com + +# Backup OWNERS +zentaro@chromium.org
diff --git a/ash/webui/print_preview_cros/README.md b/ash/webui/print_preview_cros/README.md new file mode 100644 index 0000000..f2d7162 --- /dev/null +++ b/ash/webui/print_preview_cros/README.md
@@ -0,0 +1,6 @@ +# CrOS Print Preview + +//ash/webui/print_preview_cros contains code that is Chrome OS-specific print +preview experience. + +See b/323421684 for more information on the project. \ No newline at end of file
diff --git a/ash/webui/print_preview_cros/print_preview_cros_ui.cc b/ash/webui/print_preview_cros/print_preview_cros_ui.cc new file mode 100644 index 0000000..0d7e98f --- /dev/null +++ b/ash/webui/print_preview_cros/print_preview_cros_ui.cc
@@ -0,0 +1,70 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/webui/print_preview_cros/print_preview_cros_ui.h" + +#include "ash/constants/ash_features.h" +#include "ash/webui/common/trusted_types_util.h" +#include "ash/webui/grit/ash_print_preview_cros_app_resources.h" +#include "ash/webui/grit/ash_print_preview_cros_app_resources_map.h" +#include "ash/webui/print_preview_cros/url_constants.h" +#include "base/containers/span.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/resources/grit/webui_resources.h" + +namespace ash::printing::print_preview { + +namespace { + +void ConfigurePolicies(content::WebUIDataSource* source) { + // Enable common and test resources. + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, + "script-src chrome://resources chrome://webui-test 'self';"); + // Configure ash specific trusted type polices. + ash::EnableTrustedTypesCSP(source); +} + +// Setup app resources and ensure default resource is the app index page. +void ConfigureResources(content::WebUIDataSource* source, + int default_resource) { + const auto resources = base::make_span(kAshPrintPreviewCrosAppResources, + kAshPrintPreviewCrosAppResourcesSize); + source->AddResourcePaths(resources); + source->SetDefaultResource(default_resource); + source->AddResourcePath("", default_resource); +} + +// Setup common test resources used in browser tests. +void ConfigureTestResources(content::WebUIDataSource* source) { + source->AddResourcePath("test_loader.html", IDR_WEBUI_TEST_LOADER_HTML); + source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER_JS); + source->AddResourcePath("test_loader_util.js", + IDR_WEBUI_JS_TEST_LOADER_UTIL_JS); +} + +} // namespace + +bool PrintPreviewCrosUIConfig::IsWebUIEnabled( + content::BrowserContext* browser_context) { + return ChromeOSWebUIConfig::IsWebUIEnabled(browser_context) && + ash::features::IsPrinterPreviewCrosAppEnabled(); +} + +PrintPreviewCrosUI::PrintPreviewCrosUI(content::WebUI* web_ui) + : MojoWebDialogUI(web_ui) { + // Configure resources. + auto* source = content::WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + ash::kChromeUIPrintPreviewCrosHost); + ConfigurePolicies(source); + ConfigureResources(source, IDR_ASH_PRINT_PREVIEW_CROS_APP_INDEX_HTML); + ConfigureTestResources(source); +} + +PrintPreviewCrosUI::~PrintPreviewCrosUI() = default; + +} // namespace ash::printing::print_preview
diff --git a/ash/webui/print_preview_cros/print_preview_cros_ui.h b/ash/webui/print_preview_cros/print_preview_cros_ui.h new file mode 100644 index 0000000..6265655 --- /dev/null +++ b/ash/webui/print_preview_cros/print_preview_cros_ui.h
@@ -0,0 +1,45 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WEBUI_PRINT_PREVIEW_CROS_PRINT_PREVIEW_CROS_UI_H_ +#define ASH_WEBUI_PRINT_PREVIEW_CROS_PRINT_PREVIEW_CROS_UI_H_ + +#include "ash/webui/common/chrome_os_webui_config.h" +#include "ash/webui/print_preview_cros/url_constants.h" +#include "content/public/common/url_constants.h" +#include "ui/web_dialogs/web_dialog_ui.h" + +namespace content { +class BrowserContext; +class WebUI; +} // namespace content + +namespace ash::printing::print_preview { + +class PrintPreviewCrosUI; + +// The WebUI configuration for chrome://os-print. +class PrintPreviewCrosUIConfig + : public ash::ChromeOSWebUIConfig<PrintPreviewCrosUI> { + public: + PrintPreviewCrosUIConfig() + : ChromeOSWebUIConfig(content::kChromeUIScheme, + ash::kChromeUIPrintPreviewCrosHost) {} + + // ash::ChromeOSWebUIConfig: + bool IsWebUIEnabled(content::BrowserContext* browser_context) override; +}; + +// The WebUI controller for chrome://os-print. +class PrintPreviewCrosUI : public ui::MojoWebDialogUI { + public: + explicit PrintPreviewCrosUI(content::WebUI* web_ui); + PrintPreviewCrosUI(const PrintPreviewCrosUI&) = delete; + PrintPreviewCrosUI& operator=(const PrintPreviewCrosUI&) = delete; + ~PrintPreviewCrosUI() override; +}; + +} // namespace ash::printing::print_preview + +#endif // ASH_WEBUI_PRINT_PREVIEW_CROS_PRINT_PREVIEW_CROS_UI_H_
diff --git a/ash/webui/print_preview_cros/resources/BUILD.gn b/ash/webui/print_preview_cros/resources/BUILD.gn new file mode 100644 index 0000000..5d13767 --- /dev/null +++ b/ash/webui/print_preview_cros/resources/BUILD.gn
@@ -0,0 +1,29 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chromeos/ui_mode.gni") +import("//ui/webui/resources/tools/build_webui.gni") + +assert(is_chromeos_ash, "Print Preview CrOS is ChromeOS only") + +build_webui("build") { + static_files = [ + "images/app_icon_192.png", + "index.html", + ] + + web_component_files = [ "js/print_preview_cros_app.ts" ] + + ts_composite = true + + ts_deps = [ + "//ash/webui/common/resources:build_ts", + "//third_party/polymer/v3_0:library", + "//ui/webui/resources/js:build_ts", + "//ui/webui/resources/mojo:build_ts", + ] + + grd_prefix = "ash_print_preview_cros_app" + grit_output_dir = "$root_gen_dir/ash/webui" +}
diff --git a/ash/webui/print_preview_cros/resources/images/app_icon_192.png b/ash/webui/print_preview_cros/resources/images/app_icon_192.png new file mode 100644 index 0000000..1419460f --- /dev/null +++ b/ash/webui/print_preview_cros/resources/images/app_icon_192.png Binary files differ
diff --git a/ash/webui/print_preview_cros/resources/index.html b/ash/webui/print_preview_cros/resources/index.html new file mode 100644 index 0000000..661aefb4 --- /dev/null +++ b/ash/webui/print_preview_cros/resources/index.html
@@ -0,0 +1,15 @@ +<!-- Copyright 2024 The Chromium Authors + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<!DOCTYPE html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> + <head> + <meta charset="utf-8"> + <title>Print</title> + </head> + <body> + <print-preview-cros-app></print-preview-cros-app> + <script type="module" src="/js/print_preview_cros_app.js"></script> + </script> + </body> +</html>
diff --git a/ash/webui/print_preview_cros/resources/js/print_preview_cros_app.html b/ash/webui/print_preview_cros/resources/js/print_preview_cros_app.html new file mode 100644 index 0000000..71e6316 --- /dev/null +++ b/ash/webui/print_preview_cros/resources/js/print_preview_cros_app.html
@@ -0,0 +1 @@ +<span>Print</span> \ No newline at end of file
diff --git a/ash/webui/print_preview_cros/resources/js/print_preview_cros_app.ts b/ash/webui/print_preview_cros/resources/js/print_preview_cros_app.ts new file mode 100644 index 0000000..c0ecce7e --- /dev/null +++ b/ash/webui/print_preview_cros/resources/js/print_preview_cros_app.ts
@@ -0,0 +1,32 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './print_preview_cros_app.html.js'; + +/** + * @fileoverview + * 'print-preview-cros-app' is the main landing page for the print preview + * for ChromeOS app. + */ + +export class PrintPreviewCrosAppElement extends PolymerElement { + static get is() { + return 'print-preview-cros-app' as const; + } + + static get template() { + return getTemplate(); + } +} + +declare global { + interface HTMLElementTagNameMap { + [PrintPreviewCrosAppElement.is]: PrintPreviewCrosAppElement; + } +} + +customElements.define( + PrintPreviewCrosAppElement.is, PrintPreviewCrosAppElement);
diff --git a/ash/webui/print_preview_cros/url_constants.cc b/ash/webui/print_preview_cros/url_constants.cc new file mode 100644 index 0000000..c2722b9 --- /dev/null +++ b/ash/webui/print_preview_cros/url_constants.cc
@@ -0,0 +1,12 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/webui/print_preview_cros/url_constants.h" + +namespace ash { + +const char kChromeUIPrintPreviewCrosHost[] = "os-print"; +const char kChromeUIPrintPreviewCrosURL[] = "chrome://os-print"; + +} // namespace ash
diff --git a/ash/webui/print_preview_cros/url_constants.h b/ash/webui/print_preview_cros/url_constants.h new file mode 100644 index 0000000..592209c --- /dev/null +++ b/ash/webui/print_preview_cros/url_constants.h
@@ -0,0 +1,15 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WEBUI_PRINT_PREVIEW_CROS_URL_CONSTANTS_H_ +#define ASH_WEBUI_PRINT_PREVIEW_CROS_URL_CONSTANTS_H_ + +namespace ash { + +extern const char kChromeUIPrintPreviewCrosHost[]; +extern const char kChromeUIPrintPreviewCrosURL[]; + +} // namespace ash + +#endif // ASH_WEBUI_PRINT_PREVIEW_CROS_URL_CONSTANTS_H_
diff --git a/ash/webui/system_apps/public/system_web_app_type.h b/ash/webui/system_apps/public/system_web_app_type.h index d1cf32e3..93b3c97 100644 --- a/ash/webui/system_apps/public/system_web_app_type.h +++ b/ash/webui/system_apps/public/system_web_app_type.h
@@ -116,6 +116,11 @@ // Contact: assistive-eng@google.com VC_BACKGROUND = 25, + // CrOS implementation of the print preview surface. + // Source: //ash/webui/print_preview_cros/ + // Contact: cros-peripherals@google.com + PRINT_PREVIEW_CROS = 26, + // When adding a new System App, remember to: // // 1. Add a corresponding histogram suffix in WebAppSystemAppInternalName @@ -155,7 +160,7 @@ // // 8. Have one of System Web App Platform owners review the CL. // See: //ash/webui/PLATFORM_OWNERS - kMaxValue = VC_BACKGROUND, + kMaxValue = PRINT_PREVIEW_CROS, }; } // namespace ash
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 4eed6c34..7188038 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -2249,6 +2249,13 @@ container->save_desk_for_later_button()->GetVisible(); } +void OverviewGrid::OnTabletModeChanged() { + // We may not show virtual desk bar in clamshell mode such as in faster split + // screen setup session, and the desk bar will be created in tablet mode + // either. In this case, we may need to init the virtual desk bar. + MaybeInitDesksWidget(); +} + size_t OverviewGrid::GetNumWindows() const { size_t size = 0u; for (const std::unique_ptr<OverviewItemBase>& item : item_list_) { @@ -2311,8 +2318,7 @@ if (state == SplitViewController::State::kBothSnapped || unsnappable_window_activated || (split_view_controller->InClamshellSplitViewMode() && - overview_session_->IsEmpty() && - !window_util::IsInFasterSplitScreenSetupSession(root_window_))) { + overview_session_->IsEmpty())) { overview_session_->RestoreWindowActivation(false); overview_controller->EndOverview( state == SplitViewController::State::kBothSnapped
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index b8d630f..b0094e37e 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -386,6 +386,10 @@ bool IsSaveDeskAsTemplateButtonVisible() const; bool IsSaveDeskForLaterButtonVisible() const; + // Called by `OverviewSession` when tablet mode changes to update necessary UI + // if needed. + void OnTabletModeChanged(); + // This is different from `item_list_.size()` which contains the drop target // if it exists, and if two windows are in a snap group, they are a single // item.
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc index 693222c..efa51e42 100644 --- a/ash/wm/overview/overview_session.cc +++ b/ash/wm/overview/overview_session.cc
@@ -1592,6 +1592,10 @@ } void OverviewSession::OnTabletModeChanged() { + for (auto& overview_grid : grid_list_) { + overview_grid->OnTabletModeChanged(); + } + DCHECK(saved_desk_util::ShouldShowSavedDesksButtons()); DCHECK(saved_desk_presenter_); saved_desk_presenter_->UpdateUIForSavedDeskLibrary();
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 6da0c73c..c6140e9c 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -9329,6 +9329,53 @@ EXPECT_FALSE(split_view_controller()->InSplitViewMode()); } +// Tests that there will be no crash when dragging a snapped window in overview +// toward the edge. In this case, the overview components will become too small +// to meet the minimum requirement of the fundamental UI layers such as virtual +// desk bar, shadow. See the regression behavior in http://b/324478757. +TEST_F(SplitViewOverviewSessionInClamshellTest, + NoCrashWhenDraggingSnappedWindowToEdge) { + ui::ScopedAnimationDurationScaleMode animation_scale( + ui::ScopedAnimationDurationScaleMode::SLOW_DURATION); + + // Create another desk to ensure the desk bar shows in overview. + auto* desks_controller = DesksController::Get(); + desks_controller->NewDesk(DesksCreationRemovalSource::kButton); + ASSERT_EQ(2u, desks_controller->desks().size()); + + ToggleOverview(); + WaitForOverviewEnterAnimation(); + EXPECT_TRUE(IsInOverviewSession()); + std::unique_ptr<aura::Window> window1( + CreateAppWindow(gfx::Rect(0, 0, 200, 100))); + std::unique_ptr<aura::Window> window2( + CreateAppWindow(gfx::Rect(100, 100, 200, 100))); + const WindowSnapWMEvent event( + WM_EVENT_SNAP_PRIMARY, chromeos::kDefaultSnapRatio, + WindowSnapActionSource::kSnapByWindowLayoutMenu); + auto* window1_state = WindowState::Get(window1.get()); + window1_state->OnWMEvent(&event); + WaitForOverviewEntered(); + EXPECT_TRUE(window1_state->IsSnapped()); + EXPECT_TRUE(IsInOverviewSession()); + + auto* event_generator = GetEventGenerator(); + event_generator->set_current_screen_location( + window1.get()->GetBoundsInScreen().right_center()); + gfx::Point drag_end_point = GetWorkAreaInScreen(window1.get()).right_center(); + drag_end_point.Offset(/*delta_x=*/-10, 0); + event_generator->PressLeftButton(); + event_generator->MoveMouseTo(drag_end_point); + EXPECT_TRUE(IsInOverviewSession()); + EXPECT_TRUE(WindowState::Get(window1.get())->is_dragged()); + + // Verify that shadow is applied on the overview item. + auto* overview_item2 = GetOverviewItemForWindow(window2.get()); + const auto shadow_content_bounds = + overview_item2->get_shadow_content_bounds_for_testing(); + EXPECT_FALSE(shadow_content_bounds.IsEmpty()); +} + // Tests that when a split view window carries over to clamshell split view // while the divider is being dragged, the window resize is properly completed. TEST_F(SplitViewOverviewSessionInClamshellTest,
diff --git a/ash/wm/overview/overview_utils.cc b/ash/wm/overview/overview_utils.cc index be5dfa31..1dc3cb36 100644 --- a/ash/wm/overview/overview_utils.cc +++ b/ash/wm/overview/overview_utils.cc
@@ -201,8 +201,14 @@ if (auto* split_view_overview_session = RootWindowController::ForWindow(target_root) ->split_view_overview_session()) { - gfx::Rect target_bounds_in_screen( - split_view_overview_session->window()->GetTargetBounds()); + aura::Window* snapped_window = split_view_overview_session->window(); + gfx::Rect target_bounds_in_screen(snapped_window->GetTargetBounds()); + WindowState* window_state = WindowState::Get(snapped_window); + CHECK(window_state->IsSnapped()); + opposite_position = window_state->GetStateType() == + chromeos::WindowStateType::kPrimarySnapped + ? SnapPosition::kSecondary + : SnapPosition::kPrimary; wm::ConvertRectToScreen(target_root, &target_bounds_in_screen); bounds.Subtract(target_bounds_in_screen); } else { @@ -256,12 +262,8 @@ } } - if (!opposite_position) { - // `opposite_position` is only non-empty if we are in split view state not - // `kNoSnap`. - return bounds; - } - + // Clamp the bounds of the overview grid such that it doesn't go below 1/3 of + // the work area length const bool horizontal = IsLayoutHorizontal(target_root); const int min_length = (horizontal ? work_area.width() : work_area.height()) / 3; @@ -270,13 +272,21 @@ if (current_length > min_length) return bounds; - // Clamp bounds' length to the minimum length. + // Clamp bounds' corresponding length to the minimum length. if (horizontal) bounds.set_width(min_length); else bounds.set_height(min_length); - if (IsPhysicalLeftOrTop(*opposite_position, target_root)) { + // These changes below are crucial for better visualization and help + // preventing crashes when dragging the snapped window towards the edge. In + // this case, the overview components will become too small to allow any + // gradient painting on desk bar or applying shadows. Please ensure to go + // through the bounds update below when one window is snapped in overview both + // in clamshell and tablet mode. See the regression behavior in + // http://b/324478757. + if (opposite_position && + IsPhysicalLeftOrTop(*opposite_position, target_root)) { // If we are shifting to the left or top we need to update the origin as // well. const int offset = min_length - current_length;
diff --git a/ash/wm/snap_group/snap_group_unittest.cc b/ash/wm/snap_group/snap_group_unittest.cc index a9bcfabf..1244f1a 100644 --- a/ash/wm/snap_group/snap_group_unittest.cc +++ b/ash/wm/snap_group/snap_group_unittest.cc
@@ -4,6 +4,7 @@ #include "ash/wm/snap_group/snap_group.h" +#include <algorithm> #include <memory> #include <vector> @@ -23,6 +24,7 @@ #include "ash/system/toast/toast_manager_impl.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_util.h" +#include "ash/wm/desks/desks_controller.h" #include "ash/wm/desks/desks_test_util.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/desks/legacy_desk_bar_view.h" @@ -155,7 +157,7 @@ SplitViewOverviewSession* VerifySplitViewOverviewSession( aura::Window* window, bool faster_split_screen_setup = true) { - auto* overview_controller = Shell::Get()->overview_controller(); + auto* overview_controller = OverviewController::Get(); EXPECT_TRUE(overview_controller->InOverviewSession()); EXPECT_FALSE( overview_controller->overview_session()->IsWindowInOverview(window)); @@ -170,13 +172,25 @@ expected_grid_bounds.Subtract(split_view_divider_bounds_in_screen()); } + // Clamp the length on the side that can be shrunk by resizing to avoid going + // below the threshold i.e. 1/3 of the corresponding work area length. + const bool is_horizontal = IsLayoutHorizontal(Shell::GetPrimaryRootWindow()); + const int min_length = (is_horizontal ? work_area_bounds().width() + : work_area_bounds().height()) / + 3; + if (is_horizontal) { + expected_grid_bounds.set_width( + std::max(expected_grid_bounds.width(), min_length)); + } else { + expected_grid_bounds.set_height( + std::max(expected_grid_bounds.height(), min_length)); + } + if (!Shell::Get()->IsInTabletMode()) { EXPECT_EQ(expected_grid_bounds, GetOverviewGridBounds()); } EXPECT_TRUE(expected_grid_bounds.Contains(GetOverviewGridBounds())); - // Hotseat may be on the bottom of the work area. - EXPECT_TRUE(work_area_bounds().Contains(expected_grid_bounds)); if (!Shell::Get()->IsInTabletMode() && faster_split_screen_setup) { auto* overview_grid = GetOverviewGridForRoot(window->GetRootWindow()); @@ -339,13 +353,31 @@ EXPECT_EQ(chromeos::WindowStateType::kPrimarySnapped, WindowState::Get(w3.get())->GetStateType()); - // Enter overview normally. Test no widget. + // Enter overview normally. Test that no windows widget will not show. ToggleOverview(); auto* overview_grid = GetOverviewGridForRoot(w1->GetRootWindow()); EXPECT_FALSE(overview_grid->no_windows_widget()); EXPECT_FALSE(overview_grid->faster_splitview_widget()); } +// Tests that on one window snapped, `SnapGroupController` starts +// `SplitViewOverviewSession` (snap group creation session). +TEST_F(FasterSplitScreenTest, CloseSnappedWindowEndsSplitViewOverviewSession) { + std::unique_ptr<aura::Window> w1(CreateAppWindow()); + std::unique_ptr<aura::Window> w2(CreateAppWindow()); + + // Snap `w1` to the left. Test that we are in split view overview, excluding + // `w1` and taking half the screen. + SnapOneTestWindow(w1.get(), + /*state_type=*/chromeos::WindowStateType::kPrimarySnapped, + chromeos::kDefaultSnapRatio); + VerifySplitViewOverviewSession(w1.get()); + + // Close `w1`. Test that we end overview. + w1.reset(); + EXPECT_FALSE(OverviewController::Get()->InOverviewSession()); +} + // Tests that faster split screen can only start with certain snap action // sources. TEST_F(FasterSplitScreenTest, SnapActionSourceLimitations) { @@ -399,6 +431,7 @@ TEST_F(FasterSplitScreenTest, EndSplitViewOverviewSession) { std::unique_ptr<aura::Window> w1(CreateAppWindow()); + std::unique_ptr<aura::Window> w2(CreateAppWindow()); SnapOneTestWindow(w1.get(), chromeos::WindowStateType::kSecondarySnapped, chromeos::kDefaultSnapRatio); VerifySplitViewOverviewSession(w1.get()); @@ -429,7 +462,9 @@ } TEST_F(FasterSplitScreenTest, ResizeSplitViewOverviewAndWindow) { + UpdateDisplay("900x600"); std::unique_ptr<aura::Window> w1(CreateAppWindow()); + std::unique_ptr<aura::Window> w2(CreateAppWindow()); SnapOneTestWindow(w1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kDefaultSnapRatio); VerifySplitViewOverviewSession(w1.get()); @@ -442,25 +477,28 @@ generator->set_current_screen_location(start_point); // Resize to less than 1/3. Test we don't end overview. - int x = 200; - ASSERT_LT(x, work_area_bounds().width() * chromeos::kOneThirdSnapRatio); - generator->DragMouseTo(gfx::Point(x, start_point.y())); + const auto drag_point1 = + gfx::Point(work_area_bounds().width() * chromeos::kOneThirdSnapRatio - 10, + start_point.y()); + generator->DragMouseTo(drag_point1); gfx::Rect expected_window_bounds(initial_bounds); - expected_window_bounds.set_width(x); + expected_window_bounds.set_width(drag_point1.x()); EXPECT_EQ(expected_window_bounds, w1->GetBoundsInScreen()); VerifySplitViewOverviewSession(w1.get()); // Resize to greater than 2/3. Test we don't end overview. - x = 600; - ASSERT_GT(x, work_area_bounds().width() * chromeos::kTwoThirdSnapRatio); - generator->DragMouseTo(gfx::Point(x, start_point.y())); - expected_window_bounds.set_width(x); + const auto drag_point2 = + gfx::Point(work_area_bounds().width() * chromeos::kTwoThirdSnapRatio + 10, + start_point.y()); + generator->DragMouseTo(drag_point2); + expected_window_bounds.set_width(drag_point2.x()); EXPECT_EQ(expected_window_bounds, w1->GetBoundsInScreen()); VerifySplitViewOverviewSession(w1.get()); } TEST_F(FasterSplitScreenTest, ResizeAndAutoSnap) { - std::unique_ptr<aura::Window> w1(CreateTestWindow()); + std::unique_ptr<aura::Window> w1(CreateAppWindow()); + std::unique_ptr<aura::Window> w2(CreateAppWindow()); SnapOneTestWindow(w1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kDefaultSnapRatio); const gfx::Rect initial_bounds(w1->GetBoundsInScreen()); @@ -481,11 +519,11 @@ expected_grid_bounds.Subtract(w1->GetBoundsInScreen()); EXPECT_EQ(expected_grid_bounds, GetOverviewGridBounds()); - // Select a window to auto snap. Test it snaps to the correct ratio. - std::unique_ptr<aura::Window> w2(CreateTestWindow()); + // Create a window and test that it auto snaps. + std::unique_ptr<aura::Window> w3(CreateAppWindow()); EXPECT_EQ(chromeos::WindowStateType::kSecondarySnapped, - WindowState::Get(w2.get())->GetStateType()); - EXPECT_EQ(expected_grid_bounds, w2->GetBoundsInScreen()); + WindowState::Get(w3.get())->GetStateType()); + EXPECT_EQ(expected_grid_bounds, w3->GetBoundsInScreen()); } TEST_F(FasterSplitScreenTest, DragToPartialOverview) { @@ -759,6 +797,41 @@ EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession()); } +// Tests that partial overview will not be triggered if the window to be snapped +// is only one window for the active desk and on the current display. +TEST_F(FasterSplitScreenTest, DontStartPartiOverviewIfThereIsOnlyOneWindow) { + UpdateDisplay("900x600, 901+0-900x600"); + ASSERT_EQ(Shell::GetAllRootWindows().size(), 2u); + + DesksController* desks_controller = DesksController::Get(); + desks_controller->NewDesk(DesksCreationRemovalSource::kButton); + ASSERT_EQ(2u, desks_controller->desks().size()); + Desk* desk0 = desks_controller->GetDeskAtIndex(0); + Desk* desk1 = desks_controller->GetDeskAtIndex(1); + + std::unique_ptr<aura::Window> w1( + CreateAppWindow(gfx::Rect(10, 20, 200, 100))); + + // Create the 2nd window and move it to another desk. + std::unique_ptr<aura::Window> w2( + CreateAppWindow(gfx::Rect(100, 20, 200, 100))); + ASSERT_EQ(desks_util::GetDeskForContext(w1.get()), desk0); + ASSERT_EQ(desks_util::GetDeskForContext(w2.get()), desk0); + desks_controller->MoveWindowFromActiveDeskTo( + w2.get(), desk1, w2->GetRootWindow(), + DesksMoveWindowFromActiveDeskSource::kShortcut); + ASSERT_EQ(desks_util::GetDeskForContext(w2.get()), desk1); + + // Create the 3rd window on the 2nd display. + std::unique_ptr<aura::Window> w3( + CreateAppWindow(gfx::Rect(1000, 20, 200, 100))); + + // Verify that snapping `w1` won't trigger partial overview. + SnapOneTestWindow(w1.get(), chromeos::WindowStateType::kPrimarySnapped, + chromeos::kDefaultSnapRatio); + EXPECT_FALSE(IsInOverviewSession()); +} + // Tests that only when there is a non-occluded window snapped on the opposite // side should we skip showing partial overview on window snapped. This test // focuses on the window layout setup **with** intersections. @@ -888,18 +961,21 @@ display::test::DisplayManagerTestApi display_manager_test(display_manager()); // Snap `window` on the second display. Test its bounds are updated. - std::unique_ptr<aura::Window> window( + std::unique_ptr<aura::Window> window1( CreateTestWindowInShellWithBounds(gfx::Rect(900, 0, 100, 100))); - SnapOneTestWindow(window.get(), chromeos::WindowStateType::kPrimarySnapped, + std::unique_ptr<aura::Window> window2( + CreateTestWindowInShellWithBounds(gfx::Rect(1000, 0, 100, 100))); + SnapOneTestWindow(window1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kDefaultSnapRatio); - ASSERT_EQ( - display_manager_test.GetSecondaryDisplay().id(), - display::Screen::GetScreen()->GetDisplayNearestWindow(window.get()).id()); + ASSERT_EQ(display_manager_test.GetSecondaryDisplay().id(), + display::Screen::GetScreen() + ->GetDisplayNearestWindow(window1.get()) + .id()); const gfx::Rect work_area( display_manager_test.GetSecondaryDisplay().work_area()); EXPECT_EQ(gfx::Rect(800, 0, work_area.width() / 2, work_area.height()), - window->GetBoundsInScreen()); - VerifySplitViewOverviewSession(window.get()); + window1->GetBoundsInScreen()); + VerifySplitViewOverviewSession(window1.get()); // Disconnect the second display. Test no crash. UpdateDisplay("800x600"); @@ -967,13 +1043,15 @@ // Tests we start partial overview if there's an opposite snapped window on // another display. TEST_F(FasterSplitScreenTest, OppositeSnappedWindowOnOtherDisplay) { - UpdateDisplay("800x600,1000x600"); + UpdateDisplay("800x600,801+0-800x600"); // Create 3 test windows, with `w3` on display 2. std::unique_ptr<aura::Window> w1(CreateAppWindow()); std::unique_ptr<aura::Window> w2(CreateAppWindow()); std::unique_ptr<aura::Window> w3( CreateAppWindow(gfx::Rect(900, 0, 100, 100))); + std::unique_ptr<aura::Window> w4( + CreateAppWindow(gfx::Rect(1000, 0, 100, 100))); // Snap `w1` to primary on display 1. SnapOneTestWindow(w1.get(), chromeos::WindowStateType::kPrimarySnapped, @@ -1008,26 +1086,27 @@ // preserve the snap ratio. TEST_F(FasterSplitScreenTest, WindowBoundsRefreshedOnDisplayChanges) { UpdateDisplay("900x600"); - std::unique_ptr<aura::Window> window(CreateAppWindow()); - SnapOneTestWindow(window.get(), chromeos::WindowStateType::kPrimarySnapped, + std::unique_ptr<aura::Window> window1(CreateAppWindow()); + std::unique_ptr<aura::Window> window2(CreateAppWindow()); + SnapOneTestWindow(window1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kTwoThirdSnapRatio, WindowSnapActionSource::kSnapByWindowLayoutMenu); - VerifySplitViewOverviewSession(window.get()); - ASSERT_EQ(WindowState::Get(window.get())->snap_ratio(), + VerifySplitViewOverviewSession(window1.get()); + ASSERT_EQ(WindowState::Get(window1.get())->snap_ratio(), chromeos::kTwoThirdSnapRatio); const auto work_area_bounds_1 = work_area_bounds(); ASSERT_EQ( - window->GetBoundsInScreen(), + window1->GetBoundsInScreen(), gfx::Rect(0, 0, work_area_bounds_1.width() * chromeos::kTwoThirdSnapRatio, work_area_bounds_1.height())); UpdateDisplay("1200x600"); - VerifySplitViewOverviewSession(window.get()); - EXPECT_EQ(WindowState::Get(window.get())->snap_ratio(), + VerifySplitViewOverviewSession(window1.get()); + EXPECT_EQ(WindowState::Get(window1.get())->snap_ratio(), chromeos::kTwoThirdSnapRatio); const auto work_area_bounds_2 = work_area_bounds(); EXPECT_EQ( - window->GetBoundsInScreen(), + window1->GetBoundsInScreen(), gfx::Rect(0, 0, work_area_bounds_2.width() * chromeos::kTwoThirdSnapRatio, work_area_bounds_2.height())); } @@ -1035,16 +1114,17 @@ // Test to verify that there will be no crash when dragging the snapped window // out without resizing the window see crash in b/321111182. TEST_F(FasterSplitScreenTest, NoCrashWhenDraggingTheSnappedWindow) { - std::unique_ptr<aura::Window> window(CreateAppWindow()); - SnapOneTestWindow(window.get(), chromeos::WindowStateType::kPrimarySnapped, + std::unique_ptr<aura::Window> window1(CreateAppWindow()); + std::unique_ptr<aura::Window> window2(CreateAppWindow()); + SnapOneTestWindow(window1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kTwoThirdSnapRatio, WindowSnapActionSource::kSnapByWindowLayoutMenu); - VerifySplitViewOverviewSession(window.get()); + VerifySplitViewOverviewSession(window1.get()); std::unique_ptr<WindowResizer> resizer(CreateWindowResizer( - window.get(), gfx::PointF(), HTCAPTION, wm::WINDOW_MOVE_SOURCE_MOUSE)); + window1.get(), gfx::PointF(), HTCAPTION, wm::WINDOW_MOVE_SOURCE_MOUSE)); resizer->Drag(gfx::PointF(500, 100), /*event_flags=*/0); - WindowState* window_state = WindowState::Get(window.get()); + WindowState* window_state = WindowState::Get(window1.get()); EXPECT_TRUE(window_state->is_dragged()); resizer->CompleteDrag(); EXPECT_FALSE(window_state->IsSnapped()); @@ -1106,7 +1186,8 @@ // Verifies that there will be no crash when transitioning the // `SplitViewOverviewSession` between clamshell and tablet mode. TEST_F(FasterSplitScreenTest, ClamshellTabletTransitionOneSnappedWindow) { - std::unique_ptr<aura::Window> w1(CreateTestWindow()); + std::unique_ptr<aura::Window> w1(CreateAppWindow()); + std::unique_ptr<aura::Window> w2(CreateAppWindow()); SnapOneTestWindow(w1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kDefaultSnapRatio); VerifySplitViewOverviewSession(w1.get()); @@ -1482,10 +1563,11 @@ kOverviewStartActionHistogram, OverviewStartAction::kFasterSplitScreenSetup, /*expected_count=*/0); - std::unique_ptr<aura::Window> window(CreateAppWindow()); - SnapOneTestWindow(window.get(), chromeos::WindowStateType::kPrimarySnapped, + std::unique_ptr<aura::Window> window1(CreateAppWindow()); + std::unique_ptr<aura::Window> window2(CreateAppWindow()); + SnapOneTestWindow(window1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kDefaultSnapRatio); - VerifySplitViewOverviewSession(window.get()); + VerifySplitViewOverviewSession(window1.get()); histogram_tester_.ExpectBucketCount( kOverviewStartActionHistogram, OverviewStartAction::kFasterSplitScreenSetup, @@ -1496,15 +1578,51 @@ // setup session. TEST_F(FasterSplitScreenTest, A11yAlertOnEnteringFaterSplitScreenSetup) { TestAccessibilityControllerClient client; - std::unique_ptr<aura::Window> window(CreateAppWindow()); + std::unique_ptr<aura::Window> window1(CreateAppWindow()); + std::unique_ptr<aura::Window> window2(CreateAppWindow()); EXPECT_NE(AccessibilityAlert::FASTER_SPLIT_SCREEN_SETUP, client.last_a11y_alert()); - SnapOneTestWindow(window.get(), chromeos::WindowStateType::kPrimarySnapped, + SnapOneTestWindow(window1.get(), chromeos::WindowStateType::kPrimarySnapped, chromeos::kDefaultSnapRatio); EXPECT_EQ(AccessibilityAlert::FASTER_SPLIT_SCREEN_SETUP, client.last_a11y_alert()); } +// Tests that there will be no crash when dragging a snapped window in overview +// toward the edge. In this case, the overview components will become too small +// to meet the minimum requirement of the fundamental UI layer such as shadow. +// See the regression behavior in http://b/324478757. +TEST_F(FasterSplitScreenTest, NoCrashWhenDraggingSnappedWindowToEdge) { + std::unique_ptr<aura::Window> window1( + CreateAppWindow(gfx::Rect(0, 0, 200, 100))); + std::unique_ptr<aura::Window> window2( + CreateAppWindow(gfx::Rect(100, 100, 200, 100))); + SnapOneTestWindow(window1.get(), chromeos::WindowStateType::kPrimarySnapped, + chromeos::kDefaultSnapRatio, + WindowSnapActionSource::kSnapByWindowLayoutMenu); + WaitForOverviewEntered(); + VerifySplitViewOverviewSession(window1.get()); + + // Drag the snapped window towards the edge of the work area and verify that + // there is no crash. + auto* event_generator = GetEventGenerator(); + event_generator->set_current_screen_location( + window1.get()->GetBoundsInScreen().right_center()); + gfx::Point drag_end_point = work_area_bounds().right_center(); + drag_end_point.Offset(/*delta_x=*/-10, 0); + event_generator->PressLeftButton(); + event_generator->MoveMouseTo(drag_end_point); + + // Verify that shadow exists for overview item. + auto* overview_item2 = GetOverviewItemForWindow(window2.get()); + const auto shadow_content_bounds = + overview_item2->get_shadow_content_bounds_for_testing(); + EXPECT_FALSE(shadow_content_bounds.IsEmpty()); + + VerifySplitViewOverviewSession(window1.get()); + EXPECT_TRUE(WindowState::Get(window1.get())->is_dragged()); +} + // ----------------------------------------------------------------------------- // SnapGroupTest: @@ -1729,32 +1847,6 @@ EXPECT_FALSE(split_view_controller()->InSplitViewMode()); } -// Tests that on one window snapped, `SnapGroupController` starts -// `SplitViewOverviewSession` (snap group creation session). -TEST_F(SnapGroupTest, SnapOneTestWindowStartsOverview) { - std::unique_ptr<aura::Window> w(CreateAppWindow()); - // Snap `w` to the left. Test that we are in split view overview, excluding - // `w` and taking half the screen. - SnapOneTestWindow(w.get(), - /*state_type=*/chromeos::WindowStateType::kPrimarySnapped); - VerifySplitViewOverviewSession(w.get()); - - // Snap `w` to the left again. Test we are still in split view overview. - SnapOneTestWindow(w.get(), - /*state_type=*/chromeos::WindowStateType::kPrimarySnapped); - VerifySplitViewOverviewSession(w.get()); - - // Snap `w` to the right. Test we are still in split view overview. - SnapOneTestWindow( - w.get(), - /*state_type=*/chromeos::WindowStateType::kSecondarySnapped); - VerifySplitViewOverviewSession(w.get()); - - // Close `w`. Test that we end overview. - w.reset(); - EXPECT_FALSE(OverviewController::Get()->InOverviewSession()); -} - // Tests that when there is one snapped window and overview open, creating a new // window, i.e. by clicking the shelf icon, will auto-snap it. // TODO(michelefan): Re-enable this test after the divider refactor work is @@ -1845,24 +1937,27 @@ // Tests that removing a display during split view overview session doesn't // crash. TEST_F(SnapGroupTest, RemoveDisplay) { - UpdateDisplay("800x600,800x600"); + UpdateDisplay("800x600,801+0-800x600"); display::test::DisplayManagerTestApi display_manager_test(display_manager()); // Snap `window` on the second display to start split view overview session. - std::unique_ptr<aura::Window> window( + std::unique_ptr<aura::Window> window1( CreateTestWindowInShellWithBounds(gfx::Rect(900, 0, 100, 100))); - WindowState* window_state = WindowState::Get(window.get()); + std::unique_ptr<aura::Window> window2( + CreateTestWindowInShellWithBounds(gfx::Rect(1000, 0, 100, 100))); + WindowState* window_state = WindowState::Get(window1.get()); const WindowSnapWMEvent snap_type( WM_EVENT_SNAP_PRIMARY, /*snap_action_source=*/WindowSnapActionSource::kTest); window_state->OnWMEvent(&snap_type); - ASSERT_EQ( - display_manager_test.GetSecondaryDisplay().id(), - display::Screen::GetScreen()->GetDisplayNearestWindow(window.get()).id()); + ASSERT_EQ(display_manager_test.GetSecondaryDisplay().id(), + display::Screen::GetScreen() + ->GetDisplayNearestWindow(window1.get()) + .id()); EXPECT_EQ(chromeos::WindowStateType::kPrimarySnapped, window_state->GetStateType()); EXPECT_TRUE(OverviewController::Get()->InOverviewSession()); - EXPECT_TRUE(RootWindowController::ForWindow(window.get()) + EXPECT_TRUE(RootWindowController::ForWindow(window1.get()) ->split_view_overview_session()); // Disconnect the second display. Test no crash. @@ -1995,44 +2090,6 @@ EXPECT_TRUE(window_to_snap_group_map.empty()); } -// Tests that, after a window is snapped with overview on the other side, -// resizing overview works as expected. -// TODO(b/308170967): Combine this with FasterSplitScreenTest. -TEST_F(SnapGroupTest, ResizeSplitViewOverviewAndWindow) { - auto* snap_group_controller = SnapGroupController::Get(); - // TODO(sophiewen): Make this the default for SnapGroupTest. - snap_group_controller->set_can_enter_overview_for_testing( - /*can_enter_overview=*/true); - - std::unique_ptr<aura::Window> w1(CreateAppWindow()); - SnapOneTestWindow(w1.get(), chromeos::WindowStateType::kPrimarySnapped); - VerifySplitViewOverviewSession(w1.get()); - const gfx::Rect initial_bounds(w1->GetBoundsInScreen()); - - // Drag the right edge of the window to resize the window and overview at the - // same time. Test that the bounds are updated. - const gfx::Point start_point(w1->GetBoundsInScreen().right_center()); - auto* generator = GetEventGenerator(); - generator->set_current_screen_location(start_point); - - // Resize to less than 1/3. Test we don't end overview. - int x = 200; - ASSERT_LT(x, work_area_bounds().width() * chromeos::kOneThirdSnapRatio); - generator->DragMouseTo(gfx::Point(x, start_point.y())); - gfx::Rect expected_window_bounds(initial_bounds); - expected_window_bounds.set_width(x); - EXPECT_EQ(expected_window_bounds, w1->GetBoundsInScreen()); - VerifySplitViewOverviewSession(w1.get()); - - // Resize to greater than 2/3. Test we don't end overview. - x = 600; - ASSERT_GT(x, work_area_bounds().width() * chromeos::kTwoThirdSnapRatio); - generator->DragMouseTo(gfx::Point(x, start_point.y())); - expected_window_bounds.set_width(x); - EXPECT_EQ(expected_window_bounds, w1->GetBoundsInScreen()); - VerifySplitViewOverviewSession(w1.get()); -} - // Tests that the split view divider will be stacked on top of both windows in // the snap group and that on a third window activated the split view divider // will be stacked below the newly activated window. @@ -2596,7 +2653,7 @@ for (const auto& overview_item : window_list) { const auto shadow_content_bounds = overview_item->get_shadow_content_bounds_for_testing(); - ASSERT_TRUE(!shadow_content_bounds.IsEmpty()); + ASSERT_FALSE(shadow_content_bounds.IsEmpty()); EXPECT_EQ(shadow_content_bounds.size(), gfx::ToRoundedSize(overview_item->target_bounds().size())); } @@ -3640,41 +3697,42 @@ // snap action source with top-usage in clamshell. TEST_F(SnapGroupHistogramTest, SnapActionSourcePipeline) { UpdateDisplay("800x600"); - std::unique_ptr<aura::Window> window(CreateAppWindow(gfx::Rect(100, 100))); + std::unique_ptr<aura::Window> window1(CreateAppWindow(gfx::Rect(100, 100))); + std::unique_ptr<aura::Window> window2(CreateAppWindow(gfx::Rect(200, 100))); // Drag a window to snap and verify the snap action source info. std::unique_ptr<WindowResizer> resizer(CreateWindowResizer( - window.get(), gfx::PointF(), HTCAPTION, wm::WINDOW_MOVE_SOURCE_MOUSE)); + window1.get(), gfx::PointF(), HTCAPTION, wm::WINDOW_MOVE_SOURCE_MOUSE)); resizer->Drag(gfx::PointF(0, 400), /*event_flags=*/0); resizer->CompleteDrag(); resizer.reset(); SplitViewOverviewSession* split_view_overview_session = - VerifySplitViewOverviewSession(window.get()); + VerifySplitViewOverviewSession(window1.get()); EXPECT_EQ(split_view_overview_session->snap_action_source_for_testing(), WindowSnapActionSource::kDragWindowToEdgeToSnap); - MaximizeToClearTheSession(window.get()); + MaximizeToClearTheSession(window1.get()); // Mock snap from window layout menu and verify the snap action source info. chromeos::SnapController::Get()->CommitSnap( - window.get(), chromeos::SnapDirection::kSecondary, + window1.get(), chromeos::SnapDirection::kSecondary, chromeos::kDefaultSnapRatio, chromeos::SnapController::SnapRequestSource::kWindowLayoutMenu); - split_view_overview_session = VerifySplitViewOverviewSession(window.get()); + split_view_overview_session = VerifySplitViewOverviewSession(window1.get()); EXPECT_TRUE(split_view_overview_session); EXPECT_EQ(split_view_overview_session->snap_action_source_for_testing(), WindowSnapActionSource::kSnapByWindowLayoutMenu); - MaximizeToClearTheSession(window.get()); + MaximizeToClearTheSession(window1.get()); // Mock snap from window snap button and verify the snap action source info. chromeos::SnapController::Get()->CommitSnap( - window.get(), chromeos::SnapDirection::kPrimary, + window1.get(), chromeos::SnapDirection::kPrimary, chromeos::kDefaultSnapRatio, chromeos::SnapController::SnapRequestSource::kSnapButton); - split_view_overview_session = VerifySplitViewOverviewSession(window.get()); + split_view_overview_session = VerifySplitViewOverviewSession(window1.get()); EXPECT_TRUE(split_view_overview_session); EXPECT_EQ(split_view_overview_session->snap_action_source_for_testing(), WindowSnapActionSource::kLongPressCaptionButtonToSnap); - MaximizeToClearTheSession(window.get()); + MaximizeToClearTheSession(window1.get()); } } // namespace ash
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index c689314..a6371bd 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -32,6 +32,7 @@ #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_item.h" +#include "ash/wm/overview/overview_metrics.h" #include "ash/wm/overview/overview_types.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/snap_group/snap_group.h" @@ -2571,11 +2572,21 @@ const int divider_position = GetClosestFixedDividerPosition(ash::GetEquivalentDividerPosition( primary_window_ ? primary_window_ : secondary_window_, - /*should_consider_divider=*/false)); + /*account_for_divider_width=*/false)); split_view_divider_.ShowFor(divider_position); UpdateSnappedWindowsAndDividerBounds(); NotifyDividerPositionChanged(); + + // Ends `SplitViewOverviewSession` if it is currently alive, as + // `SplitViewOverviewSession` is for clamshell only. + RootWindowController* root_window_controller = + RootWindowController::ForWindow(root_window_); + if (SplitViewOverviewSession* split_view_overview_session = + root_window_controller->split_view_overview_session()) { + root_window_controller->EndSplitViewOverviewSession( + SplitViewOverviewSessionExitPoint::kTabletConversion); + } } }
diff --git a/ash/wm/splitview/split_view_overview_session.h b/ash/wm/splitview/split_view_overview_session.h index cebe8d0..5635971 100644 --- a/ash/wm/splitview/split_view_overview_session.h +++ b/ash/wm/splitview/split_view_overview_session.h
@@ -34,14 +34,15 @@ // Enumeration of the exit point of the `SplitViewOverviewSession`. // Please keep in sync with "OverviewEndAction" in -// tools/metrics/histograms/enums.xml. +// tools/metrics/histograms/metadata/ash/enums.xml. enum class SplitViewOverviewSessionExitPoint { kCompleteByActivating, kSkip, kWindowDestroy, kShutdown, kUnspecified, - kMaxValue = kUnspecified, + kTabletConversion, + kMaxValue = kTabletConversion, }; // Encapsulates the split view state with a single snapped window and
diff --git a/ash/wm/splitview/split_view_utils.cc b/ash/wm/splitview/split_view_utils.cc index d3541180..561d528 100644 --- a/ash/wm/splitview/split_view_utils.cc +++ b/ash/wm/splitview/split_view_utils.cc
@@ -231,21 +231,20 @@ // state of the opposite snapped window. gfx::Rect union_bounds; for (aura::Window* top_window : windows) { - if (top_window->GetRootWindow() != window->GetRootWindow()) { - // Skip any windows that aren't on the same root as `window`. - continue; - } - const auto* top_window_state = WindowState::Get(top_window); // The `top_window` should be excluded for occlusion check under the // following conditions: // 1. When it is the `window` itself; - // 2. When it is not visible or minimized; + // 2. When `top_window` is not on the same root window of the given + // `window`; // 3. When it is the transient child of the `window`, for example the window // layout menu or other bubble widget; - // 4. When it is a float or pip window. + // 4. When it is not visible or minimized; + // 5. When it is a float or pip window. const bool should_be_excluded_for_occlusion_check = - top_window == window || wm::GetTransientRoot(top_window) == window || + top_window == window || + top_window->GetRootWindow() != window->GetRootWindow() || + wm::GetTransientRoot(top_window) == window || !top_window->IsVisible() || top_window_state->IsMinimized() || top_window_state->IsFloated() || top_window_state->IsPip(); @@ -274,6 +273,20 @@ return false; } +// Returns true if there is no window in partial overview (excluding the given +// `window`). +bool IsPartialOverviewEmptyForActiveDesk(aura::Window* window) { + for (auto win : + Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk)) { + if (win != window && wm::GetTransientRoot(win) != window && + win->GetRootWindow() == window->GetRootWindow()) { + return false; + } + } + + return true; +} + } // namespace WindowTransformAnimationObserver::WindowTransformAnimationObserver( @@ -888,7 +901,8 @@ return false; } - if (!OverviewController::Get()->CanEnterOverview()) { + if (!OverviewController::Get()->CanEnterOverview() || + IsPartialOverviewEmptyForActiveDesk(window)) { return false; }
diff --git a/ash/wm/window_restore/pine_contents_data.cc b/ash/wm/window_restore/pine_contents_data.cc index d267a06..ff25566 100644 --- a/ash/wm/window_restore/pine_contents_data.cc +++ b/ash/wm/window_restore/pine_contents_data.cc
@@ -4,12 +4,22 @@ #include "ash/wm/window_restore/pine_contents_data.h" -#include "components/app_restore/restore_data.h" - namespace ash { PineContentsData::PineContentsData() = default; PineContentsData::~PineContentsData() = default; +PineContentsData::AppInfo::AppInfo(const std::string& app_id) + : app_id(app_id) {} + +PineContentsData::AppInfo::AppInfo(const std::string& app_id, + const std::string& tab_title, + const std::vector<std::string>& tab_urls) + : app_id(app_id), tab_title(tab_title), tab_urls(tab_urls) {} + +PineContentsData::AppInfo::AppInfo(const AppInfo&) = default; + +PineContentsData::AppInfo::~AppInfo() = default; + } // namespace ash
diff --git a/ash/wm/window_restore/pine_contents_data.h b/ash/wm/window_restore/pine_contents_data.h index 0b1d73d5..2ec99ca 100644 --- a/ash/wm/window_restore/pine_contents_data.h +++ b/ash/wm/window_restore/pine_contents_data.h
@@ -5,15 +5,12 @@ #ifndef ASH_WM_WINDOW_RESTORE_PINE_CONTENTS_DATA_H_ #define ASH_WM_WINDOW_RESTORE_PINE_CONTENTS_DATA_H_ -#include <memory> +#include <string> +#include <vector> #include "ash/ash_export.h" #include "ui/gfx/image/image_skia.h" -namespace app_restore { -class RestoreData; -} - namespace ash { // Various data needed to populate the pine dialog. @@ -24,18 +21,38 @@ PineContentsData& operator=(const PineContentsData&) = delete; ~PineContentsData(); + struct AppInfo { + explicit AppInfo(const std::string& id); + AppInfo(const std::string& app_id, + const std::string& tab_title, + const std::vector<std::string>& tab_urls); + AppInfo(const AppInfo&); + ~AppInfo(); + // App id. Used to retrieve the app name and app icon from the app registry + // cache. + std::string app_id; + // Used for browser and PWAs. Shows a more descriptive title than "Chrome". + std::string tab_title; + // Used by browser only. Urls of up to 5 tabs including the active tab. Used + // to retrieve favicons. + std::vector<std::string> tab_urls; + }; + + using AppsInfos = std::vector<AppInfo>; + // Image read from the pine image file. Will be null if pine image file was // missing or decoding failed. gfx::ImageSkia image; - // Contains the app data needed to show app titles, app icons, favicons, etc. - // Read from the full restore file. - // TODO(sammiequon): Use a subset of `app_restore::RestoreData` here instead - // as it contains a lot of unnecessary information. - std::unique_ptr<app_restore::RestoreData> restore_data; + // List of `AppInfo`'s. Each one representing an app window. There may be + // multiple entries with the same app id. + AppsInfos apps_infos; + + // True if the previous session crashed. The pine dialog will have slightly + // different strings in this case. + bool last_session_crashed = false; // TODO(sammiequon): Add ok/cancel callbacks. - // TODO(sammiequon): Add dialog type (crash, update, normal). }; } // namespace ash
diff --git a/ash/wm/window_restore/pine_contents_view.cc b/ash/wm/window_restore/pine_contents_view.cc index b933a81b..2e66e8e3 100644 --- a/ash/wm/window_restore/pine_contents_view.cc +++ b/ash/wm/window_restore/pine_contents_view.cc
@@ -15,7 +15,7 @@ #include "ash/wm/window_properties.h" #include "ash/wm/window_restore/pine_contents_data.h" #include "ash/wm/window_restore/pine_context_menu_model.h" -#include "ash/wm/window_restore/window_restore_controller.h" +#include "ash/wm/window_restore/pine_controller.h" #include "base/barrier_callback.h" #include "base/i18n/number_formatting.h" #include "base/strings/strcat.h" @@ -214,8 +214,9 @@ METADATA_HEADER(PineItemsOverflowView, views::BoxLayoutView) public: - explicit PineItemsOverflowView(const PineContentsView::AppsData& apps) { - const int elements = static_cast<int>(apps.size()); + explicit PineItemsOverflowView( + const PineContentsData::AppsInfos& apps_infos) { + const int elements = static_cast<int>(apps_infos.size()); CHECK_GE(elements, kOverflowMinElements); // TODO(hewer): Fix margins so the icons and text are aligned with @@ -257,9 +258,9 @@ image_view_map_[i] = image_view; // The callback may be called synchronously. - const auto& [app_id, favicons] = apps[i]; + const PineContentsData::AppInfo& app_info = apps_infos[i]; delegate->GetIconForAppId( - app_id, kAppIdImageSize, + app_info.app_id, kAppIdImageSize, base::BindOnce(&PineItemsOverflowView::SetIconForIndex, weak_ptr_factory_.GetWeakPtr(), i)); } @@ -301,9 +302,9 @@ image_view_map_[i] = image_view; // The callback may be called synchronously. - const auto& [app_id, favicons] = apps[i]; + const PineContentsData::AppInfo& app_info = apps_infos[i]; delegate->GetIconForAppId( - app_id, kAppIdImageSize, + app_info.app_id, kAppIdImageSize, base::BindOnce(&PineItemsOverflowView::SetIconForIndex, weak_ptr_factory_.GetWeakPtr(), i)); } @@ -420,8 +421,9 @@ METADATA_HEADER(PineItemsContainerView, views::BoxLayoutView) public: - explicit PineItemsContainerView(const PineContentsView::AppsData& apps) { - const int elements = static_cast<int>(apps.size()); + explicit PineItemsContainerView( + const PineContentsData::AppsInfos& apps_infos) { + const int elements = static_cast<int>(apps_infos.size()); CHECK_GT(elements, 0); SetBackground(views::CreateRoundedRectBackground(SK_ColorWHITE, @@ -438,11 +440,11 @@ auto* delegate = Shell::Get()->saved_desk_delegate(); for (int i = 0; i < elements; ++i) { - const auto& [app_id, favicons] = apps[i]; + const PineContentsData::AppInfo& app_info = apps_infos[i]; // If there are more than four elements, we will need to save the last // space for the overflow view to condense the remaining info. if (elements >= kOverflowMinElements && i >= kOverflowMinThreshold) { - AddChildView(std::make_unique<PineItemsOverflowView>(apps)); + AddChildView(std::make_unique<PineItemsOverflowView>(apps_infos)); break; } @@ -450,17 +452,19 @@ // `cache` might be null in a test environment. In that case, we will // use an empty title. if (cache) { - cache->ForOneApp(app_id, [&title](const apps::AppUpdate& update) { - title = update.Name(); - }); + cache->ForOneApp( + app_info.app_id, + [&title](const apps::AppUpdate& update) { title = update.Name(); }); } - PineItemView* item_view = - AddChildView(std::make_unique<PineItemView>(title, favicons)); + // TODO(hewer|sammiequon): `PineItemView` should just take `app_info` and + // `cache` as a constructor argument. + PineItemView* item_view = AddChildView( + std::make_unique<PineItemView>(title, app_info.tab_urls)); // The callback may be called synchronously. delegate->GetIconForAppId( - app_id, kAppIdImageSize, + app_info.app_id, kAppIdImageSize, base::BindOnce( [](base::WeakPtr<PineItemView> item_view_ptr, const gfx::ImageSkia& icon) { @@ -548,24 +552,12 @@ ->SetFlexForView(spacer, 1); const PineContentsData* pine_contents_data = - WindowRestoreController::Get()->pine_contents_data(); + Shell::Get()->pine_controller()->pine_contents_data(); CHECK(pine_contents_data); if (pine_contents_data->image.isNull()) { - // TODO(hewer|sammiequon): Move this developer testing data to - // `WindowRestoreController::MaybeStartPineOverviewSessionDevAccelerator()`. - AppsData kTestingAppsData = { - {"mgndgikekgjfcpckkfioiadnlibdjbkf", // Chrome - {"https://www.cnn.com/", "https://www.youtube.com/", - "https://www.google.com/"}}, - {"njfbnohfdkmbmnjapinfcopialeghnmh", {}}, // Camera - {"odknhmnlageboeamepcngndbggdpaobj", {}}, // Settings - {"fkiggjmkendpmbegkagpmagjepfkpmeb", {}}, // Files - {"oabkinaljpjeilageghcdlnekhphhphl", {}}, // Calculator - {"mgndgikekgjfcpckkfioiadnlibdjbkf", // Chrome - {"https://www.google.com/maps/"}}, - }; - PineItemsContainerView* container_view = AddChildView( - std::make_unique<PineItemsContainerView>(kTestingAppsData)); + PineItemsContainerView* container_view = + AddChildView(std::make_unique<PineItemsContainerView>( + pine_contents_data->apps_infos)); container_view->SetPreferredSize(kItemsContainerPreferredSize); } else { views::ImageView* preview =
diff --git a/ash/wm/window_restore/pine_contents_view.h b/ash/wm/window_restore/pine_contents_view.h index 8cc391ec..ded89b4 100644 --- a/ash/wm/window_restore/pine_contents_view.h +++ b/ash/wm/window_restore/pine_contents_view.h
@@ -28,11 +28,6 @@ METADATA_HEADER(PineContentsView, views::BoxLayoutView) public: - // Temporary typedefs to describe a bunch of apps. An app is described by an - // app id and a vector of urls, which can be empty if the app is not Chrome. - using AppData = std::pair<std::string, std::vector<std::string>>; - using AppsData = std::vector<AppData>; - PineContentsView(); PineContentsView(const PineContentsView&) = delete; PineContentsView& operator=(const PineContentsView&) = delete;
diff --git a/ash/wm/window_restore/pine_context_menu_model_unittest.cc b/ash/wm/window_restore/pine_context_menu_model_unittest.cc index 4142462c..82eb06fc 100644 --- a/ash/wm/window_restore/pine_context_menu_model_unittest.cc +++ b/ash/wm/window_restore/pine_context_menu_model_unittest.cc
@@ -16,7 +16,7 @@ #include "ash/wm/window_restore/pine_contents_data.h" #include "ash/wm/window_restore/pine_contents_view.h" #include "ash/wm/window_restore/pine_context_menu_model.h" -#include "ash/wm/window_restore/window_restore_controller.h" +#include "ash/wm/window_restore/pine_controller.h" #include "ash/wm/window_restore/window_restore_util.h" #include "base/test/scoped_feature_list.h" #include "components/prefs/pref_registry_simple.h" @@ -102,7 +102,7 @@ // context menu. TEST_F(PineContextMenuModelTest, ShowContextMenuOnSettingsButtonClicked) { Shell::Get() - ->window_restore_controller() + ->pine_controller() ->MaybeStartPineOverviewSessionDevAccelerator(); WaitForOverviewEntered();
diff --git a/ash/wm/window_restore/pine_controller.cc b/ash/wm/window_restore/pine_controller.cc new file mode 100644 index 0000000..8b208fc22 --- /dev/null +++ b/ash/wm/window_restore/pine_controller.cc
@@ -0,0 +1,114 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/window_restore/pine_controller.h" + +#include "ash/constants/ash_pref_names.h" +#include "ash/public/cpp/image_util.h" +#include "ash/shell.h" +#include "ash/wm/overview/overview_controller.h" +#include "ash/wm/window_restore/pine_contents_data.h" +#include "ash/wm/window_restore/window_restore_util.h" +#include "base/functional/bind.h" +#include "base/metrics/histogram_functions.h" +#include "components/prefs/pref_service.h" + +namespace ash { + +namespace { + +// Records the UMA metrics for the pine screenshot taken on the last shutdown. +// Resets the prefs used to store the metrics across shutdowns. +void RecordPineScreenshotMetrics(PrefService* local_state) { + auto record_uma = [](PrefService* local_state, const std::string& name, + const std::string& pref_name) -> void { + const base::TimeDelta duration = local_state->GetTimeDelta(pref_name); + // Don't record the metric if we don't have a value. + if (!duration.is_zero()) { + base::UmaHistogramTimes(name, duration); + // Reset the pref in case the next shutdown doesn't take the screenshot. + local_state->SetTimeDelta(pref_name, base::TimeDelta()); + } + }; + + record_uma(local_state, "Ash.Pine.ScreenshotTakenDuration", + prefs::kPineScreenshotTakenDuration); + record_uma(local_state, "Ash.Pine.ScreenshotEncodeAndSaveDuration", + prefs::kPineScreenshotEncodeAndSaveDuration); +} + +} // namespace + +PineController::PineController() = default; + +PineController::~PineController() = default; + +void PineController::MaybeStartPineOverviewSessionDevAccelerator() { + auto data = std::make_unique<PineContentsData>(); + data->last_session_crashed = false; + + // Chrome. + data->apps_infos.emplace_back( + "mgndgikekgjfcpckkfioiadnlibdjbkf", /*tab_title=*/"Cnn", + std::vector<std::string>{"https://www.cnn.com/", + "https://www.youtube.com/", + "https://www.google.com/"}); + // Camera. + data->apps_infos.emplace_back("njfbnohfdkmbmnjapinfcopialeghnmh"); + // Settings. + data->apps_infos.emplace_back("odknhmnlageboeamepcngndbggdpaobj"); + // Files. + data->apps_infos.emplace_back("fkiggjmkendpmbegkagpmagjepfkpmeb"); + // Calculator. + data->apps_infos.emplace_back("oabkinaljpjeilageghcdlnekhphhphl"); + // Chrome. + data->apps_infos.emplace_back( + "mgndgikekgjfcpckkfioiadnlibdjbkf", /*tab_title=*/"Maps", + std::vector<std::string>{"https://www.google.com/maps/"}); + + MaybeStartPineOverviewSession(std::move(data)); +} + +void PineController::MaybeStartPineOverviewSession( + std::unique_ptr<PineContentsData> pine_contents_data) { + CHECK(features::IsForestFeatureEnabled()); + + if (OverviewController::Get()->InOverviewSession()) { + return; + } + + // TODO(hewer|sammiequon): This function should only be called once in + // production code when `pine_contents_data_` is null. It can be called + // multiple times currently via dev accelerator. Remove this block when + // `MaybeStartPineOverviewSessionDevAccelerator()` is removed. + if (pine_contents_data_) { + StartPineOverviewSession(); + return; + } + + pine_contents_data_ = std::move(pine_contents_data); + + // TODO(minch|sammiequon): Record the metrics on start up when determining + // whether to show the pine dialog. + RecordPineScreenshotMetrics(Shell::Get()->local_state()); + image_util::DecodeImageFile( + base::BindOnce(&PineController::OnPineImageDecoded, + weak_ptr_factory_.GetWeakPtr()), + GetShutdownPineImagePath(), data_decoder::mojom::ImageCodec::kPng); +} + +void PineController::OnPineImageDecoded(const gfx::ImageSkia& pine_image) { + CHECK(pine_contents_data_); + pine_contents_data_->image = pine_image; + + StartPineOverviewSession(); +} + +void PineController::StartPineOverviewSession() { + // TODO(sammiequon): Add a new start action for this type of overview session. + OverviewController::Get()->StartOverview(OverviewStartAction::kAccelerator, + OverviewEnterExitType::kPine); +} + +} // namespace ash
diff --git a/ash/wm/window_restore/pine_controller.h b/ash/wm/window_restore/pine_controller.h new file mode 100644 index 0000000..f677fd1b --- /dev/null +++ b/ash/wm/window_restore/pine_controller.h
@@ -0,0 +1,68 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_WINDOW_RESTORE_PINE_CONTROLLER_H_ +#define ASH_WM_WINDOW_RESTORE_PINE_CONTROLLER_H_ + +#include "ash/ash_export.h" +#include "base/memory/weak_ptr.h" +#include "ui/gfx/image/image_skia.h" + +namespace ash { + +struct PineContentsData; + +// Controls showing the pine dialog. Receives data from the full restore +// service. +class ASH_EXPORT PineController { + public: + PineController(); + PineController(const PineController&) = delete; + PineController& operator=(const PineController&) = delete; + ~PineController(); + + const PineContentsData* pine_contents_data() const { + return pine_contents_data_.get(); + } + + // Starts an overview session with the pine contents view if certain + // conditions are met. Uses fake for testing only data. + // TODO(hewer): Remove this temporary function. + void MaybeStartPineOverviewSessionDevAccelerator(); + + // Starts an overview session with the pine contents view if certain + // conditions are met. Triggered by developer accelerator or on login. + // `pine_contents_data` is stored in `pine_contents_data_` as we will support + // re-entering the pine session if no windows have opened for example. It will + // be populated with a screenshot if possible and then referenced when an + // overview pine session is entered. + void MaybeStartPineOverviewSession( + std::unique_ptr<PineContentsData> pine_contents_data); + + // TODO(sammiequon): Create a separate controller for pine related things as + // we need to support first-time experience and other things. + // TODO(sammiequon): Add a `MaybeEndPineOverviewSession()` function which is + // controlled by the full restore service. This will clear + // `pine_contents_data_`. + // TODO(sammiequon): Entering overview normally should show the pine dialog if + // `pine_contents_data_` is not null. + + private: + // Callback function for when the pine image is finished decoding. + void OnPineImageDecoded(const gfx::ImageSkia& pine_image); + + void StartPineOverviewSession(); + + // Stores the data needed to display the pine dialog. Created on login, and + // deleted after the user interacts with the dialog. If the user exits + // overview, this will persist until a window is opened. + // TODO(sammiequon): Delete this object when an app window is created. + std::unique_ptr<PineContentsData> pine_contents_data_; + + base::WeakPtrFactory<PineController> weak_ptr_factory_{this}; +}; + +} // namespace ash + +#endif // ASH_WM_WINDOW_RESTORE_PINE_CONTROLLER_H_
diff --git a/ash/wm/window_restore/pine_unittest.cc b/ash/wm/window_restore/pine_unittest.cc index d3305643..421ad92 100644 --- a/ash/wm/window_restore/pine_unittest.cc +++ b/ash/wm/window_restore/pine_unittest.cc
@@ -16,7 +16,7 @@ #include "ash/wm/window_restore/pine_contents_data.h" #include "ash/wm/window_restore/pine_contents_view.h" #include "ash/wm/window_restore/pine_context_menu_model.h" -#include "ash/wm/window_restore/window_restore_controller.h" +#include "ash/wm/window_restore/pine_controller.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "ui/views/controls/button/image_button.h" @@ -39,7 +39,7 @@ TEST_F(PineTest, Show) { Shell::Get() - ->window_restore_controller() + ->pine_controller() ->MaybeStartPineOverviewSessionDevAccelerator(); WaitForOverviewEntered();
diff --git a/ash/wm/window_restore/window_restore_controller.cc b/ash/wm/window_restore/window_restore_controller.cc index 9fe460bcb..263e2b71 100644 --- a/ash/wm/window_restore/window_restore_controller.cc +++ b/ash/wm/window_restore/window_restore_controller.cc
@@ -8,9 +8,7 @@ #include "ash/app_list/app_list_controller_impl.h" #include "ash/constants/app_types.h" -#include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/app_types_util.h" -#include "ash/public/cpp/image_util.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_properties.h" #include "ash/session/session_controller_impl.h" @@ -19,11 +17,9 @@ #include "ash/wm/desks/desk.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/desks/templates/saved_desk_util.h" -#include "ash/wm/float/float_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/window_positioning_utils.h" -#include "ash/wm/window_restore/pine_contents_data.h" #include "ash/wm/window_restore/window_restore_util.h" #include "ash/wm/window_state.h" #include "ash/wm/wm_event.h" @@ -32,7 +28,6 @@ #include "base/containers/adapters.h" #include "base/containers/contains.h" #include "base/functional/bind.h" -#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/task/single_thread_task_runner.h" #include "components/app_restore/full_restore_utils.h" @@ -128,26 +123,6 @@ } } -// Records the UMA metrics for the pine screenshot taken on the last shutdown. -// Resets the prefs used to store the metrics across shutdowns. -void RecordPineScreenshotMetrics(PrefService* local_state) { - auto record_uma = [](PrefService* local_state, const std::string& name, - const std::string& pref_name) -> void { - const base::TimeDelta duration = local_state->GetTimeDelta(pref_name); - // Don't record the metric if we don't have a value. - if (!duration.is_zero()) { - base::UmaHistogramTimes(name, duration); - // Reset the pref in case the next shutdown doesn't take the screenshot. - local_state->SetTimeDelta(pref_name, base::TimeDelta()); - } - }; - - record_uma(local_state, "Ash.Pine.ScreenshotTakenDuration", - prefs::kPineScreenshotTakenDuration); - record_uma(local_state, "Ash.Pine.ScreenshotEncodeAndSaveDuration", - prefs::kPineScreenshotEncodeAndSaveDuration); -} - // Self deleting class which watches a unparented window and deletes itself once // the window has a parent. class ParentChangeObserver : public aura::WindowObserver { @@ -526,38 +501,6 @@ return windows_observation_.IsObservingSource(window); } -void WindowRestoreController::MaybeStartPineOverviewSessionDevAccelerator() { - MaybeStartPineOverviewSession(std::make_unique<PineContentsData>()); -} - -void WindowRestoreController::MaybeStartPineOverviewSession( - std::unique_ptr<PineContentsData> pine_contents_data) { - CHECK(features::IsForestFeatureEnabled()); - - if (OverviewController::Get()->InOverviewSession()) { - return; - } - - // TODO(hewer|sammiequon): This function should only be called once in - // production code when `pine_contents_data_` is null. It can be called - // multiple times currently via dev accelerator. Remove this block when - // `MaybeStartPineOverviewSessionDevAccelerator()` is removed. - if (pine_contents_data_) { - StartPineOverviewSession(); - return; - } - - pine_contents_data_ = std::move(pine_contents_data); - - // TODO(minch|sammiequon): Record the metrics on start up when determining - // whether to show the pine dialog. - RecordPineScreenshotMetrics(Shell::Get()->local_state()); - image_util::DecodeImageFile( - base::BindOnce(&WindowRestoreController::OnPineImageDecoded, - weak_ptr_factory_.GetWeakPtr()), - GetShutdownPineImagePath(), data_decoder::mojom::ImageCodec::kPng); -} - void WindowRestoreController::SaveWindowImpl( WindowState* window_state, std::optional<int> activation_index) { @@ -688,20 +631,6 @@ restore_property_clear_callbacks_.erase(window); } -void WindowRestoreController::OnPineImageDecoded( - const gfx::ImageSkia& pine_image) { - CHECK(pine_contents_data_); - pine_contents_data_->image = pine_image; - - StartPineOverviewSession(); -} - -void WindowRestoreController::StartPineOverviewSession() { - // TODO(sammiequon): Add a new start action for this type of overview session. - OverviewController::Get()->StartOverview(OverviewStartAction::kAccelerator, - OverviewEnterExitType::kPine); -} - void WindowRestoreController::SetSaveWindowCallbackForTesting( SaveWindowCallback callback) { g_save_window_callback_for_testing = std::move(callback);
diff --git a/ash/wm/window_restore/window_restore_controller.h b/ash/wm/window_restore/window_restore_controller.h index f962a041..409cb153 100644 --- a/ash/wm/window_restore/window_restore_controller.h +++ b/ash/wm/window_restore/window_restore_controller.h
@@ -18,7 +18,6 @@ #include "components/app_restore/window_info.h" #include "ui/aura/window_observer.h" #include "ui/display/display_observer.h" -#include "ui/gfx/image/image_skia.h" namespace aura { class Window; @@ -34,7 +33,6 @@ namespace ash { -struct PineContentsData; class WindowState; class ASH_EXPORT WindowRestoreController @@ -81,10 +79,6 @@ return to_be_snapped_window_; } - const PineContentsData* pine_contents_data() const { - return pine_contents_data_.get(); - } - // Calls SaveWindowImpl for |window_state|. The activation index will be // calculated in SaveWindowImpl. void SaveWindow(WindowState* window_state); @@ -105,28 +99,6 @@ // `this`. bool IsRestoringWindow(aura::Window* window) const; - // Starts an overview session with the pine contents view if certain - // conditions are met. Uses fake for testing only data. - // TODO(hewer): Remove this temporary function. - void MaybeStartPineOverviewSessionDevAccelerator(); - - // Starts an overview session with the pine contents view if certain - // conditions are met. Triggered by developer accelerator or on login. - // `pine_contents_data` is stored in `pine_contents_data_` as we will support - // re-entering the pine session if no windows have opened for example. It will - // be populated with a screenshot if possible and then referenced when an - // overview pine session is entered. - void MaybeStartPineOverviewSession( - std::unique_ptr<PineContentsData> pine_contents_data); - - // TODO(sammiequon): Create a separate controller for pine related things as - // we need to support first-time experience and other things. - // TODO(sammiequon): Add a `MaybeEndPineOverviewSession()` function which is - // controlled by the full restore service. This will clear - // `pine_contents_data_`. - // TODO(sammiequon): Entering overview normally should show the pine dialog if - // `pine_contents_data_` is not null. - // display::DisplayObserver: void OnDisplayTabletStateChanged(display::TabletState state) override; @@ -175,11 +147,6 @@ // from `restore_property_clear_callbacks_`. void CancelAndRemoveRestorePropertyClearCallback(aura::Window* window); - // Callback function for when the pine image is finished decoding. - void OnPineImageDecoded(const gfx::ImageSkia& pine_image); - - void StartPineOverviewSession(); - // Sets a callback for testing that will be fired immediately when // `SaveWindowImpl()` is about to notify the window restore component we want // to write to file. @@ -203,12 +170,6 @@ std::map<aura::Window*, base::CancelableOnceClosure> restore_property_clear_callbacks_; - // Stores the data needed to display the pine dialog. Created on login, and - // deleted after the user interacts with the dialog. If the user exits - // overview, this will persist until a window is opened. - // TODO(sammiequon): Delete this object when an app window is created. - std::unique_ptr<PineContentsData> pine_contents_data_; - display::ScopedDisplayObserver display_observer_{this}; base::ScopedObservation<app_restore::AppRestoreInfo,
diff --git a/base/compiler_specific.h b/base/compiler_specific.h index fbe0bb2..17ba104 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h
@@ -443,11 +443,12 @@ // Additionally, the initial implementation in clang <= 16 overwrote the return // register(s) in the epilogue of a preserve_most function, so we only use // preserve_most in clang >= 17 (see https://reviews.llvm.org/D143425). +// Clang only supports preserve_most on X86-64 and AArch64 for now. // See https://clang.llvm.org/docs/AttributeReference.html#preserve-most for // more details. -#if defined(ARCH_CPU_64_BITS) && \ - !(BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)) && \ - !defined(COMPONENT_BUILD) && defined(__clang__) && \ +#if (defined(ARCH_CPU_ARM64) || defined(ARCH_CPU_X86_64)) && \ + !(BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)) && \ + !defined(COMPONENT_BUILD) && defined(__clang__) && \ __clang_major__ >= 17 && HAS_ATTRIBUTE(preserve_most) #define PRESERVE_MOST __attribute__((preserve_most)) #else
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index a109df4..aa6b5be1 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1850,6 +1850,9 @@ cflags_cc += [ # TODO(https://crbug.com/1474434): fix and reenable "-Wno-missing-field-initializers", + + # TODO(https://crbug.com/324953188): fix and reenable + "-Wno-extra-qualification", ] }
diff --git a/cc/input/input_handler.cc b/cc/input/input_handler.cc index 5fad139..adfbaf1 100644 --- a/cc/input/input_handler.cc +++ b/cc/input/input_handler.cc
@@ -547,7 +547,9 @@ } PointerResultType InputHandler::HitTest(const gfx::PointF& viewport_point) { - return scrollbar_controller_->HitTest(viewport_point).type; + return scrollbar_controller_->HitTest(viewport_point) + ? PointerResultType::kScrollbarScroll + : PointerResultType::kUnhandled; } InputHandlerPointerResult InputHandler::MouseDown(
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h index 0b8dba5..1bd128c 100644 --- a/cc/input/input_handler.h +++ b/cc/input/input_handler.h
@@ -58,13 +58,6 @@ kMaxValue = kScrollingOnMain, }; -struct CC_EXPORT PointerHitTestResult { - PointerHitTestResult() = default; - - PointerResultType type = PointerResultType::kUnhandled; - raw_ptr<const LayerImpl> layer_impl = nullptr; -}; - struct CC_EXPORT InputHandlerPointerResult { InputHandlerPointerResult() = default; // Tells what type of processing occurred in the input handler as a result of
diff --git a/cc/input/scrollbar_controller.cc b/cc/input/scrollbar_controller.cc index 64d7762..eee49d58 100644 --- a/cc/input/scrollbar_controller.cc +++ b/cc/input/scrollbar_controller.cc
@@ -51,7 +51,7 @@ return nullptr; } -PointerHitTestResult ScrollbarController::HitTest( +const ScrollbarLayerImplBase* ScrollbarController::HitTest( const gfx::PointF position_in_widget) const { // If a non-custom scrollbar layer was not found, we return early as there is // no point in setting additional state in the ScrollbarController. Return an @@ -59,20 +59,13 @@ // to InputHandlerProxy::RouteToTypeSpecificHandler, the pointer event gets // passed on to the main thread. const LayerImpl* layer_impl = GetLayerHitByPoint(position_in_widget); - PointerHitTestResult result; - if (!(layer_impl && layer_impl->IsScrollbarLayer())) - return result; + return nullptr; // If the scrollbar layer has faded out (eg: Overlay scrollbars), don't // initiate a scroll. const ScrollbarLayerImplBase* scrollbar = ToScrollbarLayer(layer_impl); - if (scrollbar->OverlayScrollbarOpacity() == 0.f) - return result; - - result.type = PointerResultType::kScrollbarScroll; - result.layer_impl = layer_impl; - return result; + return scrollbar->OverlayScrollbarOpacity() == 0.f ? nullptr : scrollbar; } // Performs hit test and prepares scroll deltas that will be used by GSB and @@ -80,15 +73,11 @@ InputHandlerPointerResult ScrollbarController::HandlePointerDown( const gfx::PointF position_in_widget, bool jump_key_modifier) { - PointerHitTestResult hit_test_result = HitTest(position_in_widget); - if (hit_test_result.type != PointerResultType::kScrollbarScroll) { + const ScrollbarLayerImplBase* scrollbar = HitTest(position_in_widget); + if (!scrollbar) { return InputHandlerPointerResult(); } - // TODO(arakeri): GetLayerHitByPoint should ideally be called only once per - // pointerdown. This needs to be optimized. See crbug.com/1156922. - const ScrollbarLayerImplBase* scrollbar = - ToScrollbarLayer(hit_test_result.layer_impl); captured_scrollbar_metadata_ = CapturedScrollbarMetadata(); captured_scrollbar_metadata_->scroll_element_id = scrollbar->scroll_element_id();
diff --git a/cc/input/scrollbar_controller.h b/cc/input/scrollbar_controller.h index 692117f..d236416 100644 --- a/cc/input/scrollbar_controller.h +++ b/cc/input/scrollbar_controller.h
@@ -157,7 +157,8 @@ ScrollbarLayerImplBase* ScrollbarLayer() const; void WillBeginImplFrame(); void ResetState(); - PointerHitTestResult HitTest(const gfx::PointF position_in_widget) const; + const ScrollbarLayerImplBase* HitTest( + const gfx::PointF position_in_widget) const; private: FRIEND_TEST_ALL_PREFIXES(LayerTreeHostImplTest, ThumbDragAfterJumpClick);
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index 4e97945d..f67501c 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1730,9 +1730,8 @@ FakeContentLayerClient client_; }; -// Disabled on ChromeOS ASAN due to test flakiness. See -// https://crbug.com/1517464 -#if BUILDFLAG(IS_CHROMEOS) && defined(ADDRESS_SANITIZER) +// Disabled on ASAN/debug due to test flakiness. See https://crbug.com/1517464 +#if defined(ADDRESS_SANITIZER) || !defined(NDEBUG) SINGLE_THREAD_TEST_F(LayerTreeHostAnimationTestIsAnimating); #else SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestIsAnimating);
diff --git a/chrome/VERSION b/chrome/VERSION index 531cb78..8634f4c92 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=123 MINOR=0 -BUILD=6298 +BUILD=6299 PATCH=0
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index 53d1c46..c6186af 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -68,7 +68,6 @@ "java/res/layout/closable_tab_list_card_item.xml", "java/res/layout/color_picker_item.xml", "java/res/layout/custom_message_card_item.xml", - "java/res/layout/data_sharing_group_bar.xml", "java/res/layout/declutter_message_card_layout.xml", "java/res/layout/incognito_description_container_layout.xml", "java/res/layout/iph_drag_and_drop_dialog_layout.xml",
diff --git a/chrome/android/features/tab_ui/java/res/layout/data_sharing_group_bar.xml b/chrome/android/features/tab_ui/java/res/layout/data_sharing_group_bar.xml deleted file mode 100644 index 76df847c..0000000 --- a/chrome/android/features/tab_ui/java/res/layout/data_sharing_group_bar.xml +++ /dev/null
@@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2024 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:id="@+id/dialog_data_sharing_group_bar" - android:orientation="vertical" - android:layout_alignParentBottom="true" - tools:ignore="UseCompoundDrawables"> - <ImageView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:src="@drawable/toolbar_hairline" - tools:ignore="ContentDescription" /> - <org.chromium.ui.widget.ButtonCompat - android:drawableStart="@drawable/ic_person_add_40dp" - android:drawableTint="@color/default_icon_color_accent1_tint_list" - android:id="@+id/dialog_share_invite_button" - android:layout_gravity="end" - android:layout_height="@dimen/bottom_sheet_peek_height" - android:layout_marginEnd="8dp" - android:layout_width="wrap_content" - android:paddingEnd="16dp" - android:text="@string/tab_grid_invite_button_text" - style="@style/TextButton" /> -</LinearLayout>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java index d37a60ba..7178b68 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java
@@ -14,7 +14,6 @@ import android.graphics.RectF; import android.graphics.drawable.GradientDrawable; import android.util.AttributeSet; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -35,7 +34,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; import org.chromium.base.ResettersForTesting; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.tab_ui.R; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.components.browser_ui.widget.scrim.ScrimProperties; @@ -815,13 +813,7 @@ mDialogContainerView.addView(toolbarView); mDialogContainerView.addView(recyclerView); mDialogContainerView.addView(mUngroupBar); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.DATA_SHARING_ANDROID)) { - // Add the data sharing bottom toolbar view. - LayoutInflater inflater = LayoutInflater.from(mDialogContainerView.getContext()); - inflater.inflate(R.layout.data_sharing_group_bar, mDialogContainerView, true); - } mDialogContainerView.addView(mSnackBarContainer); - RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) recyclerView.getLayoutParams(); params.setMargins(0, mToolbarHeight, 0, 0);
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd index 1b07376..4d1ec48 100644 --- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd
@@ -205,9 +205,6 @@ <message name="IDS_ACCESSIBILITY_BOTTOM_TAB_GRID_CLOSE_TAB_SHEET" desc="Accessibility string for BottomTabGridToolbar button indicated visually by the 'v' sign."> Hide fullscreen grid </message> - <message name="IDS_TAB_GRID_INVITE_BUTTON_TEXT" desc="Text for sharing the current tab group from the tab group dialog bottom toolbar."> - Invite people - </message> <!-- Bottom Tab Strip strings --> <message name="IDS_ACCESSIBILITY_BOTTOM_TAB_STRIP_EXPAND_TAB_SHEET" desc="Accessibility string for BottomTabStripToolbar button indicated visually by the '^' sign.">
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_TAB_GRID_INVITE_BUTTON_TEXT.png.sha1 b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_TAB_GRID_INVITE_BUTTON_TEXT.png.sha1 deleted file mode 100644 index 2ab5fe1..0000000 --- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_TAB_GRID_INVITE_BUTTON_TEXT.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -6c332f87ae2fd945fa234c9e8d6189b9de0b85a7 \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java index 89ff505..9b324db 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java
@@ -21,9 +21,7 @@ import org.hamcrest.Matchers; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.chromium.base.test.UiThreadTest; @@ -31,10 +29,6 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.Features; -import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tasks.tab_management.TabGridDialogView.VisibilityListener; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -55,7 +49,6 @@ private FrameLayout mTestParent; private View mSourceView; private View mUngroupBar; - private View mDataSharingBar; private View mAnimationCardView; private View mBackgroundFrameView; private TextView mUngroupBarTextView; @@ -63,8 +56,6 @@ private FrameLayout.LayoutParams mContainerParams; private TabGridDialogView mTabGridDialogView; - @Rule public TestRule mProcessor = new Features.JUnitProcessor(); - @Override public void setUpTest() throws Exception { super.setUpTest(); @@ -80,9 +71,6 @@ mTabGridDialogView.findViewById(R.id.dialog_container_view); mUngroupBar = mTabGridDialogContainer.findViewById(R.id.dialog_ungroup_bar); mUngroupBarTextView = mUngroupBar.findViewById(R.id.dialog_ungroup_bar_text); - mDataSharingBar = - mTabGridDialogContainer.findViewById( - R.id.dialog_data_sharing_group_bar); mContainerParams = (FrameLayout.LayoutParams) mTabGridDialogContainer.getLayoutParams(); mAnimationCardView = @@ -151,7 +139,6 @@ @Test @SmallTest @UiThreadTest - @DisableFeatures({ChromeFeatureList.DATA_SHARING_ANDROID}) public void testResetDialog() { mTabGridDialogContainer.removeAllViews(); View toolbarView = new View(getActivity()); @@ -173,25 +160,7 @@ } @Test - @SmallTest - @UiThreadTest - @EnableFeatures({ChromeFeatureList.DATA_SHARING_ANDROID}) - public void testResetDialogWithDataSharing() { - mTabGridDialogContainer.removeAllViews(); - View toolbarView = new View(getActivity()); - View recyclerView = new View(getActivity()); - recyclerView.setVisibility(View.GONE); - - mTabGridDialogView.resetDialog(toolbarView, recyclerView); - - // It should contain five child views: top tool bar, recyclerview, ungroup bar, data sharing - // bar and undo bar container. - Assert.assertEquals(5, mTabGridDialogContainer.getChildCount()); - } - - @Test @MediumTest - @DisableFeatures({ChromeFeatureList.DATA_SHARING_ANDROID}) public void testUpdateUngroupBar() { AtomicReference<ColorStateList> showTextColorReference = new AtomicReference<>(); AtomicReference<ColorStateList> hoverTextColorReference = new AtomicReference<>();
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java index 87160fb..fec7f67 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java
@@ -48,9 +48,7 @@ import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.Features; -import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tasks.tab_management.TabGridDialogView.VisibilityListener; import org.chromium.chrome.browser.theme.ThemeUtils; import org.chromium.chrome.tab_ui.R; @@ -266,7 +264,6 @@ @Test @SmallTest @UiThreadTest - @DisableFeatures({ChromeFeatureList.DATA_SHARING_ANDROID}) public void testSetScrimViewObserver() { AtomicBoolean scrimViewClicked = new AtomicBoolean(); scrimViewClicked.set(false); @@ -282,7 +279,6 @@ @Test @SmallTest - @DisableFeatures({ChromeFeatureList.DATA_SHARING_ANDROID}) public void testSetDialogVisibility() { Assert.assertNull(mTabGridDialogView.getCurrentDialogAnimatorForTesting());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java index 7ffdf92..ed73c91 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java
@@ -382,19 +382,15 @@ DragDropTabResult.IGNORED_DIFF_MODEL_NOT_SUPPORTED); return false; } - int sourceInstanceId = - DragDropGlobalState.getState(sDragTrackerToken).getDragSourceInstance(); if (!tabDraggedBelongToCurrentModel) { mMultiInstanceManager.moveTabToWindow( getActivity(), tabBeingDragged, - mTabModelSelector.getModel(tabBeingDragged.isIncognito()).getCount(), - sourceInstanceId); + mTabModelSelector.getModel(tabBeingDragged.isIncognito()).getCount()); showDroppedDifferentModelToast(mWindowAndroid.getContext().get()); } else { int tabIndex = helper.getTabIndexForTabDrop(dropEvent.getX() * mPxToDp); - mMultiInstanceManager.moveTabToWindow( - getActivity(), tabBeingDragged, tabIndex, sourceInstanceId); + mMultiInstanceManager.moveTabToWindow(getActivity(), tabBeingDragged, tabIndex); helper.mergeToGroupForTabDropIfNeeded(groupRootId, tabBeingDragged.getId(), tabIndex); } DragDropMetricUtils.recordTabDragDropType(DragDropType.TAB_STRIP_TO_TAB_STRIP); @@ -436,6 +432,10 @@ mMultiInstanceManager.moveTabToNewWindow(tabBeingDragged); } + // Get the drag source Chrome instance id before it is cleared as it may be closed. + int sourceInstanceId = + DragDropGlobalState.getState(sDragTrackerToken).getDragSourceInstance(); + // TODO (crbug.com/1497784): Remove this method. mStripLayoutHelperSupplier.get().clearTabDragState(); if (mShadowView != null) { @@ -449,6 +449,9 @@ if (dropHandled) { DragDropMetricUtils.recordTabDragDropResult(DragDropTabResult.SUCCESS); } + + // Close the source instance window if it has no tabs. + mMultiInstanceManager.closeChromeWindowIfEmpty(sourceInstanceId); return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java b/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java index 96b3524..030eeb5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java
@@ -103,8 +103,7 @@ TabModelUtils.getTabIndexById( mTabModelSelector.getModel(currentTab.isIncognito()), currentTab.getId()) - + 1, - globalState.getDragSourceInstance()); + + 1); DragDropMetricUtils.recordTabDragDropType(DragDropType.TAB_STRIP_TO_CONTENT); return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManager.java index 55e4954..b073bd22 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManager.java
@@ -497,7 +497,7 @@ // Not implemented } - public void moveTabToWindow(Activity activity, Tab tab, int atIndex, int fromWindowInstanceId) { + public void moveTabToWindow(Activity activity, Tab tab, int atIndex) { // Not implemented } @@ -597,4 +597,13 @@ public int getCurrentInstanceId() { return MultiWindowUtils.INVALID_INSTANCE_ID; } + + /** + * Close a Chrome window instance only if it contains no open tabs including incognito ones. + * + * @param instanceId Instance id of the Chrome window that needs to be closed. + */ + public void closeChromeWindowIfEmpty(int instanceId) { + // Not implemented. + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java index 369c6da5..4a60015 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
@@ -12,8 +12,6 @@ import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Pair; @@ -76,7 +74,6 @@ public static final int INVALID_TASK_ID = MultiWindowUtils.INVALID_TASK_ID; private static final String EMPTY_DATA = ""; - private static final long DEFAULT_WINDOW_CLOSING_DELAY_FOR_DRAG_DROP_IN_MILLIS = 50; @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) protected final int mMaxInstances; @@ -146,30 +143,19 @@ mModalDialogManagerSupplier.get(), new LargeIconBridge(getProfile()), (instanceInfo) -> { - moveTabAction(instanceInfo, tab, TabList.INVALID_TAB_INDEX, mInstanceId, false); + moveTabAction(instanceInfo, tab, TabList.INVALID_TAB_INDEX); + + // Close the source instance window, if needed. + closeChromeWindowIfEmpty(mInstanceId); }, getInstanceInfo()); } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - void moveTabAction( - InstanceInfo info, - Tab tab, - int tabAtIndex, - int fromWindowInstanceId, - boolean delayInWindowClosing) { + void moveTabAction(InstanceInfo info, Tab tab, int tabAtIndex) { Activity targetActivity = getActivityById(info.instanceId); if (targetActivity != null) { reparentTabToRunningActivity((ChromeTabbedActivity) targetActivity, tab, tabAtIndex); - - // Close the source instance window, if needed. - if (canCloseEmptyChromeWindow(fromWindowInstanceId)) { - closeEmptyChromeWindowAsynchronously( - fromWindowInstanceId, - delayInWindowClosing - ? DEFAULT_WINDOW_CLOSING_DELAY_FOR_DRAG_DROP_IN_MILLIS - : 0); - } } else { moveAndReparentTabToNewWindow( tab, @@ -953,16 +939,15 @@ * @param activity Activity of the Chrome Window in which the tab is to be moved. * @param tab Tab that is to be moved to the current instance. * @param atIndex Tab position index in the destination window instance. - * @param fromWindowInstanceId InNstance Id of the Chrome window it is being moved from. */ @Override - public void moveTabToWindow(Activity activity, Tab tab, int atIndex, int fromWindowInstanceId) { + public void moveTabToWindow(Activity activity, Tab tab, int atIndex) { if (!TabUiFeatureUtilities.isTabDragEnabled()) return; // Get the current instance and move tab there. InstanceInfo info = getInstanceInfoFor(activity); if (info != null) { - moveTabAction(info, tab, atIndex, fromWindowInstanceId, true); + moveTabAction(info, tab, atIndex); } else { Log.w(TAG, "DnD: InstanceInfo of Chrome Window not found."); } @@ -995,32 +980,35 @@ return null; } - private boolean canCloseEmptyChromeWindow(int windowInstanceId) { + /** + * Determine if a Chrome instance can be closed based on the environment. + * + * @param instanceId Instance Id of the Chrome window that needs to be closed. + */ + private boolean canCloseChromeWindow(int instanceId) { // Close the source instance window after reparenting if permitted by the feature flag and // the source instance is known. - if (TabUiFeatureUtilities.isTabDragAsWindowEnabled() - && windowInstanceId != INVALID_INSTANCE_ID) { - TabModelSelector selector = - TabWindowManagerSingleton.getInstance() - .getTabModelSelectorById(windowInstanceId); - // Lastly determine if the drag source Chrome instance window has any tabs including - // incognito ones left so as to close if it is empty. - return selector.getTotalTabCount() == 0; - } - return false; + return TabUiFeatureUtilities.isTabDragAsWindowEnabled() + && instanceId != INVALID_INSTANCE_ID; } - private void closeEmptyChromeWindowAsynchronously( - final int instanceId, long delayInMilliseconds) { - new Handler(Looper.getMainLooper()) - // Posting the message to process at the end of the current event queue. - // Delay is needed for closing the instance during drag and drop as the - // DragEvent.ACTION_DRAG_ENDED requires processing in the source instance. - .postDelayed( - () -> { - Log.i(TAG, "Closing empty Chrome instance as no tabs exist."); - closeInstance(instanceId, INVALID_TASK_ID); - }, - delayInMilliseconds); + /** + * Close a Chrome window instance only if it contains no open tabs including incognito ones. + * + * @param instanceId Instance id of the Chrome window that needs to be closed. + */ + @Override + public void closeChromeWindowIfEmpty(int instanceId) { + if (canCloseChromeWindow(instanceId)) { + TabModelSelector selector = + TabWindowManagerSingleton.getInstance().getTabModelSelectorById(instanceId); + // Determine if the drag source Chrome instance window has any tabs including incognito + // ones + // left so as to close if it is empty. + if (selector.getTotalTabCount() == 0) { + Log.i(TAG, "Closing empty Chrome instance as no tabs exist."); + closeInstance(instanceId, INVALID_TASK_ID); + } + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 3be78a8..7b8be25 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -42,7 +42,6 @@ import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; -import org.chromium.chrome.browser.download.DownloadManagerService; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.feature_guide.notifications.FeatureNotificationUtils; import org.chromium.chrome.browser.feature_guide.notifications.FeatureType; @@ -71,7 +70,6 @@ import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.profiles.ProfileKey; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.search_resumption.SearchResumptionModuleCoordinator; import org.chromium.chrome.browser.search_resumption.SearchResumptionModuleUtils; @@ -534,9 +532,6 @@ }); mBrowserControlsStateProvider.addObserver(this); - DownloadManagerService.getDownloadManagerService() - .checkForExternallyRemovedDownloads(ProfileKey.getLastUsedRegularProfileKey()); - mToolbarHeight = activity.getResources().getDimensionPixelSize(R.dimen.toolbar_height_no_shadow);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSourceTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSourceTest.java index be9ffc3..b82f32d 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSourceTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSourceTest.java
@@ -478,8 +478,7 @@ verify(mSourceStripLayoutHelper, times(1)).onUpOrCancel(anyLong()); // Verify tab is not moved. verify(mSourceMultiInstanceManager, times(0)).moveTabToNewWindow(mTabBeingDragged); - verify(mSourceMultiInstanceManager, times(0)) - .moveTabToWindow(any(), any(), anyInt(), anyInt()); + verify(mSourceMultiInstanceManager, times(0)).moveTabToWindow(any(), any(), anyInt()); // Verify clear. verify(mSourceStripLayoutHelper, times(1)).clearTabDragState(); // Verify destination strip not invoked. @@ -516,8 +515,7 @@ .clearForTabDrop(anyLong(), anyBoolean(), anyBoolean()); // Verify tab is not moved since drop is on source toolbar. verify(mSourceMultiInstanceManager, times(0)).moveTabToNewWindow(mTabBeingDragged); - verify(mSourceMultiInstanceManager, times(0)) - .moveTabToWindow(any(), any(), anyInt(), anyInt()); + verify(mSourceMultiInstanceManager, times(0)).moveTabToWindow(any(), any(), anyInt()); // Verify tab cleared. verify(mSourceStripLayoutHelper, times(1)).clearTabDragState(); // Verify destination strip not invoked. @@ -546,8 +544,7 @@ .clearForTabDrop(anyLong(), anyBoolean(), anyBoolean()); // Verify tab is not moved since drop is outside strip. verify(mSourceMultiInstanceManager, times(0)).moveTabToNewWindow(mTabBeingDragged); - verify(mSourceMultiInstanceManager, times(0)) - .moveTabToWindow(any(), any(), anyInt(), anyInt()); + verify(mSourceMultiInstanceManager, times(0)).moveTabToWindow(any(), any(), anyInt()); // Verify tab cleared. verify(mSourceStripLayoutHelper, times(1)).clearTabDragState(); // Verify destination strip not invoked. @@ -596,7 +593,7 @@ // Verify - Tab moved to destination window at TAB_INDEX. verify(mDestMultiInstanceManager, times(1)) - .moveTabToWindow(any(), eq(mTabBeingDragged), eq(TAB_INDEX), eq(CURR_INSTANCE_ID)); + .moveTabToWindow(any(), eq(mTabBeingDragged), eq(TAB_INDEX)); // Verify tab cleared. verify(mSourceStripLayoutHelper, times(1)).clearTabDragState(); // Verify destination strip calls. @@ -630,7 +627,7 @@ // Verify - Tab moved to destination window at end. verify(mDestMultiInstanceManager, times(1)) - .moveTabToWindow(any(), eq(mTabBeingDragged), eq(5), eq(CURR_INSTANCE_ID)); + .moveTabToWindow(any(), eq(mTabBeingDragged), eq(5)); assertNotNull(ShadowToast.getLatestToast()); TextView textView = (TextView) ShadowToast.getLatestToast().getView(); @@ -696,8 +693,7 @@ .clearForTabDrop(anyLong(), anyBoolean(), anyBoolean()); // Verify tab is not moved since drop is on source toolbar. verify(mSourceMultiInstanceManager, times(0)).moveTabToNewWindow(mTabBeingDragged); - verify(mSourceMultiInstanceManager, times(0)) - .moveTabToWindow(any(), any(), anyInt(), anyInt()); + verify(mSourceMultiInstanceManager, times(0)).moveTabToWindow(any(), any(), anyInt()); // Verify tab cleared. verify(mSourceStripLayoutHelper, times(1)).clearTabDragState(); histogramExpectation.assertExpected(); @@ -730,8 +726,7 @@ verify(mSourceStripLayoutHelper, times(1)).onUpOrCancel(anyLong()); // Verify tab is not moved. verify(mSourceMultiInstanceManager, times(0)).moveTabToNewWindow(mTabBeingDragged); - verify(mSourceMultiInstanceManager, times(0)) - .moveTabToWindow(any(), any(), anyInt(), anyInt()); + verify(mSourceMultiInstanceManager, times(0)).moveTabToWindow(any(), any(), anyInt()); // Verify clear. verify(mSourceStripLayoutHelper, times(1)).clearTabDragState(); // Verify destination strip not invoked. @@ -778,7 +773,7 @@ // Verify - Move to new window not invoked. verify(mDestMultiInstanceManager, times(0)) - .moveTabToWindow(any(), eq(mTabBeingDragged), anyInt(), anyInt()); + .moveTabToWindow(any(), eq(mTabBeingDragged), anyInt()); histogramExpectation.assertExpected(); } @@ -805,7 +800,7 @@ // Verify - Tab is not moved to destination window. verify(mDestMultiInstanceManager, times(0)) - .moveTabToWindow(any(), eq(mTabBeingDragged), anyInt(), anyInt()); + .moveTabToWindow(any(), eq(mTabBeingDragged), anyInt()); assertNull(ShadowToast.getLatestToast()); histogramExpectation.assertExpected();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java index 6ec0f46..8496a3b1d 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java
@@ -1131,15 +1131,13 @@ Mockito.doNothing() .when(mMultiInstanceManager) - .moveTabAction(any(), eq(mTab1), eq(tabAtIndex), anyInt(), eq(true)); + .moveTabAction(any(), eq(mTab1), eq(tabAtIndex)); // Action - mMultiInstanceManager.moveTabToWindow( - mTabbedActivityTask63, mTab1, tabAtIndex, INSTANCE_ID_1); + mMultiInstanceManager.moveTabToWindow(mTabbedActivityTask63, mTab1, tabAtIndex); // Verify moveTabAction and getCurrentInstanceInfo are each called once. - verify(mMultiInstanceManager, times(1)) - .moveTabAction(any(), eq(mTab1), eq(tabAtIndex), anyInt(), eq(true)); + verify(mMultiInstanceManager, times(1)).moveTabAction(any(), eq(mTab1), eq(tabAtIndex)); verify(mMultiInstanceManager, times(1)).getInstanceInfoFor(any()); } @@ -1154,15 +1152,13 @@ INSTANCE_ID_1, TASK_ID_62, List.of(mTab1, mTab2, mTab3))); Mockito.doNothing() .when(multiInstanceManager) - .moveTabAction(any(), eq(mTab2), eq(tabAtIndex), anyInt(), eq(false)); + .moveTabAction(any(), eq(mTab2), eq(tabAtIndex)); // Action - multiInstanceManager.moveTabToWindow( - mTabbedActivityTask62, mTab2, tabAtIndex, INSTANCE_ID_1); + multiInstanceManager.moveTabToWindow(mTabbedActivityTask62, mTab2, tabAtIndex); // Verify moveTabAction is not called. - verify(multiInstanceManager, times(0)) - .moveTabAction(any(), eq(mTab2), eq(tabAtIndex), anyInt(), eq(false)); + verify(multiInstanceManager, times(0)).moveTabAction(any(), eq(mTab2), eq(tabAtIndex)); } @Test @@ -1177,7 +1173,7 @@ // Action InstanceInfo info = mMultiInstanceManager.getInstanceInfoFor(mTabbedActivityTask63); - mMultiInstanceManager.moveTabAction(info, mTab1, /* atIndex= */ 0, INSTANCE_ID_1, true); + mMultiInstanceManager.moveTabAction(info, mTab1, /* atIndex= */ 0); // Verify reparentTabToRunningActivity is called once. verify(mMultiInstanceManager, times(1)) @@ -1223,7 +1219,7 @@ 0, false); - mMultiInstanceManager.moveTabAction(info, mTab1, /* atIndex= */ 0, INSTANCE_ID_1, true); + mMultiInstanceManager.moveTabAction(info, mTab1, /* atIndex= */ 0); // Verify moveAndReparentTabToNewWindow is called made with desired parameters once. The // method is validated in integration test here @@ -1235,4 +1231,43 @@ verify(mMultiInstanceManager, times(0)) .reparentTabToRunningActivity(any(), eq(mTab1), eq(0)); } + + @Test + @UiThreadTest + @EnableFeatures(ChromeFeatureList.TAB_DRAG_DROP_ANDROID) + @Config(sdk = 31) + public void testTabMove_CloseChromeWindowIfEmpty_closed() { + mMultiInstanceManager.mTestBuildInstancesList = true; + MultiWindowTestUtils.enableMultiInstance(); + // Create an empty instance before asking it to close. The flag that provides permission to + // close is enabled. + assertEquals(INSTANCE_ID_1, allocInstanceIndex(INSTANCE_ID_1, mTabbedActivityTask62, true)); + assertEquals(1, mMultiInstanceManager.getInstanceInfo().size()); + + // Action + mMultiInstanceManager.closeChromeWindowIfEmpty(INSTANCE_ID_1); + + // Verify moveTabAction and getCurrentInstanceInfo are each called once. + verify(mMultiInstanceManager, times(1)) + .closeInstance(anyInt(), eq(MultiWindowUtils.INVALID_TASK_ID)); + } + + @Test + @UiThreadTest + @DisableFeatures(ChromeFeatureList.TAB_DRAG_DROP_ANDROID) + @Config(sdk = 31) + public void testTabMove_CloseChromeWindowIfEmpty_notClosed() { + mMultiInstanceManager.mTestBuildInstancesList = true; + MultiWindowTestUtils.enableMultiInstance(); + // Create an empty instance before asking it to close. The flag that provides permission to + // close is disabled. + assertEquals(INSTANCE_ID_1, allocInstanceIndex(INSTANCE_ID_1, mTabbedActivityTask62, true)); + assertEquals(1, mMultiInstanceManager.getInstanceInfo().size()); + + // Action + mMultiInstanceManager.closeChromeWindowIfEmpty(INSTANCE_ID_1); + + // Verify moveTabAction and getCurrentInstanceInfo are each called once. + verify(mMultiInstanceManager, times(0)).closeInstance(anyInt(), anyInt()); + } }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 162bc89..a1ab750 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6404,6 +6404,9 @@ <message name="IDS_EXTENSIONS_MENU_MESSAGE_SECTION_RESTRICTED_ACCESS_TEXT" desc="Text of the message section when this site is restricted to all extensions."> No extensions need access to this site </message> + <message name="IDS_EXTENSIONS_MENU_MESSAGE_SECTION_POLICY_BLOCKED_ACCESS_TEXT" desc="Text of the message section when the site is restricted to all non-enterprise extensions."> + Extensions are not allowed on this site + </message> <message name="IDS_EXTENSIONS_MENU_MESSAGE_SECTION_USER_BLOCKED_ACCESS_TEXT" desc="Text of the message section when the user blocked access to this site to all extensions."> Extensions are not allowed on this site </message> @@ -10804,45 +10807,24 @@ Learn more about tab group suggestions </message> <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SIGNED_OUT" desc="The body text for the not started state in the tab organization UI, when not signed in"> - Sign in and turn on sync to let Chrome suggest tab groups and keep your tabs organized - </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED" desc="The body text for the not started state in the tab organization UI, when signed in but unsynced"> - Turn on sync to let Chrome suggest tab groups and keep your tabs organized - </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED_HISTORY" desc="The body text for the not started state in the tab organization UI, when history sync is disabled"> - Turn on History sync in Settings to let Chrome suggest tab groups and keep your tabs organized - </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SYNC_PAUSED" desc="The body text for the not started state in the tab organization UI, sync is paused"> Sign in to let Chrome suggest tab groups and keep your tabs organized </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON" desc="The label for the button in the not started state of the tab organization UI, when synced"> + <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON" desc="The label for the button in the not started state of the tab organization UI, when signed in"> Check now </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_FRE" desc="The first run experience label for the button in the not started state of the tab organization UI, when synced"> + <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_FRE" desc="The first run experience label for the button in the not started state of the tab organization UI, when signed in"> Let's go </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED" desc="The label for the button in the not started state of the tab organization UI, when not signed in or signed in but unsynced"> - Turn on sync - </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_HISTORY" desc="The label for the button in the not started state of the tab organization UI, when history sync is disabled"> - Settings - </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SYNC_PAUSED" desc="The label for the button in the not started state of the tab organization UI, when sync is paused"> + <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SIGNED_OUT" desc="The label for the button in the not started state of the tab organization UI, when not signed in"> Sign in </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_ARIA_LABEL" desc="The a11y label for the button in the not started state of the tab organization UI, when synced" is_accessibility_with_no_ui="true"> + <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_ARIA_LABEL" desc="The a11y label for the button in the not started state of the tab organization UI, when signed in" is_accessibility_with_no_ui="true"> Check now if tabs can be organized </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_FRE_ARIA_LABEL" desc="The first run experience a11y label for the button in the not started state of the tab organization UI, when synced" is_accessibility_with_no_ui="true"> + <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_FRE_ARIA_LABEL" desc="The first run experience a11y label for the button in the not started state of the tab organization UI, when signed in" is_accessibility_with_no_ui="true"> Let's go and organize your tabs </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_ARIA_LABEL" desc="The a11y label for the button in the not started state of the tab organization UI, when not signed in or signed in but unsynced" is_accessibility_with_no_ui="true"> - Turn on sync to let Chrome suggest tab groups - </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_HISTORY_ARIA_LABEL" desc="The a11y label for the button in the not started state of the tab organization UI, when history sync is disabled" is_accessibility_with_no_ui="true"> - Open settings to let Chrome suggest tab groups - </message> - <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SYNC_PAUSED_ARIA_LABEL" desc="The a11y label for the button in the not started state of the tab organization UI, when sync is paused" is_accessibility_with_no_ui="true"> + <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SIGNED_OUT_ARIA_LABEL" desc="The a11y label for the button in the not started state of the tab organization UI, when not signed in" is_accessibility_with_no_ui="true"> Sign in to let Chrome suggest tab groups </message> <message name="IDS_TAB_ORGANIZATION_IN_PROGRESS_TITLE" desc="The header text for the in progress state in the tab organization UI">
diff --git a/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_MESSAGE_SECTION_POLICY_BLOCKED_ACCESS_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_MESSAGE_SECTION_POLICY_BLOCKED_ACCESS_TEXT.png.sha1 new file mode 100644 index 0000000..3722c20 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_MESSAGE_SECTION_POLICY_BLOCKED_ACCESS_TEXT.png.sha1
@@ -0,0 +1 @@ +9781c8bf768b7ae3a705476eee9afadbebdf9434 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SIGNED_OUT.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SIGNED_OUT.png.sha1 index 3cce170..bfb6f7e 100644 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SIGNED_OUT.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SIGNED_OUT.png.sha1
@@ -1 +1 @@ -229d5d94f765211db84552b420734b2b414350c6 \ No newline at end of file +dc79c4fc4f970e8152b9ea60ee0e1cb4aa6984fe \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SYNC_PAUSED.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SYNC_PAUSED.png.sha1 deleted file mode 100644 index acecd83..0000000 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SYNC_PAUSED.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -aefddc2ca85392563aac0b8b121109b4bb8983b4 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED.png.sha1 deleted file mode 100644 index 738a73b9..0000000 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9db679e9293cdc7b8abe42195e49f6ef183348cf \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED_HISTORY.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED_HISTORY.png.sha1 deleted file mode 100644 index 4107492..0000000 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED_HISTORY.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -2242a9208af02e6f0ca4e650c967b96df8e08a54 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SIGNED_OUT.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SIGNED_OUT.png.sha1 new file mode 100644 index 0000000..bfb6f7e --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SIGNED_OUT.png.sha1
@@ -0,0 +1 @@ +dc79c4fc4f970e8152b9ea60ee0e1cb4aa6984fe \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SYNC_PAUSED.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SYNC_PAUSED.png.sha1 deleted file mode 100644 index acecd83..0000000 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SYNC_PAUSED.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -aefddc2ca85392563aac0b8b121109b4bb8983b4 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED.png.sha1 deleted file mode 100644 index 738a73b9..0000000 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9db679e9293cdc7b8abe42195e49f6ef183348cf \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_HISTORY.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_HISTORY.png.sha1 deleted file mode 100644 index 4107492..0000000 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_HISTORY.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -2242a9208af02e6f0ca4e650c967b96df8e08a54 \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 6eefb9c2..180a1b3 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4819,6 +4819,9 @@ flag_descriptions::kInstallIsolatedWebAppFromUrlDescription, kOsAll, ORIGIN_LIST_VALUE_TYPE(switches::kInstallIsolatedWebAppFromUrl, "")}, #endif + {"enable-controlled-frame", flag_descriptions::kEnableControlledFrameName, + flag_descriptions::kEnableControlledFrameDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kControlledFrame)}, {"isolate-origins", flag_descriptions::kIsolateOriginsName, flag_descriptions::kIsolateOriginsDescription, kOsAll, ORIGIN_LIST_VALUE_TYPE(switches::kIsolateOrigins, "")},
diff --git a/chrome/browser/android/persisted_tab_data/persisted_tab_data_android_browsertest.cc b/chrome/browser/android/persisted_tab_data/persisted_tab_data_android_browsertest.cc index 538c0cca..247b1db 100644 --- a/chrome/browser/android/persisted_tab_data/persisted_tab_data_android_browsertest.cc +++ b/chrome/browser/android/persisted_tab_data/persisted_tab_data_android_browsertest.cc
@@ -177,6 +177,12 @@ OnDeferredStartup(); content::RunAllTasksUntilIdle(); + if (!tab_android()->GetUserData(FooPersistedTabDataAndroid::UserDataKey())) { + tab_android()->SetUserData( + FooPersistedTabDataAndroid::UserDataKey(), + std::make_unique<FooPersistedTabDataAndroid>(tab_android())); + } + FooPersistedTabDataAndroid* foo_persisted_tab_data_android = static_cast<FooPersistedTabDataAndroid*>(tab_android()->GetUserData( FooPersistedTabDataAndroid::UserDataKey()));
diff --git a/chrome/browser/apps/app_service/policy_util.cc b/chrome/browser/apps/app_service/policy_util.cc index 2a72e3a..71b30ae8 100644 --- a/chrome/browser/apps/app_service/policy_util.cc +++ b/chrome/browser/apps/app_service/policy_util.cc
@@ -63,7 +63,8 @@ {"os_url_handler", ash::SystemWebAppType::OS_URL_HANDLER}, {"firmware_update", ash::SystemWebAppType::FIRMWARE_UPDATE}, {"os_flags", ash::SystemWebAppType::OS_FLAGS}, - {"vc_background", ash::SystemWebAppType::VC_BACKGROUND}}); + {"vc_background", ash::SystemWebAppType::VC_BACKGROUND}, + {"print_preview_cros", ash::SystemWebAppType::PRINT_PREVIEW_CROS}}); constexpr ash::SystemWebAppType GetMaxSystemWebAppType() { return base::ranges::max(kSystemWebAppsMapping, base::ranges::less{},
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 2f0043f..7062c0da 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -3407,6 +3407,8 @@ "system_web_apps/apps/personalization_app/wallpaper_metrics_provider.h", "system_web_apps/apps/print_management_web_app_info.cc", "system_web_apps/apps/print_management_web_app_info.h", + "system_web_apps/apps/print_preview_cros_system_web_app_info.cc", + "system_web_apps/apps/print_preview_cros_system_web_app_info.h", "system_web_apps/apps/projector_app/untrusted_projector_annotator_ui_config.cc", "system_web_apps/apps/projector_app/untrusted_projector_annotator_ui_config.h", "system_web_apps/apps/projector_app/untrusted_projector_ui_config.cc", @@ -3618,6 +3620,8 @@ "//ash/webui/os_feedback_ui/backend", "//ash/webui/personalization_app", "//ash/webui/personalization_app/mojom", + "//ash/webui/print_preview_cros", + "//ash/webui/print_preview_cros:url_constants", "//ash/webui/projector_app", "//ash/webui/scanning", "//ash/webui/scanning/mojom", @@ -4014,6 +4018,8 @@ "//ash/webui/print_management", "//ash/webui/print_management/backend:backend", "//ash/webui/print_management/resources", + "//ash/webui/print_preview_cros", + "//ash/webui/print_preview_cros/resources:resources", "//ash/webui/projector_app/public/cpp", "//ash/webui/resources:camera_app_resources", "//ash/webui/resources:demo_mode_app_resources",
diff --git a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc index d64996ca..8bf404ef 100644 --- a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc
@@ -512,8 +512,6 @@ // Validating decoded content does not fit well for unit tests. ArcAppIcon::DisableSafeDecodingForTesting(); - - scoped_feature_list_.InitAndEnableFeature(arc::kPerAppLanguage); } void TearDown() override { @@ -876,8 +874,6 @@ prefs->SimulateDefaultAppAvailabilityTimeoutForTesting(); } - void ResetFeatureFlag() { scoped_feature_list_.Reset(); } - AppListControllerDelegate* controller() { return controller_.get(); } TestingProfile* profile() { return profile_.get(); } @@ -920,7 +916,6 @@ scoped_callback_; std::unique_ptr<ChromeShelfController> shelf_controller_; std::unique_ptr<ash::ShelfModel> model_; - base::test::ScopedFeatureList scoped_feature_list_; }; class ArcAppModelBuilderRecreate : public ArcAppModelBuilderTest { @@ -1455,7 +1450,8 @@ TEST_P(ArcAppModelBuilderTest, ArcPackagePref_PerAppLanguageFlagDisabled) { ValidateHavePackages({}); - ResetFeatureFlag(); + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(arc::kPerAppLanguage); app_instance()->SendRefreshPackageList( ArcAppTest::ClonePackages(fake_packages()));
diff --git a/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.cc b/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.cc index e2bb49f..6a7a2ed 100644 --- a/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.cc +++ b/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ash/app_list/search/essential_search/essential_search_manager.h" +#include "base/check_is_test.h" #include "base/time/time.h" #include "chrome/browser/ash/app_list/search/essential_search/socs_cookie_fetcher.h" #include "chrome/browser/ash/profiles/profile_helper.h" @@ -47,8 +48,12 @@ retry_backoff_(&kFetchSocsCookieRetryBackoffPolicy) { DCHECK(primary_profile_); auto* session_controller = ash::SessionController::Get(); - CHECK(session_controller); - scoped_observation_.Observe(session_controller); + if (!session_controller) { + CHECK_IS_TEST(); + } else { + CHECK(session_controller); + session_controller->AddObserver(this); + } // Listen to pref changes. pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); @@ -60,12 +65,19 @@ // Handle the case where EssentialSearchManager is initialized after the // session was started. - if (session_manager::SessionManager::Get()->IsSessionStarted()) { + if (!session_manager::SessionManager::Get()) { + CHECK_IS_TEST(); + } else if (session_manager::SessionManager::Get()->IsSessionStarted()) { MaybeFetchSocsCookie(); } } -EssentialSearchManager::~EssentialSearchManager() = default; +EssentialSearchManager::~EssentialSearchManager() { + auto* session_controller = ash::SessionController::Get(); + if (session_controller) { + session_controller->RemoveObserver(this); + } +} // static std::unique_ptr<EssentialSearchManager> EssentialSearchManager::Create( @@ -73,10 +85,6 @@ return std::make_unique<EssentialSearchManager>(primary_profile); } -void EssentialSearchManager::OnChromeTerminating() { - scoped_observation_.Reset(); -} - void EssentialSearchManager::OnSessionStateChanged( session_manager::SessionState state) { // EssentialSearchManager only update SOCS cookie when user sign in/unlock the
diff --git a/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.h b/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.h index 5255c55..a853f646 100644 --- a/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.h +++ b/chrome/browser/ash/app_list/search/essential_search/essential_search_manager.h
@@ -46,7 +46,6 @@ // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; - void OnChromeTerminating() override; // SocsCookieFetcher::Consumer void OnCookieFetched(const std::string& socs_cookie) override; @@ -69,10 +68,6 @@ // Cancel all active requests void CancelPendingRequests(); - // Used to observe the change in session state. - base::ScopedObservation<ash::SessionController, ash::SessionObserver> - scoped_observation_{this}; - // Observer for EssentialSearch-related prefs. std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
diff --git a/chrome/browser/ash/app_restore/full_restore_service.cc b/chrome/browser/ash/app_restore/full_restore_service.cc index 8311048b7..208ab14 100644 --- a/chrome/browser/ash/app_restore/full_restore_service.cc +++ b/chrome/browser/ash/app_restore/full_restore_service.cc
@@ -15,7 +15,7 @@ #include "ash/webui/settings/public/constants/setting.mojom-shared.h" #include "ash/wm/desks/templates/saved_desk_controller.h" #include "ash/wm/window_restore/pine_contents_data.h" -#include "ash/wm/window_restore/window_restore_controller.h" +#include "ash/wm/window_restore/pine_controller.h" #include "ash/wm/window_restore/window_restore_util.h" #include "base/command_line.h" #include "base/metrics/histogram_functions.h" @@ -88,6 +88,30 @@ } } +std::unique_ptr<PineContentsData> CreatePineContentsData( + ::app_restore::RestoreData* restore_data, + bool last_session_crashed) { + auto pine_contents_data = std::make_unique<PineContentsData>(); + pine_contents_data->last_session_crashed = last_session_crashed; + + // Retrieve app id's from `restore_data`. There can be multiple entries with + // the same app id, these denote different windows. + // TODO(sammiequon): App id's for PWAs are stored in the full restore file + // with the chrome browser app id. We need to get the app name from the + // session restore. + // TODO(sammiequon): Retrieve the browser tab info from session restore. + // TODO(sammiequon): Order these by activation index. + for (const auto& [app_id, launch_list] : + restore_data->app_id_to_launch_list()) { + for (size_t i = 0; i < launch_list.size(); ++i) { + pine_contents_data->apps_infos.emplace_back( + app_id, /*tab_title=*/"", + /*tab_urls=*/std::vector<std::string>()); + } + } + return pine_contents_data; +} + } // namespace bool g_restore_for_testing = true; @@ -131,15 +155,11 @@ ~DelegateImpl() override = default; void MaybeStartPineOverviewSession( - std::unique_ptr<::app_restore::RestoreData> restore_data) override { + std::unique_ptr<PineContentsData> pine_contents_data) override { // A unit test that does not override this default delegate may not have ash // shell. if (Shell::HasInstance()) { - // TODO(sammiequon): Instead of passing the whole restore data, we should - // pull out the data we need. - auto pine_contents_data = std::make_unique<PineContentsData>(); - pine_contents_data->restore_data = std::move(restore_data); - Shell::Get()->window_restore_controller()->MaybeStartPineOverviewSession( + Shell::Get()->pine_controller()->MaybeStartPineOverviewSession( std::move(pine_contents_data)); } } @@ -480,8 +500,10 @@ // session restore to help set the browser saving flag. ExitTypeService* exit_type_service = ExitTypeService::GetInstanceForProfile(profile_); - if (id == kRestoreForCrashNotificationId && exit_type_service) + const bool last_session_crashed = id == kRestoreForCrashNotificationId; + if (last_session_crashed && exit_type_service) { crashed_lock_ = exit_type_service->CreateCrashedLock(); + } if (Shell::HasInstance()) { Shell::Get() @@ -491,8 +513,8 @@ if (features::IsForestFeatureEnabled()) { CHECK(delegate_); - delegate_->MaybeStartPineOverviewSession( - app_launch_handler_->restore_data()->Clone()); + delegate_->MaybeStartPineOverviewSession(CreatePineContentsData( + app_launch_handler_->restore_data(), last_session_crashed)); // Set to true as we might want to show the post reboot notification. show_notification = true; return;
diff --git a/chrome/browser/ash/app_restore/full_restore_service.h b/chrome/browser/ash/app_restore/full_restore_service.h index 60871e2..3c984956 100644 --- a/chrome/browser/ash/app_restore/full_restore_service.h +++ b/chrome/browser/ash/app_restore/full_restore_service.h
@@ -21,15 +21,15 @@ class Profile; -namespace app_restore { -class RestoreData; -} // namespace app_restore - namespace message_center { class Notification; } // namespace message_center -namespace ash::full_restore { +namespace ash { + +struct PineContentsData; + +namespace full_restore { class FullRestoreAppLaunchHandler; class FullRestoreDataHandler; @@ -78,7 +78,7 @@ virtual ~Delegate() = default; // Starts overview with the pine dialog unless overview is already active. virtual void MaybeStartPineOverviewSession( - std::unique_ptr<::app_restore::RestoreData> restore_data) = 0; + std::unique_ptr<PineContentsData> pine_contents_data) = 0; }; static FullRestoreService* GetForProfile(Profile* profile); @@ -210,6 +210,8 @@ ~ScopedRestoreForTesting(); }; -} // namespace ash::full_restore +} // namespace full_restore + +} // namespace ash #endif // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_SERVICE_H_
diff --git a/chrome/browser/ash/app_restore/full_restore_service_unittest.cc b/chrome/browser/ash/app_restore/full_restore_service_unittest.cc index a0a472d..8d71592c 100644 --- a/chrome/browser/ash/app_restore/full_restore_service_unittest.cc +++ b/chrome/browser/ash/app_restore/full_restore_service_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/constants/ash_switches.h" +#include "ash/wm/window_restore/pine_contents_data.h" #include "ash/wm/window_restore/window_restore_util.h" #include "base/command_line.h" #include "base/files/scoped_temp_dir.h" @@ -107,7 +108,7 @@ MOCK_METHOD(void, MaybeStartPineOverviewSession, - (std::unique_ptr<::app_restore::RestoreData> restore_data), + (std::unique_ptr<ash::PineContentsData> restore_data), (override)); }; @@ -618,33 +619,6 @@ FullRestoreService::MaybeCloseNotification(profile()); } -// TODO(sammiequon): These forest tests should be either parameterized or use -// their own suite, once the direction is more clear. -TEST_F(FullRestoreServiceTestHavingFullRestoreFile, - AskEveryTimeAndRestoreForest) { - base::test::ScopedFeatureList scoped_feature_list_{features::kForestFeature}; - switches::SetIgnoreForestSecretKeyForTest(true); - - profile()->GetPrefs()->SetInteger( - prefs::kRestoreAppsAndPagesPrefName, - static_cast<int>(RestoreOption::kAskEveryTime)); - auto mock_delegate = std::make_unique<MockFullRestoreServiceDelegate>(); - EXPECT_CALL(*mock_delegate, MaybeStartPineOverviewSession(testing::_)) - .Times(1); - CreateFullRestoreServiceForTesting(std::move(mock_delegate)); - - // The notification should not show up anymore with forest enabled. - VerifyRestoreInitSettingHistogram(RestoreOption::kAskEveryTime, 1); - VerifyNotification(/*has_crash_notification=*/false, - /*has_restore_notification=*/false); - - EXPECT_EQ(RestoreOption::kAskEveryTime, GetRestoreOption()); - EXPECT_TRUE(CanPerformRestore(account_id())); - EXPECT_TRUE(allow_save()); - - switches::SetIgnoreForestSecretKeyForTest(false); -} - // If the OS restore setting is 'Ask every time', after reboot, show the restore // notification, and verify the restore flag when click the Settings button. TEST_F(FullRestoreServiceTestHavingFullRestoreFile, AskEveryTimeAndSettings) { @@ -782,6 +756,71 @@ EXPECT_FALSE(CanPerformRestore(account_id())); } +class ForestFullRestoreServiceTestHavingFullRestoreFile + : public FullRestoreServiceTestHavingFullRestoreFile { + protected: + ForestFullRestoreServiceTestHavingFullRestoreFile() = default; + ForestFullRestoreServiceTestHavingFullRestoreFile( + const ForestFullRestoreServiceTestHavingFullRestoreFile&) = delete; + ForestFullRestoreServiceTestHavingFullRestoreFile& operator=( + const ForestFullRestoreServiceTestHavingFullRestoreFile&) = delete; + ~ForestFullRestoreServiceTestHavingFullRestoreFile() override = default; + + void SetUp() override { + switches::SetIgnoreForestSecretKeyForTest(true); + FullRestoreServiceTestHavingFullRestoreFile::SetUp(); + } + + void TearDown() override { + switches::SetIgnoreForestSecretKeyForTest(false); + FullRestoreServiceTestHavingFullRestoreFile::TearDown(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_{features::kForestFeature}; +}; + +// If the system is crash, the delegate is notified. +TEST_F(ForestFullRestoreServiceTestHavingFullRestoreFile, CrashAndRestore) { + ExitTypeService::GetInstanceForProfile(profile()) + ->SetLastSessionExitTypeForTest(ExitType::kCrashed); + + auto mock_delegate = std::make_unique<MockFullRestoreServiceDelegate>(); + EXPECT_CALL(*mock_delegate, MaybeStartPineOverviewSession(testing::_)) + .WillOnce([](std::unique_ptr<PineContentsData> data) { + ASSERT_TRUE(data); + EXPECT_TRUE(data->last_session_crashed); + }); + CreateFullRestoreServiceForTesting(std::move(mock_delegate)); + + // The notification should not show up anymore with forest enabled. + VerifyNotification(/*has_crash_notification=*/false, + /*has_restore_notification=*/false); + + EXPECT_TRUE(CanPerformRestore(account_id())); + EXPECT_TRUE(allow_save()); +} + +TEST_F(ForestFullRestoreServiceTestHavingFullRestoreFile, + AskEveryTimeAndRestore) { + profile()->GetPrefs()->SetInteger( + prefs::kRestoreAppsAndPagesPrefName, + static_cast<int>(RestoreOption::kAskEveryTime)); + auto mock_delegate = std::make_unique<MockFullRestoreServiceDelegate>(); + EXPECT_CALL(*mock_delegate, MaybeStartPineOverviewSession(testing::_)) + .Times(1); + CreateFullRestoreServiceForTesting(std::move(mock_delegate)); + + // The notification should not show up anymore with forest enabled. + VerifyRestoreInitSettingHistogram(RestoreOption::kAskEveryTime, 1); + VerifyNotification(/*has_crash_notification=*/false, + /*has_restore_notification=*/false); + + EXPECT_EQ(RestoreOption::kAskEveryTime, GetRestoreOption()); + EXPECT_TRUE(CanPerformRestore(account_id())); + EXPECT_TRUE(allow_save()); +} + class FullRestoreServiceMultipleUsersTest : public FullRestoreServiceTestHavingFullRestoreFile { protected:
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_edit_view.cc b/chrome/browser/ash/arc/input_overlay/ui/action_edit_view.cc index dae1498..d4d67ff 100644 --- a/chrome/browser/ash/arc/input_overlay/ui/action_edit_view.cc +++ b/chrome/browser/ash/arc/input_overlay/ui/action_edit_view.cc
@@ -66,7 +66,9 @@ : kNameTagAndLabelsPaddingForButtonOptionsMenu; container ->AddColumn(/*h_align=*/views::LayoutAlignment::kStart, - /*v_align=*/views::LayoutAlignment::kStart, + /*v_align=*/ + for_editing_list ? views::LayoutAlignment::kCenter + : views::LayoutAlignment::kStart, /*horizontal_resize=*/1.0f, /*size_type=*/views::TableLayout::ColumnSize::kUsePreferred, /*fixed_width=*/0, /*min_width=*/0)
diff --git a/chrome/browser/ash/arc/input_overlay/ui/edit_label.cc b/chrome/browser/ash/arc/input_overlay/ui/edit_label.cc index 7af5d2ab..b23023dc 100644 --- a/chrome/browser/ash/arc/input_overlay/ui/edit_label.cc +++ b/chrome/browser/ash/arc/input_overlay/ui/edit_label.cc
@@ -38,6 +38,8 @@ constexpr float kCornerRadius = 8.0f; constexpr int kLabelSize = 32; +constexpr ui::ColorId kPenIconColor = cros_tokens::kCrosSysOnPrimaryContainer; + // Pulse animation specs. constexpr int kPulseTimes = 3; constexpr int kPulseExtraHalfSize = 32; @@ -146,10 +148,10 @@ // Clear icon if it is a valid key for new action. SetImageModel(views::Button::STATE_NORMAL, - output_string.empty() ? ui::ImageModel::FromVectorIcon( - kGameControlsEditPenIcon, - cros_tokens::kCrosSysHighlightShape) - : ui::ImageModel()); + output_string.empty() + ? ui::ImageModel::FromVectorIcon(kGameControlsEditPenIcon, + kPenIconColor) + : ui::ImageModel()); // Set text label by `output_string` even it is empty to clear the text label. SetTextLabel(output_string); } @@ -229,10 +231,9 @@ } if (action_->is_new() && GetText().empty()) { - SetImageModel( - views::Button::STATE_NORMAL, - ui::ImageModel::FromVectorIcon(kGameControlsEditPenIcon, - cros_tokens::kCrosSysHighlightShape)); + SetImageModel(views::Button::STATE_NORMAL, + ui::ImageModel::FromVectorIcon(kGameControlsEditPenIcon, + kPenIconColor)); } SetToDefault(); // Reset the error state if an reserved key was pressed.
diff --git a/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc b/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc index 2e78c90..d976ccd2 100644 --- a/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc +++ b/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc
@@ -504,7 +504,25 @@ bool persistent, storage::AsyncFileUtil::StatusCallback callback, storage::WatcherManager::NotificationCallback notification_callback) { - // TODO(b/251698485): Implement it once needed. + // Check if watcher already exists. + const WatcherKey key(entry_watcher, recursive); + const Watchers::iterator it = watchers_.find(key); + if (it != watchers_.end()) { + std::move(callback).Run(base::File::FILE_OK); + return PostAbortableTask( + base::BindOnce(std::move(callback), base::File::FILE_OK)); + } + + // Add watcher. + Watcher* const watcher = &watchers_[key]; + watcher->entry_path = entry_watcher; + watcher->recursive = recursive; + + // Notify observers. + for (auto& observer : observers_) { + observer.OnWatcherListChanged(file_system_info_, watchers_); + } + return PostAbortableTask( base::BindOnce(std::move(callback), base::File::FILE_OK)); } @@ -514,7 +532,18 @@ const base::FilePath& entry_path, bool recursive, storage::AsyncFileUtil::StatusCallback callback) { - // TODO(b/251698485): Implement it once needed. + // Remove watcher. + const WatcherKey key(entry_path, recursive); + const auto it = watchers_.find(key); + if (it != watchers_.end()) { + watchers_.erase(it); + } + + // Notify observers. + for (auto& observer : observers_) { + observer.OnWatcherListChanged(file_system_info_, watchers_); + } + std::move(callback).Run(base::File::FILE_OK); }
diff --git a/chrome/browser/ash/fileapi/external_file_url_loader_factory_unittest.cc b/chrome/browser/ash/fileapi/external_file_url_loader_factory_unittest.cc index 314d78f..beae13b 100644 --- a/chrome/browser/ash/fileapi/external_file_url_loader_factory_unittest.cc +++ b/chrome/browser/ash/fileapi/external_file_url_loader_factory_unittest.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include <memory> +#include <string_view> #include "base/functional/bind.h" #include "chrome/browser/ash/file_system_provider/fake_extension_provider.h" @@ -190,7 +191,7 @@ std::string response_body; ASSERT_TRUE(mojo::BlockingCopyToString(client.response_body_release(), &response_body)); - EXPECT_EQ(base::StringPiece(kExpectedFileContents).substr(3, 3), + EXPECT_EQ(std::string_view(kExpectedFileContents).substr(3, 3), response_body); }
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc index 4c49a850..4c768b0 100644 --- a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc +++ b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
@@ -718,6 +718,20 @@ SetAndVerifyInvalidRetailerNameAndStoreNumber("ValidRetailer", ""); SetAndVerifyInvalidRetailerNameAndStoreNumber("ValidRetailer", "1234a"); SetAndVerifyInvalidRetailerNameAndStoreNumber("ValidRetailer", "12-34"); + // Have the store number numerical but have 257 characters + SetAndVerifyInvalidRetailerNameAndStoreNumber( + "ValidRetailer", + "257257257257257257257257257257257257257257257257257257257257257257257257" + "257257257257257257257257257257257257257257257257257257257257257257257257" + "257257257257257257257257257257257257257257257257257257257257257257257257" + "25725725725725725725725725725725725725725"); + // Have the retailer Name have 257 characters + SetAndVerifyInvalidRetailerNameAndStoreNumber( + "257characters257characters257characters257characters257characters257char" + "acters257characters257characters257characters257characters257characters2" + "57characters257characters257characters257characters257characters257chara" + "cters257characters257characters257charact", + "1234"); // Verify that continue button goes back to being disabled after enabled // for correct input
diff --git a/chrome/browser/ash/system_web_apps/apps/BUILD.gn b/chrome/browser/ash/system_web_apps/apps/BUILD.gn index 1860613c..f45613e 100644 --- a/chrome/browser/ash/system_web_apps/apps/BUILD.gn +++ b/chrome/browser/ash/system_web_apps/apps/BUILD.gn
@@ -25,6 +25,7 @@ "personalization_app/personalization_app_time_of_day_browsertest.cc", "personalization_app/personalization_app_wallpaper_daily_refresh_browsertest.cc", "print_management_app_integration_browsertest.cc", + "print_preview_cros_app_integration_browsertest.cc", "projector_app/projector_app_integration_browsertest.cc", "scanning_app_integration_browsertest.cc", "settings_app_integration_browsertest.cc", @@ -46,6 +47,7 @@ "//ash/webui/media_app_ui:buildflags", "//ash/webui/os_feedback_ui", "//ash/webui/print_management", + "//ash/webui/print_preview_cros", "//ash/webui/projector_app:buildflags", "//ash/webui/web_applications/test:test_support", "//chrome/browser/accessibility/media_app/test:test_support",
diff --git a/chrome/browser/ash/system_web_apps/apps/OWNERS b/chrome/browser/ash/system_web_apps/apps/OWNERS index 9f0105d..1c49fecb 100644 --- a/chrome/browser/ash/system_web_apps/apps/OWNERS +++ b/chrome/browser/ash/system_web_apps/apps/OWNERS
@@ -10,5 +10,6 @@ per-file diagnostics*=file://ash/webui/diagnostics_ui/OWNERS per-file file_manager*=file://ash/webui/file_manager/OWNERS per-file files_internals*=file://ash/webui/file_manager/OWNERS +per-file print_preview_cros*=file://ash/webui/print_preview_cros/OWNERS per-file terminal*=file://chromeos/TERMINAL_OWNERS per-file eche*=file://ash/webui/eche_app_ui/OWNERS
diff --git a/chrome/browser/ash/system_web_apps/apps/print_preview_cros_app_integration_browsertest.cc b/chrome/browser/ash/system_web_apps/apps/print_preview_cros_app_integration_browsertest.cc new file mode 100644 index 0000000..cbe4ad75 --- /dev/null +++ b/chrome/browser/ash/system_web_apps/apps/print_preview_cros_app_integration_browsertest.cc
@@ -0,0 +1,40 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/constants/ash_features.h" +#include "ash/webui/print_preview_cros/url_constants.h" +#include "ash/webui/system_apps/public/system_web_app_type.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/ash/system_web_apps/test_support/system_web_app_integration_test.h" +#include "content/public/test/browser_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +class PrintPreviewCrosAppIntegrationTest + : public ash::SystemWebAppIntegrationTest { + public: + PrintPreviewCrosAppIntegrationTest() { + features_.InitAndEnableFeature(ash::features::kPrintPreviewCrosApp); + } + + private: + base::test::ScopedFeatureList features_; +}; + +} // namespace + +// Test that the Print Preview CrOS App installs and launches correctly. Runs +// some spot checks on the manifest. +IN_PROC_BROWSER_TEST_P(PrintPreviewCrosAppIntegrationTest, + PrintPreviewCrosApp) { + const GURL url{ash::kChromeUIPrintPreviewCrosURL}; + EXPECT_NO_FATAL_FAILURE( + ExpectSystemWebAppValid(ash::SystemWebAppType::PRINT_PREVIEW_CROS, url, + /*title=*/"Print")); +} + +INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_REGULAR_PROFILE_P( + PrintPreviewCrosAppIntegrationTest);
diff --git a/chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.cc b/chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.cc new file mode 100644 index 0000000..e2e9189 --- /dev/null +++ b/chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.cc
@@ -0,0 +1,74 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.h" + +#include <memory> + +#include "ash/constants/ash_features.h" +#include "ash/webui/grit/ash_print_preview_cros_app_resources.h" +#include "ash/webui/print_preview_cros/url_constants.h" +#include "chrome/browser/ash/system_web_apps/apps/system_web_app_install_utils.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h" +#include "chrome/browser/web_applications/web_app_install_info.h" +#include "url/gurl.h" + +namespace { + +constexpr char kPrintPreviewCrosInternalName[] = "PrintPreviewCros"; +constexpr char16_t kPrintPreviewCrosTitle[] = u"Print"; + +} // namespace + +PrintPreviewCrosDelegate::PrintPreviewCrosDelegate(Profile* profile) + : ash::SystemWebAppDelegate( + ash::SystemWebAppType::PRINT_PREVIEW_CROS, + /*internal_name=*/kPrintPreviewCrosInternalName, + /*install_url=*/GURL(ash::kChromeUIPrintPreviewCrosURL), + profile) {} + +std::unique_ptr<web_app::WebAppInstallInfo> +PrintPreviewCrosDelegate::GetWebAppInfo() const { + return CreateWebAppInfoForPrintPreviewCrosSystemWebApp(); +} + +bool PrintPreviewCrosDelegate::IsAppEnabled() const { + return ash::features::IsPrinterPreviewCrosAppEnabled(); +} + +bool PrintPreviewCrosDelegate::ShouldShowInLauncher() const { + return false; +} + +bool PrintPreviewCrosDelegate::ShouldShowInSearchAndShelf() const { + return false; +} + +bool PrintPreviewCrosDelegate::ShouldCaptureNavigations() const { + return true; +} + +std::unique_ptr<web_app::WebAppInstallInfo> +CreateWebAppInfoForPrintPreviewCrosSystemWebApp() { + std::unique_ptr<web_app::WebAppInstallInfo> info = + std::make_unique<web_app::WebAppInstallInfo>(); + const GURL url = GURL(ash::kChromeUIPrintPreviewCrosURL); + info->start_url = url; + info->scope = url; + info->display_mode = blink::mojom::DisplayMode::kStandalone; + info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone; + + // TODO(b/323585997): Localize title. + info->title = kPrintPreviewCrosTitle; + + // TODO(b/323421684): Replace with actual app icons when available. + web_app::CreateIconInfoForSystemWebApp( + info->start_url, + {{"app_icon_192.png", 192, + IDR_ASH_PRINT_PREVIEW_CROS_APP_IMAGES_APP_ICON_192_PNG}}, + *info); + + return info; +}
diff --git a/chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.h b/chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.h new file mode 100644 index 0000000..57e4396 --- /dev/null +++ b/chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.h
@@ -0,0 +1,32 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_APPS_PRINT_PREVIEW_CROS_SYSTEM_WEB_APP_INFO_H_ +#define CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_APPS_PRINT_PREVIEW_CROS_SYSTEM_WEB_APP_INFO_H_ + +#include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate.h" + +class Profile; + +namespace web_app { +struct WebAppInstallInfo; +} // namespace web_app + +class PrintPreviewCrosDelegate : public ash::SystemWebAppDelegate { + public: + explicit PrintPreviewCrosDelegate(Profile* profile); + + // ash::SystemWebAppDelegate: + std::unique_ptr<web_app::WebAppInstallInfo> GetWebAppInfo() const override; + bool IsAppEnabled() const override; + bool ShouldShowInLauncher() const override; + bool ShouldShowInSearchAndShelf() const override; + bool ShouldCaptureNavigations() const override; +}; + +// Returns a WebAppInstallInfo used to install the app. +std::unique_ptr<web_app::WebAppInstallInfo> +CreateWebAppInfoForPrintPreviewCrosSystemWebApp(); + +#endif // CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_APPS_PRINT_PREVIEW_CROS_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc index 34d2b33..5090e49 100644 --- a/chrome/browser/ash/system_web_apps/system_web_app_manager.cc +++ b/chrome/browser/ash/system_web_apps/system_web_app_manager.cc
@@ -55,6 +55,7 @@ #include "chrome/browser/ash/system_web_apps/apps/os_url_handler_system_web_app_info.h" #include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_system_app_delegate.h" #include "chrome/browser/ash/system_web_apps/apps/print_management_web_app_info.h" +#include "chrome/browser/ash/system_web_apps/apps/print_preview_cros_system_web_app_info.h" #include "chrome/browser/ash/system_web_apps/apps/projector_system_web_app_info.h" #include "chrome/browser/ash/system_web_apps/apps/scanning_system_web_app_info.h" #include "chrome/browser/ash/system_web_apps/apps/shimless_rma_system_web_app_info.h" @@ -143,6 +144,7 @@ info_vec.push_back( std::make_unique<vc_background_ui::VcBackgroundUISystemAppDelegate>( profile)); + info_vec.push_back(std::make_unique<PrintPreviewCrosDelegate>(profile)); #if !defined(OFFICIAL_BUILD) info_vec.push_back(std::make_unique<SampleSystemAppDelegate>(profile));
diff --git a/chrome/browser/ash/system_web_apps/types/proto/system_web_app_data.proto b/chrome/browser/ash/system_web_apps/types/proto/system_web_app_data.proto index a993f63..e233d6f 100644 --- a/chrome/browser/ash/system_web_apps/types/proto/system_web_app_data.proto +++ b/chrome/browser/ash/system_web_apps/types/proto/system_web_app_data.proto
@@ -36,6 +36,7 @@ OS_FLAGS = 23; FACE_ML = 24; VC_BACKGROUND = 25; + PRINT_PREVIEW_CROS = 26; }; optional SystemWebAppType system_app_type = 1;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 85b768c..b63a796f4 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -447,10 +447,8 @@ #endif #if BUILDFLAG(ENABLE_COMPOSE) -#include "chrome/browser/compose/compose_enabling.h" -#include "chrome/browser/ui/webui/compose/compose_ui.h" +#include "chrome/browser/ui/webui/compose/compose_untrusted_ui.h" #include "chrome/common/compose/compose.mojom.h" -#include "components/compose/core/browser/compose_features.h" // nogncheck crbug.com/1125897 #endif #if BUILDFLAG(ENABLE_PRINT_PREVIEW) @@ -1172,9 +1170,6 @@ ash::multidevice_setup::MultiDeviceSetupDialogUI, ash::ParentAccessUI, ash::EmojiUI, ash::RemoteMaintenanceCurtainUI, #endif -#if BUILDFLAG(ENABLE_COMPOSE) - ComposeUI, -#endif NewTabPageUI, OmniboxPopupUI, BookmarksSidePanelUI, CustomizeChromeUI, InternalsUI, ReadingListUI, TabSearchUI, WebuiGalleryUI, HistoryClustersSidePanelUI, PerformanceSidePanelUI, @@ -1752,14 +1747,6 @@ } #endif -#if BUILDFLAG(ENABLE_COMPOSE) - if (ComposeEnabling::IsEnabledForProfile(Profile::FromBrowserContext( - render_frame_host->GetBrowserContext()))) { - RegisterWebUIControllerInterfaceBinder< - compose::mojom::ComposeSessionPageHandlerFactory, ComposeUI>(map); - } -#endif // BUILDFLAG(ENABLE_COMPOSE) - if (base::FeatureList::IsEnabled( privacy_sandbox::kPrivacySandboxInternalsDevUI)) { RegisterWebUIControllerInterfaceBinder< @@ -1840,6 +1827,11 @@ registry.ForWebUI<feed::FeedUI>() .Add<feed::mojom::FeedSidePanelHandlerFactory>(); #endif // !BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(ENABLE_COMPOSE) + registry.ForWebUI<ComposeUntrustedUI>() + .Add<color_change_listener::mojom::PageHandler>() + .Add<compose::mojom::ComposeSessionPageHandlerFactory>(); +#endif // BUILDFLAG(ENABLE_COMPOSE) #if !BUILDFLAG(IS_ANDROID) if (companion::IsCompanionFeatureEnabled()) { registry.ForWebUI<CompanionSidePanelUntrustedUI>()
diff --git a/chrome/browser/compose/chrome_compose_client.cc b/chrome/browser/compose/chrome_compose_client.cc index c3f530b..3748422 100644 --- a/chrome/browser/compose/chrome_compose_client.cc +++ b/chrome/browser/compose/chrome_compose_client.cc
@@ -57,8 +57,6 @@ namespace { -const char kComposeURL[] = "chrome://compose/"; - bool ShouldResumeSessionFromEntryPoint( ChromeComposeClient::EntryPoint entry_point) { switch (entry_point) { @@ -122,7 +120,8 @@ url::Origin origin = GetWebContents().GetPrimaryMainFrame()->GetLastCommittedOrigin(); - if (origin == url::Origin::Create(GURL(kComposeURL))) { + if (origin == + url::Origin::Create(GURL(chrome::kChromeUIUntrustedComposeUrl))) { debug_session_ = std::make_unique<ComposeSession>( &GetWebContents(), GetModelExecutor(), GetModelQualityLogsUploader(), GetSessionId(), GetInnerTextProvider(), autofill::FieldRendererId(-1));
diff --git a/chrome/browser/compose/chrome_compose_client.h b/chrome/browser/compose/chrome_compose_client.h index a1d1b54..8cebe54 100644 --- a/chrome/browser/compose/chrome_compose_client.h +++ b/chrome/browser/compose/chrome_compose_client.h
@@ -227,7 +227,7 @@ // Time that the last call to show the dialog was started. base::TimeTicks show_dialog_start_; - // Used to test Compose in a tab at |chrome://compose|. + // Used to test Compose in a tab at |chrome-untrusted://compose|. std::unique_ptr<ComposeSession> debug_session_; // Collects per-pageload UKM metrics and reports them on destruction (if any
diff --git a/chrome/browser/compose/chrome_compose_client_unittest.cc b/chrome/browser/compose/chrome_compose_client_unittest.cc index bfa030c..8b11fca 100644 --- a/chrome/browser/compose/chrome_compose_client_unittest.cc +++ b/chrome/browser/compose/chrome_compose_client_unittest.cc
@@ -1121,7 +1121,7 @@ } TEST_F(ChromeComposeClientTest, NoStateWorksAtChromeCompose) { - NavigateAndCommitActiveTab(GURL("chrome://compose")); + NavigateAndCommitActiveTab(GURL(chrome::kChromeUIUntrustedComposeUrl)); // We skip the dialog showing here, as there is no dialog required at this // URL. BindMojo(); @@ -1178,10 +1178,10 @@ ukm::builders::Compose_SessionProgress::kCanceledName, 1))); } -// Tests that closing the session at chrome://compose does not crash the -// browser, even though there is no dialog shown at that URL. +// Tests that closing the session at chrome-untrusted://compose does not crash +// the browser, even though there is no dialog shown at that URL. TEST_F(ChromeComposeClientTest, TestCloseUIAtChromeCompose) { - NavigateAndCommitActiveTab(GURL("chrome://compose")); + NavigateAndCommitActiveTab(GURL(chrome::kChromeUIUntrustedComposeUrl)); // We skip the dialog showing here, as there is no dialog required at this // URL. BindMojo(); @@ -2981,11 +2981,12 @@ } // Tests that the Compose client crashes the browser if a webcontents -// sends any more messages after closing the dialog at chrome://contents. +// sends any more messages after closing the dialog at +// chrome-untrusted://compose. TEST_F(ChromeComposeClientTest, TestCannotSendMessagesAfterClosingDialogAtChromeCompose) { GTEST_FLAG_SET(death_test_style, "threadsafe"); - NavigateAndCommitActiveTab(GURL("chrome://compose")); + NavigateAndCommitActiveTab(GURL(chrome::kChromeUIUntrustedComposeUrl)); // We skip the dialog showing here, as there is no dialog required at this // URL. BindMojo();
diff --git a/chrome/browser/controlled_frame/controlled_frame_apitest.cc b/chrome/browser/controlled_frame/controlled_frame_apitest.cc index 38692f3..66f92e88 100644 --- a/chrome/browser/controlled_frame/controlled_frame_apitest.cc +++ b/chrome/browser/controlled_frame/controlled_frame_apitest.cc
@@ -195,6 +195,23 @@ // TODO(odejesush): Add tests for the rest of the Promise API methods. const char* kControlledFramePromiseApiMethods[]{"back", "forward", "go"}; +[[nodiscard]] bool IsControlledFramePresent( + content::WebContents* web_contents) { + return ExecJs(web_contents, R"( + (async function() { + return await new Promise((resolve, reject) => { + const controlledframe = document.createElement('controlledframe'); + if (('src' in controlledframe)) { + // Tag is defined. + resolve('SUCCESS'); + } else { + reject('FAIL'); + } + }); + })(); + )"); +} + } // namespace class ControlledFrameApiTest @@ -885,15 +902,6 @@ ControlledFrameAvailableChannelTest& operator=( const ControlledFrameAvailableChannelTest&) = delete; - void CheckIsAvailable() { - // Test if Controlled Frame is available. - const GURL& kOriginalControlledFrameUrl = - isolated_web_app_dev_server().GetURL("/controlled_frame.html"); - ASSERT_TRUE( - CreateControlledFrame(app_contents(), kOriginalControlledFrameUrl)); - EXPECT_EQ(kEvalSuccessStr, ExecuteScriptRedBackgroundFile(app_contents())); - } - private: extensions::ScopedCurrentChannel channel_; }; @@ -907,11 +915,16 @@ version_info::Channel::DEFAULT)); IN_PROC_BROWSER_TEST_P(ControlledFrameAvailableChannelTest, Test) { - CheckIsAvailable(); + // Test if Controlled Frame is available. + const GURL& kOriginalControlledFrameUrl = + isolated_web_app_dev_server().GetURL("/controlled_frame.html"); + ASSERT_TRUE( + CreateControlledFrame(app_contents(), kOriginalControlledFrameUrl)); + EXPECT_EQ(kEvalSuccessStr, ExecuteScriptRedBackgroundFile(app_contents())); } class ControlledFrameNotAvailableChannelTest - : public web_app::WebAppControllerBrowserTest, + : public ControlledFrameApiTest, public testing::WithParamInterface<version_info::Channel> { protected: ControlledFrameNotAvailableChannelTest() : channel_(GetParam()) {} @@ -921,33 +934,6 @@ ControlledFrameNotAvailableChannelTest& operator=( const ControlledFrameNotAvailableChannelTest&) = delete; - [[nodiscard]] bool IsControlledFramePresent( - content::WebContents* web_contents) { - return ExecJs(web_contents, R"( - (async function() { - return await new Promise((resolve, reject) => { - const controlledframe = document.createElement('controlledframe'); - if (('src' in controlledframe)) { - // Tag is defined. - resolve('SUCCESS'); - } else { - reject('FAIL'); - } - }); - })(); - )"); - } - - void CheckIsNotAvailable() { - // Test if Controlled Frame is not available. - const GURL start_url("https://app.site.test/example/index"); - const webapps::AppId app_id = InstallPWA(start_url); - content::WebContents* app_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - ASSERT_FALSE(IsControlledFramePresent(app_contents)); - } - private: extensions::ScopedCurrentChannel channel_; }; @@ -961,7 +947,38 @@ version_info::Channel::DEFAULT)); IN_PROC_BROWSER_TEST_P(ControlledFrameNotAvailableChannelTest, Test) { - CheckIsNotAvailable(); + // Test if Controlled Frame is not available. + const GURL start_url("https://app.site.test/example/index"); + const webapps::AppId app_id = InstallPWA(start_url); + content::WebContents* app_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + ASSERT_FALSE(IsControlledFramePresent(app_contents)); +} + +class ControlledFrameDisabledTest : public ControlledFrameApiTest { + public: + ControlledFrameDisabledTest(const ControlledFrameDisabledTest&) = delete; + ControlledFrameDisabledTest& operator=(const ControlledFrameDisabledTest&) = + delete; + + protected: + ControlledFrameDisabledTest() { + feature_list.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{features::kControlledFrame}); + } + + ~ControlledFrameDisabledTest() override = default; + + private: + base::test::ScopedFeatureList feature_list; +}; + +IN_PROC_BROWSER_TEST_F(ControlledFrameDisabledTest, MissingFeature) { + const GURL& kOriginalControlledFrameUrl = + isolated_web_app_dev_server().GetURL("/controlled_frame.html"); + ASSERT_FALSE(IsControlledFramePresent(app_contents())); } } // namespace controlled_frame
diff --git a/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc b/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc index f45444a..b9ac83ec 100644 --- a/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc +++ b/chrome/browser/enterprise/connectors/device_trust/device_trust_browsertest.cc
@@ -411,8 +411,15 @@ current_key_pair); } +// Flaky on Win. See http://crbug.com/324937427. +#if BUILDFLAG(IS_WIN) +#define MAYBE_RemoteCommandKeyRotationFailure \ + DISABLED_RemoteCommandKeyRotationFailure +#else +#define MAYBE_RemoteCommandKeyRotationFailure RemoteCommandKeyRotationFailure +#endif IN_PROC_BROWSER_TEST_F(DeviceTrustKeyRotationBrowserTest, - RemoteCommandKeyRotationFailure) { + MAYBE_RemoteCommandKeyRotationFailure) { // Make sure key presents and stores its current value. std::vector<uint8_t> current_key_pair = device_trust_test_environment_win_->GetWrappedKey();
diff --git a/chrome/browser/extensions/events_apitest.cc b/chrome/browser/extensions/events_apitest.cc index 58d8c1da6..4cad0c1 100644 --- a/chrome/browser/extensions/events_apitest.cc +++ b/chrome/browser/extensions/events_apitest.cc
@@ -699,6 +699,83 @@ EXPECT_EQ(extension_host->GetUnackedMessagesSizeForTesting(), 0UL); } +// TODO(crbug.com/41493334): Refactor this test into the +// DispatchToEventPage_Acks test since they are so similar. +using PersistentBackgroundPageEventDispatchToSenderApiTest = + EventPageEventDispatchingApiTest; + +// Tests that persistent background pages will receive an event message (routed +// through the EventRouter::DispatchToSender() flow) and properly track and +// remove the unacked event message in ExtensionHost. Only persistent background +// pages can use the webRequest API so event pages are not tested. +IN_PROC_BROWSER_TEST_F(PersistentBackgroundPageEventDispatchToSenderApiTest, + DispatchToPage_Acks) { + // Load an extension with a chrome.webRequest.onBeforeRequest + // (EventRouter::DispatchToSender()) listener and wait for the + // chrome.runtime.onInstalled listener to fire. + static constexpr char kManifest[] = + R"({ + "name": "Persistent background page", + "version": "0.1", + "manifest_version": 2, + "background": { + "scripts": ["background.js"], + "persistent": true + }, + "permissions": ["webRequest", "http://example.com/*"] + })"; + TestExtensionDir test_dir; + test_dir.WriteManifest(kManifest); + constexpr char kBackgroundJs[] = + R"({ + chrome.runtime.onInstalled.addListener((details) => { + // Asynchronously send the message that the listener fired so that the + // event is considered ack'd in the browser C++ code. + setTimeout(() => { + chrome.test.sendMessage('installed listener fired'); + }, 0); + }); + + chrome.webRequest.onBeforeRequest.addListener( + (details) => { + setTimeout(() => { + chrome.test.sendMessage('listener fired'); + }, 0); + }, + {urls: ['<all_urls>'], types: ['main_frame']}, + [] + ); + })"; + test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs); + ExtensionTestMessageListener extension_oninstall_listener_fired( + "installed listener fired"); + const Extension* extension = LoadExtension(test_dir.UnpackedPath()); + ASSERT_TRUE(extension); + // This ensures that we wait until the the browser receives the ack from the + // renderer. This prevents unexpected event state later when we check it. + ASSERT_TRUE(extension_oninstall_listener_fired.WaitUntilSatisfied()); + + // Confirm there are no unacked messages before we send the test event. + ProcessManager* process_manager = ProcessManager::Get(profile()); + ExtensionHost* extension_host = + process_manager->GetBackgroundHostForExtension(extension->id()); + ASSERT_EQ(extension_host->GetUnackedMessagesSizeForTesting(), 0UL); + + ExtensionTestMessageListener extension_event_listener_fired("listener fired"); + + // Navigate somewhere to trigger webRequest.onBeforeRequest event to the + // extension listener. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("example.com", "/simple.html"))); + + // Confirm that the listener in the persistent background page script fired. + EXPECT_TRUE(extension_event_listener_fired.WaitUntilSatisfied()); + // TODO(crbug.com/1496093): Can we add an observer so that we know that an + // unacked message was added and then removed? + EXPECT_EQ(extension_host->GetUnackedMessagesSizeForTesting(), 0UL); +} + // Tests that an event targeted to a content script listener is not recorded // in unacked event messages in ExtensionHost. IN_PROC_BROWSER_TEST_F(EventPageEventDispatchingApiTest,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 4504392..45d0bca 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2354,6 +2354,11 @@ "expiry_milestone": 140 }, { + "name": "enable-controlled-frame", + "owners": [ "cmp@chromium.org", "odejesush@chromium.org" ], + "expiry_milestone": 140 + }, + { "name": "enable-cooperative-scheduling", "owners": [ "keishi@chromium.org" ], "expiry_milestone": 85
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index f555451..d96477c 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1242,6 +1242,12 @@ const char kEnableIsolatedWebAppDevModeDescription[] = "Enables the installation of unverified Isolated Web Apps"; +const char kEnableControlledFrameName[] = "Enable Controlled Frame"; +const char kEnableControlledFrameDescription[] = + "Enables experimental support for Controlled Frame. See " + "https://github.com/WICG/controlled-frame/blob/main/EXPLAINER.md " + "for more information."; + const char kEnableShortcutCustomizationAppName[] = "Enable shortcut customization app"; const char kEnableShortcutCustomizationAppDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index f627879..a0e40fa9 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -805,6 +805,9 @@ extern const char kEnableIsolatedWebAppDevModeName[]; extern const char kEnableIsolatedWebAppDevModeDescription[]; +extern const char kEnableControlledFrameName[]; +extern const char kEnableControlledFrameDescription[]; + extern const char kEnableLensStandaloneFlagId[]; extern const char kEnableLensStandaloneName[]; extern const char kEnableLensStandaloneDescription[];
diff --git a/chrome/browser/metrics/structured/ash_event_storage.cc b/chrome/browser/metrics/structured/ash_event_storage.cc index 2a2fe81..539eeb09 100644 --- a/chrome/browser/metrics/structured/ash_event_storage.cc +++ b/chrome/browser/metrics/structured/ash_event_storage.cc
@@ -6,7 +6,7 @@ #include "base/functional/callback_forward.h" #include "base/task/current_thread.h" -#include "components/metrics/structured/histogram_util.h" +#include "components/metrics/structured/lib/histogram_util.h" namespace metrics::structured {
diff --git a/chrome/browser/metrics/structured/chrome_structured_metrics_recorder_unittest.cc b/chrome/browser/metrics/structured/chrome_structured_metrics_recorder_unittest.cc index 72c36ee7..ebb77f4 100644 --- a/chrome/browser/metrics/structured/chrome_structured_metrics_recorder_unittest.cc +++ b/chrome/browser/metrics/structured/chrome_structured_metrics_recorder_unittest.cc
@@ -16,7 +16,7 @@ #include "base/threading/scoped_blocking_call.h" #include "components/metrics/structured/event.h" #include "components/metrics/structured/key_data_prefs_delegate.h" -#include "components/metrics/structured/key_util.h" +#include "components/metrics/structured/lib/key_util.h" #include "components/metrics/structured/lib/proto/key.pb.h" #include "components/metrics/structured/proto/event_storage.pb.h" #include "components/metrics/structured/structured_events.h"
diff --git a/chrome/browser/metrics/structured/key_data_provider_ash.h b/chrome/browser/metrics/structured/key_data_provider_ash.h index b0ca0117..f71d605 100644 --- a/chrome/browser/metrics/structured/key_data_provider_ash.h +++ b/chrome/browser/metrics/structured/key_data_provider_ash.h
@@ -12,7 +12,7 @@ #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "components/metrics/structured/key_data_provider.h" +#include "components/metrics/structured/lib/key_data_provider.h" namespace metrics::structured {
diff --git a/chrome/browser/metrics/structured/key_data_provider_ash_unittest.cc b/chrome/browser/metrics/structured/key_data_provider_ash_unittest.cc index 5547425..88c5f4d 100644 --- a/chrome/browser/metrics/structured/key_data_provider_ash_unittest.cc +++ b/chrome/browser/metrics/structured/key_data_provider_ash_unittest.cc
@@ -13,7 +13,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" #include "base/time/time.h" -#include "components/metrics/structured/key_data_provider.h" +#include "components/metrics/structured/lib/key_data_provider.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/metrics/structured/key_data_provider_chrome.h b/chrome/browser/metrics/structured/key_data_provider_chrome.h index 392c635..0edc0c0 100644 --- a/chrome/browser/metrics/structured/key_data_provider_chrome.h +++ b/chrome/browser/metrics/structured/key_data_provider_chrome.h
@@ -7,8 +7,8 @@ #include <string> -#include "components/metrics/structured/key_data_provider.h" #include "components/metrics/structured/key_data_provider_prefs.h" +#include "components/metrics/structured/lib/key_data_provider.h" #include "components/metrics/structured/lib/proto/key.pb.h" class PrefRegistrySimple;
diff --git a/chrome/browser/metrics/variations/chrome_variations_service_client.cc b/chrome/browser/metrics/variations/chrome_variations_service_client.cc index c07d7b9..fa08d98f 100644 --- a/chrome/browser/metrics/variations/chrome_variations_service_client.cc +++ b/chrome/browser/metrics/variations/chrome_variations_service_client.cc
@@ -91,8 +91,8 @@ // branded Lacros build, see crbug.com/1474764. if (!g_browser_process->browser_policy_connector()->GetDeviceSettings()) { CHECK_IS_TEST(); // IN-TEST - CHECK(chromeos::BrowserParamsProxy::Get() - ->IsCrosapiDisabledForTesting()); // IN-TEST + CHECK(chromeos::BrowserParamsProxy:: + IsCrosapiDisabledForTesting()); // IN-TEST return false; }
diff --git a/chrome/browser/notifications/mac/OWNERS b/chrome/browser/notifications/mac/OWNERS index 14fce2ae..e69de29 100644 --- a/chrome/browser/notifications/mac/OWNERS +++ b/chrome/browser/notifications/mac/OWNERS
@@ -1 +0,0 @@ -rsesek@chromium.org
diff --git a/chrome/browser/notifications/notification_permission_browsertest.cc b/chrome/browser/notifications/notification_permission_browsertest.cc index 2d727d7..ed6e034f 100644 --- a/chrome/browser/notifications/notification_permission_browsertest.cc +++ b/chrome/browser/notifications/notification_permission_browsertest.cc
@@ -3,20 +3,30 @@ // found in the LICENSE file. #include "chrome/browser/chrome_content_browser_client.h" +#include "chrome/browser/notifications/non_persistent_notification_handler.h" #include "chrome/browser/notifications/notification_permission_context.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/permissions/permission_request_manager.h" +#include "components/permissions/permission_util.h" +#include "components/permissions/request_type.h" +#include "components/permissions/test/mock_permission_prompt_factory.h" +#include "components/permissions/test/mock_permission_request.h" +#include "components/ukm/test_ukm_recorder.h" #include "content/public/common/content_client.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_mock_cert_verifier.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/metrics/public/cpp/ukm_builders.h" namespace { +using Permission = ukm::builders::Permission; + const char kTestFilePath[] = "/notifications/notification_permission_checker.html"; const char kTesterHost[] = "notification.com"; @@ -302,3 +312,66 @@ histogram_tester.ExpectBucketCount(histogram_name, false, 2); histogram_tester.ExpectBucketCount(histogram_name, true, 1); } + +// Tests that non-persistent notifications (i.e. doesn't use +// the Push API) records PermissionUsage and Notification UKMs. +IN_PROC_BROWSER_TEST_F(NotificationPermissionBrowserTest, + NonPersistentNotificationRecordsUkms) { + GrantNotificationPermissionForTest(TesterUrl()); + + EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), TesterUrl())); + content::RenderFrameHost* main_frame = + GetActiveWebContents()->GetPrimaryMainFrame(); + + ukm::TestAutoSetUkmRecorder ukm_recorder; + + const std::string show_notification_js = R"(new Promise((resolve) => { + const notification = new Notification("done"); + notification.onshow = () => { + const title = notification.title; + notification.close(); + resolve(title); + }; + });)"; + + EXPECT_EQ("done", EvalJs(main_frame, show_notification_js)); + const auto usage_entries = ukm_recorder.GetEntriesByName("PermissionUsage"); + ASSERT_EQ(1u, usage_entries.size()); +} + +IN_PROC_BROWSER_TEST_F(NotificationPermissionBrowserTest, + DisablePermissionRecordsUkms) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + + auto* manager = permissions::PermissionRequestManager::FromWebContents( + GetActiveWebContents()); + std::unique_ptr<permissions::MockPermissionPromptFactory> bubble_factory = + std::make_unique<permissions::MockPermissionPromptFactory>(manager); + EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), TesterUrl())); + permissions::MockPermissionRequest req( + permissions::RequestType::kNotifications); + manager->AddRequest(GetActiveWebContents()->GetPrimaryMainFrame(), &req); + bubble_factory->WaitForPermissionBubble(); + manager->Accept(); + + GrantNotificationPermissionForTest(TesterUrl()); + + std::unique_ptr<NotificationHandler> handler = + std::make_unique<NonPersistentNotificationHandler>(); + handler->DisableNotifications(browser()->profile(), TesterUrl()); + + const auto action_entries = ukm_recorder.GetEntriesByName("Permission"); + ASSERT_EQ(2u, action_entries.size()); + + // The revocation event uses the notification source_id type + EXPECT_EQ(ukm::SourceIdType::NOTIFICATION_ID, + ukm::GetSourceIdType(action_entries[1]->source_id)); + + // Expect one GRANT and one REVOKE event + ukm_recorder.ExpectEntryMetric( + action_entries[0], Permission::kActionName, + static_cast<int>(permissions::PermissionAction::GRANTED)); + ukm_recorder.ExpectEntryMetric( + action_entries[1], Permission::kActionName, + static_cast<int>(permissions::PermissionAction::REVOKED)); +}
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index b6f6c6a..371f6640 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -390,13 +390,11 @@ return; } - // Check if this event can be recorded via UKM. - auto* ukm_background_service = - ukm::UkmBackgroundRecorderFactory::GetForProfile(profile_); - ukm_background_service->GetBackgroundSourceIdIfAllowed( - url::Origin::Create(data.origin), - base::BindOnce(&PlatformNotificationServiceImpl::DidGetBackgroundSourceId, - std::move(ukm_recorded_closure_for_testing_), data)); + ukm::SourceId source_id = ukm::UkmRecorder::GetSourceIdForNotificationEvent( + base::PassKey<PlatformNotificationServiceImpl>(), data.origin); + + RecordNotificationUkmEventWithSourceId( + std::move(ukm_recorded_closure_for_testing_), data, source_id); } NotificationTriggerScheduler* @@ -405,15 +403,11 @@ } // static -void PlatformNotificationServiceImpl::DidGetBackgroundSourceId( +void PlatformNotificationServiceImpl::RecordNotificationUkmEventWithSourceId( base::OnceClosure recorded_closure, const content::NotificationDatabaseData& data, - std::optional<ukm::SourceId> source_id) { - // This background event did not meet the requirements for the UKM service. - if (!source_id) - return; - - ukm::builders::Notification builder(*source_id); + ukm::SourceId source_id) { + ukm::builders::Notification builder(source_id); int64_t time_until_first_click_millis = data.time_until_first_click_millis.has_value()
diff --git a/chrome/browser/notifications/platform_notification_service_impl.h b/chrome/browser/notifications/platform_notification_service_impl.h index 557b1dae..231a266 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.h +++ b/chrome/browser/notifications/platform_notification_service_impl.h
@@ -121,10 +121,10 @@ const ContentSettingsPattern& secondary_pattern, ContentSettingsTypeSet content_type_set) override; - static void DidGetBackgroundSourceId( + static void RecordNotificationUkmEventWithSourceId( base::OnceClosure recorded_closure, const content::NotificationDatabaseData& data, - std::optional<ukm::SourceId> source_id); + ukm::SourceId source_id); // Creates a new Web Notification-based Notification object. Should only be // called when the notification is first shown. |web_app_hint_url| is used to
diff --git a/chrome/browser/permissions/chrome_permissions_client.cc b/chrome/browser/permissions/chrome_permissions_client.cc index e1638042..bc5c31e 100644 --- a/chrome/browser/permissions/chrome_permissions_client.cc +++ b/chrome/browser/permissions/chrome_permissions_client.cc
@@ -62,6 +62,7 @@ #include "content/public/browser/web_contents.h" #include "extensions/buildflags/buildflags.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "services/metrics/public/cpp/ukm_recorder.h" #include "url/origin.h" #if BUILDFLAG(IS_ANDROID) @@ -232,6 +233,7 @@ } void ChromePermissionsClient::GetUkmSourceId( + ContentSettingsType permission_type, content::BrowserContext* browser_context, content::WebContents* web_contents, const GURL& requesting_origin, @@ -240,6 +242,11 @@ ukm::SourceId source_id = web_contents->GetPrimaryMainFrame()->GetPageUkmSourceId(); std::move(callback).Run(source_id); + } else if (permission_type == ContentSettingsType::NOTIFICATIONS) { + ukm::SourceId source_id = + ukm::UkmRecorder::GetSourceIdForNotificationPermission( + base::PassKey<ChromePermissionsClient>(), requesting_origin); + std::move(callback).Run(source_id); } else { // We only record a permission change if the origin is in the user's // history.
diff --git a/chrome/browser/permissions/chrome_permissions_client.h b/chrome/browser/permissions/chrome_permissions_client.h index 006617fb..4a9a81e 100644 --- a/chrome/browser/permissions/chrome_permissions_client.h +++ b/chrome/browser/permissions/chrome_permissions_client.h
@@ -46,7 +46,8 @@ std::vector<std::pair<url::Origin, bool>>* urls) override; bool IsCookieDeletionDisabled(content::BrowserContext* browser_context, const GURL& origin) override; - void GetUkmSourceId(content::BrowserContext* browser_context, + void GetUkmSourceId(ContentSettingsType permission_type, + content::BrowserContext* browser_context, content::WebContents* web_contents, const GURL& requesting_origin, GetUkmSourceIdCallback callback) override;
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_host.cc b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_host.cc index 76a053ff..4533df37 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_host.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_host.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.h" #include "content/public/browser/render_frame_host.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h" namespace { @@ -56,7 +57,7 @@ void LCPCriticalPathPredictorHost::SetLcpInfluencerScriptUrls( const std::vector<GURL>& lcp_influencer_scripts) { - if (!base::FeatureList::IsEnabled(blink::features::kLCPScriptObserver)) { + if (!blink::LcppScriptObserverEnabled()) { return; } if (auto* page_data =
diff --git a/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts index 0931076..6c03cae1 100644 --- a/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts +++ b/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts
@@ -144,7 +144,7 @@ this.browserProxy_.removeEnrollment(e.model.index, this.authToken) .then(success => { if (success) { - recordSettingChange(); + recordSettingChange(Setting.kRemoveFingerprintV2); this.updateFingerprintsList_(); } });
diff --git a/chrome/browser/resources/ash/settings/os_people_page/setup_fingerprint_dialog.ts b/chrome/browser/resources/ash/settings/os_people_page/setup_fingerprint_dialog.ts index 145f90fb..03e01c3a 100644 --- a/chrome/browser/resources/ash/settings/os_people_page/setup_fingerprint_dialog.ts +++ b/chrome/browser/resources/ash/settings/os_people_page/setup_fingerprint_dialog.ts
@@ -9,14 +9,15 @@ import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js'; import '../settings_shared.css.js'; -import {FingerprintProgressElement} from 'chrome://resources/ash/common/quick_unlock/fingerprint_progress.js'; import {CrDialogElement} from 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {WebUiListenerMixin} from 'chrome://resources/ash/common/cr_elements/web_ui_listener_mixin.js'; +import {FingerprintProgressElement} from 'chrome://resources/ash/common/quick_unlock/fingerprint_progress.js'; import {assertNotReached} from 'chrome://resources/js/assert.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {recordSettingChange} from '../metrics_recorder.js'; +import {Setting} from '../mojom-webui/setting.mojom-webui.js'; import {FingerprintBrowserProxy, FingerprintBrowserProxyImpl, FingerprintResultType, FingerprintScan} from './fingerprint_browser_proxy.js'; import {getTemplate} from './setup_fingerprint_dialog.html.js'; @@ -308,7 +309,7 @@ this.$.arc.reset(); this.step_ = FingerprintSetupStep.MOVE_FINGER; this.browserProxy_.startEnroll(this.authToken); - recordSettingChange(); + recordSettingChange(Setting.kAddFingerprintV2); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/common/automation_util.ts b/chrome/browser/resources/chromeos/accessibility/common/automation_util.ts index c979d41f..bb340d1 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/automation_util.ts +++ b/chrome/browser/resources/chromeos/accessibility/common/automation_util.ts
@@ -8,6 +8,7 @@ import {AutomationPredicate} from './automation_predicate.js'; import {constants} from './constants.js'; +import {TestImportManager} from './testing/test_import_manager.js'; import {AutomationTreeWalker, AutomationTreeWalkerRestriction} from './tree_walker.js'; type AutomationNode = chrome.automation.AutomationNode; @@ -540,3 +541,5 @@ return new AutomationTreeWalker(cur, dir, restrictions); } + +TestImportManager.exportForTesting(AutomationUtil);
diff --git a/chrome/browser/resources/chromeos/accessibility/common/paragraph_utils.ts b/chrome/browser/resources/chromeos/accessibility/common/paragraph_utils.ts index 0e360fa..3746457 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/paragraph_utils.ts +++ b/chrome/browser/resources/chromeos/accessibility/common/paragraph_utils.ts
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {TestImportManager} from './testing/test_import_manager.js'; import {WordUtils} from './word_utils.js'; type AutomationNode = chrome.automation.AutomationNode; @@ -676,3 +677,5 @@ } } + +TestImportManager.exportForTesting(ParagraphUtils);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.ts b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.ts index f3895ec..8d2ba3e3 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.ts +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.ts
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {TestImportManager} from '/common/testing/test_import_manager.js'; + import {SelectToSpeakConstants} from './select_to_speak_constants.js'; /** @@ -697,3 +699,5 @@ export const WORD_HIGHLIGHT_KEY = 'settings.a11y.select_to_speak_word_highlight'; } + +TestImportManager.exportForTesting(PrefsManager);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.ts b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.ts index 14930ee..1aec9fbb 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.ts +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.ts
@@ -9,6 +9,7 @@ import {NodeNavigationUtils} from '/common/node_navigation_utils.js'; import {NodeUtils} from '/common/node_utils.js'; import {ParagraphUtils} from '/common/paragraph_utils.js'; +import {TestImportManager} from '/common/testing/test_import_manager.js'; import {WordUtils} from '/common/word_utils.js'; import {InputHandler} from './input_handler.js'; @@ -1741,3 +1742,5 @@ callback(); } } + +TestImportManager.exportForTesting(getGSuiteAppRoot);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_constants.ts b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_constants.ts index 2b3bd659..c941066 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_constants.ts +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_constants.ts
@@ -3,6 +3,7 @@ // found in the LICENSE file. import {KeyCodeData} from '/common/key_code.js'; +import {TestImportManager} from '/common/testing/test_import_manager.js'; export namespace SelectToSpeakConstants { export const SEARCH_KEY_CODE: number = KeyCodeData.SEARCH.code; @@ -30,3 +31,6 @@ useVoiceSwitching: boolean; } } + +TestImportManager.exportForTesting( + ['SelectToSpeakConstants', SelectToSpeakConstants]);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_enhanced_voices_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_enhanced_voices_test.js index ddde2e7..837016f 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_enhanced_voices_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_enhanced_voices_test.js
@@ -26,19 +26,6 @@ }; } - /** @override */ - async setUpDeferred() { - await super.setUpDeferred(); - - await Promise.all([ - importModule('selectToSpeak', '/select_to_speak/select_to_speak_main.js'), - importModule( - 'SelectToSpeakConstants', - '/select_to_speak/select_to_speak_constants.js'), - importModule('PrefsManager', '/select_to_speak/prefs_manager.js'), - ]); - } - // Sets the policy to allow or disallow the network voices. // Waits for the setting to propagate. async setEnhancedNetworkVoicesPolicy(allowed) {
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js index 4f25ff82..b982c211f 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js
@@ -20,14 +20,6 @@ async setUpDeferred() { await super.setUpDeferred(); - await Promise.all([ - importModule('selectToSpeak', '/select_to_speak/select_to_speak_main.js'), - importModule( - 'SelectToSpeakConstants', - '/select_to_speak/select_to_speak_constants.js'), - importModule('PrefsManager', '/select_to_speak/prefs_manager.js'), - ]); - await new Promise(resolve => { chrome.settingsPrivate.setPref( PrefsManager.ENHANCED_VOICES_DIALOG_SHOWN_KEY, true,
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.ts b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.ts index c7f3c37..b9d603af 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.ts +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.ts
@@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import '/common/testing/test_import_manager.js'; - import {InstanceChecker} from '/common/instance_checker.js'; +import {TestImportManager} from '/common/testing/test_import_manager.js'; import {SelectToSpeak} from './select_to_speak.js'; @@ -12,4 +11,5 @@ if (InstanceChecker.isActiveInstance()) { selectToSpeak = new SelectToSpeak(); + TestImportManager.exportForTesting(['selectToSpeak', selectToSpeak]); }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js index 99590e3..4d960d0 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js
@@ -22,15 +22,6 @@ window.EventType = chrome.automation.EventType; window.SelectToSpeakState = chrome.accessibilityPrivate.SelectToSpeakState; - await Promise.all([ - importModule('selectToSpeak', '/select_to_speak/select_to_speak_main.js'), - importModule( - 'SELECT_TO_SPEAK_TRAY_CLASS_NAME', '/select_to_speak/ui_manager.js'), - importModule( - 'SelectToSpeakConstants', - '/select_to_speak/select_to_speak_constants.js'), - importModule('PrefsManager', '/select_to_speak/prefs_manager.js'), - ]); await new Promise(resolve => { chrome.settingsPrivate.setPref( PrefsManager.ENHANCED_VOICES_DIALOG_SHOWN_KEY, true,
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js index 37bed5b..dbbf05d 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js
@@ -29,15 +29,6 @@ chrome.accessibilityPrivate.updateSelectToSpeakPanel = this.updateSelectToSpeakPanel; - await Promise.all([ - importModule('selectToSpeak', '/select_to_speak/select_to_speak_main.js'), - importModule( - 'SelectToSpeakConstants', - '/select_to_speak/select_to_speak_constants.js'), - importModule('AutomationUtil', '/common/automation_util.js'), - importModule('PrefsManager', '/select_to_speak/prefs_manager.js'), - ]); - await new Promise(resolve => { chrome.settingsPrivate.setPref( PrefsManager.ENHANCED_VOICES_DIALOG_SHOWN_KEY, true,
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js index 790c50c3..c0f064b 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js
@@ -25,14 +25,6 @@ /** @override */ async setUpDeferred() { await super.setUpDeferred(); - - await Promise.all([ - importModule('selectToSpeak', '/select_to_speak/select_to_speak_main.js'), - importModule( - 'SelectToSpeakConstants', - '/select_to_speak/select_to_speak_constants.js'), - importModule('PrefsManager', '/select_to_speak/prefs_manager.js'), - ]); await this.resetStorage(); }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js index b9a7bc3..7f272d1 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js
@@ -7,14 +7,7 @@ /** * Test fixture for select_to_speak.js. */ -SelectToSpeakUnitTest = class extends SelectToSpeakE2ETest { - /** @override */ - async setUpDeferred() { - await super.setUpDeferred(); - await importModule( - 'getGSuiteAppRoot', '/select_to_speak/select_to_speak.js'); - } -}; +SelectToSpeakUnitTest = class extends SelectToSpeakE2ETest {}; AX_TEST_F('SelectToSpeakUnitTest', 'getGSuiteAppRoot', function() { const root = {url: 'https://docs.google.com/presentation/p/cats_r_awesome'};
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.ts b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.ts index 2af10e8a..6793317 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.ts +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.ts
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {TestImportManager} from '/common/testing/test_import_manager.js'; + /** * The wrapper for Select-to-speak's text-to-speech features. */ @@ -254,3 +256,5 @@ RESUME_WITH_EMPTY_CONTENT = 'Cannot resume with empty content.', } } + +TestImportManager.exportForTesting(TtsManager);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js index b835f79..c9f3273 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js
@@ -31,8 +31,6 @@ /** @override */ async setUpDeferred() { await super.setUpDeferred(); - const module = await import('/select_to_speak/tts_manager.js'); - window.TtsManager = module.TtsManager; this.mockTtsClient = new MockTtsClient(); this.ttsManager = new TtsManager();
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.ts b/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.ts index 8b01d91..431149f 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.ts +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.ts
@@ -4,6 +4,7 @@ import {AutomationUtil} from '/common/automation_util.js'; import {ParagraphUtils} from '/common/paragraph_utils.js'; +import {TestImportManager} from '/common/testing/test_import_manager.js'; import {PrefsManager} from './prefs_manager.js'; @@ -400,3 +401,7 @@ }) !== undefined; } } + +TestImportManager.exportForTesting( + UiManager, + ['SELECT_TO_SPEAK_TRAY_CLASS_NAME', SELECT_TO_SPEAK_TRAY_CLASS_NAME]);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager_unittest.js index 25429e2b..d678042b 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager_unittest.js
@@ -95,12 +95,6 @@ async setUpDeferred() { await super.setUpDeferred(); - await Promise.all([ - importModule('ParagraphUtils', '/common/paragraph_utils.js'), - importModule('UiManager', '/select_to_speak/ui_manager.js'), - importModule('PrefsManager', '/select_to_speak/prefs_manager.js'), - ]); - this.mockPrefsManager = new MockPrefsManager(); this.mockListener = new MockUiListener(); this.uiManager = new UiManager(this.mockPrefsManager, this.mockListener);
diff --git a/chrome/browser/resources/chromeos/arc_support/background.js b/chrome/browser/resources/chromeos/arc_support/background.js index 821e739..6237563 100644 --- a/chrome/browser/resources/chromeos/arc_support/background.js +++ b/chrome/browser/resources/chromeos/arc_support/background.js
@@ -350,7 +350,7 @@ /** Called when the TermsOfService page is shown. */ onShow() { - if (this.isManaged_ || this.state_ == LoadState.LOADED) { + if (this.isManaged_ || this.state_ === LoadState.LOADED) { // Note: in managed case, because it does not show the contents of terms // of service, it is ok to show the content container immediately. this.showContent_(); @@ -382,7 +382,7 @@ /** Callback for getDropDown in showContext_. */ focusOnLangZoneSelect_(results) { - if (results.length != 1) { + if (results.length !== 1) { console.error('unexpected return value of the script'); return; } @@ -425,7 +425,7 @@ /** Starts to load the terms of service webview content. */ startTermsViewLoading_() { - if (this.state_ == LoadState.LOADING) { + if (this.state_ === LoadState.LOADING) { // If there already is inflight loading task, do nothing. return; } @@ -434,7 +434,7 @@ if (this.termsView_.src) { // This is reloading the page, typically clicked RETRY on error page. this.fastLocation_ = undefined; - if (this.termsView_.src == defaultLocation) { + if (this.termsView_.src === defaultLocation) { this.termsView_.reload(); } else { this.termsView_.src = defaultLocation; @@ -478,7 +478,7 @@ // In such a case, onTermsViewLoadAborted_() is called in advance, and // state_ is set to ABORTED. Here, switch the view only for the // successful loading case. - if (this.state_ == LoadState.LOADING) { + if (this.state_ === LoadState.LOADING) { const getToSContent = {code: 'getToSContent();'}; termsPage.termsView_.executeScript( getToSContent, this.onGetToSContent_.bind(this)); @@ -487,8 +487,8 @@ /** Callback for getToSContent. */ onGetToSContent_(results) { - if (this.state_ == LoadState.LOADING) { - if (!results || results.length != 1 || typeof results[0] !== 'string') { + if (this.state_ === LoadState.LOADING) { + if (!results || results.length !== 1 || typeof results[0] !== 'string') { this.onTermsViewLoadAborted_('unable to get ToS content'); return; } @@ -524,7 +524,7 @@ /** Called when the terms-view's load request is completed. */ onTermsViewRequestCompleted_(details) { - if (this.state_ != LoadState.LOADING || details.statusCode == 200) { + if (this.state_ !== LoadState.LOADING || details.statusCode === 200) { return; } @@ -636,25 +636,25 @@ return; } - if (message.action == 'initialize') { + if (message.action === 'initialize') { initialize(message.data, message.deviceId); - } else if (message.action == 'setMetricsMode') { + } else if (message.action === 'setMetricsMode') { termsPage.onMetricsPreferenceChanged(message.enabled, message.managed); - } else if (message.action == 'setBackupAndRestoreMode') { + } else if (message.action === 'setBackupAndRestoreMode') { termsPage.onBackupRestorePreferenceChanged( message.enabled, message.managed); - } else if (message.action == 'setLocationServiceMode') { + } else if (message.action === 'setLocationServiceMode') { termsPage.onLocationServicePreferenceChanged( message.enabled, message.managed); - } else if (message.action == 'showPage') { + } else if (message.action === 'showPage') { showPage(message.page); - } else if (message.action == 'showErrorPage') { + } else if (message.action === 'showErrorPage') { showErrorPage( message.errorMessage, message.shouldShowSendFeedback, message.shouldShowNetworkTests); - } else if (message.action == 'closeWindow') { + } else if (message.action === 'closeWindow') { closeWindow(); - } else if (message.action == 'setWindowBounds') { + } else if (message.action === 'setWindowBounds') { setWindowBounds( message.displayWorkareaX, message.displayWorkareaY, message.displayWorkareaWidth, message.displayWorkareaHeight); @@ -686,17 +686,17 @@ const pages = doc.getElementsByClassName('section'); for (let i = 0; i < pages.length; i++) { - pages[i].hidden = pages[i].id != pageDivId; + pages[i].hidden = pages[i].id !== pageDivId; } appWindow.show(); - if (pageDivId == 'terms') { + if (pageDivId === 'terms') { termsPage.onShow(); } // Start progress bar animation for the page that has the dynamic progress // bar. 'error' page has the static progress bar that no need to be animated. - if (pageDivId == 'terms' || pageDivId == 'arc-loading') { + if (pageDivId === 'terms' || pageDivId === 'arc-loading') { appWindow.contentWindow.startProgressAnimation(pageDivId); } } @@ -802,7 +802,7 @@ } const details = {code: 'getPrivacyPolicyLink();'}; termsPage.termsView_.executeScript(details, function(results) { - if (results && results.length == 1 && typeof results[0] == 'string') { + if (results && results.length === 1 && typeof results[0] === 'string') { showURLOverlay(results[0]); } else { showURLOverlay(defaultLink);
diff --git a/chrome/browser/resources/chromeos/arc_support/playstore.js b/chrome/browser/resources/chromeos/arc_support/playstore.js index 563d53f..e8e57f9 100644 --- a/chrome/browser/resources/chromeos/arc_support/playstore.js +++ b/chrome/browser/resources/chromeos/arc_support/playstore.js
@@ -8,11 +8,11 @@ */ function getPlayFooterElement() { const elements = document.getElementsByClassName('glue-footer'); - if (!elements || elements.length == 0) { + if (!elements || elements.length === 0) { console.error('Failed to find play-footer element in ToS.'); return null; } - if (elements.length != 1) { + if (elements.length !== 1) { console.error('Found more than one play-footer element in ToS.'); } return elements[0]; @@ -28,11 +28,11 @@ } const elements = footer.getElementsByTagName('select'); - if (!elements || elements.length == 0) { + if (!elements || elements.length === 0) { console.error('Cannot find zone/language select select element'); return null; } - if (elements.length != 1) { + if (elements.length !== 1) { console.error('Found more than one zone/language select element in ToS.'); } return elements[0]; @@ -57,7 +57,7 @@ const matchDefaultUs = null; if (window.location.href.startsWith( 'https://play.google/intl/en_us/play-terms') && - termsLang == 'en' && countryCode == 'us' && + termsLang === 'en' && countryCode === 'us' && selectLangZoneTerms.value.startsWith('/intl/en/play-terms')) { return true; } @@ -84,7 +84,7 @@ return true; } const langSegments = language.split('-'); - if (langSegments.length == 2 && applyTermsForLangAndZone(langSegments[0])) { + if (langSegments.length === 2 && applyTermsForLangAndZone(langSegments[0])) { return true; } @@ -117,7 +117,7 @@ const matchByLang = '/intl/' + language + '_'; let matchByLangShort = null; - if (langSegments.length == 2) { + if (langSegments.length === 2) { matchByLangShort = '/intl/' + langSegments[0] + '_'; } @@ -137,7 +137,7 @@ for (let i = selectLangZoneTerms.options.length - 1; i >= 0; --i) { const option = selectLangZoneTerms.options[i]; - if (selectLangZoneTerms.selectedIndex == i) { + if (selectLangZoneTerms.selectedIndex === i) { langMatch = option.value.startsWith(matchByLang) || (matchByLangShort && option.value.startsWith(matchByLangShort)); continue; @@ -150,7 +150,7 @@ option.hidden = !option.value.startsWith(matchByLang) && !option.value.includes(matchByZone) && !(matchByLangShort && option.value.startsWith(matchByLangShort)) && - option.text != 'English'; + option.text !== 'English'; } if (initialLoad && !langMatch && defaultExist) {
diff --git a/chrome/browser/resources/chromeos/emoji_picker/store.ts b/chrome/browser/resources/chromeos/emoji_picker/store.ts index c82d725..c0481da 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/store.ts +++ b/chrome/browser/resources/chromeos/emoji_picker/store.ts
@@ -4,9 +4,10 @@ import {EmojiPickerApiProxy} from 'emoji_picker_api_proxy.js'; +import {EMOJI_PER_ROW} from './constants.js'; import {CategoryEnum, Emoji, EmojiVariants, Gender, PreferenceMapping, Tone, VisualContent} from './types.js'; -const MAX_RECENTS = 10; +const MAX_RECENTS = EMOJI_PER_ROW * 2; class Store<T> { data: T;
diff --git a/chrome/browser/resources/chromeos/launcher_internals/launcher_internals.ts b/chrome/browser/resources/chromeos/launcher_internals/launcher_internals.ts index 4a01983..2cc2738 100644 --- a/chrome/browser/resources/chromeos/launcher_internals/launcher_internals.ts +++ b/chrome/browser/resources/chromeos/launcher_internals/launcher_internals.ts
@@ -87,13 +87,13 @@ } if (searchResults.length > 0) { - if (this.query != query) { + if (this.query !== query) { // Only reset search results if the query changes. this.$.searchResults.clearResults(); this.query = query; } - if (this.keywords != keywords) { + if (this.keywords !== keywords) { this.keywords = keywords; }
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/demo_preferences.ts b/chrome/browser/resources/chromeos/login/screens/oobe/demo_preferences.ts index bf7ba4e..59fa85a 100644 --- a/chrome/browser/resources/chromeos/login/screens/oobe/demo_preferences.ts +++ b/chrome/browser/resources/chromeos/login/screens/oobe/demo_preferences.ts
@@ -26,6 +26,11 @@ import {getTemplate} from './demo_preferences.html.js'; +// The retailer name input has the max length of 256 characters. +const RETAILER_NAME_INPUT_MAX_LENGTH = 256; +// The store number input has the max length of 256 characters. +const STORE_NUMBER_INPUT_MAX_LENGTH = 256; + const DemoPreferencesScreenBase = mixinBehaviors( [OobeI18nBehavior, OobeDialogHostBehavior, LoginScreenBehavior], @@ -205,12 +210,26 @@ * Based on the country, retailer name, and store number preferences being * correctly set. * + * We need to check all fields (parameters) are not undefined, not null and + * non-empty (console.log(!!"") => false) before checking their value or + * length. + * + * The retailer name must be a non-empty string in the max length of 256 + * characters. + * The store number must be a non-empty numerical string in the max length + * of 256 characters. + * + * TODO(b/324086625): Add help text of the string length limit on the + * retailer name field and store number field. */ private userCanContinue_( retailerNameInput: string, storeNumberInput: string, isCountrySelected: boolean): boolean { - return !!retailerNameInput && RegExp('^[0-9]+$').test(storeNumberInput) && - isCountrySelected; + return !!retailerNameInput && !!isCountrySelected && !!storeNumberInput && + isCountrySelected && + storeNumberInput.length <= STORE_NUMBER_INPUT_MAX_LENGTH && + retailerNameInput.length <= RETAILER_NAME_INPUT_MAX_LENGTH && + RegExp('^[0-9]+$').test(storeNumberInput); } /** @@ -218,6 +237,9 @@ * only consider the input invalid if it's nonempty, thus the different * pattern than in {@link userCanContinue_} * + * TODO(b/324086625): Add help text of the string length limit on the + * retailer name field and store number field on the Demo Mode preferences + * screen. */ private isStoreNumberInputInvalid_(storeNumberInput: string): boolean { return !RegExp('^[0-9]*$').test(storeNumberInput);
diff --git a/chrome/browser/resources/tab_search/BUILD.gn b/chrome/browser/resources/tab_search/BUILD.gn index 5303430..90091769 100644 --- a/chrome/browser/resources/tab_search/BUILD.gn +++ b/chrome/browser/resources/tab_search/BUILD.gn
@@ -43,7 +43,7 @@ "tab_data.ts", "tab_group_color_helper.ts", "tab_search_api_proxy.ts", - "tab_search_sync_browser_proxy.ts", + "tab_search_sign_in_browser_proxy.ts", "tab_search.ts", "tab_search_utils.ts", "title_item.ts",
diff --git a/chrome/browser/resources/tab_search/tab_organization_not_started.html b/chrome/browser/resources/tab_search/tab_organization_not_started.html index 06df4264..661879d 100644 --- a/chrome/browser/resources/tab_search/tab_organization_not_started.html +++ b/chrome/browser/resources/tab_search/tab_organization_not_started.html
@@ -45,9 +45,9 @@ [[getTitle_(showFre)]] </div> <div class="tab-organization-body"> - [[getBody_(showFre, sync_, account_)]] + [[getBody_(showFre, signedIn_)]] <template is="dom-if" - if="[[shouldShowBodyLink_(showFre, sync_, account_)]]"> + if="[[shouldShowBodyLink_(showFre, signedIn_)]]"> <a class="tab-organization-link" role="link" tabindex="0" @@ -58,22 +58,9 @@ </template> </div> </div> - <template is="dom-if" if="[[shouldShowAccountInfo_(sync_, account_)]]"> - <div class="account-row"> - <!-- Decorative image, intentionally empty alt text --> - <img class="account-image" alt="" - src="[[getAccountImageSrc_(account_.avatarImage)]]"> - <div class="account-text"> - <div class="tab-organization-header">[[account_.name]]</div> - <div class="tab-organization-body account-email"> - [[account_.email]] - </div> - </div> - </div> - </template> <cr-button class="action-button" - aria-label="[[getButtonAriaLabel_(sync_, account_)]]" + aria-label="[[getButtonAriaLabel_(showFre, signedIn_)]]" on-click="onButtonClick_"> - [[getButtonText_(sync_, account_)]] + [[getButtonText_(showFre, signedIn_)]] </cr-button> </div>
diff --git a/chrome/browser/resources/tab_search/tab_organization_not_started.ts b/chrome/browser/resources/tab_search/tab_organization_not_started.ts index e73f641..28b6a41 100644 --- a/chrome/browser/resources/tab_search/tab_organization_not_started.ts +++ b/chrome/browser/resources/tab_search/tab_organization_not_started.ts
@@ -12,16 +12,8 @@ import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './tab_organization_not_started.html.js'; -import type {AccountInfo, SyncInfo, TabSearchSyncBrowserProxy} from './tab_search_sync_browser_proxy.js'; -import {TabSearchSyncBrowserProxyImpl} from './tab_search_sync_browser_proxy.js'; - -enum SyncState { - SIGNED_OUT, - UNSYNCED, - UNSYNCED_HISTORY, - SYNC_PAUSED, - SYNCED, -} +import type {TabSearchSignInBrowserProxy} from './tab_search_sign_in_browser_proxy.js'; +import {TabSearchSignInBrowserProxyImpl} from './tab_search_sign_in_browser_proxy.js'; const TabOrganizationNotStartedElementBase = WebUiListenerMixin(PolymerElement); @@ -41,17 +33,15 @@ static get properties() { return { showFre: Boolean, - account_: Object, - sync_: Object, + signedIn_: Boolean, }; } showFre: boolean; - private account_?: AccountInfo; - private sync_?: SyncInfo; - private syncBrowserProxy_: TabSearchSyncBrowserProxy = - TabSearchSyncBrowserProxyImpl.getInstance(); + private signedIn_: boolean = false; + private signInBrowserProxy_: TabSearchSignInBrowserProxy = + TabSearchSignInBrowserProxyImpl.getInstance(); static get template() { return getTemplate(); @@ -60,11 +50,9 @@ override connectedCallback() { super.connectedCallback(); - this.syncBrowserProxy_.getAccountInfo().then(this.setAccount_.bind(this)); - this.addWebUiListener('account-info-changed', this.setAccount_.bind(this)); - - this.syncBrowserProxy_.getSyncInfo().then(this.setSync_.bind(this)); - this.addWebUiListener('sync-info-changed', this.setSync_.bind(this)); + this.signInBrowserProxy_.getSignInState().then( + this.setSignedIn_.bind(this)); + this.addWebUiListener('has-account-changed', this.setSignedIn_.bind(this)); } announceHeader() { @@ -72,26 +60,8 @@ this.$.header.textContent = this.getTitle_(); } - private setAccount_(account: AccountInfo) { - this.account_ = account; - } - - private setSync_(sync: SyncInfo) { - this.sync_ = sync; - } - - private getSyncState_(): SyncState { - if (!this.account_) { - return SyncState.SIGNED_OUT; - } else if (!this.sync_?.syncing) { - return SyncState.UNSYNCED; - } else if (this.sync_.paused) { - return SyncState.SYNC_PAUSED; - } else if (!this.sync_.syncingHistory) { - return SyncState.UNSYNCED_HISTORY; - } else { - return SyncState.SYNCED; - } + private setSignedIn_(signedIn: boolean) { + this.signedIn_ = signedIn; } private getTitle_(): string { @@ -103,101 +73,51 @@ } private getBody_(): string { - switch (this.getSyncState_()) { - case SyncState.SIGNED_OUT: - return loadTimeData.getString('notStartedBodySignedOut'); - case SyncState.UNSYNCED: - return loadTimeData.getString('notStartedBodyUnsynced'); - case SyncState.SYNC_PAUSED: - return loadTimeData.getString('notStartedBodySyncPaused'); - case SyncState.UNSYNCED_HISTORY: - return loadTimeData.getString('notStartedBodyUnsyncedHistory'); - case SyncState.SYNCED: { - if (this.showFre) { - return loadTimeData.getString('notStartedBodyFRE'); - } else { - return loadTimeData.getString('notStartedBody'); - } - } + if (!this.signedIn_) { + return loadTimeData.getString('notStartedBodySignedOut'); + } else if (this.showFre) { + return loadTimeData.getString('notStartedBodyFRE'); + } else { + return loadTimeData.getString('notStartedBody'); } } private shouldShowBodyLink_(): boolean { - return this.getSyncState_() === SyncState.SYNCED && this.showFre; - } - - private shouldShowAccountInfo_(): boolean { - return !!this.account_ && - (!this.sync_ || !this.sync_.syncing || this.sync_.paused || - !this.sync_.syncingHistory); - } - - private getAccountImageSrc_(image: string|null): string { - // image can be undefined if the account has not set an avatar photo. - return image || 'chrome://theme/IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE'; + return this.signedIn_ && this.showFre; } private getButtonAriaLabel_(): string { - switch (this.getSyncState_()) { - case SyncState.SIGNED_OUT: - case SyncState.UNSYNCED: - return loadTimeData.getString('notStartedButtonUnsyncedAriaLabel'); - case SyncState.SYNC_PAUSED: - return loadTimeData.getString('notStartedButtonSyncPausedAriaLabel'); - case SyncState.UNSYNCED_HISTORY: - return loadTimeData.getString( - 'notStartedButtonUnsyncedHistoryAriaLabel'); - case SyncState.SYNCED: - if (this.showFre) { - return loadTimeData.getString('notStartedButtonFREAriaLabel'); - } else { - return loadTimeData.getString('notStartedButtonAriaLabel'); - } + if (!this.signedIn_) { + return loadTimeData.getString('notStartedButtonSignedOutAriaLabel'); + } else if (this.showFre) { + return loadTimeData.getString('notStartedButtonFREAriaLabel'); + } else { + return loadTimeData.getString('notStartedButtonAriaLabel'); } } private getButtonText_(): string { - switch (this.getSyncState_()) { - case SyncState.SIGNED_OUT: - case SyncState.UNSYNCED: - return loadTimeData.getString('notStartedButtonUnsynced'); - case SyncState.SYNC_PAUSED: - return loadTimeData.getString('notStartedButtonSyncPaused'); - case SyncState.UNSYNCED_HISTORY: - return loadTimeData.getString('notStartedButtonUnsyncedHistory'); - case SyncState.SYNCED: - if (this.showFre) { - return loadTimeData.getString('notStartedButtonFRE'); - } else { - return loadTimeData.getString('notStartedButton'); - } + if (!this.signedIn_) { + return loadTimeData.getString('notStartedButtonSignedOut'); + } else if (this.showFre) { + return loadTimeData.getString('notStartedButtonFRE'); + } else { + return loadTimeData.getString('notStartedButton'); } } private onButtonClick_() { - switch (this.getSyncState_()) { - case SyncState.SIGNED_OUT: - case SyncState.UNSYNCED: - this.dispatchEvent( - new CustomEvent('sync-click', {bubbles: true, composed: true})); - break; - case SyncState.SYNC_PAUSED: - this.dispatchEvent( - new CustomEvent('sign-in-click', {bubbles: true, composed: true})); - break; - case SyncState.UNSYNCED_HISTORY: - this.dispatchEvent( - new CustomEvent('settings-click', {bubbles: true, composed: true})); - break; - case SyncState.SYNCED: - // Start a tab organization - this.dispatchEvent(new CustomEvent( - 'organize-tabs-click', {bubbles: true, composed: true})); - chrome.metricsPrivate.recordBoolean( - 'Tab.Organization.AllEntrypoints.Clicked', true); - chrome.metricsPrivate.recordBoolean( - 'Tab.Organization.TabSearch.Clicked', true); - break; + if (!this.signedIn_) { + this.dispatchEvent( + new CustomEvent('sign-in-click', {bubbles: true, composed: true})); + } else { + // Start a tab organization + this.dispatchEvent(new CustomEvent( + 'organize-tabs-click', {bubbles: true, composed: true})); + chrome.metricsPrivate.recordBoolean( + 'Tab.Organization.AllEntrypoints.Clicked', true); + chrome.metricsPrivate.recordBoolean( + 'Tab.Organization.TabSearch.Clicked', true); } }
diff --git a/chrome/browser/resources/tab_search/tab_organization_page.html b/chrome/browser/resources/tab_search/tab_organization_page.html index 7a2b69e..63ca696f 100644 --- a/chrome/browser/resources/tab_search/tab_organization_page.html +++ b/chrome/browser/resources/tab_search/tab_organization_page.html
@@ -54,9 +54,7 @@ <div id="body"> <tab-organization-not-started id="notStarted" shown$="[[isState_(tabOrganizationStateEnum_.kNotStarted, state_)]]" - on-sync-click="onSyncClick_" on-sign-in-click="onSignInClick_" - on-settings-click="onSettingsClick_" on-organize-tabs-click="onOrganizeTabsClick_" on-learn-more-click="onLearnMoreClick_" show-fre="[[showFRE_]]">
diff --git a/chrome/browser/resources/tab_search/tab_organization_page.ts b/chrome/browser/resources/tab_search/tab_organization_page.ts index 50e9e72..a688bfef 100644 --- a/chrome/browser/resources/tab_search/tab_organization_page.ts +++ b/chrome/browser/resources/tab_search/tab_organization_page.ts
@@ -230,18 +230,10 @@ return this.state_ === state; } - private onSyncClick_() { - this.apiProxy_.triggerSync(); - } - private onSignInClick_() { this.apiProxy_.triggerSignIn(); } - private onSettingsClick_() { - this.apiProxy_.openSyncSettings(); - } - private onOrganizeTabsClick_() { this.apiProxy_.requestTabOrganization(); }
diff --git a/chrome/browser/resources/tab_search/tab_search.ts b/chrome/browser/resources/tab_search/tab_search.ts index d7d13d1..aab3cc9 100644 --- a/chrome/browser/resources/tab_search/tab_search.ts +++ b/chrome/browser/resources/tab_search/tab_search.ts
@@ -17,6 +17,6 @@ export {TabSearchGroupItem} from './tab_search_group_item.js'; export {TabSearchItem} from './tab_search_item.js'; export {TabSearchPageElement} from './tab_search_page.js'; -export {AccountInfo, SyncInfo, TabSearchSyncBrowserProxy, TabSearchSyncBrowserProxyImpl} from './tab_search_sync_browser_proxy.js'; +export {TabSearchSignInBrowserProxy, TabSearchSignInBrowserProxyImpl} from './tab_search_sign_in_browser_proxy.js'; export {TabAlertState} from './tabs.mojom-webui.js'; export {TitleItem} from './title_item.js';
diff --git a/chrome/browser/resources/tab_search/tab_search_api_proxy.ts b/chrome/browser/resources/tab_search/tab_search_api_proxy.ts index f98597c..793683a 100644 --- a/chrome/browser/resources/tab_search/tab_search_api_proxy.ts +++ b/chrome/browser/resources/tab_search/tab_search_api_proxy.ts
@@ -51,14 +51,10 @@ triggerFeedback(sessionId: number): void; - triggerSync(): void; - triggerSignIn(): void; openHelpPage(): void; - openSyncSettings(): void; - setUserFeedback( sessionId: number, organizationId: number, feedback: UserFeedback): void; @@ -151,10 +147,6 @@ this.handler.triggerFeedback(sessionId); } - triggerSync() { - this.handler.triggerSync(); - } - triggerSignIn() { this.handler.triggerSignIn(); } @@ -163,10 +155,6 @@ this.handler.openHelpPage(); } - openSyncSettings() { - this.handler.openSyncSettings(); - } - setUserFeedback( sessionId: number, organizationId: number, feedback: UserFeedback) { this.handler.setUserFeedback(sessionId, organizationId, feedback);
diff --git a/chrome/browser/resources/tab_search/tab_search_sign_in_browser_proxy.ts b/chrome/browser/resources/tab_search/tab_search_sign_in_browser_proxy.ts new file mode 100644 index 0000000..ee63733 --- /dev/null +++ b/chrome/browser/resources/tab_search/tab_search_sign_in_browser_proxy.ts
@@ -0,0 +1,32 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {sendWithPromise} from 'chrome://resources/js/cr.js'; + +/** + * @see chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.cc + */ +export interface TabSearchSignInBrowserProxy { + /** + * Returns whether the user is signed in + */ + getSignInState(): Promise<boolean>; +} + +export class TabSearchSignInBrowserProxyImpl implements + TabSearchSignInBrowserProxy { + getSignInState() { + return sendWithPromise('GetSignInState'); + } + + static getInstance(): TabSearchSignInBrowserProxy { + return instance || (instance = new TabSearchSignInBrowserProxyImpl()); + } + + static setInstance(obj: TabSearchSignInBrowserProxy) { + instance = obj; + } +} + +let instance: TabSearchSignInBrowserProxy|null = null;
diff --git a/chrome/browser/resources/tab_search/tab_search_sync_browser_proxy.ts b/chrome/browser/resources/tab_search/tab_search_sync_browser_proxy.ts deleted file mode 100644 index 7e5e1e33..0000000 --- a/chrome/browser/resources/tab_search/tab_search_sync_browser_proxy.ts +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {sendWithPromise} from 'chrome://resources/js/cr.js'; - -/** - * @see chrome/browser/ui/webui/tab_search/tab_search_sync_handler.cc - */ -export interface AccountInfo { - name: string; - email: string; - avatarImage?: string; -} - -export interface SyncInfo { - syncing: boolean; - paused: boolean; - syncingHistory: boolean; -} - -export interface TabSearchSyncBrowserProxy { - /** - * Gets the current sync info. - */ - getSyncInfo(): Promise<SyncInfo>; - - /** - * Gets the current account info. - */ - getAccountInfo(): Promise<AccountInfo>; -} - -export class TabSearchSyncBrowserProxyImpl implements - TabSearchSyncBrowserProxy { - getSyncInfo() { - return sendWithPromise('GetSyncInfo'); - } - - getAccountInfo() { - return sendWithPromise('GetAccountInfo'); - } - - static getInstance(): TabSearchSyncBrowserProxy { - return instance || (instance = new TabSearchSyncBrowserProxyImpl()); - } - - static setInstance(obj: TabSearchSyncBrowserProxy) { - instance = obj; - } -} - -let instance: TabSearchSyncBrowserProxy|null = null;
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc index 173954e..a1b9ec1 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -133,14 +133,6 @@ #include "ui/events/test/test_event.h" #include "ui/views/controls/styled_label.h" -#if BUILDFLAG(ENABLE_EXTENSIONS) -// Delayed warnings feature checks if the Suspicious Site Reporter extension -// is installed. These includes are to fake-install this extension. -#include "chrome/browser/extensions/crx_installer.h" -#include "extensions/browser/test_extension_registry_observer.h" -#include "extensions/common/extension.h" -#endif - #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" #endif @@ -2960,8 +2952,6 @@ host_resolver()->AddRule("*", "127.0.0.1"); content::SetupCrossSiteRedirector(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); - SafeBrowsingUserInteractionObserver:: - ResetSuspiciousSiteReporterExtensionIdForTesting(); } void CreatedBrowserMainParts( @@ -3106,41 +3096,6 @@ } protected: -#if BUILDFLAG(ENABLE_EXTENSIONS) - // Installs an extension and returns its ID. - std::string InstallTestExtension() { - using extensions::CrxInstaller; - using extensions::CrxInstallError; - using extensions::ExtensionService; - using extensions::ExtensionSystem; - - base::FilePath path = ui_test_utils::GetTestFilePath( - base::FilePath().AppendASCII("extensions"), - base::FilePath().AppendASCII("theme.crx")); - ExtensionService* service = - ExtensionSystem::Get(browser()->profile())->extension_service(); - scoped_refptr<CrxInstaller> installer = CrxInstaller::CreateSilent(service); - - installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION); - installer->set_install_immediately(true); - installer->set_allow_silent_install(true); - installer->set_off_store_install_allow_reason( - CrxInstaller::OffStoreInstallAllowedInTest); - installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE); - - base::test::TestFuture<std::optional<CrxInstallError>> done_future; - installer->AddInstallerCallback( - done_future.GetCallback<const std::optional<CrxInstallError>&>()); - - installer->InstallCrx(path); - - auto optional_error = done_future.Get(); - EXPECT_FALSE(optional_error.has_value()); - - return installer->extension()->id(); - } -#endif - base::test::ScopedFeatureList scoped_feature_list_; private: @@ -3213,61 +3168,6 @@ ->GetLastCommittedURL()); } -// Same as KeyPress_WarningShown, but user disabled URL elision by enabling -// "Always Show Full URLs" option. A separate histogram must be recorded. -IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageDelayedWarningBrowserTest, - KeyPress_WarningShown_UrlElisionDisabled) { - constexpr int kTimeOnPage = 10; - browser()->profile()->GetPrefs()->SetBoolean( - omnibox::kPreventUrlElisionsInOmnibox, true); - - base::HistogramTester histograms; - NavigateAndAssertNoInterstitial(); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - // Inject a test clock to test the histogram that records the time on the - // delayed warning page before the warning shows or the user leaves the page. - base::SimpleTestClock clock; - SafeBrowsingUserInteractionObserver* observer = - SafeBrowsingUserInteractionObserver::FromWebContents(web_contents); - ASSERT_TRUE(observer); - clock.SetNow(observer->GetCreationTimeForTesting()); - observer->SetClockForTesting(&clock); - clock.Advance(base::Seconds(kTimeOnPage)); - - // Type something. An interstitial should be shown. - EXPECT_TRUE(TypeAndWaitForInterstitial(browser())); - - EXPECT_TRUE(ClickAndWaitForDetach(browser(), "primary-button")); - AssertNoInterstitial(browser(), false); // Assert the interstitial is gone - EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank" - web_contents->GetLastCommittedURL()); -} - -// Same as KeyPress_WarningShown_UrlElisionDisabled, but user disabled URL -// elision by installing Suspicious Site Reporter extension. -IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageDelayedWarningBrowserTest, - KeyPress_WarningShown_UrlElisionDisabled_Extension) { - const std::string extension_id = InstallTestExtension(); - SafeBrowsingUserInteractionObserver:: - SetSuspiciousSiteReporterExtensionIdForTesting(extension_id.c_str()); - - base::HistogramTester histograms; - NavigateAndAssertNoInterstitial(); - - // Type something. An interstitial should be shown. - EXPECT_TRUE(TypeAndWaitForInterstitial(browser())); - - EXPECT_TRUE(ClickAndWaitForDetach(browser(), "primary-button")); - AssertNoInterstitial(browser(), false); // Assert the interstitial is gone - EXPECT_EQ(GURL(url::kAboutBlankURL), // Back to "about:blank" - browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); -} - IN_PROC_BROWSER_TEST_P(SafeBrowsingBlockingPageDelayedWarningBrowserTest, KeyPress_ESC_WarningNotShown) { base::HistogramTester histograms;
diff --git a/chrome/browser/safe_browsing/user_interaction_observer.cc b/chrome/browser/safe_browsing/user_interaction_observer.cc index cd6fe29..0a4e2d8 100644 --- a/chrome/browser/safe_browsing/user_interaction_observer.cc +++ b/chrome/browser/safe_browsing/user_interaction_observer.cc
@@ -19,25 +19,12 @@ #include "third_party/blink/public/common/input/web_mouse_event.h" #include "ui/events/keycodes/keyboard_codes.h" -#if BUILDFLAG(ENABLE_EXTENSIONS) -#include "extensions/browser/extension_registry.h" -#endif // BUILDFLAG(ENABLE_EXTENSIONS) - using blink::WebInputEvent; -namespace { -// Id for extension that enables users to report sites to Safe Browsing. -const char kPreventElisionExtensionId[] = "jknemblkbdhdcpllfgbfekkdciegfboi"; -} // namespace - namespace safe_browsing { WEB_CONTENTS_USER_DATA_KEY_IMPL(SafeBrowsingUserInteractionObserver); -// static -const char* SafeBrowsingUserInteractionObserver:: - suspicious_site_reporter_extension_id_ = kPreventElisionExtensionId; - SafeBrowsingUserInteractionObserver::SafeBrowsingUserInteractionObserver( content::WebContents* web_contents, const security_interstitials::UnsafeResource& resource, @@ -236,18 +223,6 @@ // DO NOT add code past this point. |this| is destroyed. } -// static -void SafeBrowsingUserInteractionObserver:: - SetSuspiciousSiteReporterExtensionIdForTesting(const char* extension_id) { - suspicious_site_reporter_extension_id_ = extension_id; -} - -// static -void SafeBrowsingUserInteractionObserver:: - ResetSuspiciousSiteReporterExtensionIdForTesting() { - suspicious_site_reporter_extension_id_ = kPreventElisionExtensionId; -} - void SafeBrowsingUserInteractionObserver::SetClockForTesting( base::Clock* clock) { clock_ = clock;
diff --git a/chrome/browser/safe_browsing/user_interaction_observer.h b/chrome/browser/safe_browsing/user_interaction_observer.h index 49d08fa4..3ddb6b9 100644 --- a/chrome/browser/safe_browsing/user_interaction_observer.h +++ b/chrome/browser/safe_browsing/user_interaction_observer.h
@@ -59,14 +59,6 @@ kMaxValue = kWarningShownOnPaste, }; -// Name of the recorded histograms when the user did not disable URL elision via -// "Always Show Full URLs" menu option or by installing Suspicious Site Reporter -// extension. -extern const char kDelayedWarningsTimeOnPageHistogram[]; - -// Same as above but only recorded if the user disabled URL elision. -extern const char kDelayedWarningsTimeOnPageWithElisionDisabledHistogram[]; - // Observes user interactions and shows an interstitial if necessary. // Only created when an interstitial was about to be displayed but was delayed // due to the Delayed Warnings experiment. Deleted once the interstitial is @@ -112,10 +104,6 @@ // a desktop capture. Shows the delayed interstitial immediately. void OnDesktopCaptureRequest(); - static void SetSuspiciousSiteReporterExtensionIdForTesting( - const char* extension_id); - static void ResetSuspiciousSiteReporterExtensionIdForTesting(); - void SetClockForTesting(base::Clock* clock); base::Time GetCreationTimeForTesting() const; @@ -153,9 +141,6 @@ // it the first time the hook is called. bool initial_navigation_finished_ = false; - // Id of the Suspicious Site Reporter extension. Only set in tests. - static const char* suspicious_site_reporter_extension_id_; - // The time that this observer was created. Used for recording histograms. base::Time creation_time_; // This clock is used to record the delta from |creation_time_| when the
diff --git a/chrome/browser/screen_ai/screen_ai_install_state.cc b/chrome/browser/screen_ai/screen_ai_install_state.cc index 3d88d7aa..8817b21 100644 --- a/chrome/browser/screen_ai/screen_ai_install_state.cc +++ b/chrome/browser/screen_ai/screen_ai_install_state.cc
@@ -29,7 +29,7 @@ namespace { const int kScreenAICleanUpDelayInDays = 30; -const char kMinExpectedVersion[] = "121.1"; +const char kMinExpectedVersion[] = "123.1"; bool IsDeviceCompatible() { // Check if the CPU has the required instruction set to run the Screen AI
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 19270d52f..47f3dd6 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1932,8 +1932,8 @@ "webui/tab_search/tab_search_page_handler.h", "webui/tab_search/tab_search_prefs.cc", "webui/tab_search/tab_search_prefs.h", - "webui/tab_search/tab_search_sync_handler.cc", - "webui/tab_search/tab_search_sync_handler.h", + "webui/tab_search/tab_search_sign_in_handler.cc", + "webui/tab_search/tab_search_sign_in_handler.h", "webui/tab_search/tab_search_ui.cc", "webui/tab_search/tab_search_ui.h", "webui/theme_handler.cc", @@ -3689,6 +3689,7 @@ "//ash/webui/personalization_app/proto", "//ash/webui/personalization_app/search:mojo_bindings", "//ash/webui/print_management", + "//ash/webui/print_preview_cros", "//ash/webui/projector_app", "//ash/webui/projector_app/public/mojom:projector_mojo_bindings", "//ash/webui/scanning", @@ -6879,8 +6880,8 @@ if (enable_compose) { sources += [ - "webui/compose/compose_ui.cc", - "webui/compose/compose_ui.h", + "webui/compose/compose_untrusted_ui.cc", + "webui/compose/compose_untrusted_ui.h", ] deps += [ "//chrome/common/compose:mojo_bindings",
diff --git a/chrome/browser/ui/ash/app_list/app_list_search_browsertest.cc b/chrome/browser/ui/ash/app_list/app_list_search_browsertest.cc index 61076a0..86b0be1 100644 --- a/chrome/browser/ui/ash/app_list/app_list_search_browsertest.cc +++ b/chrome/browser/ui/ash/app_list/app_list_search_browsertest.cc
@@ -7,12 +7,14 @@ #include "ash/app_list/views/app_list_search_view.h" #include "ash/app_list/views/search_box_view.h" #include "ash/app_list/views/search_result_list_view.h" +#include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/test/app_list_test_api.h" #include "ash/public/cpp/window_properties.h" #include "ash/shell.h" #include "ash/test/active_window_waiter.h" #include "ash/webui/os_feedback_ui/url_constants.h" +#include "ash/webui/shortcut_customization_ui/url_constants.h" #include "base/run_loop.h" #include "chrome/browser/ash/app_list/app_list_client_impl.h" #include "chrome/browser/ash/app_list/search/test/app_list_search_test_helper.h" @@ -74,13 +76,15 @@ base::RunLoop().RunUntilIdle(); } - void ClickTopSearchResult(aura::Window* primary_root_window, - const std::u16string app_title) { + void ClickTopSearchResult( + aura::Window* primary_root_window, + const std::u16string app_title, + SearchResultListView::SearchResultListType list_type) { SearchResultListView* top_result_list = AppListTestApi().GetTopVisibleSearchResultListView(); ASSERT_TRUE(top_result_list); - EXPECT_EQ(top_result_list->list_type_for_test(), - SearchResultListView::SearchResultListType::kApps); + EXPECT_EQ(top_result_list->list_type_for_test(), list_type); + SearchResultView* top_result_view = top_result_list->GetResultViewAt(0); ASSERT_TRUE(top_result_view); ASSERT_TRUE(top_result_view->result()); @@ -101,6 +105,12 @@ chromeos::features::kCrosWebAppShortcutUiUpdate}; }; +class AppListSearchWithCustomizableShortcutsBrowserTest + : public AppListSearchBrowserTest { + base::test::ScopedFeatureList scoped_feature_list_{ + features::kSearchCustomizableShortcutsInLauncher}; +}; + IN_PROC_BROWSER_TEST_F(AppListSearchBrowserTest, SearchBuiltInApps) { const std::string app_id = web_app::kOsSettingsAppId; aura::Window* const primary_root_window = Shell::GetPrimaryRootWindow(); @@ -109,7 +119,8 @@ ActiveWindowWaiter window_waiter(primary_root_window); - ClickTopSearchResult(primary_root_window, u"Settings"); + ClickTopSearchResult(primary_root_window, u"Settings", + SearchResultListView::SearchResultListType::kApps); // Wait for the OS Settings window to activate. aura::Window* app_window = window_waiter.Wait(); @@ -128,7 +139,8 @@ content::TestNavigationObserver navigation_observer(feedback_url); navigation_observer.StartWatchingNewWebContents(); - ClickTopSearchResult(primary_root_window, u"Feedback"); + ClickTopSearchResult(primary_root_window, u"Feedback", + SearchResultListView::SearchResultListType::kApps); // Wait for the Feedback app to launch. navigation_observer.Wait(); @@ -137,6 +149,49 @@ EXPECT_TRUE(feedback_browser); } +IN_PROC_BROWSER_TEST_F(AppListSearchBrowserTest, OpenShortcutsApp) { + aura::Window* const primary_root_window = Shell::GetPrimaryRootWindow(); + SearchForSystemApp(primary_root_window, u"Key Shortcuts", + web_app::kShortcutCustomizationAppId); + + GURL shortcut_customization_url = GURL(kChromeUIShortcutCustomizationAppURL); + content::TestNavigationObserver navigation_observer( + shortcut_customization_url); + navigation_observer.StartWatchingNewWebContents(); + + ClickTopSearchResult(primary_root_window, u"Key Shortcuts", + SearchResultListView::SearchResultListType::kApps); + + // Wait for the Shortcut Customization app to launch. + navigation_observer.Wait(); + Browser* shortcut_customization_browser = FindSystemWebAppBrowser( + browser()->profile(), SystemWebAppType::SHORTCUT_CUSTOMIZATION); + EXPECT_TRUE(shortcut_customization_browser); +} + +// Flaky. See http://crbug.com/324930012. +IN_PROC_BROWSER_TEST_F(AppListSearchWithCustomizableShortcutsBrowserTest, + DISABLED_OpenShortcutsAppFromShortcut) { + // Launch the app from the Launcher via searching for a shortcut + aura::Window* const primary_root_window = Shell::GetPrimaryRootWindow(); + SearchForSystemApp(primary_root_window, u"Open notifications", + web_app::kShortcutCustomizationAppId); + + GURL shortcut_customization_url = GURL(kChromeUIShortcutCustomizationAppURL); + content::TestNavigationObserver navigation_observer( + shortcut_customization_url); + navigation_observer.StartWatchingNewWebContents(); + + ClickTopSearchResult(primary_root_window, u"Open notifications", + SearchResultListView::SearchResultListType::kHelp); + + // Wait for the Shortcut Customization app to launch. + navigation_observer.Wait(); + Browser* shortcut_customization_browser = FindSystemWebAppBrowser( + browser()->profile(), SystemWebAppType::SHORTCUT_CUSTOMIZATION); + EXPECT_TRUE(shortcut_customization_browser); +} + IN_PROC_BROWSER_TEST_F(AppListSearchWithAppShortcutsBrowserTest, SearchWebAppShortcut) { Profile* profile = ProfileManager::GetActiveUserProfile();
diff --git a/chrome/browser/ui/ash/faster_split_screen_browsertest.cc b/chrome/browser/ui/ash/faster_split_screen_browsertest.cc index b3b2837..2571da6 100644 --- a/chrome/browser/ui/ash/faster_split_screen_browsertest.cc +++ b/chrome/browser/ui/ash/faster_split_screen_browsertest.cc
@@ -65,8 +65,9 @@ ash::SystemWebAppManager::GetForTest(browser()->profile()) ->InstallSystemAppsForTesting(); - // Snap the window to start partial overview. + // Create two browser windows and snap `window` to start partial overview. aura::Window* window = browser()->window()->GetNativeWindow(); + CreateBrowser(browser()->profile()); ash::WindowState* window_state = ash::WindowState::Get(window); const ash::WindowSnapWMEvent primary_snap_event( ash::WM_EVENT_SNAP_PRIMARY, ash::WindowSnapActionSource::kTest); @@ -108,13 +109,15 @@ // restore'd, partial overview auto-snaps the window. See b/314816288. IN_PROC_BROWSER_TEST_F(FasterSplitScreenBrowserTest, AutoSnapWhileInSessionRestore) { - // Snap the window to start partial overview. - aura::Window* window = browser()->window()->GetNativeWindow(); - ash::WindowState* window_state = ash::WindowState::Get(window); + // Create two browser windows and snap `window1` to start partial overview. + aura::Window* window1 = browser()->window()->GetNativeWindow(); + ash::WindowState* window_state = ash::WindowState::Get(window1); + CreateBrowser(browser()->profile()); + const ash::WindowSnapWMEvent primary_snap_event( ash::WM_EVENT_SNAP_PRIMARY, ash::WindowSnapActionSource::kTest); window_state->OnWMEvent(&primary_snap_event); - ash::WaitForOverviewEnterAnimation(); + ash::WaitForOverviewEntered(); ASSERT_TRUE(ash::OverviewController::Get()->InOverviewSession()); // Open a new browser window. Test it gets auto-snapped.
diff --git a/chrome/browser/ui/ash/picker/picker_client_impl.cc b/chrome/browser/ui/ash/picker/picker_client_impl.cc index cb6acfd1..b99606607 100644 --- a/chrome/browser/ui/ash/picker/picker_client_impl.cc +++ b/chrome/browser/ui/ash/picker/picker_client_impl.cc
@@ -148,7 +148,7 @@ app_list_controller_delegate_.GetUrlForSearchResult(*result); if (result_url.has_value()) { picker_results.push_back(ash::PickerSearchResult::BrowsingHistory( - *result_url, result->icon().icon)); + *result_url, result->title(), result->icon().icon)); } else { picker_results.push_back(ash::PickerSearchResult::Text(result->title())); }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc index 580de814..81d7bb0 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -551,8 +551,8 @@ if (chrome::IsRunningInAppMode()) return; - CHECK(fullscreen_start_time_); - if (exclusive_access_tab()) { + // `fullscreen_start_time_` is null if a fullscreen tab moves to a new window. + if (fullscreen_start_time_ && exclusive_access_tab()) { ukm::SourceId source_id = exclusive_access_tab()->GetPrimaryMainFrame()->GetPageUkmSourceId(); ukm::builders::Fullscreen_Exit(source_id)
diff --git a/chrome/browser/ui/tabs/organization/tab_organization_service.cc b/chrome/browser/ui/tabs/organization/tab_organization_service.cc index 4a1be5a7..b506554 100644 --- a/chrome/browser/ui/tabs/organization/tab_organization_service.cc +++ b/chrome/browser/ui/tabs/organization/tab_organization_service.cc
@@ -11,14 +11,14 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/flag_descriptions.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/sync_service_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/organization/request_factory.h" #include "chrome/browser/ui/tabs/organization/tab_organization_session.h" #include "chrome/browser/ui/tabs/organization/tab_sensitivity_cache.h" #include "chrome/browser/ui/tabs/organization/trigger_policies.h" #include "chrome/browser/ui/webui/tab_search/tab_search_prefs.h" -#include "components/sync/service/sync_user_settings.h" +#include "components/signin/public/identity_manager/identity_manager.h" #if BUILDFLAG(IS_CHROMEOS_ASH) #include "base/system/sys_info.h" @@ -118,29 +118,18 @@ } bool TabOrganizationService::CanStartRequest() const { - const syncer::SyncService* const sync_service = - SyncServiceFactory::GetForProfile(profile_); - if (!sync_service) { - return false; - } - - // Sync must be enabled. - if (!sync_service->IsSyncFeatureEnabled()) { - return false; - } - - // Sync must not be paused. - if (!sync_service->IsSyncFeatureActive()) { - return false; - } - - // History Sync must be enabled. - if (!sync_service->GetUserSettings()->GetSelectedTypes().Has( - syncer::UserSelectableType::kHistory)) { - return false; - } - +// The signin flow is not used on ChromeOS. +#if !BUILDFLAG(IS_CHROMEOS) + const signin::IdentityManager* const identity_manager( + IdentityManagerFactory::GetInstance()->GetForProfile(profile_)); + const auto primary_account_info = + identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin); + const auto extended_account_info = + identity_manager->FindExtendedAccountInfo(primary_account_info); + return !extended_account_info.IsEmpty(); +#else return true; +#endif // !BUILDFLAG(IS_CHROMEOS) } void TabOrganizationService::StartRequestIfNotFRE(const Browser* browser) {
diff --git a/chrome/browser/ui/tabs/organization/tab_organization_service_unittest.cc b/chrome/browser/ui/tabs/organization/tab_organization_service_unittest.cc index 5b692b4..21691920 100644 --- a/chrome/browser/ui/tabs/organization/tab_organization_service_unittest.cc +++ b/chrome/browser/ui/tabs/organization/tab_organization_service_unittest.cc
@@ -5,7 +5,7 @@ #include <memory> #include "base/test/scoped_feature_list.h" -#include "chrome/browser/sync/sync_service_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/organization/tab_organization_observer.h" #include "chrome/browser/ui/tabs/organization/tab_organization_service.h" @@ -15,8 +15,7 @@ #include "chrome/browser/ui/ui_features.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "components/sync/test/test_sync_service.h" +#include "components/signin/public/identity_manager/identity_test_utils.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_renderer_host.h" #include "content/public/test/web_contents_tester.h" @@ -30,21 +29,11 @@ constexpr char kValidURL[] = "http://zombo.com"; constexpr char kInvalidURL[] = "chrome://page"; -std::unique_ptr<KeyedService> CreateSyncService( - content::BrowserContext* context) { - return std::make_unique<syncer::TestSyncService>(); -} - } // anonymous namespace class TabOrganizationServiceTest : public BrowserWithTestWindowTest { public: - TabOrganizationServiceTest() - : dependency_manager_subscription_( - BrowserContextDependencyManager::GetInstance() - ->RegisterCreateServicesCallbackForTesting(base::BindRepeating( - &TabOrganizationServiceTest::SetTestingFactories, - base::Unretained(this)))) {} + TabOrganizationServiceTest() {} TabOrganizationServiceTest(const TabOrganizationServiceTest&) = delete; TabOrganizationServiceTest& operator=(const TabOrganizationServiceTest&) = delete; @@ -86,15 +75,20 @@ TestingProfile* profile() { return profile_.get(); } TabOrganizationService* service() { return service_.get(); } - syncer::TestSyncService* sync_service() { return sync_service_; } private: void SetUp() override { feature_list_.InitWithFeatures({features::kTabOrganization}, {}); profile_ = std::make_unique<TestingProfile>(); service_ = std::make_unique<TabOrganizationService>(profile_.get()); - sync_service_ = static_cast<syncer::TestSyncService*>( - SyncServiceFactory::GetInstance()->GetForProfile(profile_.get())); +// The signin flow is not used on ChromeOS. +#if !BUILDFLAG(IS_CHROMEOS) + signin::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile()); + signin::MakeAccountAvailable(identity_manager, "test@example.com"); + signin::SetPrimaryAccount(identity_manager, "test@example.com", + signin::ConsentLevel::kSignin); +#endif // !BUILDFLAG(IS_CHROMEOS) } void TearDown() override { for (auto& browser : browsers_) { @@ -102,19 +96,11 @@ } } - void SetTestingFactories(content::BrowserContext* context) { - SyncServiceFactory::GetInstance()->SetTestingFactory( - context, base::BindRepeating(&CreateSyncService)); - } - content::RenderViewHostTestEnabler rvh_test_enabler_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<TabOrganizationService> service_; std::vector<std::unique_ptr<Browser>> browsers_; base::test::ScopedFeatureList feature_list_; - - raw_ptr<syncer::TestSyncService> sync_service_; - base::CallbackListSubscription dependency_manager_subscription_; }; class MockTabOrganizationObserver : public TabOrganizationObserver { @@ -295,39 +281,23 @@ EXPECT_NE(session->request()->base_tab_id(), std::nullopt); } +// The signin flow is not used on ChromeOS. +#if !BUILDFLAG(IS_CHROMEOS) TEST_F(TabOrganizationServiceTest, CanStartRequest) { - // // Not Synced - sync_service()->SetDisableReasons( - {syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN}); - EXPECT_FALSE(service()->CanStartRequest()); - sync_service()->SetDisableReasons({}); - - // Sync Paused - sync_service()->SetPersistentAuthError(); - EXPECT_FALSE(service()->CanStartRequest()); - sync_service()->ClearAuthError(); - - // Sync History not enabled - ASSERT_TRUE(sync_service()->GetActiveDataTypes().HasAll({syncer::HISTORY})); - sync_service()->GetUserSettings()->SetSelectedTypes(false, {}); - ASSERT_FALSE(sync_service()->GetActiveDataTypes().HasAll({syncer::HISTORY})); + // Not signed in + signin::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile()); + signin::SetPrimaryAccount(identity_manager, "unavailable@example.com", + signin::ConsentLevel::kSignin); EXPECT_FALSE(service()->CanStartRequest()); - sync_service()->GetUserSettings()->SetSelectedTypes( - false, {syncer::UserSelectableType::kHistory}); - EXPECT_TRUE(service()->CanStartRequest()); - - // Should return true if everything is enabled. - sync_service()->GetUserSettings()->SetSelectedTypes(true, {}); + // Signed in + signin::MakeAccountAvailable(identity_manager, "available@example.com"); + signin::SetPrimaryAccount(identity_manager, "available@example.com", + signin::ConsentLevel::kSignin); EXPECT_TRUE(service()->CanStartRequest()); } - -TEST_F(TabOrganizationServiceTest, EnterpriseDisabledPolicy) { - EXPECT_TRUE(service()->CanStartRequest()); - sync_service()->SetDisableReasons( - {syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY}); - EXPECT_FALSE(service()->CanStartRequest()); -} +#endif // !BUILDFLAG(IS_CHROMEOS) TEST_F(TabOrganizationServiceTest, TabStripAddRemoveDestroysSession) { Browser* browser1 = AddBrowser();
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc index bb14cc5..18da142 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -239,6 +239,40 @@ }); } +bool ToolbarActionsModel::IsPolicyBlockedHost(const GURL& url) const { + extensions::ManagementPolicy* policy = + extensions::ExtensionSystem::Get(profile_)->management_policy(); + auto is_enterprise_extension = + [policy](const extensions::Extension& extension) { + return !policy->UserMayModifySettings(&extension, nullptr) || + policy->MustRemainInstalled(&extension, nullptr); + }; + + // `url` is NOT a policy-blockedsite when there are no extensions installed. + if (action_ids().empty()) { + return false; + } + + for (auto& action_id : action_ids()) { + // Skip enterprise extensions since they could still access policy-blocked + // sites. + const extensions::Extension* extension = GetExtensionById(action_id); + if (is_enterprise_extension(*extension)) { + continue; + } + + // `url` is NOT a policy-blocked sit when it's allowed for any + // non-enterprise extension. + if (!extension->permissions_data()->IsPolicyBlockedHost(url)) { + return false; + } + } + + // `url` is a policy-blocked site when it's blocked for every non-enterprise + // extension. + return true; +} + bool ToolbarActionsModel::IsActionPinned(const ActionId& action_id) const { return base::Contains(pinned_action_ids_, action_id); }
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.h b/chrome/browser/ui/toolbar/toolbar_actions_model.h index d41ee2ef..550caa2 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.h
@@ -109,10 +109,14 @@ // Returns true if `action_id` is in the toolbar model. bool HasAction(const ActionId& action_id) const; - // Returns true if `url` is restricted for all extensions with actions in the - // toolbar.ß + // Returns if `url` is restricted for all extensions with actions in the + // toolbar. bool IsRestrictedUrl(const GURL& url) const; + // Returns if `url` is a policy-blocked url for all non-enterprise extensions + // with actions in the toolbar. + bool IsPolicyBlockedHost(const GURL& url) const; + // Returns true if the action is pinned to the toolbar. bool IsActionPinned(const ActionId& action_id) const;
diff --git a/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.cc b/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.cc index 9605acc..d554e95 100644 --- a/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.cc +++ b/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.cc
@@ -14,14 +14,6 @@ #include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" -// Default size from Figma spec. The size of the view will follow the requested -// size of the WebUI, once these are connected. -namespace { - -const char kComposeURL[] = "chrome://compose/"; - -} - namespace chrome { std::unique_ptr<compose::ComposeDialogController> ShowComposeDialog( @@ -56,8 +48,10 @@ Profile* profile = Profile::FromBrowserContext(web_contents_->GetBrowserContext()); - auto bubble_wrapper = std::make_unique<WebUIContentsWrapperT<ComposeUI>>( - GURL(kComposeURL), profile, IDS_COMPOSE_DIALOG_TITLE); + auto bubble_wrapper = + std::make_unique<WebUIContentsWrapperT<ComposeUntrustedUI>>( + GURL(chrome::kChromeUIUntrustedComposeUrl), profile, + IDS_COMPOSE_DIALOG_TITLE); bubble_wrapper->ReloadWebContents(); // This WebUI needs to know the calling BrowserContents so that the compose @@ -102,7 +96,7 @@ } } -WebUIContentsWrapperT<ComposeUI>* +WebUIContentsWrapperT<ComposeUntrustedUI>* ChromeComposeDialogController::GetBubbleWrapper() const { if (bubble_) { return bubble_->bubble_wrapper();
diff --git a/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.h b/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.h index 71f1048..733ebe9c 100644 --- a/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.h +++ b/chrome/browser/ui/views/compose/chrome_compose_dialog_controller.h
@@ -9,7 +9,7 @@ #include "base/scoped_observation.h" #include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h" #include "chrome/browser/ui/views/compose/compose_dialog_view.h" -#include "chrome/browser/ui/webui/compose/compose_ui.h" +#include "chrome/browser/ui/webui/compose/compose_untrusted_ui.h" #include "chrome/browser/ui/webui/top_chrome/webui_contents_wrapper.h" #include "components/compose/core/browser/compose_dialog_controller.h" #include "components/strings/grit/components_strings.h" @@ -39,7 +39,7 @@ // Returns the currently shown compose dialog. Returns nullptr if the dialog // is not currently shown. - WebUIContentsWrapperT<ComposeUI>* GetBubbleWrapper() const; + WebUIContentsWrapperT<ComposeUntrustedUI>* GetBubbleWrapper() const; // Shows the current dialog view, if there is one. void ShowUI() override;
diff --git a/chrome/browser/ui/views/compose/compose_dialog_view.cc b/chrome/browser/ui/views/compose/compose_dialog_view.cc index ef18e50..5ed7130 100644 --- a/chrome/browser/ui/views/compose/compose_dialog_view.cc +++ b/chrome/browser/ui/views/compose/compose_dialog_view.cc
@@ -141,7 +141,7 @@ ComposeDialogView::ComposeDialogView( View* anchor_view, - std::unique_ptr<WebUIContentsWrapperT<ComposeUI>> bubble_wrapper, + std::unique_ptr<WebUIContentsWrapperT<ComposeUntrustedUI>> bubble_wrapper, const gfx::Rect& anchor_bounds, views::BubbleBorder::Arrow anchor_position) : WebUIBubbleDialogView(anchor_view,
diff --git a/chrome/browser/ui/views/compose/compose_dialog_view.h b/chrome/browser/ui/views/compose/compose_dialog_view.h index 3efde30..d58cb12b 100644 --- a/chrome/browser/ui/views/compose/compose_dialog_view.h +++ b/chrome/browser/ui/views/compose/compose_dialog_view.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_UI_VIEWS_COMPOSE_COMPOSE_DIALOG_VIEW_H_ #include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h" -#include "chrome/browser/ui/webui/compose/compose_ui.h" +#include "chrome/browser/ui/webui/compose/compose_untrusted_ui.h" #include "content/public/browser/web_contents.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/view.h" @@ -34,7 +34,7 @@ explicit ComposeDialogView( View* anchor_view, - std::unique_ptr<WebUIContentsWrapperT<ComposeUI>> bubble_wrapper, + std::unique_ptr<WebUIContentsWrapperT<ComposeUntrustedUI>> bubble_wrapper, const gfx::Rect& anchor_bounds, views::BubbleBorder::Arrow anchor_position); @@ -47,7 +47,7 @@ bool HandleContextMenu(content::RenderFrameHost& render_frame_host, const content::ContextMenuParams& params) override; - WebUIContentsWrapperT<ComposeUI>* bubble_wrapper() { + WebUIContentsWrapperT<ComposeUntrustedUI>* bubble_wrapper() { return bubble_wrapper_.get(); } @@ -55,7 +55,7 @@ private: gfx::Rect anchor_bounds_; - std::unique_ptr<WebUIContentsWrapperT<ComposeUI>> bubble_wrapper_; + std::unique_ptr<WebUIContentsWrapperT<ComposeUntrustedUI>> bubble_wrapper_; base::WeakPtrFactory<ComposeDialogView> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc index 0fe8840..54beb79 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc
@@ -328,6 +328,13 @@ label_id = IDS_EXTENSIONS_MENU_MESSAGE_SECTION_RESTRICTED_ACCESS_TEXT; show_label_tooltip = false; break; + case ExtensionsMenuMainPageView::MessageSectionState::kPolicyBlockedAccess: + container_type = ContainerType::kTextContainer; + label_id = IDS_EXTENSIONS_MENU_MESSAGE_SECTION_POLICY_BLOCKED_ACCESS_TEXT; + // Tooltip can only be visible on this state, and if there are any + // enterprise extensions installed. + show_label_tooltip = has_enterprise_extensions; + break; case ExtensionsMenuMainPageView::MessageSectionState::kUserCustomizedAccess: container_type = ContainerType::kRequestsAccessContainer; // This state has a static label, thus we don't need to pass a label id.
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h index 732a880..3f42856 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h +++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h
@@ -40,6 +40,8 @@ enum class MessageSectionState { // Site is restricted to all extensions. kRestrictedAccess, + // Site is restricted all non-enterprise extensions by policy. + kPolicyBlockedAccess, // User can customize each extension's access to the site. kUserCustomizedAccess, // User can customize each extension's access to the site, but a page
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc index f31372e..4cf3be7 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc
@@ -1025,8 +1025,8 @@ EXPECT_EQ(menu_items().size(), 0u); } -// Tests that extension's site permission button is always hidden when site is -// restricted. +// Tests that the site setting toggle, and extensions' site access toggle and +// site permission button are always hidden when site is restricted. TEST_F(ExtensionsMenuMainPageViewUnitTest, RestrictedSite) { constexpr char kExtension[] = "Extension"; constexpr char kEnterpriseExtension[] = "Enterprise extension"; @@ -1046,71 +1046,104 @@ ShowMenu(); ASSERT_EQ(menu_items().size(), 2u); - // Both extension's site permissions button should be hidden. - EXPECT_FALSE( - menu_items()[0]->site_permissions_button_for_testing()->GetVisible()); - EXPECT_FALSE( - menu_items()[1]->site_permissions_button_for_testing()->GetVisible()); + // Verify site setting toggle is not visible, since no extension can customize + // a restricted site. + EXPECT_FALSE(main_page()->GetSiteSettingsToggleForTesting()->GetVisible()); - // Change site settings to "block all extensions". - extensions::PermissionsManagerWaiter waiter( - PermissionsManager::Get(browser()->profile())); - permissions_manager->UpdateUserSiteSetting( - restricted_origin, - PermissionsManager::UserSiteSetting::kBlockAllExtensions); - waiter.WaitForUserPermissionsSettingsChange(); - - // Both extension's site permission button should still be hidden (restricted - // sites have priority over enterprise extensions). + // Verify both extensions': + // - site access toggle is hidden, since site access cannot be changed + // - site permission button is hidden, since restricted sites have priority + // over enterprise extensions. + EXPECT_FALSE(menu_items()[0]->site_access_toggle_for_testing()->GetVisible()); + EXPECT_FALSE(menu_items()[1]->site_access_toggle_for_testing()->GetVisible()); EXPECT_FALSE( menu_items()[0]->site_permissions_button_for_testing()->GetVisible()); EXPECT_FALSE( menu_items()[1]->site_permissions_button_for_testing()->GetVisible()); } -// Tests that the extension's site access toggle is always hidden and site -// permissions button is visible and disabled when site is blocked by policy. +// Tests that the site setting toggle and extension's site access toggle is +// always hidden, and extensions' site permissions button is visible and +// disabled when site is blocked by policy. TEST_F(ExtensionsMenuMainPageViewUnitTest, PolicyBlockedSite) { - // Add a policy blocked site. - extensions::URLPatternSet default_blocked_hosts; + URLPattern default_policy_blocked_pattern = + URLPattern(URLPattern::SCHEME_ALL, "*://*.policy-blocked.com/*"); + + // Add a policy-blocked site. extensions::URLPatternSet default_allowed_hosts; - default_blocked_hosts.AddPattern( - URLPattern(URLPattern::SCHEME_ALL, "*://*.policy-blocked.com/*")); + extensions::URLPatternSet default_blocked_hosts; + default_blocked_hosts.AddPattern(default_policy_blocked_pattern); extensions::PermissionsData::SetDefaultPolicyHostRestrictions( extensions::util::GetBrowserContextId(browser()->profile()), default_blocked_hosts, default_allowed_hosts); - // Install extensions that request host permissions. - InstallExtensionWithHostPermissions("Extension", {"<all_urls>"}); + // Install extensions requesting host permissions. + auto extension = + InstallExtensionWithHostPermissions("Extension", {"<all_urls>"}); + auto enterprise_extension = + InstallEnterpriseExtension("Enterprise extension", + /*host_permissions=*/{"<all_urls>"}); - InstallEnterpriseExtension("Enterprise extension", - /*host_permissions=*/{"<all_urls>"}); + // Allow enterprise extension access to policy-blocked site. + extensions::URLPatternSet allowed_hosts; + extensions::URLPatternSet blocked_hosts; + allowed_hosts.AddPattern(default_policy_blocked_pattern); + enterprise_extension->permissions_data()->SetPolicyHostRestrictions( + blocked_hosts, allowed_hosts); // Navigate to the policy-blocked site. const GURL policy_blocked_url("https://www.policy-blocked.com"); auto restricted_origin = url::Origin::Create(policy_blocked_url); web_contents_tester()->NavigateAndCommit(policy_blocked_url); - // By default, site settings is set to "customize by extension". - PermissionsManager* permissions_manager = PermissionsManager::Get(profile()); - EXPECT_EQ(permissions_manager->GetUserSiteSetting(restricted_origin), - PermissionsManager::UserSiteSetting::kCustomizeByExtension); - ShowMenu(); ASSERT_EQ(menu_items().size(), 2u); - // Both extensions' site access toggle should be hidden, since site access - // cannot be changed. - EXPECT_FALSE(menu_items()[0]->site_access_toggle_for_testing()->GetVisible()); - EXPECT_FALSE(menu_items()[1]->site_access_toggle_for_testing()->GetVisible()); + // Verify site setting toggle is not visible, since no extension can customize + // a policy-blocked site. + EXPECT_FALSE(main_page()->GetSiteSettingsToggleForTesting()->GetVisible()); - // Both extension's site permissions button should be visible and disabled. We - // leave them visible because enterprise extensions can still have access to - // the site, but disabled because site access cannot be changed. + // Retrieve menu items. + ExtensionMenuItemView* enterprise_extension_item = menu_items()[0]; + ExtensionMenuItemView* extension_item = menu_items()[1]; + ASSERT_EQ(enterprise_extension_item->primary_action_button_for_testing() + ->label_text_for_testing(), + u"Enterprise extension"); + ASSERT_EQ(extension_item->primary_action_button_for_testing() + ->label_text_for_testing(), + u"Extension"); + + // Verify both extensions': + // - site access toggle is hidden, since site access cannot be changed + // - site permissions button is visible and disabled. We leave them visible + // because enterprise extensions can still have access to the site, but + // disabled because site access cannot be changed. + EXPECT_FALSE(extension_item->site_access_toggle_for_testing()->GetVisible()); + EXPECT_FALSE(enterprise_extension_item->site_access_toggle_for_testing() + ->GetVisible()); + EXPECT_TRUE( + extension_item->site_permissions_button_for_testing()->GetVisible()); + EXPECT_TRUE(enterprise_extension_item->site_permissions_button_for_testing() + ->GetVisible()); EXPECT_FALSE( - menu_items()[0]->site_permissions_button_for_testing()->GetEnabled()); - EXPECT_FALSE( - menu_items()[1]->site_permissions_button_for_testing()->GetEnabled()); + extension_item->site_permissions_button_for_testing()->GetEnabled()); + EXPECT_FALSE(enterprise_extension_item->site_permissions_button_for_testing() + ->GetEnabled()); + + // Verify site permission button text for: + // - extension is "none", since site is blocked by policy + // - enterprise extension is "on all sites", since site is allowed to the + // extension by policy. + EXPECT_EQ( + extension_item->site_permissions_button_for_testing()->title()->GetText(), + l10n_util::GetStringUTF16( + IDS_EXTENSIONS_MENU_MAIN_PAGE_EXTENSION_SITE_ACCESS_NONE)); + EXPECT_EQ( + enterprise_extension_item->site_permissions_button_for_testing() + ->title() + ->GetText(), + l10n_util::GetStringUTF16( + IDS_EXTENSIONS_MENU_MAIN_PAGE_EXTENSION_SITE_ACCESS_ON_ALL_SITES)); } // Tests that the message section only displays the text container when the @@ -1139,6 +1172,44 @@ } // Tests that the message section only displays the text container when the +// site has policy-blocked access to all non-enterprise extensions. +TEST_F(ExtensionsMenuMainPageViewUnitTest, MessageSection_PolicyBlockedAccess) { + // Add a policy blocked site. + extensions::URLPatternSet default_blocked_hosts; + extensions::URLPatternSet default_allowed_hosts; + default_blocked_hosts.AddPattern( + URLPattern(URLPattern::SCHEME_ALL, "*://*.policy-blocked.com/*")); + extensions::PermissionsData::SetDefaultPolicyHostRestrictions( + extensions::util::GetBrowserContextId(browser()->profile()), + default_blocked_hosts, default_allowed_hosts); + + InstallExtensionWithHostPermissions("Extension", {"<all_urls>"}); + InstallEnterpriseExtension("Enterprise extension", {"<all_urls>"}); + + // Navigate to the policy-blocked site. + const GURL policy_blocked_url("https://www.policy-blocked.com"); + web_contents_tester()->NavigateAndCommit(policy_blocked_url); + + ShowMenu(); + views::View* text_container = main_page()->GetTextContainerForTesting(); + views::View* reload_container = main_page()->GetReloadContainerForTesting(); + views::View* requests_access_container = + main_page()->GetRequestsAccessContainerForTesting(); + + // Only the text container is displayed with policy blocked site message and + // tooltip, when site access is blocked to all non-enterprise extensions. + EXPECT_TRUE(text_container->GetVisible()); + EXPECT_FALSE(reload_container->GetVisible()); + EXPECT_FALSE(requests_access_container->GetVisible()); + EXPECT_EQ( + views::AsViewClass<views::Label>(text_container->children()[0]) + ->GetText(), + l10n_util::GetStringUTF16( + IDS_EXTENSIONS_MENU_MESSAGE_SECTION_POLICY_BLOCKED_ACCESS_TEXT)); + EXPECT_TRUE(text_container->children()[1]->GetVisible()); +} + +// Tests that the message section only displays the text container when the // user has blocked all extensions on the site. TEST_F(ExtensionsMenuMainPageViewUnitTest, MessageSection_UserBlockedAccess) { InstallExtensionWithHostPermissions("Extension", {"<all_urls>"});
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc index 0738d611..baa5fbd 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view_controller.cc
@@ -102,7 +102,9 @@ // Returns whether the site setting toggle for `web_contents` should be visible. bool IsSiteSettingsToggleVisible(const ToolbarActionsModel& toolbar_model, content::WebContents* web_contents) { - return !toolbar_model.IsRestrictedUrl(web_contents->GetLastCommittedURL()); + const GURL& url = web_contents->GetLastCommittedURL(); + return !toolbar_model.IsRestrictedUrl(url) && + !toolbar_model.IsPolicyBlockedHost(url); } // Returns whether the site settings toggle for `web_contents` should be on. @@ -259,10 +261,16 @@ Profile& profile, const ToolbarActionsModel& toolbar_model, content::WebContents& web_contents) { - if (toolbar_model.IsRestrictedUrl(web_contents.GetLastCommittedURL())) { + const GURL& url = web_contents.GetLastCommittedURL(); + if (toolbar_model.IsRestrictedUrl(url)) { return ExtensionsMenuMainPageView::MessageSectionState::kRestrictedAccess; } + if (toolbar_model.IsPolicyBlockedHost(url)) { + return ExtensionsMenuMainPageView::MessageSectionState:: + kPolicyBlockedAccess; + } + PermissionsManager::UserSiteSetting site_setting = PermissionsManager::Get(&profile)->GetUserSiteSetting( web_contents.GetPrimaryMainFrame()->GetLastCommittedOrigin()); @@ -586,10 +594,12 @@ GetMessageSectionState(*browser_->profile(), *toolbar_model_, *web_contents); bool has_enterprise_extensions = false; - // Only kUserBlockedAccess state cares whether there are any extensions - // installed by enterprise. + // Only kUserBlockedAccess or kPolicyBlockedAccess states care whether there + // are any extensions installed by enterprise. if (message_section_state == - ExtensionsMenuMainPageView::MessageSectionState::kUserBlockedAccess) { + ExtensionsMenuMainPageView::MessageSectionState::kUserBlockedAccess || + message_section_state == ExtensionsMenuMainPageView::MessageSectionState:: + kPolicyBlockedAccess) { has_enterprise_extensions = std::any_of( toolbar_model_->action_ids().begin(), toolbar_model_->action_ids().end(),
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc index bd44a6d..c6c9e0b1 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/ui/views/extensions/extensions_menu_view.h" #include "chrome/browser/ui/views/extensions/extensions_request_access_button.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" +#include "chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/toolbar_button_provider.h" #include "chrome/browser/ui/views/toolbar/toolbar_action_hover_card_controller.h" @@ -58,11 +59,6 @@ using ::ui::mojom::DragOperation; -// Flex behavior precedence for the container's views. -constexpr int kFlexOrderExtensionsButton = 1; -constexpr int kFlexOrderRequestAccessButton = 2; -constexpr int kFlexOrderActionView = 3; - base::OnceClosure& GetOnVisibleCallbackForTesting() { static base::NoDestructor<base::OnceClosure> callback; return *callback; @@ -194,11 +190,15 @@ // order preference. extensions_button_->SetProperty( views::kFlexBehaviorKey, - hide_icon_flex_specification.WithOrder(kFlexOrderExtensionsButton)); + hide_icon_flex_specification.WithOrder( + ExtensionsToolbarContainerViewController:: + kFlexOrderExtensionsButton)); if (request_access_button_) { request_access_button_->SetProperty( - views::kFlexBehaviorKey, hide_icon_flex_specification.WithOrder( - kFlexOrderRequestAccessButton)); + views::kFlexBehaviorKey, + hide_icon_flex_specification.WithOrder( + ExtensionsToolbarContainerViewController:: + kFlexOrderRequestAccessButton)); } break; } @@ -505,7 +505,8 @@ views::FlexSpecification(min_flex_rule, views::MaximumFlexSizeRule::kPreferred) .WithWeight(0) - .WithOrder(kFlexOrderActionView)); + .WithOrder(ExtensionsToolbarContainerViewController:: + kFlexOrderActionView)); break; } } else { @@ -972,27 +973,6 @@ UpdateContainerVisibility(); } -void ExtensionsToolbarContainer::WindowControlsOverlayEnabledChanged( - bool enabled) { - if (!main_item()) - return; - - UpdateContainerVisibility(); - - main_item()->ClearProperty(views::kFlexBehaviorKey); - views::MinimumFlexSizeRule min_flex_rule = - views::MinimumFlexSizeRule::kPreferredSnapToZero; - - if (enabled) - min_flex_rule = views::MinimumFlexSizeRule::kPreferred; - - main_item()->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(min_flex_rule, - views::MaximumFlexSizeRule::kPreferred) - .WithOrder(kFlexOrderExtensionsButton)); -} - void ExtensionsToolbarContainer::UpdateSidePanelState(bool is_active) { close_side_panel_button_->SetVisible(is_active); if (is_active) {
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h index f95c241..b63652b 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
@@ -114,6 +114,9 @@ extensions::PermissionsManager::UserSiteSetting site_setting, content::WebContents* web_contents); + // Updates the container visibility and animation as needed. + void UpdateContainerVisibility(); + // Updates the controls visibility. void UpdateControlsVisibility(); @@ -163,13 +166,6 @@ return close_side_panel_button_; } - // Updates the flex layout rules for the extension toolbar container to have - // views::MinimumFlexSizeRule::kPreferred when WindowControlsOverlay (WCO) is - // toggled on for PWAs. Otherwise the extensions icon does not stay visible as - // it is not considered for during the calculation of the preferred size of - // it's parent (in the case of WCO PWAs, WebAppFrameToolbarView). - void WindowControlsOverlayEnabledChanged(bool enabled); - // Called when the side panel state has changed for an extensions side panel // to pop out button reflecting the side panel being open. void UpdateSidePanelState(bool is_active); @@ -281,9 +277,6 @@ void SetExtensionIconVisibility(ToolbarActionsModel::ActionId id, bool visible); - // Calls SetVisible() with ShouldContainerBeVisible(). - void UpdateContainerVisibility(); - // Returns whether the contianer should be showing, e.g. not if there are no // extensions installed, nor if the container is inactive in kAutoHide mode. bool ShouldContainerBeVisible() const;
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.cc index 9074553..e08bb43 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.cc +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.cc
@@ -31,6 +31,26 @@ permissions_manager_observation_.Reset(); } +void ExtensionsToolbarContainerViewController:: + WindowControlsOverlayEnabledChanged(bool enabled) { + if (!extensions_container_->main_item()) { + return; + } + + extensions_container_->UpdateContainerVisibility(); + extensions_container_->main_item()->ClearProperty(views::kFlexBehaviorKey); + + views::MinimumFlexSizeRule min_flex_rule = + enabled ? views::MinimumFlexSizeRule::kPreferred + : views::MinimumFlexSizeRule::kPreferredSnapToZero; + extensions_container_->main_item()->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(min_flex_rule, + views::MaximumFlexSizeRule::kPreferred) + .WithOrder(ExtensionsToolbarContainerViewController:: + kFlexOrderExtensionsButton)); +} + void ExtensionsToolbarContainerViewController::MaybeShowIPH() { // IPH is only shown for the kExtensionsMenuAccessControl feature. if (!base::FeatureList::IsEnabled(
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.h b/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.h index 9a626e5..e88b5b2 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.h +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.h
@@ -15,6 +15,11 @@ public ToolbarActionsModel::Observer, public extensions::PermissionsManager::Observer { public: + // Flex behavior precedence for the container's views. + static constexpr int kFlexOrderExtensionsButton = 1; + static constexpr int kFlexOrderRequestAccessButton = 2; + static constexpr int kFlexOrderActionView = 3; + ExtensionsToolbarContainerViewController( Browser* browser, ExtensionsToolbarContainer* extensions_container); @@ -24,6 +29,13 @@ const ExtensionsToolbarContainerViewController&) = delete; ~ExtensionsToolbarContainerViewController() override; + // Updates the flex layout rules for the extension toolbar container to have + // views::MinimumFlexSizeRule::kPreferred when WindowControlsOverlay (WCO) is + // toggled on for PWAs. Otherwise the extensions icon does not stay visible as + // it is not considered for during the calculation of the preferred size of + // it's parent (in the case of WCO PWAs, WebAppFrameToolbarView). + void WindowControlsOverlayEnabledChanged(bool enabled); + private: // Maybe displays the In-Product-Help with a specific priority order. void MaybeShowIPH();
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_coordinator.h b/chrome/browser/ui/views/extensions/extensions_toolbar_coordinator.h index 1d81c54c..a17dcdd 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_coordinator.h +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_coordinator.h
@@ -21,6 +21,11 @@ const ExtensionsToolbarCoordinator&) = delete; ~ExtensionsToolbarCoordinator(); + ExtensionsToolbarContainerViewController* + GetExtensionsContainerViewController() { + return extensions_container_controller_.get(); + } + private: void ResetCoordinatorState();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc index 14587e0..ba02a15 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
@@ -8,8 +8,11 @@ #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" +#include "base/test/run_until.h" +#include "base/test/test_future.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/app/chrome_command_ids.h" #include "chrome/browser/apps/app_service/app_registry_cache_waiter.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/sessions/session_restore_test_helper.h" @@ -17,76 +20,22 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/view_ids.h" -#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/immersive_mode_controller.h" -#include "chrome/browser/ui/views/frame/immersive_mode_tester.h" -#include "chrome/browser/web_applications/test/prevent_close_test_base.h" -#include "chrome/browser/web_applications/web_app_id_constants.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "chromeos/constants/chromeos_features.h" -#include "chromeos/ui/base/window_properties.h" -#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h" -#include "chromeos/ui/frame/caption_buttons/frame_size_button.h" -#include "components/keep_alive_registry/keep_alive_types.h" -#include "components/keep_alive_registry/scoped_keep_alive.h" -#include "components/services/app_service/public/cpp/app_update.h" -#include "content/public/test/browser_test.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/gfx/geometry/size.h" -#include "ui/views/test/views_test_utils.h" -#include "ui/views/widget/widget.h" - -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/constants/ash_switches.h" -#include "ash/public/cpp/shelf_test_api.h" -#include "ash/public/cpp/split_view_test_api.h" -#include "ash/public/cpp/test/shell_test_api.h" -#include "ash/shell.h" -#include "ash/wm/overview/overview_controller.h" -#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" -#include "ash/wm/tablet_mode/tablet_mode_multitask_menu_controller.h" -#include "ash/wm/tablet_mode/tablet_mode_window_manager.h" -#include "base/functional/callback_helpers.h" -#include "base/ranges/algorithm.h" -#include "base/run_loop.h" -#include "base/scoped_observation.h" -#include "base/test/test_future.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.h" -#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h" -#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h" -#include "chrome/browser/command_updater.h" -#include "chrome/browser/profiles/profile_avatar_icon_util.h" -#include "chrome/browser/profiles/profile_io_data.h" -#include "chrome/browser/sessions/session_service_factory.h" -#include "chrome/browser/ui/ash/multi_user/multi_user_util.h" -#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" -#include "chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h" -#include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" -#include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" -#include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/chromeos/window_pin_util.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" -#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chromeos/test_util.h" +#include "chrome/browser/ui/lacros/window_utility.h" #include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h" -#include "chrome/browser/ui/settings_window_manager_chromeos.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/ui_features.h" +#include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" +#include "chrome/browser/ui/views/frame/app_menu_button.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h" -#include "chrome/browser/ui/views/frame/tab_strip_region_view.h" +#include "chrome/browser/ui/views/frame/immersive_mode_tester.h" #include "chrome/browser/ui/views/frame/webui_tab_strip_container_view.h" -#include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.h" #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h" #include "chrome/browser/ui/views/location_bar/custom_tab_bar_view.h" #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h" @@ -102,55 +51,103 @@ #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" +#include "chrome/browser/web_applications/test/prevent_close_test_base.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/web_app_id_constants.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/browser/web_applications/web_app_provider.h" -#include "chrome/test/base/interactive_test_utils.h" +#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "chromeos/constants/chromeos_features.h" +#include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h" +#include "chromeos/crosapi/mojom/test_controller.mojom.h" +#include "chromeos/lacros/lacros_service.h" #include "chromeos/ui/base/chromeos_ui_constants.h" -#include "chromeos/ui/base/window_pin_type.h" +#include "chromeos/ui/base/window_properties.h" +#include "chromeos/ui/base/window_state_type.h" +#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h" +#include "chromeos/ui/frame/caption_buttons/frame_size_button.h" #include "chromeos/ui/frame/default_frame_header.h" #include "chromeos/ui/frame/frame_header.h" +#include "chromeos/ui/frame/multitask_menu/float_controller_base.h" #include "components/account_id/account_id.h" +#include "components/keep_alive_registry/keep_alive_types.h" +#include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/password_manager/core/browser/password_form.h" +#include "components/services/app_service/public/cpp/app_update.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" -#include "content/public/test/background_color_change_waiter.h" +#include "content/public/test/browser_test.h" #include "content/public/test/content_mock_cert_verifier.h" #include "content/public/test/test_navigation_observer.h" #include "net/dns/mock_host_resolver.h" #include "third_party/blink/public/common/page/page_zoom.h" -#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" -#include "ui/aura/test/env_test_helper.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/window.h" #include "ui/base/class_property.h" #include "ui/base/hit_test.h" #include "ui/base/page_transition_types.h" #include "ui/base/pointer/touch_ui_controller.h" -#include "ui/base/window_open_disposition.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/display/screen.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" #include "ui/events/test/event_generator.h" #include "ui/gfx/color_palette.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/vector_icon_types.h" #include "ui/views/focus/focus_manager.h" -#include "ui/views/view_observer.h" +#include "ui/views/test/views_test_utils.h" +#include "ui/views/test/widget_test.h" +#include "ui/views/widget/widget.h" #include "ui/views/window/caption_button_layout_constants.h" #include "ui/views/window/frame_caption_button.h" -#endif // BUILDFLAG(IS_CHROMEOS_ASH) -#if BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/public/cpp/test/shell_test_api.h" +#include "ash/shell.h" +#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" +#include "ash/wm/tablet_mode/tablet_mode_multitask_menu_controller.h" +#include "ash/wm/tablet_mode/tablet_mode_window_manager.h" +#include "chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.h" +#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h" +#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h" +#include "chrome/browser/profiles/profile_avatar_icon_util.h" +#include "chrome/browser/ui/ash/multi_user/multi_user_util.h" +#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" +#include "chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h" +#include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" +#include "chrome/browser/ui/settings_window_manager_chromeos.h" +#include "content/public/test/background_color_change_waiter.h" +#else // BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chrome/browser/lacros/browser_test_util.h" +#include "chrome/browser/ui/lacros/window_properties.h" #include "chrome/browser/web_applications/app_service/test/loopback_crosapi_app_service_proxy.h" -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) +#include "ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h" +#endif -using views::Widget; +namespace { -// TODO(crbug.com/1235203): Identify tests that should also run under Lacros. +bool WaitForFocus(bool expected, views::View* view) { + return base::test::RunUntil([&]() { return view->HasFocus() == expected; }); +} + +bool WaitForVisible(bool expected, views::View* view) { + return base::test::RunUntil([&]() { return view->GetVisible() == expected; }); +} + +bool WaitForPaintAsActive(bool expected, views::FrameCaptionButton* button) { + return base::test::RunUntil( + [&]() { return button->GetPaintAsActive() == expected; }); +} + +} // namespace using BrowserNonClientFrameViewChromeOSTest = - TopChromeMdParamTest<InProcessBrowserTest>; + TopChromeMdParamTest<ChromeOSBrowserUITest>; using BrowserNonClientFrameViewChromeOSTestNoWebUiTabStrip = WebUiTabStripOverrideTest<false, BrowserNonClientFrameViewChromeOSTest>; using BrowserNonClientFrameViewChromeOSTestWithWebUiTabStrip = @@ -181,19 +178,12 @@ const raw_ptr<BrowserNonClientFrameViewChromeOS> frame_view_; }; -#if BUILDFLAG(IS_CHROMEOS_ASH) -using BrowserNonClientFrameViewChromeOSTouchTest = - TopChromeTouchTest<InProcessBrowserTest>; -using BrowserNonClientFrameViewChromeOSTouchTestWithWebUiTabStrip = - WebUiTabStripOverrideTest<true, BrowserNonClientFrameViewChromeOSTouchTest>; - - // This test does not make sense for the webUI tabstrip, since the window layout // is different in that case. IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTestNoWebUiTabStrip, NonClientHitTest) { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); - Widget* widget = browser_view->GetWidget(); + views::Widget* widget = browser_view->GetWidget(); BrowserNonClientFrameViewChromeOS* frame_view = GetFrameViewChromeOS(browser_view); @@ -210,47 +200,79 @@ // Click in the top edge of a maximized window now hits the client area, // because we want it to fall through to the tab strip and select a tab. - widget->Maximize(); - int expected_value = HTCLIENT; - EXPECT_EQ(expected_value, frame_view->NonClientHitTest(top_edge)); + { + gfx::Rect old_bounds = frame_view->bounds(); + widget->Maximize(); + auto* window = widget->GetNativeWindow(); + ASSERT_TRUE(base::test::RunUntil([&]() { + return window->GetProperty(chromeos::kWindowStateTypeKey) == + chromeos::WindowStateType::kMaximized; + })); + // TODO(crbug.com/1466385): Remove waiting for bounds change when the bug is + // fixed. + ASSERT_TRUE(base::test::RunUntil( + [&]() { return frame_view->bounds() != old_bounds; })); + } + EXPECT_EQ(HTCLIENT, frame_view->NonClientHitTest(top_edge)); } +using BrowserNonClientFrameViewChromeOSTouchTest = + TopChromeTouchTest<ChromeOSBrowserUITest>; + +using BrowserNonClientFrameViewChromeOSTouchTestWithWebUiTabStrip = + WebUiTabStripOverrideTest<true, BrowserNonClientFrameViewChromeOSTouchTest>; + IN_PROC_BROWSER_TEST_F( BrowserNonClientFrameViewChromeOSTouchTestWithWebUiTabStrip, TabletSplitViewNonClientHitTest) { + if (!IsSnapWindowSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); BrowserNonClientFrameViewChromeOS* frame_view = GetFrameViewChromeOS(browser_view); + views::Widget* widget = browser_view->GetWidget(); + aura::Window* window = widget->GetNativeWindow(); + const int expect_y = frame_view->GetBorder() ? frame_view->GetBorder()->GetInsets().top() : 0; EXPECT_EQ(expect_y, frame_view->GetBoundsForClientView().y()); - Widget* widget = browser_view->GetWidget(); - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); - ash::SplitViewTestApi().SnapWindow(widget->GetNativeWindow(), - ash::SnapPosition::kPrimary); + EnterTabletMode(); + SnapWindow(window, crosapi::mojom::SnapPosition::kPrimary); // Touch on the top of the window is interpreted as client hit. gfx::Point top_point(widget->GetWindowBoundsInScreen().width() / 2, 0); EXPECT_EQ(HTCLIENT, frame_view->NonClientHitTest(top_point)); } +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1494785): Find out why the test fails and fix it. May require +// ui_controls for global touch events. +#define MAYBE_TabletSplitViewSwipeDownFromEdgeOpensWebUiTabStrip \ + DISABLED_TabletSplitViewSwipeDownFromEdgeOpensWebUiTabStrip +#else +#define MAYBE_TabletSplitViewSwipeDownFromEdgeOpensWebUiTabStrip \ + TabletSplitViewSwipeDownFromEdgeOpensWebUiTabStrip +#endif IN_PROC_BROWSER_TEST_F( BrowserNonClientFrameViewChromeOSTouchTestWithWebUiTabStrip, - TabletSplitViewSwipeDownFromEdgeOpensWebUiTabStrip) { + MAYBE_TabletSplitViewSwipeDownFromEdgeOpensWebUiTabStrip) { + if (!IsSnapWindowSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); BrowserNonClientFrameViewChromeOS* frame_view = GetFrameViewChromeOS(browser_view); const int expect_y = frame_view->GetBorder() ? frame_view->GetBorder()->GetInsets().top() : 0; EXPECT_EQ(expect_y, frame_view->GetBoundsForClientView().y()); + views::Widget* widget = browser_view->GetWidget(); - Widget* widget = browser_view->GetWidget(); - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); - ash::SplitViewTestApi().SnapWindow(widget->GetNativeWindow(), - ash::SnapPosition::kPrimary); + EnterTabletMode(); + SnapWindow(widget->GetNativeWindow(), crosapi::mojom::SnapPosition::kPrimary); // A point above the window, but not in the center horizontally, as a swipe // down from the top center will show the chromeos tablet mode multitask menu. @@ -263,16 +285,21 @@ event_generator.PressTouch(edge_point); event_generator.MoveTouchBy(0, 100); event_generator.ReleaseTouch(); - ASSERT_TRUE(browser_view->webui_tab_strip()->GetVisible()); + ASSERT_TRUE(WaitForVisible(true, browser_view->webui_tab_strip())); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) // Test that the frame view does not do any painting in non-immersive // fullscreen. // This test does not make sense for the webUI tabstrip, since the frame is not // painted in that case. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1235203): Find out why the test is flaky. +#define MAYBE_NonImmersiveFullscreen DISABLED_NonImmersiveFullscreen +#else +#define MAYBE_NonImmersiveFullscreen NonImmersiveFullscreen +#endif IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTestNoWebUiTabStrip, - NonImmersiveFullscreen) { + MAYBE_NonImmersiveFullscreen) { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); content::WebContents* web_contents = browser_view->GetActiveWebContents(); BrowserNonClientFrameViewChromeOS* frame_view = @@ -284,7 +311,7 @@ // No painting should occur in non-immersive fullscreen. (We enter into tab // fullscreen here because tab fullscreen is non-immersive even on ChromeOS). - EnterFullscreenModeForTabAndWait(browser(), web_contents); + EnterTabFullscreenMode(browser(), web_contents); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_TRUE(browser_view->IsFullscreen()); EXPECT_FALSE(test_api.GetShouldPaint()); @@ -294,15 +321,23 @@ // The frame should be painted again when fullscreen is exited and the caption // buttons should be visible. - ui_test_utils::ToggleFullscreenModeAndWait(browser()); + ExitTabFullscreenMode(browser(), web_contents); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(browser_view->IsFullscreen()); EXPECT_TRUE(test_api.GetShouldPaint()); } // Tests that caption buttons are hidden when entering tab fullscreen. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1235203): Find out why the test is flaky. +#define MAYBE_CaptionButtonsHiddenNonImmersiveFullscreen \ + DISABLED_CaptionButtonsHiddenNonImmersiveFullscreen +#else +#define MAYBE_CaptionButtonsHiddenNonImmersiveFullscreen \ + CaptionButtonsHiddenNonImmersiveFullscreen +#endif IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTestNoWebUiTabStrip, - CaptionButtonsHiddenNonImmersiveFullscreen) { + MAYBE_CaptionButtonsHiddenNonImmersiveFullscreen) { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); content::WebContents* web_contents = browser_view->GetActiveWebContents(); BrowserNonClientFrameViewChromeOS* frame_view = @@ -310,7 +345,7 @@ EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); - EnterFullscreenModeForTabAndWait(browser(), web_contents); + EnterTabFullscreenMode(browser(), web_contents); EXPECT_TRUE(browser_view->IsFullscreen()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); // Caption buttons are hidden. @@ -318,15 +353,13 @@ // The frame should be painted again when fullscreen is exited and the caption // buttons should be visible. - ui_test_utils::ToggleFullscreenModeAndWait(browser()); + ExitTabFullscreenMode(browser(), web_contents); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(browser_view->IsFullscreen()); // Caption button container visible again. EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); } -#if BUILDFLAG(IS_CHROMEOS_ASH) - // There should be no top inset when using the WebUI tab strip since the frame // is invisible. Regression test for crbug.com/1076675 IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTestWithWebUiTabStrip, @@ -340,13 +373,12 @@ BrowserView* const browser_view = BrowserView::GetBrowserViewForBrowser(browser()); - StartOverview(); EXPECT_EQ(0, GetFrameViewChromeOS(browser_view)->GetTopInset(false)); - - EndOverview(); + EnterOverviewMode(); + EXPECT_EQ(0, GetFrameViewChromeOS(browser_view)->GetTopInset(false)); + ExitOverviewMode(); EXPECT_EQ(0, GetFrameViewChromeOS(browser_view)->GetTopInset(false)); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) // Tests to ensure caption buttons are not painted when the WebUI tab strip is // present for the browser window (crbug.com/1362731). @@ -421,7 +453,7 @@ // Check that a layout occurs. BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(new_browser); - Widget* widget = browser_view->GetWidget(); + views::Widget* widget = browser_view->GetWidget(); BrowserNonClientFrameViewChromeOS* frame_view = static_cast<BrowserNonClientFrameViewChromeOS*>( @@ -432,55 +464,17 @@ EXPECT_TRUE(test.size_button()->icon_definition_for_test()); } -#if BUILDFLAG(IS_CHROMEOS_ASH) namespace { -class ViewVisibilityWaiter : public views::ViewObserver { +class WebAppNonClientFrameViewChromeOSTest + : public TopChromeMdParamTest<ChromeOSBrowserUITest> { public: - ViewVisibilityWaiter(views::View* observed_view, bool expected_visible) - : view_(observed_view), expected_visible_(expected_visible) { - observation_.Observe(view_.get()); - } - ViewVisibilityWaiter(const ViewVisibilityWaiter&) = delete; - ViewVisibilityWaiter& operator=(const ViewVisibilityWaiter&) = delete; - ~ViewVisibilityWaiter() override = default; - - // Wait for changes to occur, or return immediately if view already has - // expected visibility. - bool Wait() { - if (expected_visible_ == view_->GetVisible()) { - return true; - } - return future_.Wait(); - } - - private: - // views::ViewObserver: - void OnViewVisibilityChanged(views::View* observed_view, - views::View* starting_view) override { - bool visible = observed_view->GetVisible(); - if (visible == expected_visible_) { - future_.SetValue(); - } - } - - raw_ptr<views::View> view_; - const bool expected_visible_; - base::test::TestFuture<void> future_; - base::ScopedObservation<views::View, views::ViewObserver> observation_{this}; -}; - -class WebAppNonClientFrameViewAshTest - : public TopChromeMdParamTest<InProcessBrowserTest> { - public: - WebAppNonClientFrameViewAshTest() = default; - - WebAppNonClientFrameViewAshTest(const WebAppNonClientFrameViewAshTest&) = - delete; - WebAppNonClientFrameViewAshTest& operator=( - const WebAppNonClientFrameViewAshTest&) = delete; - - ~WebAppNonClientFrameViewAshTest() override = default; + WebAppNonClientFrameViewChromeOSTest() = default; + WebAppNonClientFrameViewChromeOSTest( + const WebAppNonClientFrameViewChromeOSTest&) = delete; + WebAppNonClientFrameViewChromeOSTest& operator=( + const WebAppNonClientFrameViewChromeOSTest&) = delete; + ~WebAppNonClientFrameViewChromeOSTest() override = default; GURL GetAppURL() const { return https_server_.GetURL("app.com", "/ssl/google.html"); @@ -501,24 +495,24 @@ raw_ptr<AppMenuButton, DanglingUntriaged> web_app_menu_button_ = nullptr; void SetUpCommandLine(base::CommandLine* command_line) override { - TopChromeMdParamTest<InProcessBrowserTest>::SetUpCommandLine(command_line); + TopChromeMdParamTest<ChromeOSBrowserUITest>::SetUpCommandLine(command_line); cert_verifier_.SetUpCommandLine(command_line); } void SetUpInProcessBrowserTestFixture() override { TopChromeMdParamTest< - InProcessBrowserTest>::SetUpInProcessBrowserTestFixture(); + ChromeOSBrowserUITest>::SetUpInProcessBrowserTestFixture(); cert_verifier_.SetUpInProcessBrowserTestFixture(); } void TearDownInProcessBrowserTestFixture() override { cert_verifier_.TearDownInProcessBrowserTestFixture(); TopChromeMdParamTest< - InProcessBrowserTest>::TearDownInProcessBrowserTestFixture(); + ChromeOSBrowserUITest>::TearDownInProcessBrowserTestFixture(); } void SetUpOnMainThread() override { - TopChromeMdParamTest<InProcessBrowserTest>::SetUpOnMainThread(); + TopChromeMdParamTest<ChromeOSBrowserUITest>::SetUpOnMainThread(); WebAppToolbarButtonContainer::DisableAnimationForTesting(true); @@ -545,6 +539,14 @@ navigation_observer.StartWatchingNewWebContents(); app_browser_ = web_app::LaunchWebAppBrowser(browser()->profile(), app_id); navigation_observer.WaitForNavigationFinished(); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + { + aura::Window* window = app_browser_->window()->GetNativeWindow(); + std::string id = + lacros_window_utility::GetRootWindowUniqueId(window->GetRootWindow()); + ASSERT_TRUE(browser_test_util::WaitForWindowCreation(id)); + } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) browser_view_ = BrowserView::GetBrowserViewForBrowser(app_browser_); BrowserNonClientFrameViewChromeOS* frame_view = @@ -612,9 +614,10 @@ // Tests that the page info dialog doesn't anchor in a way that puts it outside // of web-app windows. This is important as some platforms don't support bubble // anchor adjustment (see |BubbleDialogDelegateView::CreateBubble()|). -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, PageInfoBubblePosition) { SetUpWebApp(); + // Resize app window to only take up the left half of the screen. views::Widget* widget = browser_view_->GetWidget(); gfx::Size screen_size = @@ -637,29 +640,31 @@ EXPECT_TRUE(widget->GetWindowBoundsInScreen().Contains(page_info_bounds)); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, FocusableViews) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, FocusableViews) { SetUpWebApp(); - EXPECT_TRUE(browser_view_->contents_web_view()->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, browser_view_->contents_web_view())); browser_view_->GetFocusManager()->AdvanceFocus(false); - EXPECT_TRUE(web_app_menu_button_->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, web_app_menu_button_)); browser_view_->GetFocusManager()->AdvanceFocus(false); - EXPECT_TRUE(browser_view_->contents_web_view()->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, browser_view_->contents_web_view())); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, ButtonVisibilityInOverviewMode) { SetUpWebApp(); - EXPECT_TRUE(web_app_frame_toolbar_->GetVisible()); + ASSERT_TRUE(WaitForVisible(true, web_app_frame_toolbar_)); - StartOverview(); + EnterOverviewMode(); views::test::RunScheduledLayout(browser_view_); - EXPECT_FALSE(web_app_frame_toolbar_->GetVisible()); - EndOverview(); + ASSERT_TRUE(WaitForVisible(false, web_app_frame_toolbar_)); + + ExitOverviewMode(); views::test::RunScheduledLayout(browser_view_); - EXPECT_TRUE(web_app_frame_toolbar_->GetVisible()); + ASSERT_TRUE(WaitForVisible(true, web_app_frame_toolbar_)); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, FrameThemeColorIsSet) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, + FrameThemeColorIsSet) { SetUpWebApp(); aura::Window* window = browser_view_->GetWidget()->GetNativeWindow(); EXPECT_EQ(GetThemeColor(), @@ -671,7 +676,7 @@ // Make sure that for web apps, the height of the frame doesn't exceed the // height of the caption buttons. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, FrameSize) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, FrameSize) { SetUpWebApp(); const int inset = GetFrameViewChromeOS(browser_view_)->GetTopInset(false); EXPECT_EQ(inset, views::GetCaptionButtonLayoutSize( @@ -681,13 +686,13 @@ EXPECT_GE(inset, web_app_frame_toolbar_->size().height()); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, IsToolbarButtonProvider) { SetUpWebApp(); EXPECT_EQ(browser_view_->toolbar_button_provider(), web_app_frame_toolbar_); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, ShowManagePasswordsIcon) { SetUpWebApp(); content::WebContents* web_contents = @@ -706,12 +711,10 @@ ->OnPasswordAutofilled({&password_form}, url::Origin::Create(password_form.url), nullptr); chrome::ManagePasswordsForPage(app_browser_); - // Wait for manage_passwords_icon to become visible. - ViewVisibilityWaiter waiter(manage_passwords_icon, true); - ASSERT_TRUE(waiter.Wait()); + ASSERT_TRUE(WaitForVisible(true, manage_passwords_icon)); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, ShowZoomIcon) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, ShowZoomIcon) { SetUpWebApp(); content::WebContents* web_contents = app_browser_->tab_strip_model()->GetActiveWebContents(); @@ -724,13 +727,11 @@ EXPECT_FALSE(ZoomBubbleView::GetZoomBubble()); zoom_controller->SetZoomLevel(blink::PageZoomFactorToZoomLevel(1.5)); - // Wait for zoom_icon to become visible. - ViewVisibilityWaiter waiter(zoom_icon, true); - ASSERT_TRUE(waiter.Wait()); + ASSERT_TRUE(WaitForVisible(true, zoom_icon)); EXPECT_TRUE(ZoomBubbleView::GetZoomBubble()); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, ShowFindIcon) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, ShowFindIcon) { SetUpWebApp(); PageActionIconView* find_icon = GetPageActionIcon(PageActionIconType::kFind); @@ -739,10 +740,11 @@ chrome::Find(app_browser_); - EXPECT_TRUE(find_icon->GetVisible()); + ASSERT_TRUE(WaitForVisible(true, find_icon)); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, ShowTranslateIcon) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, + ShowTranslateIcon) { SetUpWebApp(); PageActionIconView* translate_icon = GetPageActionIcon(PageActionIconType::kTranslate); @@ -756,42 +758,45 @@ "en", "fr", translate::TranslateErrors::NONE, true); - EXPECT_TRUE(translate_icon->GetVisible()); + ASSERT_TRUE(WaitForVisible(true, translate_icon)); } // Tests that the focus toolbar command focuses the app menu button in web-app // windows. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, BrowserCommandFocusToolbarAppMenu) { SetUpWebApp(); + ASSERT_TRUE(WaitForFocus(true, browser_view_->contents_web_view())); + EXPECT_FALSE(web_app_menu_button_->HasFocus()); chrome::ExecuteCommand(app_browser_, IDC_FOCUS_TOOLBAR); - EXPECT_TRUE(web_app_menu_button_->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, web_app_menu_button_)); } -// TODO(): Flaky crash on Chrome OS debug. // Tests that the focus toolbar command focuses content settings icons before // the app menu button when present in web-app windows. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, - DISABLED_BrowserCommandFocusToolbarGeolocation) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, + BrowserCommandFocusToolbarGeolocation) { SetUpWebApp(); + ContentSettingImageView* geolocation_icon = GrantGeolocationPermission(); // In order to receive focus, the geo icon must be laid out (and be both // visible and nonzero size). RunScheduledLayouts(); + ASSERT_TRUE(WaitForFocus(true, browser_view_->contents_web_view())); EXPECT_FALSE(web_app_menu_button_->HasFocus()); EXPECT_FALSE(geolocation_icon->HasFocus()); chrome::ExecuteCommand(app_browser_, IDC_FOCUS_TOOLBAR); + ASSERT_TRUE(WaitForFocus(true, geolocation_icon)); EXPECT_FALSE(web_app_menu_button_->HasFocus()); - EXPECT_TRUE(geolocation_icon->HasFocus()); } // Tests that the show app menu command opens the app menu for web-app windows. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, BrowserCommandShowAppMenu) { SetUpWebApp(); EXPECT_EQ(nullptr, GetAppMenu()); @@ -801,16 +806,18 @@ // Tests that the focus next pane command focuses the app menu for web-app // windows. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, BrowserCommandFocusNextPane) { SetUpWebApp(); + ASSERT_TRUE(WaitForFocus(true, browser_view_->contents_web_view())); EXPECT_FALSE(web_app_menu_button_->HasFocus()); chrome::ExecuteCommand(app_browser_, IDC_FOCUS_NEXT_PANE); - EXPECT_TRUE(web_app_menu_button_->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, web_app_menu_button_)); } // Tests the app icon and title are not shown. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, IconAndTitleNotShown) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, + IconAndTitleNotShown) { SetUpWebApp(); auto* browser_view = BrowserView::GetBrowserViewForBrowser(app_browser_); EXPECT_FALSE(browser_view->ShouldShowWindowIcon()); @@ -818,9 +825,10 @@ } // Tests that the custom tab bar is focusable from the keyboard. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, CustomTabBarIsFocusable) { SetUpWebApp(); + ASSERT_TRUE(WaitForFocus(true, browser_view_->contents_web_view())); auto* browser_view = BrowserView::GetBrowserViewForBrowser(app_browser_); @@ -831,25 +839,27 @@ auto* custom_tab_bar = browser_view->toolbar()->custom_tab_bar(); chrome::ExecuteCommand(app_browser_, IDC_FOCUS_NEXT_PANE); - ASSERT_TRUE(web_app_menu_button_->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, web_app_menu_button_)); EXPECT_FALSE(custom_tab_bar->close_button_for_testing()->HasFocus()); chrome::ExecuteCommand(app_browser_, IDC_FOCUS_NEXT_PANE); - EXPECT_TRUE(custom_tab_bar->close_button_for_testing()->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, custom_tab_bar->close_button_for_testing())); } // Tests that the focus previous pane command focuses the app menu for web-app // windows. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, BrowserCommandFocusPreviousPane) { SetUpWebApp(); + ASSERT_TRUE(WaitForFocus(true, browser_view_->contents_web_view())); EXPECT_FALSE(web_app_menu_button_->HasFocus()); chrome::ExecuteCommand(app_browser_, IDC_FOCUS_PREVIOUS_PANE); - EXPECT_TRUE(web_app_menu_button_->HasFocus()); + ASSERT_TRUE(WaitForFocus(true, web_app_menu_button_)); } // Tests that a web app's content settings icons can be interacted with. -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, ContentSettingIcons) { +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, + ContentSettingIcons) { SetUpWebApp(); for (ContentSettingImageView* view : *content_setting_views_) { EXPECT_FALSE(view->GetVisible()); @@ -872,20 +882,29 @@ } // Regression test for https://crbug.com/839955 -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, ActiveStateOfButtonMatchesWidget) { SetUpWebApp(); chromeos::FrameCaptionButtonContainerView::TestApi test( GetFrameViewChromeOS(browser_view_)->caption_button_container()); - EXPECT_TRUE(test.size_button()->GetPaintAsActive()); + + EXPECT_TRUE(WaitForPaintAsActive(true, test.size_button())); EXPECT_TRUE(GetPaintingAsActive()); - browser_view_->GetWidget()->Deactivate(); - EXPECT_FALSE(test.size_button()->GetPaintAsActive()); + DeactivateWidget(browser_view_->GetWidget()); + EXPECT_TRUE(WaitForPaintAsActive(false, test.size_button())); EXPECT_FALSE(GetPaintingAsActive()); } -IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, PopupHasNoToolbar) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1507735): Reenable the test once the GetLastActive() race +// condition is fixed. +#define MAYBE_PopupHasNoToolbar DISABLED_PopupHasNoToolbar +#else +#define MAYBE_PopupHasNoToolbar PopupHasNoToolbar +#endif +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewChromeOSTest, + MAYBE_PopupHasNoToolbar) { SetUpWebApp(); { NavigateParams navigate_params(app_browser_, GetAppURL(), @@ -904,7 +923,6 @@ EXPECT_FALSE(browser_view->web_app_frame_toolbar_for_testing() && browser_view->web_app_frame_toolbar_for_testing()->GetVisible()); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) // Test the normal type browser's kTopViewInset is always 0. IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTest, TopViewInset) { @@ -912,12 +930,10 @@ ImmersiveModeController* immersive_mode_controller = browser_view->immersive_mode_controller(); aura::Window* window = browser()->window()->GetNativeWindow(); - EXPECT_FALSE(immersive_mode_controller->IsEnabled()); EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); // The kTopViewInset should be 0 when in immersive mode. - ui_test_utils::ToggleFullscreenModeAndWait(browser()); - EXPECT_TRUE(immersive_mode_controller->IsEnabled()); + EnterImmersiveFullscreenMode(browser()); EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); // An immersive reveal shows the top of the frame. @@ -930,18 +946,20 @@ // End the reveal and exit immersive mode. // The kTopViewInset should be 0 when immersive mode is exited. revealed_lock.reset(); - ui_test_utils::ToggleFullscreenModeAndWait(browser()); - EXPECT_FALSE(immersive_mode_controller->IsEnabled()); + ExitImmersiveFullscreenMode(browser()); EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); } -#if BUILDFLAG(IS_CHROMEOS_ASH) // Test that for a browser window, its caption buttons are always hidden in // tablet mode. IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTest, BrowserHeaderVisibilityInTabletModeTest) { + if (!IsSnapWindowSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); - Widget* widget = browser_view->GetWidget(); + views::Widget* widget = browser_view->GetWidget(); BrowserNonClientFrameViewChromeOS* frame_view = GetFrameViewChromeOS(browser_view); @@ -957,9 +975,9 @@ EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); } - StartOverview(); + EnterOverviewMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - EndOverview(); + ExitOverviewMode(); // Caption buttons are not supported when using the WebUI tab strip. if (browser_view->webui_tab_strip()) { @@ -968,32 +986,24 @@ EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); } - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EnterTabletMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - StartOverview(); + EnterOverviewMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - EndOverview(); + ExitOverviewMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - ash::SplitViewTestApi().SnapWindow(widget->GetNativeWindow(), - ash::SnapPosition::kPrimary); + SnapWindow(widget->GetNativeWindow(), crosapi::mojom::SnapPosition::kPrimary); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) // Regression test for https://crbug.com/879851. // Tests that we don't accidentally change the color of app frame title bars. // Update expectation if change is intentional. IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTest, AppFrameColor) { - browser()->window()->Close(); + Browser* app_browser = + CreateBrowserForApp("test_browser_app", browser()->profile()); - // Open a new app window. - Browser* app_browser = Browser::Create(Browser::CreateParams::CreateForApp( - "test_browser_app", true /* trusted_source */, gfx::Rect(), - browser()->profile(), true /* user_gesture */)); aura::Window* window = app_browser->window()->GetNativeWindow(); - window->Show(); - SkColor active_frame_color = window->GetProperty(chromeos::kFrameActiveColorKey); @@ -1061,7 +1071,8 @@ views::Button* GetWindowCloseButton(Browser* browser) { auto* const browser_view = BrowserView::GetBrowserViewForBrowser(browser); - auto* const frame_view = GetFrameViewChromeOS(browser_view); + auto* const frame_view = + ChromeOSBrowserUITest::GetFrameViewChromeOS(browser_view); chromeos::FrameCaptionButtonContainerView::TestApi test_api( frame_view->caption_button_container()); @@ -1123,28 +1134,20 @@ ClearWebAppSettings(); } -#if BUILDFLAG(IS_CHROMEOS_ASH) IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTest, ImmersiveModeTopViewInset) { - browser()->window()->Close(); + Browser* app_browser = + CreateBrowserForApp("test_browser_app", browser()->profile()); - // Open a new app window. - Browser::CreateParams params = Browser::CreateParams::CreateForApp( - "test_browser_app", true /* trusted_source */, gfx::Rect(), - browser()->profile(), true); - params.initial_show_state = ui::SHOW_STATE_DEFAULT; - Browser* browser = Browser::Create(params); - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + BrowserView* browser_view = + BrowserView::GetBrowserViewForBrowser(app_browser); ImmersiveModeController* immersive_mode_controller = browser_view->immersive_mode_controller(); - aura::Window* window = browser->window()->GetNativeWindow(); - window->Show(); - EXPECT_FALSE(immersive_mode_controller->IsEnabled()); + aura::Window* window = app_browser->window()->GetNativeWindow(); EXPECT_LT(0, window->GetProperty(aura::client::kTopViewInset)); // The kTopViewInset should be 0 when in immersive mode. - ui_test_utils::ToggleFullscreenModeAndWait(browser); - EXPECT_TRUE(immersive_mode_controller->IsEnabled()); + EnterImmersiveFullscreenMode(app_browser); EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); // An immersive reveal shows the top of the frame. @@ -1158,13 +1161,12 @@ // The kTopViewInset should be larger than 0 again when immersive mode is // exited. revealed_lock.reset(); - ui_test_utils::ToggleFullscreenModeAndWait(browser); - EXPECT_FALSE(immersive_mode_controller->IsEnabled()); + ExitImmersiveFullscreenMode(app_browser); EXPECT_LT(0, window->GetProperty(aura::client::kTopViewInset)); // The kTopViewInset is the same as in overview mode. const int inset_normal = window->GetProperty(aura::client::kTopViewInset); - StartOverview(); + EnterOverviewMode(); const int inset_in_overview_mode = window->GetProperty(aura::client::kTopViewInset); EXPECT_EQ(inset_normal, inset_in_overview_mode); @@ -1175,19 +1177,12 @@ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); ImmersiveModeController* immersive_mode_controller = browser_view->immersive_mode_controller(); - ASSERT_FALSE(immersive_mode_controller->IsEnabled()); - ASSERT_FALSE(browser_view->IsFullscreen()); - // Enter immersive mode. - ui_test_utils::ToggleFullscreenModeAndWait(browser()); - ASSERT_TRUE(immersive_mode_controller->IsEnabled()); - ASSERT_TRUE(browser_view->IsFullscreen()); - - // Enable tablet mode. - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EnterImmersiveFullscreenMode(browser()); // Should exit immersive mode + fullscreen when tablet mode is enabled. + EnterTabletMode(); + ImmersiveModeTester(browser()).WaitForFullscreenToExit(); EXPECT_FALSE(immersive_mode_controller->IsEnabled()); EXPECT_FALSE(browser_view->IsFullscreen()); } @@ -1200,43 +1195,38 @@ ASSERT_FALSE(immersive_mode_controller->IsEnabled()); ASSERT_FALSE(browser_view->IsFullscreen()); - // Enter tablet mode. - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EnterTabletMode(); - // Enter immersive mode. - ui_test_utils::ToggleFullscreenModeAndWait(browser()); // Should be able to enter immersive mode even when the tablet mode is // enabled. - ASSERT_TRUE(immersive_mode_controller->IsEnabled()); - ASSERT_TRUE(browser_view->IsFullscreen()); + EnterImmersiveFullscreenMode(browser()); } // TODO(b/270175923): Consider using WebUiTabStripOverrideTest, since it // makes sense for it to always be enabled. using FloatBrowserNonClientFrameViewChromeOSTest = - TopChromeMdParamTest<InProcessBrowserTest>; + TopChromeMdParamTest<ChromeOSBrowserUITest>; +// TODO(crbug.com/1494785): Port this test to Lacros. +#if BUILDFLAG(IS_CHROMEOS_ASH) IN_PROC_BROWSER_TEST_P(FloatBrowserNonClientFrameViewChromeOSTest, TabletModeMultitaskMenu) { ui::ScopedAnimationDurationScaleMode test_duration_mode( ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EnterTabletMode(); BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); - Widget* widget = browser_view->GetWidget(); + views::Widget* widget = browser_view->GetWidget(); aura::Window* window = widget->GetNativeWindow(); ui::test::EventGenerator event_generator(window->GetRootWindow()); // A normal tap on the top center of the window and in the omnibox // bounds will focus the omnibox. - const gfx::Rect omnibox_bounds = - browser_view->GetViewByID(VIEW_ID_OMNIBOX)->GetBoundsInScreen(); + views::View* omnibox = browser_view->GetViewByID(VIEW_ID_OMNIBOX); + const gfx::Rect omnibox_bounds = omnibox->GetBoundsInScreen(); ASSERT_NO_FATAL_FAILURE( event_generator.GestureTapAt(omnibox_bounds.top_center())); - ASSERT_NO_FATAL_FAILURE( - ui_test_utils::WaitForViewFocus(browser(), VIEW_ID_OMNIBOX, true)); + ASSERT_TRUE(WaitForFocus(true, omnibox)); // Swipe down from the top center opens the multitask menu. event_generator.SetTouchRadius(10, 5); @@ -1244,8 +1234,7 @@ event_generator.PressTouch(top_center); event_generator.MoveTouchBy(0, 100); event_generator.ReleaseTouch(); - ASSERT_NO_FATAL_FAILURE( - ui_test_utils::WaitForViewFocus(browser(), VIEW_ID_OMNIBOX, false)); + ASSERT_TRUE(WaitForFocus(false, omnibox)); auto* multitask_menu_event_handler = ash::TabletModeControllerTestApi() .tablet_mode_window_manager() @@ -1260,53 +1249,60 @@ // Tap on the omnibox outside the menu takes focus and closes the menu. ASSERT_NO_FATAL_FAILURE( event_generator.GestureTapAt(omnibox_bounds.left_center())); - ASSERT_NO_FATAL_FAILURE( - ui_test_utils::WaitForViewFocus(browser(), VIEW_ID_OMNIBOX, true)); + ASSERT_TRUE(WaitForFocus(true, omnibox)); EXPECT_FALSE(multitask_menu_event_handler->multitask_menu()); } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) IN_PROC_BROWSER_TEST_P(FloatBrowserNonClientFrameViewChromeOSTest, BrowserHeaderVisibilityInTabletModeTest) { + if (!IsSnapWindowSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); BrowserNonClientFrameViewChromeOS* frame_view = GetFrameViewChromeOS(browser_view); - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); - EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); + EnterTabletMode(); + ASSERT_TRUE(WaitForVisible(false, frame_view->caption_button_container())); - Widget* widget = browser_view->GetWidget(); + aura::Window* window = browser_view->GetWidget()->GetNativeWindow(); auto* immersive_controller = chromeos::ImmersiveFullscreenController::Get( - views::Widget::GetWidgetForNativeView(widget->GetNativeWindow())); + views::Widget::GetWidgetForNativeView(window)); - // Snap a window. No immersive mode from regular browsers. - ash::SplitViewTestApi().SnapWindow(widget->GetNativeWindow(), - ash::SnapPosition::kSecondary); - EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); + // Snap the window. No immersive mode from regular browsers. + SnapWindow(window, crosapi::mojom::SnapPosition::kSecondary); + ASSERT_TRUE(WaitForVisible(false, frame_view->caption_button_container())); EXPECT_FALSE(immersive_controller->IsEnabled()); - // Float the window; the title bar is visible. - ui::test::EventGenerator event_generator( - widget->GetNativeWindow()->GetRootWindow()); - event_generator.PressAndReleaseKeyAndModifierKeys( - ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN); - EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); + // Float the window; the title bar becomes visible. + chromeos::FloatControllerBase::Get()->SetFloat( + window, chromeos::FloatStartLocation::kBottomRight); + ASSERT_TRUE(WaitForVisible(true, frame_view->caption_button_container())); EXPECT_FALSE(immersive_controller->IsEnabled()); } // Test that for a browser app window, its caption buttons may or may not hide // in tablet mode. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1505656): Finish porting to Lacros when the bug is fixed. +#define MAYBE_BrowserAppHeaderVisibilityInTabletModeTest \ + DISABLED_BrowserAppHeaderVisibilityInTabletModeTest +#else +#define MAYBE_BrowserAppHeaderVisibilityInTabletModeTest \ + BrowserAppHeaderVisibilityInTabletModeTest +#endif IN_PROC_BROWSER_TEST_P(FloatBrowserNonClientFrameViewChromeOSTest, - BrowserAppHeaderVisibilityInTabletModeTest) { - // Create a browser app window. - Browser::CreateParams params = Browser::CreateParams::CreateForApp( - "test_browser_app", /*trusted_source=*/true, gfx::Rect(), - browser()->profile(), true); - params.initial_show_state = ui::SHOW_STATE_DEFAULT; - Browser* browser2 = Browser::Create(params); - AddBlankTabAndShow(browser2); + MAYBE_BrowserAppHeaderVisibilityInTabletModeTest) { + if (!IsSnapWindowSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + + Browser* browser2 = + CreateBrowserForApp("test_browser_app", browser()->profile()); BrowserView* browser_view2 = BrowserView::GetBrowserViewForBrowser(browser2); - Widget* widget2 = browser_view2->GetWidget(); + views::Widget* widget2 = browser_view2->GetWidget(); BrowserNonClientFrameViewChromeOS* frame_view2 = GetFrameViewChromeOS(browser_view2); widget2->GetNativeWindow()->SetProperty( @@ -1314,25 +1310,24 @@ aura::client::kResizeBehaviorCanMaximize | aura::client::kResizeBehaviorCanResize); - StartOverview(); + EnterOverviewMode(); EXPECT_FALSE(frame_view2->caption_button_container()->GetVisible()); - EndOverview(); + ExitOverviewMode(); EXPECT_TRUE(frame_view2->caption_button_container()->GetVisible()); - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); - StartOverview(); + EnterTabletMode(); + EnterOverviewMode(); EXPECT_FALSE(frame_view2->caption_button_container()->GetVisible()); - - EndOverview(); + ExitOverviewMode(); EXPECT_TRUE(frame_view2->caption_button_container()->GetVisible()); auto* immersive_controller = chromeos::ImmersiveFullscreenController::Get( views::Widget::GetWidgetForNativeView(widget2->GetNativeWindow())); + EXPECT_TRUE(immersive_controller->IsEnabled()); // Snap a window. Immersive mode is enabled so its title bar is not visible. - ash::SplitViewTestApi().SnapWindow(widget2->GetNativeWindow(), - ash::SnapPosition::kSecondary); + SnapWindow(widget2->GetNativeWindow(), + crosapi::mojom::SnapPosition::kSecondary); EXPECT_TRUE(frame_view2->caption_button_container()->GetVisible()); EXPECT_TRUE(immersive_controller->IsEnabled()); @@ -1362,37 +1357,18 @@ browser_view->GetWidget()->GetNativeWindow()->GetRootWindow()); event_generator.PressAndReleaseKeyAndModifierKeys(ui::VKEY_Z, ui::EF_COMMAND_DOWN); - ASSERT_TRUE(size_button->IsMultitaskMenuShown()); + ASSERT_TRUE(base::test::RunUntil( + [&]() { return size_button->IsMultitaskMenuShown(); })); // Pressing accelerator a second time should close the menu. event_generator.PressAndReleaseKeyAndModifierKeys(ui::VKEY_Z, ui::EF_COMMAND_DOWN); - ASSERT_FALSE(size_button->IsMultitaskMenuShown()); + ASSERT_TRUE(base::test::RunUntil( + [&]() { return !size_button->IsMultitaskMenuShown(); })); } -namespace { - -class HomeLauncherBrowserNonClientFrameViewChromeOSTest - : public TopChromeMdParamTest<InProcessBrowserTest> { - public: - HomeLauncherBrowserNonClientFrameViewChromeOSTest() = default; - - HomeLauncherBrowserNonClientFrameViewChromeOSTest( - const HomeLauncherBrowserNonClientFrameViewChromeOSTest&) = delete; - HomeLauncherBrowserNonClientFrameViewChromeOSTest& operator=( - const HomeLauncherBrowserNonClientFrameViewChromeOSTest&) = delete; - - ~HomeLauncherBrowserNonClientFrameViewChromeOSTest() override = default; - - void SetUpDefaultCommandLine(base::CommandLine* command_line) override { - TopChromeMdParamTest<InProcessBrowserTest>::SetUpDefaultCommandLine( - command_line); - - command_line->AppendSwitch(ash::switches::kAshEnableTabletMode); - } -}; - -} // namespace +using HomeLauncherBrowserNonClientFrameViewChromeOSTest = + BrowserNonClientFrameViewChromeOSTest; IN_PROC_BROWSER_TEST_P(HomeLauncherBrowserNonClientFrameViewChromeOSTest, TabletModeBrowserCaptionButtonVisibility) { @@ -1407,17 +1383,15 @@ EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); } - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EnterTabletMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - StartOverview(); + EnterOverviewMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - EndOverview(); + ExitOverviewMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(false)); + ExitTabletMode(); // Caption buttons are not supported when using the WebUI tab strip. if (browser_view->webui_tab_strip()) { @@ -1434,27 +1408,27 @@ // |BrowserNonClientFrameViewChromeOS|. IN_PROC_BROWSER_TEST_P(HomeLauncherBrowserNonClientFrameViewChromeOSTest, CaptionButtonVisibilityForBrowserLaunchedInTabletMode) { - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); - auto* frame_view = GetFrameViewChromeOS(BrowserView::GetBrowserViewForBrowser( - CreateBrowser(browser()->profile()))); + EnterTabletMode(); + auto* new_browser = CreateBrowser(browser()->profile()); + auto* frame_view = + GetFrameViewChromeOS(BrowserView::GetBrowserViewForBrowser(new_browser)); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); } +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1505656): Finish porting to Lacros when the bug is fixed. +#define MAYBE_TabletModeAppCaptionButtonVisibility \ + DISABLED_TabletModeAppCaptionButtonVisibility +#else +#define MAYBE_TabletModeAppCaptionButtonVisibility \ + TabletModeAppCaptionButtonVisibility +#endif IN_PROC_BROWSER_TEST_P(HomeLauncherBrowserNonClientFrameViewChromeOSTest, - TabletModeAppCaptionButtonVisibility) { - browser()->window()->Close(); - - // Open a new app window. - Browser::CreateParams params = Browser::CreateParams::CreateForApp( - "test_browser_app", true /* trusted_source */, gfx::Rect(), - browser()->profile(), true); - params.initial_show_state = ui::SHOW_STATE_DEFAULT; - Browser* browser = Browser::Create(params); - ASSERT_TRUE(browser->is_type_app()); - browser->window()->Show(); - - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + MAYBE_TabletModeAppCaptionButtonVisibility) { + Browser* app_browser = + CreateBrowserForApp("test_browser_app", browser()->profile()); + BrowserView* browser_view = + BrowserView::GetBrowserViewForBrowser(app_browser); BrowserNonClientFrameViewChromeOS* frame_view = GetFrameViewChromeOS(browser_view); EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); @@ -1463,20 +1437,18 @@ EXPECT_FALSE(immersive_mode_controller->IsEnabled()); // Tablet mode doesn't affect app's caption button's visibility. - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EnterTabletMode(); EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); EXPECT_FALSE(browser_view->IsFullscreen()); EXPECT_TRUE(immersive_mode_controller->IsEnabled()); // However, overview mode does. - StartOverview(); + EnterOverviewMode(); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); - EndOverview(); + ExitOverviewMode(); EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(false)); + ExitTabletMode(); EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); EXPECT_FALSE(browser_view->IsFullscreen()); EXPECT_FALSE(immersive_mode_controller->IsEnabled()); @@ -1485,7 +1457,7 @@ namespace { class TabSearchFrameCaptionButtonTest - : public TopChromeMdParamTest<InProcessBrowserTest> { + : public TopChromeMdParamTest<ChromeOSBrowserUITest> { public: TabSearchFrameCaptionButtonTest() = default; TabSearchFrameCaptionButtonTest(const TabSearchFrameCaptionButtonTest&) = @@ -1497,7 +1469,7 @@ void SetUp() override { scoped_feature_list_.InitAndEnableFeature( features::kChromeOSTabSearchCaptionButton); - TopChromeMdParamTest<InProcessBrowserTest>::SetUp(); + TopChromeMdParamTest<ChromeOSBrowserUITest>::SetUp(); } private: @@ -1520,6 +1492,8 @@ test.custom_button()); } +// TODO(crbug.com/1494785): Port this kiosk test to Lacros? +#if BUILDFLAG(IS_CHROMEOS_ASH) namespace { class KioskBrowserNonClientFrameViewChromeOSTest @@ -1542,7 +1516,7 @@ EXPECT_EQ(BrowserList::GetInstance()->size(), 1u); auto* browser_view = BrowserView::GetBrowserViewForBrowser(BrowserList::GetInstance()->get(0)); - auto* frame_view = GetFrameViewChromeOS(browser_view); + auto* frame_view = ChromeOSBrowserUITest::GetFrameViewChromeOS(browser_view); EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); auto* widget = browser_view->GetWidget(); @@ -1557,25 +1531,20 @@ EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); EXPECT_FALSE(immersive_controller->IsEnabled()); } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) -namespace { - -class LockedFullscreenBrowserNonClientFrameViewChromeOSTest - : public TopChromeMdParamTest<InProcessBrowserTest> { - public: - LockedFullscreenBrowserNonClientFrameViewChromeOSTest() = default; - LockedFullscreenBrowserNonClientFrameViewChromeOSTest( - const LockedFullscreenBrowserNonClientFrameViewChromeOSTest&) = delete; - LockedFullscreenBrowserNonClientFrameViewChromeOSTest& operator=( - const LockedFullscreenBrowserNonClientFrameViewChromeOSTest&) = delete; - ~LockedFullscreenBrowserNonClientFrameViewChromeOSTest() override = default; -}; - -} // namespace +using LockedFullscreenBrowserNonClientFrameViewChromeOSTest = + TopChromeMdParamTest<ChromeOSBrowserUITest>; IN_PROC_BROWSER_TEST_P(LockedFullscreenBrowserNonClientFrameViewChromeOSTest, ToggleTabletMode) { + if (!IsIsShelfVisibleSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); + EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); + // Set locked fullscreen state. PinWindow(browser_view->GetWidget()->GetNativeWindow(), /*trusted=*/true); @@ -1583,24 +1552,25 @@ // we're at it, also make sure that the shelf is hidden. EXPECT_TRUE(browser_view->GetWidget()->IsFullscreen()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // TODO(crbug.com/1466385): Enable this assertion once the bug is fixed (at + // the moment PinWindow returns too early). +#else EXPECT_FALSE(IsShelfVisible()); +#endif auto* widget = browser_view->GetWidget(); auto* immersive_controller = chromeos::ImmersiveFullscreenController::Get( views::Widget::GetWidgetForNativeView(widget->GetNativeWindow())); EXPECT_FALSE(immersive_controller->IsEnabled()); - // Enter tablet mode. - ASSERT_NO_FATAL_FAILURE( - ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EnterTabletMode(); EXPECT_TRUE(browser_view->GetWidget()->IsFullscreen()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(IsShelfVisible()); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - // The remaining tests make sense only for Ash, not for Lacros. #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -1896,14 +1866,14 @@ INSTANTIATE_TEST_SUITE(BrowserNonClientFrameViewChromeOSTest); INSTANTIATE_TEST_SUITE(BrowserNonClientFrameViewChromeOSTestNoWebUiTabStrip); INSTANTIATE_TEST_SUITE(BrowserNonClientFrameViewChromeOSTestWithWebUiTabStrip); - -#if BUILDFLAG(IS_CHROMEOS_ASH) -INSTANTIATE_TEST_SUITE(BrowserNonClientFrameViewAshTest); -INSTANTIATE_TEST_SUITE(BrowserNonClientFrameViewAshTestNoWebUiTabStrip); INSTANTIATE_TEST_SUITE(FloatBrowserNonClientFrameViewChromeOSTest); INSTANTIATE_TEST_SUITE(HomeLauncherBrowserNonClientFrameViewChromeOSTest); -INSTANTIATE_TEST_SUITE(KioskBrowserNonClientFrameViewChromeOSTest); INSTANTIATE_TEST_SUITE(LockedFullscreenBrowserNonClientFrameViewChromeOSTest); INSTANTIATE_TEST_SUITE(TabSearchFrameCaptionButtonTest); -INSTANTIATE_TEST_SUITE(WebAppNonClientFrameViewAshTest); +INSTANTIATE_TEST_SUITE(WebAppNonClientFrameViewChromeOSTest); + +#if BUILDFLAG(IS_CHROMEOS_ASH) +INSTANTIATE_TEST_SUITE(BrowserNonClientFrameViewAshTestNoWebUiTabStrip); +INSTANTIATE_TEST_SUITE(BrowserNonClientFrameViewAshTest); +INSTANTIATE_TEST_SUITE(KioskBrowserNonClientFrameViewChromeOSTest); #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc deleted file mode 100644 index fdeaaf6..0000000 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h" - -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/test/base/ui_test_utils.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_delegate.h" -#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/non_client_view.h" - -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/public/cpp/shelf_test_api.h" -#include "ash/shell.h" -#include "ash/wm/overview/overview_controller.h" -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - -// Enters fullscreen mode for tab and waits for the notification. -void EnterFullscreenModeForTabAndWait(Browser* browser, - content::WebContents* web_contents) { - ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = true}); - static_cast<content::WebContentsDelegate*>(browser) - ->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame(), {}); - waiter.Wait(); -} - -// Exits fullscreen mode for tab and waits for the notification. -void ExitFullscreenModeForTabAndWait(Browser* browser, - content::WebContents* web_contents) { - ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = false}); - browser->exclusive_access_manager() - ->fullscreen_controller() - ->ExitFullscreenModeForTab(web_contents); - waiter.Wait(); -} - -BrowserNonClientFrameViewChromeOS* GetFrameViewChromeOS( - BrowserView* browser_view) { - // We know we're using ChromeOS, so static cast. - auto* frame_view = static_cast<BrowserNonClientFrameViewChromeOS*>( - browser_view->GetWidget()->non_client_view()->frame_view()); - DCHECK(frame_view); - return frame_view; -} - -#if BUILDFLAG(IS_CHROMEOS_ASH) -void StartOverview() { - ash::Shell::Get()->overview_controller()->StartOverview( - ash::OverviewStartAction::kTests); -} - -void EndOverview() { - ash::Shell::Get()->overview_controller()->EndOverview( - ash::OverviewEndAction::kTests); -} - -bool IsShelfVisible() { - return ash::ShelfTestApi().IsVisible(); -} -#endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h deleted file mode 100644 index 58b83ce..0000000 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_CHROMEOS_TEST_UTILS_H_ -#define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_CHROMEOS_TEST_UTILS_H_ - -#include "build/chromeos_buildflags.h" - -class Browser; -class BrowserView; -class BrowserNonClientFrameViewChromeOS; - -namespace content { -class WebContents; -} - -// Enters fullscreen mode for tab and waits for the notification. -void EnterFullscreenModeForTabAndWait(Browser* browser, - content::WebContents* web_contents); - -// Exits fullscreen mode for tab and waits for the notification. -void ExitFullscreenModeForTabAndWait(Browser* browser, - content::WebContents* web_contents); - -// Returns the non client frame view for |browser_view|. -BrowserNonClientFrameViewChromeOS* GetFrameViewChromeOS( - BrowserView* browser_view); - -#if BUILDFLAG(IS_CHROMEOS_ASH) -// Starts overview session which displays an overview of all windows. -void StartOverview(); - -// Ends overview session. -void EndOverview(); - -// Returns true if the shelf is visible (e.g. not auto-hidden). -bool IsShelfVisible(); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - -#endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_CHROMEOS_TEST_UTILS_H_
diff --git a/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc b/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc index 2313d2a..7b80390 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_browser_view_test.cc
@@ -7,9 +7,8 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/chromeos/window_pin_util.h" +#include "chrome/browser/ui/chromeos/test_util.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h" @@ -36,7 +35,7 @@ namespace { class ImmersiveModeBrowserViewTest - : public TopChromeMdParamTest<InProcessBrowserTest> { + : public TopChromeMdParamTest<ChromeOSBrowserUITest> { public: ImmersiveModeBrowserViewTest() = default; ImmersiveModeBrowserViewTest(const ImmersiveModeBrowserViewTest&) = delete; @@ -44,7 +43,7 @@ delete; ~ImmersiveModeBrowserViewTest() override = default; - // TopChromeMdParamTest<InProcessBrowserTest>: + // TopChromeMdParamTest<ChromeOSBrowserUITest>: void PreRunTestOnMainThread() override { InProcessBrowserTest::PreRunTestOnMainThread(); @@ -66,8 +65,15 @@ // This test does not make sense for the webUI tabstrip, since the frame is not // painted in that case. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1255304): Reveal does not end until mouse is moved. Find out +// if this is a product or test issue and fix it. +#define MAYBE_ImmersiveFullscreen DISABLED_ImmersiveFullscreen +#else +#define MAYBE_ImmersiveFullscreen ImmersiveFullscreen +#endif IN_PROC_BROWSER_TEST_P(ImmersiveModeBrowserViewTestNoWebUiTabStrip, - ImmersiveFullscreen) { + MAYBE_ImmersiveFullscreen) { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); content::WebContents* web_contents = browser_view->GetActiveWebContents(); BrowserNonClientFrameViewChromeOS* frame_view = @@ -90,7 +96,7 @@ // Enter both browser fullscreen and tab fullscreen. Entering browser // fullscreen should enable immersive fullscreen. ui_test_utils::ToggleFullscreenModeAndWait(browser()); - EnterFullscreenModeForTabAndWait(browser(), web_contents); + EnterTabFullscreenMode(browser(), web_contents); EXPECT_TRUE(immersive_mode_controller->IsEnabled()); // Caption button container is hidden. EXPECT_FALSE(frame_view->caption_button_container_->GetVisible()); @@ -116,7 +122,7 @@ EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); // Repeat test but without tab fullscreen. - ExitFullscreenModeForTabAndWait(browser(), web_contents); + EnterTabFullscreenMode(browser(), web_contents); // Immersive reveal should have same behavior as before. revealed_lock = immersive_mode_controller->GetRevealedLock( @@ -161,6 +167,7 @@ IN_PROC_BROWSER_TEST_P(ImmersiveModeBrowserViewTest, TabNavigationAcceleratorsFullscreenBrowser) { ImmersiveModeTester tester(browser()); + // Make sure that the focus is on the webcontents rather than on the omnibox, // because if the focus is on the omnibox, the tab strip will remain revealed // in the immersive fullscreen mode and will interfere with this test waiting @@ -176,10 +183,8 @@ ASSERT_TRUE(AddTabAtIndex(0, about_blank, ui::PAGE_TRANSITION_TYPED)); browser()->tab_strip_model()->GetActiveWebContents()->Focus(); - // Toggle fullscreen mode. - chrome::ToggleFullscreenMode(browser()); - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); - EXPECT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); + EnterImmersiveFullscreenMode(browser()); + // Wait for the end of the initial reveal which results from adding the new // tabs and changing the focused tab. tester.VerifyTabIndexAfterReveal(0); @@ -210,11 +215,7 @@ // for the revealer to be dismissed. browser()->tab_strip_model()->GetActiveWebContents()->Focus(); - // Toggle fullscreen mode. - chrome::ToggleFullscreenMode(browser()); - EXPECT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); - - EXPECT_TRUE(browser()->window()->IsFullscreen()); + EnterImmersiveFullscreenMode(browser()); EXPECT_FALSE(browser()->window()->IsMaximized()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsRevealed()); @@ -223,8 +224,6 @@ ImmersiveModeController::ANIMATE_REVEAL_NO); EXPECT_TRUE(browser_view->immersive_mode_controller()->IsRevealed()); - ImmersiveModeTester tester(browser()); - // Clicking the "restore" caption button should exit the immersive mode. aura::Window* window = browser()->window()->GetNativeWindow(); ui::test::EventGenerator event_generator(window->GetRootWindow()); @@ -237,84 +236,82 @@ event_generator.MoveMouseTo(point_in_restore_button); EXPECT_TRUE(browser_view->immersive_mode_controller()->IsRevealed()); event_generator.ClickLeftButton(); - tester.WaitForFullscreenToExit(); - + ImmersiveModeTester(browser()).WaitForFullscreenToExit(); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(browser()->window()->IsFullscreen()); } IN_PROC_BROWSER_TEST_P(ImmersiveModeBrowserViewTest, TestCaptionButtonsReceiveEventsInAppImmersiveMode) { - browser()->window()->Close(); - // Open a new app window. - Browser::CreateParams params = Browser::CreateParams::CreateForApp( - "test_browser_app", true /* trusted_source */, gfx::Rect(0, 0, 300, 300), - browser()->profile(), true); - params.initial_show_state = ui::SHOW_STATE_DEFAULT; - Browser* browser = Browser::Create(params); - ASSERT_TRUE(browser->is_type_app()); - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + Browser* app_browser = + CreateBrowserForApp("test_browser_app", browser()->profile()); + BrowserView* app_view = BrowserView::GetBrowserViewForBrowser(app_browser); chromeos::ImmersiveFullscreenControllerTestApi( static_cast<ImmersiveModeControllerChromeos*>( - browser_view->immersive_mode_controller()) + app_view->immersive_mode_controller()) ->controller()) .SetupForTest(); - // Toggle fullscreen mode. - chrome::ToggleFullscreenMode(browser); - EXPECT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); - EXPECT_FALSE(browser_view->GetTabStripVisible()); - - EXPECT_TRUE(browser->window()->IsFullscreen()); - EXPECT_FALSE(browser->window()->IsMaximized()); - EXPECT_FALSE(browser_view->immersive_mode_controller()->IsRevealed()); + EnterImmersiveFullscreenMode(app_browser); + EXPECT_TRUE(app_browser->window()->IsFullscreen()); + EXPECT_FALSE(app_browser->window()->IsMaximized()); + EXPECT_FALSE(app_view->GetTabStripVisible()); + EXPECT_FALSE(app_view->immersive_mode_controller()->IsRevealed()); std::unique_ptr<ImmersiveRevealedLock> revealed_lock = - browser_view->immersive_mode_controller()->GetRevealedLock( + app_view->immersive_mode_controller()->GetRevealedLock( ImmersiveModeController::ANIMATE_REVEAL_NO); - EXPECT_TRUE(browser_view->immersive_mode_controller()->IsRevealed()); + EXPECT_TRUE(app_view->immersive_mode_controller()->IsRevealed()); - ImmersiveModeTester tester(browser); - AddBlankTabAndShow(browser); + AddBlankTabAndShow(app_browser); // Clicking the "restore" caption button should exit the immersive mode. - aura::Window* window = browser->window()->GetNativeWindow(); - ui::test::EventGenerator event_generator(window->GetRootWindow(), window); + aura::Window* app_window = app_browser->window()->GetNativeWindow(); + ui::test::EventGenerator event_generator(app_window->GetRootWindow(), + app_window); gfx::Size button_size = views::GetCaptionButtonLayoutSize( views::CaptionButtonLayoutSize::kBrowserCaptionMaximized); gfx::Point point_in_restore_button( - window->GetBoundsInRootWindow().top_right()); + app_window->GetBoundsInRootWindow().top_right()); point_in_restore_button.Offset(-2 * button_size.width(), button_size.height() / 2); event_generator.MoveMouseTo(point_in_restore_button); - EXPECT_TRUE(browser_view->immersive_mode_controller()->IsRevealed()); + EXPECT_TRUE(app_view->immersive_mode_controller()->IsRevealed()); event_generator.ClickLeftButton(); - tester.WaitForFullscreenToExit(); - - EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); - EXPECT_FALSE(browser->window()->IsFullscreen()); + ImmersiveModeTester(app_browser).WaitForFullscreenToExit(); + EXPECT_FALSE(app_view->immersive_mode_controller()->IsEnabled()); + EXPECT_FALSE(app_browser->window()->IsFullscreen()); } // Regression test for crbug.com/796171. Make sure that going from regular // fullscreen to locked fullscreen does not cause a crash. // Also test that the immersive mode is disabled afterwards (and the shelf is // hidden, and the fullscreen control popup doesn't show up). +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/1508249): Reenable test when bug is fixed. +#define MAYBE_RegularToLockedFullscreenDisablesImmersive \ + DISABLED_RegularToLockedFullscreenDisablesImmersive +#else +#define MAYBE_RegularToLockedFullscreenDisablesImmersive \ + RegularToLockedFullscreenDisablesImmersive +#endif IN_PROC_BROWSER_TEST_P(ImmersiveModeBrowserViewTest, - RegularToLockedFullscreenDisablesImmersive) { - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); + MAYBE_RegularToLockedFullscreenDisablesImmersive) { + if (!IsIsShelfVisibleSupported()) { + GTEST_SKIP() << "Ash is too old."; + } - // Toggle fullscreen mode. - chrome::ToggleFullscreenMode(browser()); - EXPECT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); + EnterImmersiveFullscreenMode(browser()); // Set locked fullscreen state. PinWindow(browser()->window()->GetNativeWindow(), /*trusted=*/true); // We're fullscreen, immersive is disabled in locked fullscreen, and while // we're at it, also make sure that the shelf is hidden. + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); EXPECT_TRUE(browser_view->GetWidget()->IsFullscreen()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(IsShelfVisible()); @@ -332,6 +329,10 @@ // fullscreen control popup doesn't show up). IN_PROC_BROWSER_TEST_P(ImmersiveModeBrowserViewTest, LockedFullscreenDisablesImmersive) { + if (!IsIsShelfVisibleSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); EXPECT_FALSE(browser_view->GetWidget()->IsFullscreen()); @@ -342,7 +343,12 @@ // we're at it, also make sure that the shelf is hidden. EXPECT_TRUE(browser_view->GetWidget()->IsFullscreen()); EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // TODO(crbug.com/1466385): Enable this assertion once the bug is fixed (at + // the moment PinWindow returns too early). +#else EXPECT_FALSE(IsShelfVisible()); +#endif // Make sure the fullscreen control popup doesn't show up. ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED, gfx::Point(1, 1), gfx::Point(), @@ -355,6 +361,10 @@ // Test the shelf visibility affected by entering and exiting tab fullscreen and // immersive fullscreen. IN_PROC_BROWSER_TEST_P(ImmersiveModeBrowserViewTest, TabAndBrowserFullscreen) { + if (!IsIsShelfVisibleSupported()) { + GTEST_SKIP() << "Ash is too old."; + } + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); ASSERT_TRUE( @@ -365,25 +375,23 @@ // 1) Test that entering tab fullscreen from immersive fullscreen hides the // shelf. - chrome::ToggleFullscreenMode(browser()); - ASSERT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); + EnterImmersiveFullscreenMode(browser()); EXPECT_FALSE(IsShelfVisible()); - content::WebContents* web_contents = browser_view->GetActiveWebContents(); - EnterFullscreenModeForTabAndWait(browser(), web_contents); + EnterTabFullscreenMode(browser(), web_contents); ASSERT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(IsShelfVisible()); // 2) Test that exiting tab fullscreen autohides the shelf. - ExitFullscreenModeForTabAndWait(browser(), web_contents); + ExitTabFullscreenMode(browser(), web_contents); ASSERT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_FALSE(IsShelfVisible()); // 3) Test that exiting tab fullscreen and immersive fullscreen correctly // updates the shelf visibility. - EnterFullscreenModeForTabAndWait(browser(), web_contents); + EnterTabFullscreenMode(browser(), web_contents); ASSERT_TRUE(browser_view->immersive_mode_controller()->IsEnabled()); - chrome::ToggleFullscreenMode(browser()); + ui_test_utils::ToggleFullscreenModeAndWait(browser()); ASSERT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); EXPECT_TRUE(IsShelfVisible()); }
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc index bf8824c1..3dbf5d6 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
@@ -499,16 +499,7 @@ TEST_F(PageInfoBubbleViewTest, NotificationPermissionRevokeUkm) { GURL origin_url = GURL(kUrl).DeprecatedGetOriginAsURL(); - TestingProfile* profile = - static_cast<TestingProfile*>(web_contents_helper_->profile()); ukm::TestAutoSetUkmRecorder ukm_recorder; - auto* history_service = HistoryServiceFactory::GetForProfile( - profile, ServiceAccessType::EXPLICIT_ACCESS); - history_service->AddPage(origin_url, base::Time::Now(), - history::SOURCE_BROWSED); - base::RunLoop origin_queried_waiter; - history_service->set_origin_queried_closure_for_testing( - origin_queried_waiter.QuitClosure()); PermissionInfoList list(1); list.back().type = ContentSettingsType::NOTIFICATIONS; @@ -519,8 +510,6 @@ list.back().setting = CONTENT_SETTING_BLOCK; api_->SetPermissionInfo(list); - origin_queried_waiter.Run(); - auto entries = ukm_recorder.GetEntriesByName("Permission"); EXPECT_EQ(1u, entries.size()); auto* entry = entries.front().get();
diff --git a/chrome/browser/ui/views/permissions/embedded_permission_prompt_interactive_uitest.cc b/chrome/browser/ui/views/permissions/embedded_permission_prompt_interactive_uitest.cc index fb4d40c..f6789fa 100644 --- a/chrome/browser/ui/views/permissions/embedded_permission_prompt_interactive_uitest.cc +++ b/chrome/browser/ui/views/permissions/embedded_permission_prompt_interactive_uitest.cc
@@ -273,7 +273,7 @@ TestAskBlockAllowFlow( "microphone", {ContentSettingsType::MEDIASTREAM_MIC}, std::queue<std::u16string>( - {u"Use your microphone", + {u"Use your microphones", u"You have allowed microphone on a.test:" + base::UTF8ToUTF16(GetOrigin().port()), u"You previously didn't allow microphone on a.test:" + @@ -284,7 +284,7 @@ MAYBE_BasicFlowCamera) { TestAskBlockAllowFlow("camera", {ContentSettingsType::MEDIASTREAM_CAMERA}, std::queue<std::u16string>( - {u"Use your camera", + {u"Use your cameras", u"You have allowed camera on a.test:" + base::UTF8ToUTF16(GetOrigin().port()), u"You previously didn't allow camera on a.test:" + @@ -298,12 +298,12 @@ {ContentSettingsType::MEDIASTREAM_CAMERA, ContentSettingsType::MEDIASTREAM_MIC}, std::queue<std::u16string>( - {u"Use your camera", + {u"Use your cameras", u"You have allowed camera and microphone on a.test:" + base::UTF8ToUTF16(GetOrigin().port()), u"You previously didn't allow camera and microphone on a.test:" + base::UTF8ToUTF16(GetOrigin().port())}), - std::queue<std::u16string>({u"Use your microphone"})); + std::queue<std::u16string>({u"Use your microphones"})); } IN_PROC_BROWSER_TEST_F(EmbeddedPermissionPromptInteractiveTest, @@ -312,9 +312,9 @@ NavigateWebContents(kWebContentsElementId, GetURL())); TestPartialPermissionsLabel(CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, - u"Use your microphone"); + u"Use your microphones"); TestPartialPermissionsLabel(CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, - u"Use your camera"); + u"Use your cameras"); TestPartialPermissionsLabel( CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK,
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index e66f6ec..d33f92c 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -117,6 +117,8 @@ #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "chrome/browser/ui/views/frame/desktop_browser_frame_lacros.h" +#include "ui/aura/window_tree_host_platform.h" +#include "ui/platform_window/extensions/wayland_extension.h" #define DESKTOP_BROWSER_FRAME_AURA DesktopBrowserFrameLacros #elif BUILDFLAG(IS_LINUX) #include "chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux.h" @@ -1894,8 +1896,15 @@ // Drags from browser that has a web dialog to separate window. // The dialog should follow the new browser window. +// TODO(crbug.com/40934892): Expectations are sometimes off by one pixel on +// Windows. Reenable once deflaked. +#if BUILDFLAG(IS_WIN) +#define MAYBE_DetachToOwnWindowWithDialog DISABLED_DetachToOwnWindowWithDialog +#else +#define MAYBE_DetachToOwnWindowWithDialog DetachToOwnWindowWithDialog +#endif IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DetachToOwnWindowWithDialog) { + MAYBE_DetachToOwnWindowWithDialog) { const gfx::Rect initial_bounds(browser()->window()->GetBounds()); AddTabsAndResetBrowser(browser(), 1); TabStrip* tab_strip = GetTabStripForBrowser(browser()); @@ -2494,7 +2503,14 @@ } // namespace // Selects multiple tabs and starts dragging the window. -IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DragAll) { +// TODO(crbug.com/40934892): Expectations are sometimes off by one pixel on +// Windows. Reenable once deflaked. +#if BUILDFLAG(IS_WIN) +#define MAYBE_DragAll DISABLED_DragAll +#else +#define MAYBE_DragAll DragAll +#endif +IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) { AddTabsAndResetBrowser(browser(), 1); TabStrip* tab_strip = GetTabStripForBrowser(browser()); browser()->tab_strip_model()->ToggleSelectionAt(0); @@ -4047,6 +4063,9 @@ EXPECT_EQ("1", IDString(app_browser1->tab_strip_model())); } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + +#if BUILDFLAG(IS_CHROMEOS) // Subclass of DetachToBrowserTabDragControllerTest that // creates multiple displays. class DetachToBrowserInSeparateDisplayTabDragControllerTest @@ -4065,10 +4084,18 @@ // 1280x800 is the default resolution for the main display in tests. // We stick to it, as opposed to a smaller one, to avoid the browser // window being shrunk and maximized when calling UpdateDisplay. + const std::string display_specs = "1280x800,1280x800"; +#if BUILDFLAG(IS_CHROMEOS_LACROS) + ui_controls::UpdateDisplaySync(display_specs); +#else display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) - .UpdateDisplay("1280x800,1280x800"); + .UpdateDisplay(display_specs); +#endif } }; +#endif // BUILDFLAG(IS_CHROMEOS) + +#if BUILDFLAG(IS_CHROMEOS_ASH) namespace { @@ -4143,8 +4170,25 @@ EXPECT_FALSE(new_browser->window()->IsMaximized()); } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + +#if BUILDFLAG(IS_CHROMEOS) + namespace { +void SetBoundsSync(BrowserWindow* window, const gfx::Rect& bounds) { + window->SetBounds(bounds); + +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // Wait for a Wayland roundtrip to ensure all side effects have been + // processed. + auto* host = static_cast<aura::WindowTreeHostPlatform*>( + window->GetNativeWindow()->GetHost()); + auto* wayland_extension = ui::GetWaylandExtension(*host->platform_window()); + wayland_extension->RoundTripQueue(); +#endif +} + // Invoked from the nested run loop. void DragTabToWindowInSeparateDisplayStep2( DetachToBrowserTabDragControllerTest* test, @@ -4180,7 +4224,7 @@ // Move the second browser to the second display. display::Screen* screen = display::Screen::GetScreen(); Display second_display = ui_test_utils::GetSecondaryDisplay(screen); - browser2->window()->SetBounds(second_display.work_area()); + SetBoundsSync(browser2->window(), second_display.work_area()); EXPECT_EQ( second_display.id(), screen->GetDisplayNearestWindow(browser2->window()->GetNativeWindow()) @@ -4210,6 +4254,10 @@ EXPECT_FALSE(browser2->window()->IsMaximized()); } +#endif // BUILDFLAG(IS_CHROMEOS) + +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Crashes on ChromeOS. crbug.com/1003288 IN_PROC_BROWSER_TEST_P( DetachToBrowserInSeparateDisplayTabDragControllerTest, @@ -4953,8 +5001,7 @@ ::testing::Values("mouse"))); #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) -// TODO(crbug.com/1488094): Enable Multi Display Test on lacros +#if BUILDFLAG(IS_CHROMEOS) INSTANTIATE_TEST_SUITE_P( TabDragging, DetachToBrowserInSeparateDisplayTabDragControllerTest, @@ -4962,6 +5009,9 @@ ::testing::Bool(), /*kTearOffWebAppTabOpensWebAppWindow=*/::testing::Values(false), ::testing::Values("mouse"))); +#endif // BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) +// TODO(crbug.com/1488094): Enable Multi Display Test on lacros INSTANTIATE_TEST_SUITE_P( TabDragging, DifferentDeviceScaleFactorDisplayTabDragControllerTest, @@ -4989,7 +5039,7 @@ ::testing::Bool(), /*kTearOffWebAppTabOpensWebAppWindow=*/::testing::Values(false), ::testing::Values("mouse", "touch"))); -#endif +#endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS) INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc index e5f9c4a..415a30f4 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc
@@ -10,6 +10,8 @@ #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" +#include "chrome/browser/ui/views/extensions/extensions_toolbar_container_view_controller.h" +#include "chrome/browser/ui/views/extensions/extensions_toolbar_coordinator.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/page_action/page_action_icon_controller.h" @@ -305,8 +307,10 @@ DestroyLayer(); views::SetHitTestComponent(this, static_cast<int>(HTNOWHERE)); } - right_container_->extensions_container()->WindowControlsOverlayEnabledChanged( - browser_view_->IsWindowControlsOverlayEnabled()); + right_container_->extensions_toolbar_coordinator() + ->GetExtensionsContainerViewController() + ->WindowControlsOverlayEnabledChanged( + browser_view_->IsWindowControlsOverlayEnabled()); } void WebAppFrameToolbarView::UpdateBorderlessModeEnabled() {
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h index 7cb0187..cfea08e 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h
@@ -18,7 +18,7 @@ #include "ui/views/view_targeter_delegate.h" namespace { -class WebAppNonClientFrameViewAshTest; +class WebAppNonClientFrameViewChromeOSTest; } namespace views { @@ -111,7 +111,7 @@ private: friend class ImmersiveModeControllerChromeosWebAppBrowserTest; friend class WebAppAshInteractiveUITest; - friend class WebAppNonClientFrameViewAshTest; + friend class WebAppNonClientFrameViewChromeOSTest; views::View* GetContentSettingContainerForTesting();
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h index 46ff5d4..0773c62 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h
@@ -77,6 +77,10 @@ return extensions_container_; } + ExtensionsToolbarCoordinator* extensions_toolbar_coordinator() { + return extensions_toolbar_coordinator_.get(); + } + DownloadToolbarButtonView* download_button() { return download_button_.get(); }
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc index 50bc46b..c684b4b3 100644 --- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
@@ -51,6 +51,10 @@ #include "chromeos/ash/components/standalone_browser/feature_refs.h" #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/startup/browser_params_proxy.h" +#endif + namespace web_app { WebAppControllerBrowserTest::WebAppControllerBrowserTest() @@ -271,7 +275,7 @@ test::LogDebugInfoToConsole(profile_manager->GetLoadedProfiles(), log_time); } #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (IsCrosapiEnabled()) { + if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { // Make sure all ash browser UI are closed before the test tears down. CloseAllAshBrowserWindows(); } @@ -288,7 +292,7 @@ void WebAppControllerBrowserTest::SetUpOnMainThread() { #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (IsCrosapiEnabled()) { + if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { CHECK(IsWebAppsCrosapiEnabled()); } #endif
diff --git a/chrome/browser/ui/webui/BUILD.gn b/chrome/browser/ui/webui/BUILD.gn index 5782fe7e..babb595 100644 --- a/chrome/browser/ui/webui/BUILD.gn +++ b/chrome/browser/ui/webui/BUILD.gn
@@ -16,6 +16,7 @@ deps = [ "//chrome/browser/ui:ui", + "//components/compose:buildflags", "//components/lens:buildflags", "//content/public/browser", "//extensions/buildflags:buildflags", @@ -48,6 +49,7 @@ "//ash/webui/help_app_ui", "//ash/webui/os_feedback_ui", "//ash/webui/print_management", + "//ash/webui/print_preview_cros", "//ash/webui/scanning", "//ash/webui/shimless_rma", "//ash/webui/shortcut_customization_ui",
diff --git a/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc b/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc index 0b289fd..d9c7a3d 100644 --- a/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc +++ b/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc
@@ -30,6 +30,7 @@ #include "ash/webui/os_feedback_ui/os_feedback_ui.h" #include "ash/webui/personalization_app/personalization_app_ui.h" #include "ash/webui/print_management/print_management_ui.h" +#include "ash/webui/print_preview_cros/print_preview_cros_ui.h" #include "ash/webui/scanning/scanning_ui.h" #include "ash/webui/shimless_rma/shimless_rma.h" #include "ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.h" @@ -281,6 +282,8 @@ base::BindRepeating( &printing::print_management::PrintingManagerFactory:: CreatePrintManagementUIController))); + map.AddWebUIConfig( + std::make_unique<printing::print_preview::PrintPreviewCrosUIConfig>()); map.AddWebUIConfig(std::make_unique<multidevice::ProximityAuthUIConfig>()); map.AddWebUIConfig(std::make_unique<RemoteMaintenanceCurtainUIConfig>()); map.AddWebUIConfig(
diff --git a/chrome/browser/ui/webui/ash/settings/services/metrics/settings_user_action_tracker_unittest.cc b/chrome/browser/ui/webui/ash/settings/services/metrics/settings_user_action_tracker_unittest.cc index eff1ad7b..6f486a8 100644 --- a/chrome/browser/ui/webui/ash/settings/services/metrics/settings_user_action_tracker_unittest.cc +++ b/chrome/browser/ui/webui/ash/settings/services/metrics/settings_user_action_tracker_unittest.cc
@@ -101,8 +101,8 @@ mojom::Setting::kTouchpadSpeed); fake_hierarchy_->AddSettingMetadata(mojom::Section::kPeople, mojom::Setting::kAddAccount); - fake_hierarchy_->AddSettingMetadata(mojom::Section::kPrinting, - mojom::Setting::kScanningApp); + fake_hierarchy_->AddSettingMetadata(mojom::Section::kPersonalization, + mojom::Setting::kOpenWallpaper); fake_hierarchy_->AddSettingMetadata(mojom::Section::kNetwork, mojom::Setting::kWifiAddNetwork); @@ -262,24 +262,24 @@ } TEST_F(SettingsUserActionTrackerTest, TestRecordSettingChangedNullValue) { - // Record that the Scan app is opened. - tracker_->RecordSettingChangeWithDetails(mojom::Setting::kScanningApp, + // Record that the Wallpaper app is opened. + tracker_->RecordSettingChangeWithDetails(mojom::Setting::kOpenWallpaper, nullptr); // The umbrella metric for which setting was changed should be updated. Note - // that kScanningApp has enum value of 1403. + // that kOpenWallpaper has enum value of 500. histogram_tester_.ExpectTotalCount("ChromeOS.Settings.SettingChanged", /*count=*/1); histogram_tester_.ExpectBucketCount("ChromeOS.Settings.SettingChanged", - /*sample=*/1403, + /*sample=*/500, /*count=*/1); - // The LogMetric fn in the Printing section should have been called. - const FakeOsSettingsSection* printing_section = + // The LogMetric fn in the Personalization section should have been called. + const FakeOsSettingsSection* personalization_section = static_cast<const FakeOsSettingsSection*>( - fake_sections_->GetSection(mojom::Section::kPrinting)); - EXPECT_TRUE(printing_section->logged_metrics().back() == - mojom::Setting::kScanningApp); + fake_sections_->GetSection(mojom::Section::kPersonalization)); + EXPECT_TRUE(personalization_section->logged_metrics().back() == + mojom::Setting::kOpenWallpaper); } } // namespace ash::settings
diff --git a/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc b/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc index fb95b5dff..dfd38cc 100644 --- a/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc +++ b/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc
@@ -15,7 +15,11 @@ #include "chrome/browser/ui/webui/hats/hats_ui.h" #include "chrome/browser/ui/webui/side_panel/companion/companion_side_panel_untrusted_ui.h" #include "chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.h" +#include "components/compose/buildflags.h" #include "components/lens/buildflags.h" +#if BUILDFLAG(ENABLE_COMPOSE) +#include "chrome/browser/ui/webui/compose/compose_untrusted_ui.h" +#endif // BUILDFLAG(ENABLE_COMPOSE) #if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) #include "chrome/browser/ui/webui/lens/lens_untrusted_ui_config.h" #endif // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) @@ -48,6 +52,10 @@ std::make_unique<ReadAnythingUIUntrustedConfig>()); map.AddUntrustedWebUIConfig(std::make_unique<HatsUIConfig>()); +#if BUILDFLAG(ENABLE_COMPOSE) + map.AddUntrustedWebUIConfig(std::make_unique<ComposeUIUntrustedConfig>()); +#endif // BUILDFLAG(ENABLE_COMPOSE) + #if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) map.AddUntrustedWebUIConfig(std::make_unique<lens::LensUntrustedUIConfig>()); #endif // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 58ba4c2c..ea7cd03 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -71,7 +71,6 @@ #include "chrome/common/webui_url_constants.h" #include "components/commerce/content/browser/commerce_internals_ui.h" #include "components/commerce/core/commerce_constants.h" -#include "components/compose/buildflags.h" #include "components/favicon/core/favicon_service.h" #include "components/favicon_base/favicon_util.h" #include "components/favicon_base/select_favicon_frames.h" @@ -160,7 +159,6 @@ #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h" #include "chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.h" #include "chrome/browser/ui/webui/side_panel/performance_controls/performance_side_panel_ui.h" -#include "chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.h" #include "chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h" #include "chrome/browser/ui/webui/side_panel/user_notes/user_notes_side_panel_ui.h" #include "chrome/browser/ui/webui/signin/sync_confirmation_ui.h" @@ -184,6 +182,7 @@ #include "ash/webui/files_internals/url_constants.h" #include "ash/webui/help_app_ui/url_constants.h" #include "ash/webui/multidevice_debug/url_constants.h" +#include "ash/webui/print_preview_cros/url_constants.h" #include "ash/webui/vc_background_ui/url_constants.h" #include "chrome/browser/ash/extensions/url_constants.h" #include "chrome/browser/extensions/extension_keeplist_chromeos.h" @@ -286,12 +285,6 @@ #include "chrome/browser/ui/webui/lens/lens_ui.h" #endif -#if BUILDFLAG(ENABLE_COMPOSE) -#include "chrome/browser/compose/compose_enabling.h" -#include "chrome/browser/ui/webui/compose/compose_ui.h" -#include "components/compose/core/browser/compose_features.h" -#endif - using content::WebUI; using content::WebUIController; using ui::WebDialogUI; @@ -726,12 +719,6 @@ if (url.host_piece() == chrome::kChromeUIWebuiGalleryHost) { return &NewWebUI<WebuiGalleryUI>; } -#if BUILDFLAG(ENABLE_COMPOSE) - if (url.host_piece() == chrome::kChromeUIComposeHost && - ComposeEnabling::IsEnabledForProfile(profile)) { - return &NewWebUI<ComposeUI>; - } -#endif if (url.host_piece() == chrome::kChromeUIWhatsNewHost && whats_new::IsEnabled()) { return &NewWebUI<WhatsNewUI>; @@ -1095,6 +1082,7 @@ GURL(ash::kChromeUICameraAppURL), GURL(ash::kChromeUIFilesInternalsURL), GURL(ash::kChromeUIHelpAppURL), + GURL(ash::kChromeUIPrintPreviewCrosURL), GURL(ash::multidevice::kChromeUIProximityAuthURL), GURL(ash::vc_background_ui::kChromeUIVcBackgroundURL), GURL(chrome::kChromeUIAccountManagerErrorURL),
diff --git a/chrome/browser/ui/webui/compose/compose_ui.h b/chrome/browser/ui/webui/compose/compose_ui.h deleted file mode 100644 index c6d6afe2..0000000 --- a/chrome/browser/ui/webui/compose/compose_ui.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_WEBUI_COMPOSE_COMPOSE_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_COMPOSE_COMPOSE_UI_H_ - -#include <memory> - -#include "base/memory/weak_ptr.h" -#include "chrome/common/compose/compose.mojom.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_ui_controller.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "ui/webui/mojo_bubble_web_ui_controller.h" -#include "ui/webui/resources/cr_components/color_change_listener/color_change_listener.mojom.h" - -namespace ui { -class ColorChangeHandler; -} - -class ComposeUI : public ui::MojoBubbleWebUIController, - public compose::mojom::ComposeSessionPageHandlerFactory { - public: - explicit ComposeUI(content::WebUI* web_ui); - - ComposeUI(const ComposeUI&) = delete; - ComposeUI& operator=(const ComposeUI&) = delete; - ~ComposeUI() override; - void BindInterface( - mojo::PendingReceiver<compose::mojom::ComposeSessionPageHandlerFactory> - factory); - - void BindInterface( - mojo::PendingReceiver<color_change_listener::mojom::PageHandler> - pending_receiver); - - void set_triggering_web_contents(content::WebContents* web_contents) { - triggering_web_contents_ = web_contents->GetWeakPtr(); - } - - static constexpr std::string GetWebUIName() { return "Compose"; } - - private: - void CreateComposeSessionPageHandler( - mojo::PendingReceiver<compose::mojom::ComposeClientPageHandler> - close_handler, - mojo::PendingReceiver<compose::mojom::ComposeSessionPageHandler> handler, - mojo::PendingRemote<compose::mojom::ComposeDialog> dialog) override; - mojo::Receiver<compose::mojom::ComposeSessionPageHandlerFactory> - session_handler_factory_{this}; - - std::unique_ptr<ui::ColorChangeHandler> color_provider_handler_; - base::WeakPtr<content::WebContents> triggering_web_contents_; - - WEB_UI_CONTROLLER_TYPE_DECL(); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_COMPOSE_COMPOSE_UI_H_
diff --git a/chrome/browser/ui/webui/compose/compose_ui.cc b/chrome/browser/ui/webui/compose/compose_untrusted_ui.cc similarity index 77% rename from chrome/browser/ui/webui/compose/compose_ui.cc rename to chrome/browser/ui/webui/compose/compose_untrusted_ui.cc index dbfe00b..a3b470bc 100644 --- a/chrome/browser/ui/webui/compose/compose_ui.cc +++ b/chrome/browser/ui/webui/compose/compose_untrusted_ui.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 "chrome/browser/ui/webui/compose/compose_ui.h" +#include "chrome/browser/ui/webui/compose/compose_untrusted_ui.h" #include <string> #include <utility> @@ -12,8 +12,8 @@ #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/compose/chrome_compose_client.h" +#include "chrome/browser/ui/webui/theme_source.h" #include "chrome/browser/ui/webui/webui_util.h" -#include "chrome/common/webui_url_constants.h" #include "chrome/grit/compose_resources.h" #include "chrome/grit/compose_resources_map.h" #include "chrome/grit/generated_resources.h" @@ -24,14 +24,21 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/resources/grit/webui_resources.h" #include "ui/webui/color_change_listener/color_change_handler.h" -ComposeUI::ComposeUI(content::WebUI* web_ui) - : ui::MojoBubbleWebUIController(web_ui) { +bool ComposeUIUntrustedConfig::IsWebUIEnabled( + content::BrowserContext* browser_context) { + return ComposeEnabling::IsEnabledForProfile( + Profile::FromBrowserContext(browser_context)); +} + +ComposeUntrustedUI::ComposeUntrustedUI(content::WebUI* web_ui) + : ui::UntrustedBubbleWebUIController(web_ui) { content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd( web_ui->GetWebContents()->GetBrowserContext(), - chrome::kChromeUIComposeHost); - webui::SetupWebUIDataSource( + chrome::kChromeUIUntrustedComposeUrl); +webui::SetupWebUIDataSource( source, base::make_span(kComposeResources, kComposeResourcesSize), IDR_COMPOSE_COMPOSE_HTML); webui::SetupChromeRefresh2023(source); @@ -100,18 +107,35 @@ const compose::Config& config = compose::GetComposeConfig(); source->AddInteger("savedStateTimeoutInMilliseconds", config.saved_state_timeout_milliseconds); + + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::StyleSrc, + "style-src 'self' chrome-untrusted://resources chrome-untrusted://theme " + "'unsafe-inline';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::FontSrc, + "font-src 'self' chrome-untrusted://resources;"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ImgSrc, + "img-src 'self' chrome-untrusted://resources;"); + + // If the ThemeSource isn't added here, since Compose is chrome-untrusted, + // it will be unable to load stylesheets until a new tab is opened. + raw_ptr<Profile> profile = Profile::FromWebUI(web_ui); + content::URLDataSource::Add(profile, std::make_unique<ThemeSource>( + profile, /*serve_untrusted=*/true)); } -ComposeUI::~ComposeUI() = default; +ComposeUntrustedUI::~ComposeUntrustedUI() = default; -void ComposeUI::BindInterface( +void ComposeUntrustedUI::BindInterface( mojo::PendingReceiver<color_change_listener::mojom::PageHandler> pending_receiver) { color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>( web_ui()->GetWebContents(), std::move(pending_receiver)); } -void ComposeUI::BindInterface( +void ComposeUntrustedUI::BindInterface( mojo::PendingReceiver<compose::mojom::ComposeSessionPageHandlerFactory> factory) { if (session_handler_factory_.is_bound()) { @@ -120,7 +144,7 @@ session_handler_factory_.Bind(std::move(factory)); } -void ComposeUI::CreateComposeSessionPageHandler( +void ComposeUntrustedUI::CreateComposeSessionPageHandler( mojo::PendingReceiver<compose::mojom::ComposeClientPageHandler> close_handler, mojo::PendingReceiver<compose::mojom::ComposeSessionPageHandler> handler, @@ -138,4 +162,4 @@ } } -WEB_UI_CONTROLLER_TYPE_IMPL(ComposeUI) +WEB_UI_CONTROLLER_TYPE_IMPL(ComposeUntrustedUI)
diff --git a/chrome/browser/ui/webui/compose/compose_untrusted_ui.h b/chrome/browser/ui/webui/compose/compose_untrusted_ui.h new file mode 100644 index 0000000..cdf8a7d --- /dev/null +++ b/chrome/browser/ui/webui/compose/compose_untrusted_ui.h
@@ -0,0 +1,78 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_COMPOSE_COMPOSE_UNTRUSTED_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_COMPOSE_COMPOSE_UNTRUSTED_UI_H_ + +#include <memory> + +#include "base/memory/weak_ptr.h" +#include "chrome/common/compose/compose.mojom.h" +#include "chrome/common/webui_url_constants.h" +#include "content/public/browser/url_data_source.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui_controller.h" +#include "content/public/browser/webui_config.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "ui/webui/resources/cr_components/color_change_listener/color_change_listener.mojom.h" +#include "ui/webui/untrusted_bubble_web_ui_controller.h" + +namespace ui { +class ColorChangeHandler; +} + +class ComposeUntrustedUI; + +class ComposeUIUntrustedConfig + : public content::DefaultWebUIConfig<ComposeUntrustedUI> { + public: + ComposeUIUntrustedConfig() + : DefaultWebUIConfig(content::kChromeUIUntrustedScheme, + chrome::kChromeUIUntrustedComposeHost) {} + + bool IsWebUIEnabled(content::BrowserContext* browser_context) override; +}; + +// TODO(b/317056725): update mojom to reflect that the page is untrusted. +class ComposeUntrustedUI + : public ui::UntrustedBubbleWebUIController, + public compose::mojom::ComposeSessionPageHandlerFactory { + public: + explicit ComposeUntrustedUI(content::WebUI* web_ui); + + ComposeUntrustedUI(const ComposeUntrustedUI&) = delete; + ComposeUntrustedUI& operator=(const ComposeUntrustedUI&) = delete; + ~ComposeUntrustedUI() override; + void BindInterface( + mojo::PendingReceiver<compose::mojom::ComposeSessionPageHandlerFactory> + factory); + + void BindInterface( + mojo::PendingReceiver<color_change_listener::mojom::PageHandler> + pending_receiver); + + void set_triggering_web_contents(content::WebContents* web_contents) { + triggering_web_contents_ = web_contents->GetWeakPtr(); + } + + static constexpr std::string GetWebUIName() { return "Compose"; } + + private: + void CreateComposeSessionPageHandler( + mojo::PendingReceiver<compose::mojom::ComposeClientPageHandler> + close_handler, + mojo::PendingReceiver<compose::mojom::ComposeSessionPageHandler> handler, + mojo::PendingRemote<compose::mojom::ComposeDialog> dialog) override; + mojo::Receiver<compose::mojom::ComposeSessionPageHandlerFactory> + session_handler_factory_{this}; + + std::unique_ptr<ui::ColorChangeHandler> color_provider_handler_; + base::WeakPtr<content::WebContents> triggering_web_contents_; + + WEB_UI_CONTROLLER_TYPE_DECL(); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_COMPOSE_COMPOSE_UNTRUSTED_UI_H_
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index fa71e16..f8c3bd0 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -2435,14 +2435,6 @@ TEST_P(SiteSettingsHandlerTest, NotificationPermissionRevokeUkm) { const std::string google("https://www.google.com"); ukm::TestAutoSetUkmRecorder ukm_recorder; - auto* history_service = HistoryServiceFactory::GetForProfile( - profile(), ServiceAccessType::EXPLICIT_ACCESS); - history_service->AddPage(GURL(google), base::Time::Now(), - history::SOURCE_BROWSED); - base::RunLoop origin_queried_waiter; - history_service->set_origin_queried_closure_for_testing( - origin_queried_waiter.QuitClosure()); - { base::Value::List set_notification_origin_args; set_notification_origin_args.Append(google); @@ -2467,8 +2459,6 @@ set_notification_origin_args); } - origin_queried_waiter.Run(); - auto entries = ukm_recorder.GetEntriesByName("Permission"); EXPECT_EQ(1u, entries.size()); auto* entry = entries.front().get();
diff --git a/chrome/browser/ui/webui/tab_search/tab_search.mojom b/chrome/browser/ui/webui/tab_search/tab_search.mojom index b961f16b..02ad38e3 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search.mojom +++ b/chrome/browser/ui/webui/tab_search/tab_search.mojom
@@ -247,18 +247,12 @@ // Initiate the feedback flow. TriggerFeedback(int32 session_id); - // Initiate the sync flow. - TriggerSync(); - // Initiate the sign in flow. TriggerSignIn(); // Open the help page associated with tab organization. OpenHelpPage(); - // Open the user's sync settings in a new tab. - OpenSyncSettings(); - // Store the user feedback supplied by the user. SetUserFeedback(int32 session_id, int32 organization_id,
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc index e6c7994..625878e 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc +++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -582,18 +582,9 @@ /*autofill_metadata=*/base::Value::Dict(), std::move(feedback_metadata)); } -void TabSearchPageHandler::TriggerSync() { - Profile* profile = chrome::FindLastActive()->profile(); - signin_ui_util::EnableSyncFromSingleAccountPromo( - profile, - IdentityManagerFactory::GetForProfile(profile)->GetPrimaryAccountInfo( - signin::ConsentLevel::kSignin), - signin_metrics::AccessPoint::ACCESS_POINT_TAB_ORGANIZATION); -} - void TabSearchPageHandler::TriggerSignIn() { Profile* profile = chrome::FindLastActive()->profile(); - signin_ui_util::ShowReauthForPrimaryAccountWithAuthError( + signin_ui_util::ShowSigninPromptFromPromo( profile, signin_metrics::AccessPoint::ACCESS_POINT_TAB_ORGANIZATION); } @@ -606,15 +597,6 @@ Navigate(¶ms); } -void TabSearchPageHandler::OpenSyncSettings() { - Browser* browser = chrome::FindLastActive(); - GURL settings_url("chrome://settings/syncSetup/advanced"); - NavigateParams params(browser, settings_url, - ui::PageTransition::PAGE_TRANSITION_LINK); - params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; - Navigate(¶ms); -} - void TabSearchPageHandler::SetUserFeedback( int32_t session_id, int32_t organization_id,
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h index 571e915..3c8cd91 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h +++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
@@ -91,10 +91,8 @@ void SetTabIndex(int32_t index) override; void StartTabGroupTutorial() override; void TriggerFeedback(int32_t session_id) override; - void TriggerSync() override; void TriggerSignIn() override; void OpenHelpPage() override; - void OpenSyncSettings() override; void SetUserFeedback(int32_t session_id, int32_t organization_id, tab_search::mojom::UserFeedback feedback) override;
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.cc new file mode 100644 index 0000000..ee584851 --- /dev/null +++ b/chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.cc
@@ -0,0 +1,61 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.h" + +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/webui/web_ui_util.h" + +TabSearchSignInHandler::TabSearchSignInHandler(Profile* profile) + : profile_(profile) {} + +TabSearchSignInHandler::~TabSearchSignInHandler() = default; + +void TabSearchSignInHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "GetSignInState", + base::BindRepeating(&TabSearchSignInHandler::HandleGetSignInState, + base::Unretained(this))); +} + +void TabSearchSignInHandler::OnJavascriptAllowed() { + signin::IdentityManager* identity_manager( + IdentityManagerFactory::GetInstance()->GetForProfile(profile_)); + if (identity_manager && !identity_manager_observation_.IsObserving()) { + identity_manager_observation_.Observe(identity_manager); + } +} + +void TabSearchSignInHandler::OnJavascriptDisallowed() { + identity_manager_observation_.Reset(); +} + +bool TabSearchSignInHandler::GetSignInState() const { + const signin::IdentityManager* const identity_manager( + IdentityManagerFactory::GetInstance()->GetForProfile(profile_)); + const auto stored_account = identity_manager->FindExtendedAccountInfo( + identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)); + return stored_account.IsValid(); +} + +void TabSearchSignInHandler::HandleGetSignInState(const base::Value::List& args) { + AllowJavascript(); + CHECK_EQ(1U, args.size()); + const base::Value& callback_id = args[0]; + + ResolveJavascriptCallback(callback_id, GetSignInState()); +} + +void TabSearchSignInHandler::OnExtendedAccountInfoUpdated( + const AccountInfo& info) { + FireWebUIListener("account-info-changed", GetSignInState()); +} + +void TabSearchSignInHandler::OnExtendedAccountInfoRemoved( + const AccountInfo& info) { + FireWebUIListener("account-info-changed", GetSignInState()); +}
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.h new file mode 100644 index 0000000..0f04346 --- /dev/null +++ b/chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.h
@@ -0,0 +1,51 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_SIGN_IN_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_SIGN_IN_HANDLER_H_ + +#include "base/memory/raw_ptr.h" +#include "base/scoped_observation.h" +#include "base/values.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "content/public/browser/web_ui_message_handler.h" + +class Profile; + +// A class allowing TabSearch WebUI to interact with the identity manager and +// observing and propagating relevant events to the WebUI. +class TabSearchSignInHandler : public content::WebUIMessageHandler, + public signin::IdentityManager::Observer { + public: + explicit TabSearchSignInHandler(Profile* profile); + + TabSearchSignInHandler(const TabSearchSignInHandler&) = delete; + TabSearchSignInHandler& operator=(const TabSearchSignInHandler&) = delete; + + ~TabSearchSignInHandler() override; + + private: + // WebUIMessageHandler: + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + // Returns whether or not the user is currently signed in. + bool GetSignInState() const; + // Handles the request for the sign in state. + void HandleGetSignInState(const base::Value::List& args); + + // IdentityManager::Observer implementation. + void OnExtendedAccountInfoUpdated(const AccountInfo& info) override; + void OnExtendedAccountInfoRemoved(const AccountInfo& info) override; + + // Weak pointer. + raw_ptr<Profile, DanglingUntriaged> profile_; + + base::ScopedObservation<signin::IdentityManager, + signin::IdentityManager::Observer> + identity_manager_observation_{this}; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_SIGN_IN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_sync_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_sync_handler.cc deleted file mode 100644 index 81f79756..0000000 --- a/chrome/browser/ui/webui/tab_search/tab_search_sync_handler.cc +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/tab_search/tab_search_sync_handler.h" - -#include "base/values.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/sync/sync_service_factory.h" -#include "chrome/browser/sync/sync_ui_util.h" -#include "components/sync/service/sync_service.h" -#include "components/sync/service/sync_service_utils.h" -#include "components/sync/service/sync_user_settings.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/webui/web_ui_util.h" - -TabSearchSyncHandler::TabSearchSyncHandler(Profile* profile) - : profile_(profile) {} - -TabSearchSyncHandler::~TabSearchSyncHandler() = default; - -void TabSearchSyncHandler::RegisterMessages() { - web_ui()->RegisterMessageCallback( - "GetAccountInfo", - base::BindRepeating(&TabSearchSyncHandler::HandleGetAccountInfo, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "GetSyncInfo", - base::BindRepeating(&TabSearchSyncHandler::HandleGetSyncInfo, - base::Unretained(this))); -} - -void TabSearchSyncHandler::OnJavascriptAllowed() { - syncer::SyncService* sync_service = GetSyncService(); - if (sync_service && !sync_service_observation_.IsObserving()) { - sync_service_observation_.Observe(sync_service); - } - - signin::IdentityManager* identity_manager( - IdentityManagerFactory::GetInstance()->GetForProfile(profile_)); - if (identity_manager && !identity_manager_observation_.IsObserving()) { - identity_manager_observation_.Observe(identity_manager); - } -} - -void TabSearchSyncHandler::OnJavascriptDisallowed() { - sync_service_observation_.Reset(); - identity_manager_observation_.Reset(); -} - -base::Value::Dict TabSearchSyncHandler::GetSyncInfo() const { - base::Value::Dict dict; - bool syncing = false; - bool syncingHistory = false; - bool paused = true; - - const syncer::SyncService* const sync_service = GetSyncService(); - // sync_service might be nullptr if SyncServiceFactory::IsSyncAllowed is - // false. - if (sync_service) { - syncing = sync_service->IsSyncFeatureEnabled(); - paused = !sync_service->IsSyncFeatureActive(); - syncer::UserSelectableTypeSet types = - sync_service->GetUserSettings()->GetSelectedTypes(); - syncingHistory = sync_service->IsSyncFeatureEnabled() && - types.Has(syncer::UserSelectableType::kHistory); - } - - dict.Set("syncing", syncing); - dict.Set("paused", paused); - dict.Set("syncingHistory", syncingHistory); - - return dict; -} - -void TabSearchSyncHandler::HandleGetSyncInfo(const base::Value::List& args) { - AllowJavascript(); - - CHECK_EQ(1U, args.size()); - const base::Value& callback_id = args[0]; - - ResolveJavascriptCallback(callback_id, GetSyncInfo()); -} - -base::Value::Dict TabSearchSyncHandler::GetAccountInfo() const { - const signin::IdentityManager* const identity_manager( - IdentityManagerFactory::GetInstance()->GetForProfile(profile_)); - const auto stored_account = identity_manager->FindExtendedAccountInfo( - identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)); - - base::Value::Dict dict; - dict.Set("name", stored_account.full_name); - dict.Set("email", stored_account.email); - const auto& avatar_image = stored_account.account_image; - if (!avatar_image.IsEmpty()) { - dict.Set("avatarImage", webui::GetBitmapDataUrl(avatar_image.AsBitmap())); - } - return dict; -} - -void TabSearchSyncHandler::HandleGetAccountInfo(const base::Value::List& args) { - AllowJavascript(); - CHECK_EQ(1U, args.size()); - const base::Value& callback_id = args[0]; - - ResolveJavascriptCallback(callback_id, GetAccountInfo()); -} - -void TabSearchSyncHandler::OnStateChanged(syncer::SyncService* sync_service) { - FireWebUIListener("sync-info-changed", GetSyncInfo()); -} - -void TabSearchSyncHandler::OnExtendedAccountInfoUpdated( - const AccountInfo& info) { - FireWebUIListener("account-info-changed", GetAccountInfo()); -} - -void TabSearchSyncHandler::OnExtendedAccountInfoRemoved( - const AccountInfo& info) { - FireWebUIListener("account-info-changed", GetAccountInfo()); -} - -syncer::SyncService* TabSearchSyncHandler::GetSyncService() const { - return SyncServiceFactory::IsSyncAllowed(profile_) - ? SyncServiceFactory::GetForProfile(profile_) - : nullptr; -}
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_sync_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_sync_handler.h deleted file mode 100644 index fd593360..0000000 --- a/chrome/browser/ui/webui/tab_search/tab_search_sync_handler.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_SYNC_HANDLER_H_ -#define CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_SYNC_HANDLER_H_ - -#include "base/memory/raw_ptr.h" -#include "base/scoped_observation.h" -#include "base/values.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/sync/service/sync_service.h" -#include "components/sync/service/sync_service_observer.h" -#include "content/public/browser/web_ui_message_handler.h" - -class Profile; - -// A class allowing TabSearch WebUI to interact with the sync -// service and identity manager and observing and propagating relevant -// events to the WebUI. -class TabSearchSyncHandler : public content::WebUIMessageHandler, - public signin::IdentityManager::Observer, - public syncer::SyncServiceObserver { - public: - explicit TabSearchSyncHandler(Profile* profile); - - TabSearchSyncHandler(const TabSearchSyncHandler&) = delete; - TabSearchSyncHandler& operator=(const TabSearchSyncHandler&) = delete; - - ~TabSearchSyncHandler() override; - - private: - // WebUIMessageHandler: - void RegisterMessages() override; - void OnJavascriptAllowed() override; - void OnJavascriptDisallowed() override; - - // Retrieves sync related information from the SyncService. - base::Value::Dict GetSyncInfo() const; - // Handles the request for sync information. - void HandleGetSyncInfo(const base::Value::List& args); - - // Retrieves information about the primary account. - base::Value::Dict GetAccountInfo() const; - // Handles the request for the primary account information. - void HandleGetAccountInfo(const base::Value::List& args); - - // syncer::SyncServiceObserver implementation. - void OnStateChanged(syncer::SyncService* sync_service) override; - - // IdentityManager::Observer implementation. - void OnExtendedAccountInfoUpdated(const AccountInfo& info) override; - void OnExtendedAccountInfoRemoved(const AccountInfo& info) override; - - syncer::SyncService* GetSyncService() const; - - // Weak pointer. - raw_ptr<Profile, DanglingUntriaged> profile_; - - base::ScopedObservation<syncer::SyncService, syncer::SyncServiceObserver> - sync_service_observation_{this}; - base::ScopedObservation<signin::IdentityManager, - signin::IdentityManager::Observer> - identity_manager_observation_{this}; -}; - -#endif // CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_SYNC_HANDLER_H_
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc index c43ee5c..3d2c3f30 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc +++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -15,7 +15,7 @@ #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/webui/favicon_source.h" #include "chrome/browser/ui/webui/tab_search/tab_search_prefs.h" -#include "chrome/browser/ui/webui/tab_search/tab_search_sync_handler.h" +#include "chrome/browser/ui/webui/tab_search/tab_search_sign_in_handler.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" @@ -98,30 +98,16 @@ {"notStartedBodyLinkFRE", IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_LINK_FRE}, {"notStartedBodySignedOut", IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SIGNED_OUT}, - {"notStartedBodySyncPaused", - IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_SYNC_PAUSED}, - {"notStartedBodyUnsynced", - IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED}, - {"notStartedBodyUnsyncedHistory", - IDS_TAB_ORGANIZATION_NOT_STARTED_BODY_UNSYNCED_HISTORY}, {"notStartedButton", IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON}, {"notStartedButtonAriaLabel", IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_ARIA_LABEL}, {"notStartedButtonFRE", IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_FRE}, {"notStartedButtonFREAriaLabel", IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_FRE_ARIA_LABEL}, - {"notStartedButtonSyncPaused", - IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SYNC_PAUSED}, - {"notStartedButtonSyncPausedAriaLabel", - IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SYNC_PAUSED_ARIA_LABEL}, - {"notStartedButtonUnsynced", - IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED}, - {"notStartedButtonUnsyncedAriaLabel", - IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_ARIA_LABEL}, - {"notStartedButtonUnsyncedHistory", - IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_HISTORY}, - {"notStartedButtonUnsyncedHistoryAriaLabel", - IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_UNSYNCED_HISTORY_ARIA_LABEL}, + {"notStartedButtonSignedOut", + IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SIGNED_OUT}, + {"notStartedButtonSignedOutAriaLabel", + IDS_TAB_ORGANIZATION_NOT_STARTED_BUTTON_SIGNED_OUT_ARIA_LABEL}, {"notStartedTitle", IDS_TAB_ORGANIZATION_NOT_STARTED_TITLE}, {"notStartedTitleFRE", IDS_TAB_ORGANIZATION_NOT_STARTED_TITLE_FRE}, {"rejectSuggestion", IDS_TAB_ORGANIZATION_REJECT_SUGGESTION}, @@ -202,7 +188,7 @@ profile, std::make_unique<FaviconSource>( profile, chrome::FaviconUrlFormat::kFavicon2)); - web_ui->AddMessageHandler(std::make_unique<TabSearchSyncHandler>(profile)); + web_ui->AddMessageHandler(std::make_unique<TabSearchSignInHandler>(profile)); page_handler_timer_ = base::ElapsedTimer(); TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
diff --git a/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc b/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc index 4d3a6419..3b3fc4d 100644 --- a/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc +++ b/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc
@@ -145,7 +145,7 @@ if (service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() < int{crosapi::mojom::AppShortcutPublisher::MethodMinVersions:: kRegisterAppShortcutControllerMinVersion} && - !chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { + !chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { LOG(WARNING) << "Ash AppShortcutPublisher version " << service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() @@ -184,7 +184,7 @@ if (service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() < int{crosapi::mojom::AppShortcutPublisher::MethodMinVersions:: kPublishShortcutsMinVersion} && - !chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { + !chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { LOG(WARNING) << "Ash AppShortcutPublisher version " << service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() @@ -289,7 +289,7 @@ if (service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() < int{crosapi::mojom::AppShortcutPublisher::MethodMinVersions:: kShortcutRemovedMinVersion} && - !chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { + !chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { LOG(WARNING) << "Ash AppShortcutPublisher version " << service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>()
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index a97088958..65a4a572 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1707738626-1696f986a8c29d92d622edf3bc95aa794f72931b.profdata +chrome-chromeos-amd64-generic-main-1707782597-603ab6846224efb8e9e965aefd96ae0f7d6982b7.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index e34ef01f..1a097ad0 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1707760725-ca04eea28cc9e7d4d347d4846c67142fe5b1f167.profdata +chrome-linux-main-1707782361-1958ba0884472c0f61b1c19b3291e3b70c003a68.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 49110b3..d79e576 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1707775072-2fdd2f085faa2b907188fab88c4f91a4d606dc33.profdata +chrome-mac-arm-main-1707803882-48776b9a5e69a7b1f5492b9fb4fb42f12f67060e.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index ade7406..a6c3ac16 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -242,6 +242,7 @@ "$root_gen_dir/ash/webui/ash_os_feedback_untrusted_resources.pak", "$root_gen_dir/ash/webui/ash_personalization_app_resources.pak", "$root_gen_dir/ash/webui/ash_print_management_resources.pak", + "$root_gen_dir/ash/webui/ash_print_preview_cros_app_resources.pak", "$root_gen_dir/ash/webui/ash_projector_annotator_untrusted_resources.pak", "$root_gen_dir/ash/webui/ash_projector_app_untrusted_resources.pak", "$root_gen_dir/ash/webui/ash_projector_common_resources.pak", @@ -319,6 +320,7 @@ "//ash/webui/os_feedback_ui/untrusted_resources:resources", "//ash/webui/personalization_app/resources:resources", "//ash/webui/print_management/resources:resources", + "//ash/webui/print_preview_cros/resources:resources", "//ash/webui/resources:camera_app_resources", "//ash/webui/resources:demo_mode_app_resources", "//ash/webui/resources:eche_app_resources",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 8302c091..6aa2d7f 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -284,6 +284,17 @@ "ChromeStructuredMetrics", base::FEATURE_DISABLED_BY_DEFAULT); +// Kill switch for Controlled Frame. This is enabled by default but is only +// tested to ensure it's enabled before proceeding with the rest of the feature +// checks like testing for IWA support or Kiosk mode. If this feature flag is +// disabled, such as via Finch, then Controlled Frame will no longer be +// available in IWA or Kiosk mode. +// See https://github.com/WICG/controlled-frame/blob/main/README.md for more +// info. +BASE_FEATURE(kControlledFrame, + "ControlledFrame", + base::FEATURE_ENABLED_BY_DEFAULT); + // When installing default installed PWAs, we wait for service workers // to cache resources. BASE_FEATURE(kDesktopPWAsCacheDuringDefaultInstall,
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 47c9846..21005c3c 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -186,6 +186,8 @@ COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kChromeStructuredMetrics); +COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kControlledFrame); + COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kDesktopPWAsCacheDuringDefaultInstall);
diff --git a/chrome/common/controlled_frame/controlled_frame.cc b/chrome/common/controlled_frame/controlled_frame.cc index 3559ed5..6954019 100644 --- a/chrome/common/controlled_frame/controlled_frame.cc +++ b/chrome/common/controlled_frame/controlled_frame.cc
@@ -7,15 +7,14 @@ #include <string> #include "base/containers/contains.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/initialize_extensions_client.h" -#include "content/public/common/content_features.h" #include "extensions/common/extension.h" #include "extensions/common/features/feature.h" #include "extensions/common/mojom/context_type.mojom.h" #if BUILDFLAG(IS_CHROMEOS) #include "base/command_line.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "url/url_constants.h" #endif @@ -60,6 +59,10 @@ int context_id, bool check_developer_mode, const extensions::ContextData& context_data) { + if (!base::FeatureList::IsEnabled(features::kControlledFrame)) { + return false; + } + bool is_allowed_for_scheme = url.SchemeIs("isolated-app"); #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 4fa070dc..83314a9 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -53,7 +53,6 @@ const char kChromeUIChromeURLsURL[] = "chrome://chrome-urls/"; const char kChromeUIComponentsHost[] = "components"; const char kChromeUIComponentsUrl[] = "chrome://components"; -const char kChromeUIComposeHost[] = "compose"; const char kChromeUIConflictsHost[] = "conflicts"; const char kChromeUIConstrainedHTMLTestURL[] = "chrome://constrained-test/"; const char kChromeUICookieSettingsURL[] = "chrome://settings/cookies"; @@ -237,6 +236,8 @@ const char kChromeUIThemeURL[] = "chrome://theme/"; const char kChromeUITranslateInternalsHost[] = "translate-internals"; const char kChromeUITopChromeDomain[] = "top-chrome"; +const char kChromeUIUntrustedComposeHost[] = "compose"; +const char kChromeUIUntrustedComposeUrl[] = "chrome-untrusted://compose/"; #if !BUILDFLAG(IS_ANDROID) const char kChromeUIUntrustedHatsHost[] = "hats"; const char kChromeUIUntrustedHatsURL[] = "chrome-untrusted://hats/";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 45e4d66..7606110 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -52,7 +52,6 @@ extern const char kChromeUIChromeURLsURL[]; extern const char kChromeUIComponentsHost[]; extern const char kChromeUIComponentsUrl[]; -extern const char kChromeUIComposeHost[]; extern const char kChromeUIConflictsHost[]; extern const char kChromeUIConstrainedHTMLTestURL[]; extern const char kChromeUICookieSettingsURL[]; @@ -226,6 +225,8 @@ extern const char kChromeUIThemeURL[]; extern const char kChromeUITopChromeDomain[]; extern const char kChromeUITranslateInternalsHost[]; +extern const char kChromeUIUntrustedComposeHost[]; +extern const char kChromeUIUntrustedComposeUrl[]; #if !BUILDFLAG(IS_ANDROID) extern const char kChromeUIUntrustedHatsHost[]; extern const char kChromeUIUntrustedHatsURL[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index c02bb8c..3317e9fca 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -734,8 +734,6 @@ "../browser/extensions/policy_test_utils.h", "../browser/ui/chromeos/test_util.cc", "../browser/ui/chromeos/test_util.h", - "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc", - "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h", "../browser/ui/views/frame/immersive_mode_tester.cc", "../browser/ui/views/frame/immersive_mode_tester.h", "base/chromeos/crosier/annotations.cc", @@ -822,6 +820,7 @@ "//ash/public/cpp:test_support", "//ash/webui/firmware_update_ui:url_constants", "//ash/webui/personalization_app:test_support", + "//ash/webui/print_preview_cros:url_constants", "//ash/webui/scanning:url_constants", "//chrome/browser/ash", "//chrome/browser/ash/crosapi:fake_device_ownership_waiter", @@ -3182,7 +3181,6 @@ "../browser/chromeos/video_conference/video_conference_media_listener_browsertest.cc", "../browser/download/notification/download_notification_browsertest.cc", "../browser/file_system_access/cloud_identifier/cloud_identifier_util_cros_browsertest.cc", - "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc", ] } @@ -4859,6 +4857,7 @@ "../browser/ui/views/editor_menu/editor_menu_browsertest.cc", "../browser/ui/views/extensions/extension_dialog_bounds_browsertest.cc", "../browser/ui/views/frame/browser_frame_ash_browsertest.cc", + "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc", "../browser/ui/views/frame/immersive_mode_browser_view_test.cc", "../browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc", "../browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc", @@ -5589,6 +5588,8 @@ "../browser/ui/lacros/screen_capture_notification_ui_lacros_browsertest.cc", "../browser/ui/sharing_hub/sharing_hub_bubble_controller_chromeos_lacros_browsertest.cc", "../browser/ui/startup/first_run_service_browsertest.cc", + "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc", + "../browser/ui/views/frame/immersive_mode_browser_view_test.cc", "../browser/ui/views/intent_picker_bubble_view_browsertest.cc", "../browser/ui/views/location_bar/intent_chip_button_browsertest.cc", "../browser/ui/views/profiles/profile_picker_view_browsertest.cc", @@ -5640,7 +5641,9 @@ "//chrome/browser/policy:test_support", "//chrome/browser/ui/web_applications:app_service_browser_tests", "//chrome/browser/web_applications:app_service_browser_tests", + "//chrome/browser/web_applications:prevent_close_test_support", "//chrome/browser/web_applications:web_applications_test_support", + "//chrome/browser/web_applications/app_service:test_support", "//chrome/test/media_router/access_code_cast:access_code_cast_integration_base", "//chromeos/components/kcer", "//chromeos/crosapi/cpp:cpp", @@ -5655,6 +5658,7 @@ "//chromeos/startup", "//chromeos/ui/base", "//chromeos/ui/frame", + "//chromeos/ui/frame:test_support", "//components/account_manager_core:test_support", "//components/captive_portal/content:content", "//components/captive_portal/core:buildflags", @@ -5678,6 +5682,7 @@ "//components/webapps/browser", "//components/webapps/common", "//services/preferences/public/cpp:cpp", + "//ui/aura:test_support", "//ui/display:test_support", "//ui/events:test_support", "//ui/gfx/codec", @@ -8630,6 +8635,7 @@ "//components/metrics/structured:structured_events", "//components/metrics/structured:structured_metrics_features", "//components/metrics/structured:test_support", + "//components/metrics/structured/lib", "//components/omnibox/browser:vector_icons", "//components/services/app_service", "//components/session_manager/core", @@ -10165,6 +10171,7 @@ "//components/metrics/structured:structured_events", "//components/metrics/structured:structured_metrics_validator", "//components/metrics/structured:test_support", + "//components/metrics/structured/lib", ] } @@ -10492,6 +10499,7 @@ ":lacros_test_support_ui", "//chromeos/lacros", "//chromeos/lacros:test_support", + "//chromeos/startup:startup", "//components/account_manager_core", "//components/account_manager_core:test_support", ]
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc index 7fa234cb..32212a34 100644 --- a/chrome/test/base/in_process_browser_test.cc +++ b/chrome/test/base/in_process_browser_test.cc
@@ -161,6 +161,7 @@ #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h" #include "chromeos/lacros/lacros_service.h" +#include "chromeos/startup/browser_params_proxy.h" #include "components/account_manager_core/chromeos/account_manager.h" #include "components/account_manager_core/chromeos/account_manager_facade_factory.h" // nogncheck #include "components/account_manager_core/chromeos/fake_account_manager_ui.h" // nogncheck @@ -291,18 +292,14 @@ // Try to find a better name. bool WaitForWindowCreation(Browser* browser) { #if BUILDFLAG(IS_CHROMEOS_LACROS) - // TODO(crbug.com/1508245): Get rid of the IsTestControllerAvailable condition - // by making it always true (when crosapi is enabled). Moreover, propagate the - // WaitForWindowCreation return value. This requires fixing some tests that - // improperly override init params. - if (InProcessBrowserTest::IsCrosapiEnabled() && IsTestControllerAvailable()) { + if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + CHECK(IsTestControllerAvailable()); // Wait for window creation to complete in Ash in order to avoid // wayland-crosapi race conditions in subsequent test steps. aura::Window* window = browser->window()->GetNativeWindow(); std::string id = lacros_window_utility::GetRootWindowUniqueId(window->GetRootWindow()); - std::ignore = browser_test_util::WaitForWindowCreation(id); - return true; + return browser_test_util::WaitForWindowCreation(id); } #endif return true; @@ -355,12 +352,6 @@ MaybeGetAshAccountManagerUIForTests()); } -bool InProcessBrowserTest::IsCrosapiEnabled() { - return !base::CommandLine::ForCurrentProcess() - ->GetSwitchValuePath("lacros-mojo-socket-for-testing") - .empty(); -} - base::Version InProcessBrowserTest::GetAshChromeVersion() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); base::FilePath ash_chrome_path = @@ -934,7 +925,8 @@ content::NetworkConnectionChangeSimulator network_change_simulator; network_change_simulator.InitializeChromeosConnectionType(); - if (IsCrosapiEnabled() && IsTestControllerAvailable()) { + if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + CHECK(IsTestControllerAvailable()); // There should NOT be any open ash browser window UI at this point. VerifyNoAshBrowserWindowOpenRightNow(); } @@ -1010,7 +1002,8 @@ CHECK(BrowserList::GetInstance()->empty()); #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (IsCrosapiEnabled() && IsTestControllerAvailable()) { + if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + CHECK(IsTestControllerAvailable()); // At this point, there should NOT be any ash browser UIs(e.g. SWA, etc) // open; otherwise, the tests running after the current one could be // polluted if the tests are running against the shared Ash (by default). @@ -1079,10 +1072,10 @@ const std::vector<std::string>& additional_cmdline_switches, const std::string& bug_number_and_reason) { DCHECK(!bug_number_and_reason.empty()); - base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - CHECK(IsCrosapiEnabled()) + CHECK(!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) << "You can only start unique ash chrome when crosapi is enabled. " << "It should not be necessary otherwise."; + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); base::FilePath ash_dir_holder = cmdline->GetSwitchValuePath("unique-ash-dir"); CHECK(!ash_dir_holder.empty()); CHECK(unique_ash_user_data_dir_.CreateUniqueTempDirUnderPath(ash_dir_holder));
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h index e2a7a8d..1e524c7c 100644 --- a/chrome/test/base/in_process_browser_test.h +++ b/chrome/test/base/in_process_browser_test.h
@@ -240,9 +240,6 @@ const std::string& bug_number_and_reason); #endif - // Returns true if crosapi is enabled for the test. - static bool IsCrosapiEnabled(); - protected: // Closes the given browser and waits for it to release all its resources. void CloseBrowserSynchronously(Browser* browser);
diff --git a/chrome/test/base/run_all_unittests.cc b/chrome/test/base/run_all_unittests.cc index 0c6e47b..0ffedec 100644 --- a/chrome/test/base/run_all_unittests.cc +++ b/chrome/test/base/run_all_unittests.cc
@@ -57,10 +57,6 @@ int main(int argc, char** argv) { base::PlatformThread::SetName("MainThread"); -#if BUILDFLAG(IS_CHROMEOS_LACROS) - chromeos::ScopedDisableCrosapiForTesting disable_crosapi; -#endif - content::UnitTestTestSuite test_suite( new ChromeUnitTestSuite(argc, argv), base::BindRepeating(CreateContentClients));
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 3fb854e..d265a916 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -101,6 +101,7 @@ "chromeos/inline_login/inline_login_browsertest.cc", "chromeos/personalization_app/personalization_app_browsertest.cc", "chromeos/personalization_app/personalization_app_sea_pen_browsertest.cc", + "chromeos/print_preview_cros/print_preview_cros_browsertest.cc", "chromeos/scanning/scanning_app_browsertest.cc", "chromeos/vc_background_ui/vc_background_ui_browsertest.cc", "settings/chromeos/os_settings_browsertest.cc", @@ -494,6 +495,7 @@ "chromeos/parent_access:build_grdp", "chromeos/personalization_app:build_grdp", "chromeos/print_management:build_grdp", + "chromeos/print_preview_cros:build_grdp", "chromeos/scanning:build_grdp", "chromeos/shortcut_customization:build_grdp", "chromeos/vc_background_ui:build_grdp", @@ -519,6 +521,7 @@ "$target_gen_dir/chromeos/parent_access/resources.grdp", "$target_gen_dir/chromeos/personalization_app/resources.grdp", "$target_gen_dir/chromeos/print_management/resources.grdp", + "$target_gen_dir/chromeos/print_preview_cros/resources.grdp", "$target_gen_dir/chromeos/resources.grdp", "$target_gen_dir/chromeos/vc_background_ui/resources.grdp", "$target_gen_dir/chromeos/scanning/resources.grdp",
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts index c62c3da..e7cd50e 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts
@@ -61,10 +61,7 @@ recentImageData: {}, recentImages: false, thumbnails: true, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, recentImageData: {}, @@ -82,10 +79,7 @@ recentImageData: {}, recentImages: false, thumbnails: true, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, recentImageData: {}, @@ -103,10 +97,7 @@ recentImageData: {}, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, recentImageData: {},
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_recent_wallpapers_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_recent_wallpapers_element_test.ts index 2bc03133..4400f68 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_recent_wallpapers_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_recent_wallpapers_element_test.ts
@@ -63,10 +63,7 @@ }, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }; @@ -140,10 +137,7 @@ recentImageData: {}, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, recentImages: seaPenProvider.recentImages, @@ -173,10 +167,7 @@ }, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, }; @@ -197,10 +188,7 @@ }, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, }; @@ -219,10 +207,7 @@ recentImageData: {}, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, recentImageData: seaPenProvider.recentImageData, @@ -247,10 +232,7 @@ }, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, }; @@ -281,10 +263,7 @@ }, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, }; @@ -422,10 +401,7 @@ '/sea_pen/333.jpg': false, }, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }; @@ -494,10 +470,7 @@ }, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }; @@ -530,10 +503,7 @@ }, recentImages: false, thumbnails: false, - selected: { - image: false, - attribution: false, - }, + currentSelected: false, setImage: 0, }, recentImages: seaPenProvider.recentImages,
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts index 2479a5f..897c57b 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts
@@ -149,7 +149,7 @@ async () => { personalizationStore.data.wallpaper.seaPen.loading = { ...personalizationStore.data.wallpaper.seaPen.loading, - selected: {image: true, attribution: false}, + currentSelected: true, setImage: 0, }; wallpaperSelectedElement = initElement(WallpaperSelectedElement); @@ -168,28 +168,12 @@ assertTrue( !!placeholder, 'image is loading, the placeholder should display'); - // Attribution still loading, loading placeholder should be shown. - personalizationStore.data.wallpaper.seaPen = { - ...personalizationStore.data.wallpaper.seaPen, - loading: { - ...personalizationStore.data.wallpaper.seaPen.loading, - selected: {image: false, attribution: true}, - setImage: 0, - }, - }; - personalizationStore.notifyObservers(); - await waitAfterNextRender(wallpaperSelectedElement); - - assertEquals( - '', placeholder.style.display, - 'attribution is loading, loading placeholder should display'); - // Loading placeholder should be hidden. personalizationStore.data.wallpaper.seaPen = { ...personalizationStore.data.wallpaper.seaPen, loading: { ...personalizationStore.data.wallpaper.seaPen.loading, - selected: {image: false, attribution: false}, + currentSelected: false, setImage: 0, }, }; @@ -213,7 +197,7 @@ ...personalizationStore.data.wallpaper.seaPen, loading: { ...personalizationStore.data.wallpaper.seaPen.loading, - selected: {image: false, attribution: false}, + currentSelected: false, setImage: 1, }, };
diff --git a/chrome/test/data/webui/chromeos/print_preview_cros/BUILD.gn b/chrome/test/data/webui/chromeos/print_preview_cros/BUILD.gn new file mode 100644 index 0000000..7e8c8d763 --- /dev/null +++ b/chrome/test/data/webui/chromeos/print_preview_cros/BUILD.gn
@@ -0,0 +1,27 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../../build_webui_tests.gni") + +build_webui_tests("build_webui_tests") { + ts_path_mappings = [ + "chrome://os-print/*|" + rebase_path( + "$root_gen_dir/ash/webui/print_preview_cros/resources/tsc/*", + target_gen_dir), + "chrome://webui-test/chromeos/*|" + + rebase_path("$root_gen_dir/chrome/test/data/webui/chromeos/tsc/*", + target_gen_dir), + ] + + files = [ "print_preview_cros_app_test.ts" ] + + ts_deps = [ + "//ash/webui/common/resources:build_ts", + "//ash/webui/print_preview_cros/resources:build_ts", + "//chrome/test/data/webui/chromeos:build_ts", + "//third_party/polymer/v3_0:library", + "//ui/webui/resources/js:build_ts", + "//ui/webui/resources/mojo:build_ts", + ] +}
diff --git a/chrome/test/data/webui/chromeos/print_preview_cros/print_preview_cros_app_test.ts b/chrome/test/data/webui/chromeos/print_preview_cros/print_preview_cros_app_test.ts new file mode 100644 index 0000000..287c8b3 --- /dev/null +++ b/chrome/test/data/webui/chromeos/print_preview_cros/print_preview_cros_app_test.ts
@@ -0,0 +1,24 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://os-print/js/print_preview_cros_app.js'; + +import {PrintPreviewCrosAppElement} from 'chrome://os-print/js/print_preview_cros_app.js'; +import {assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; +import {isVisible} from 'chrome://webui-test/test_util.js'; + +suite('PrintPreviewCrosApp', () => { + setup(() => { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + }); + + // Verify the print-preview-cros-app element can be rendered. + test('element renders', () => { + const element = document.createElement(PrintPreviewCrosAppElement.is) as + PrintPreviewCrosAppElement; + assertTrue(!!element); + document.body.append(element); + assertTrue(isVisible(element)); + }); +});
diff --git a/chrome/test/data/webui/chromeos/print_preview_cros/print_preview_cros_browsertest.cc b/chrome/test/data/webui/chromeos/print_preview_cros/print_preview_cros_browsertest.cc new file mode 100644 index 0000000..77b90bf --- /dev/null +++ b/chrome/test/data/webui/chromeos/print_preview_cros/print_preview_cros_browsertest.cc
@@ -0,0 +1,38 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/constants/ash_features.h" +#include "ash/webui/print_preview_cros/url_constants.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/test/base/web_ui_mocha_browser_test.h" +#include "content/public/test/browser_test.h" + +/** + * @fileoverview Test suite for chrome://os-print. + */ +namespace ash { + +namespace { + +class PrintPreviewCrosBrowserTest : public WebUIMochaBrowserTest { + public: + PrintPreviewCrosBrowserTest() { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{features::kPrintPreviewCrosApp}, + /*disabled_features=*/{}); + set_test_loader_host(::ash::kChromeUIPrintPreviewCrosHost); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(PrintPreviewCrosBrowserTest, PrintPreviewCrosAppTest) { + RunTest("chromeos/print_preview_cros/print_preview_cros_app_test.js", + "mocha.run()"); +} + +} // namespace + +} // namespace ash
diff --git a/chrome/test/data/webui/compose/BUILD.gn b/chrome/test/data/webui/compose/BUILD.gn index 31eae3c..88576510 100644 --- a/chrome/test/data/webui/compose/BUILD.gn +++ b/chrome/test/data/webui/compose/BUILD.gn
@@ -5,6 +5,7 @@ import("../build_webui_tests.gni") build_webui_tests("build") { + is_chrome_untrusted = true files = [ "compose_animator_test.ts", "compose_app_test.ts", @@ -16,7 +17,7 @@ ] ts_path_mappings = - [ "chrome://compose/*|" + + [ "chrome-untrusted://compose/*|" + rebase_path("$root_gen_dir/chrome/browser/resources/compose/tsc/*", target_gen_dir) ] ts_deps = [
diff --git a/chrome/test/data/webui/compose/compose_animator_test.ts b/chrome/test/data/webui/compose/compose_animator_test.ts index 0fa7838..ea64ffb 100644 --- a/chrome/test/data/webui/compose/compose_animator_test.ts +++ b/chrome/test/data/webui/compose/compose_animator_test.ts
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://compose/animations/animator.js'; +import 'chrome-untrusted://compose/animations/animator.js'; import {getTrustedHTML} from '//resources/js/static_types.js'; -import {Animator} from 'chrome://compose/animations/animator.js'; -import {assertEquals} from 'chrome://webui-test/chai_assert.js'; +import {Animator} from 'chrome-untrusted://compose/animations/animator.js'; +import {assertEquals} from 'chrome-untrusted://webui-test/chai_assert.js'; suite('ComposeAnimator', () => { let animator: Animator;
diff --git a/chrome/test/data/webui/compose/compose_app_focus_test.ts b/chrome/test/data/webui/compose/compose_app_focus_test.ts index 836fa44..d2472257 100644 --- a/chrome/test/data/webui/compose/compose_app_focus_test.ts +++ b/chrome/test/data/webui/compose/compose_app_focus_test.ts
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://compose/app.js'; +import 'chrome-untrusted://compose/app.js'; -import type {ComposeAppElement} from 'chrome://compose/app.js'; -import {Length, Tone, UserFeedback} from 'chrome://compose/compose.mojom-webui.js'; -import {ComposeApiProxyImpl} from 'chrome://compose/compose_api_proxy.js'; -import {ComposeStatus} from 'chrome://compose/compose_enums.mojom-webui.js'; -import {assertEquals} from 'chrome://webui-test/chai_assert.js'; -import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; +import type {ComposeAppElement} from 'chrome-untrusted://compose/app.js'; +import {Length, Tone, UserFeedback} from 'chrome-untrusted://compose/compose.mojom-webui.js'; +import {ComposeApiProxyImpl} from 'chrome-untrusted://compose/compose_api_proxy.js'; +import {ComposeStatus} from 'chrome-untrusted://compose/compose_enums.mojom-webui.js'; +import {assertEquals} from 'chrome-untrusted://webui-test/chai_assert.js'; +import {flushTasks} from 'chrome-untrusted://webui-test/polymer_test_util.js'; import {TestComposeApiProxy} from './test_compose_api_proxy.js';
diff --git a/chrome/test/data/webui/compose/compose_app_test.ts b/chrome/test/data/webui/compose/compose_app_test.ts index 7e258c7..1e59070 100644 --- a/chrome/test/data/webui/compose/compose_app_test.ts +++ b/chrome/test/data/webui/compose/compose_app_test.ts
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://compose/app.js'; +import 'chrome-untrusted://compose/app.js'; import {CrFeedbackOption} from '//resources/cr_elements/cr_feedback_buttons/cr_feedback_buttons.js'; import {loadTimeData} from '//resources/js/load_time_data.js'; -import type {ComposeAppElement, ComposeAppState} from 'chrome://compose/app.js'; -import type {ComposeState} from 'chrome://compose/compose.mojom-webui.js'; -import {CloseReason, Length, Tone, UserFeedback} from 'chrome://compose/compose.mojom-webui.js'; -import {ComposeApiProxyImpl} from 'chrome://compose/compose_api_proxy.js'; -import {ComposeStatus} from 'chrome://compose/compose_enums.mojom-webui.js'; -import {assertDeepEquals, assertEquals, assertFalse, assertStringContains, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; -import {isVisible, whenCheck} from 'chrome://webui-test/test_util.js'; +import type {ComposeAppElement, ComposeAppState} from 'chrome-untrusted://compose/app.js'; +import type {ComposeState} from 'chrome-untrusted://compose/compose.mojom-webui.js'; +import {CloseReason, Length, Tone, UserFeedback} from 'chrome-untrusted://compose/compose.mojom-webui.js'; +import {ComposeApiProxyImpl} from 'chrome-untrusted://compose/compose_api_proxy.js'; +import {ComposeStatus} from 'chrome-untrusted://compose/compose_enums.mojom-webui.js'; +import {assertDeepEquals, assertEquals, assertFalse, assertStringContains, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; +import {flushTasks} from 'chrome-untrusted://webui-test/polymer_test_util.js'; +import {isVisible, whenCheck} from 'chrome-untrusted://webui-test/test_util.js'; import {TestComposeApiProxy} from './test_compose_api_proxy.js';
diff --git a/chrome/test/data/webui/compose/compose_browsertest.cc b/chrome/test/data/webui/compose/compose_browsertest.cc index d639f1f7..3437f1e 100644 --- a/chrome/test/data/webui/compose/compose_browsertest.cc +++ b/chrome/test/data/webui/compose/compose_browsertest.cc
@@ -11,7 +11,8 @@ class ComposeTest : public WebUIMochaBrowserTest { protected: ComposeTest() { - set_test_loader_host(chrome::kChromeUIComposeHost); + set_test_loader_host(chrome::kChromeUIUntrustedComposeHost); + set_test_loader_scheme(content::kChromeUIUntrustedScheme); scoped_compose_enabled_ = ComposeEnabling::ScopedEnableComposeForTesting(); }
diff --git a/chrome/test/data/webui/compose/compose_focus_test.cc b/chrome/test/data/webui/compose/compose_focus_test.cc index e0b859d..534bcc5d 100644 --- a/chrome/test/data/webui/compose/compose_focus_test.cc +++ b/chrome/test/data/webui/compose/compose_focus_test.cc
@@ -11,7 +11,8 @@ class ComposeFocusTest : public WebUIMochaFocusTest { protected: ComposeFocusTest() { - set_test_loader_host(chrome::kChromeUIComposeHost); + set_test_loader_host(chrome::kChromeUIUntrustedComposeHost); + set_test_loader_scheme(content::kChromeUIUntrustedScheme); scoped_compose_enabled_ = ComposeEnabling::ScopedEnableComposeForTesting(); }
diff --git a/chrome/test/data/webui/compose/compose_textarea_test.ts b/chrome/test/data/webui/compose/compose_textarea_test.ts index b94b2e17..8016716 100644 --- a/chrome/test/data/webui/compose/compose_textarea_test.ts +++ b/chrome/test/data/webui/compose/compose_textarea_test.ts
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://compose/textarea.js'; +import 'chrome-untrusted://compose/textarea.js'; -import type {ComposeTextareaElement} from 'chrome://compose/textarea.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; +import type {ComposeTextareaElement} from 'chrome-untrusted://compose/textarea.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; +import {eventToPromise, isVisible} from 'chrome-untrusted://webui-test/test_util.js'; suite('ComposeTextarea', () => { let textarea: ComposeTextareaElement;
diff --git a/chrome/test/data/webui/compose/result_text_test.ts b/chrome/test/data/webui/compose/result_text_test.ts index 84dcd81..f8169a2e 100644 --- a/chrome/test/data/webui/compose/result_text_test.ts +++ b/chrome/test/data/webui/compose/result_text_test.ts
@@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://compose/result_text.js'; +import 'chrome-untrusted://compose/result_text.js'; -import type {ComposeResultTextElement} from 'chrome://compose/result_text.js'; -// import {assertEquals, assertFalse, assertStringEquals, assertTrue} from -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; +import type {ComposeResultTextElement} from 'chrome-untrusted://compose/result_text.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; +import {flushTasks} from 'chrome-untrusted://webui-test/polymer_test_util.js'; suite('ResultText', () => { let resultText: ComposeResultTextElement;
diff --git a/chrome/test/data/webui/compose/test_compose_api_proxy.ts b/chrome/test/data/webui/compose/test_compose_api_proxy.ts index 29930468..23da4186 100644 --- a/chrome/test/data/webui/compose/test_compose_api_proxy.ts +++ b/chrome/test/data/webui/compose/test_compose_api_proxy.ts
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import type {CloseReason, ComposeState, OpenMetadata, StyleModifiers} from 'chrome://compose/compose.mojom-webui.js'; -import {ComposeDialogCallbackRouter, UserFeedback} from 'chrome://compose/compose.mojom-webui.js'; -import type {ComposeApiProxy} from 'chrome://compose/compose_api_proxy.js'; -import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; +import type {CloseReason, ComposeState, OpenMetadata, StyleModifiers} from 'chrome-untrusted://compose/compose.mojom-webui.js'; +import {ComposeDialogCallbackRouter, UserFeedback} from 'chrome-untrusted://compose/compose.mojom-webui.js'; +import type {ComposeApiProxy} from 'chrome-untrusted://compose/compose_api_proxy.js'; +import {TestBrowserProxy} from 'chrome-untrusted://webui-test/test_browser_proxy.js'; function getDefaultComposeState(): ComposeState { return {
diff --git a/chrome/test/data/webui/compose/word_streamer_test.ts b/chrome/test/data/webui/compose/word_streamer_test.ts index 4cce1e25..b69c020 100644 --- a/chrome/test/data/webui/compose/word_streamer_test.ts +++ b/chrome/test/data/webui/compose/word_streamer_test.ts
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://compose/word_streamer.js'; +import 'chrome-untrusted://compose/word_streamer.js'; -import {WordStreamer} from 'chrome://compose/word_streamer.js'; -import {assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {MockTimer} from 'chrome://webui-test/mock_timer.js'; +import {WordStreamer} from 'chrome-untrusted://compose/word_streamer.js'; +import {assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; +import {MockTimer} from 'chrome-untrusted://webui-test/mock_timer.js'; interface Update { words: string[];
diff --git a/chrome/test/data/webui/tab_search/BUILD.gn b/chrome/test/data/webui/tab_search/BUILD.gn index 4afdaac..694079a8 100644 --- a/chrome/test/data/webui/tab_search/BUILD.gn +++ b/chrome/test/data/webui/tab_search/BUILD.gn
@@ -18,7 +18,7 @@ "tab_search_test_data.ts", "tab_search_test_helper.ts", "test_tab_search_api_proxy.ts", - "test_tab_search_sync_browser_proxy.ts", + "test_tab_search_sign_in_browser_proxy.ts", ] ts_path_mappings = [
diff --git a/chrome/test/data/webui/tab_search/tab_organization_page_test.ts b/chrome/test/data/webui/tab_search/tab_organization_page_test.ts index 0299818..a87419e 100644 --- a/chrome/test/data/webui/tab_search/tab_organization_page_test.ts +++ b/chrome/test/data/webui/tab_search/tab_organization_page_test.ts
@@ -2,37 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {webUIListenerCallback} from 'chrome://resources/js/cr.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {mojoString16ToString, stringToMojoString16} from 'chrome://resources/js/mojo_type_util.js'; -import type {SyncInfo, Tab, TabOrganizationPageElement, TabOrganizationResultsElement, TabOrganizationSession} from 'chrome://tab-search.top-chrome/tab_search.js'; -import {TabOrganizationError, TabOrganizationState, TabSearchApiProxyImpl, TabSearchSyncBrowserProxyImpl} from 'chrome://tab-search.top-chrome/tab_search.js'; +import type {Tab, TabOrganizationPageElement, TabOrganizationResultsElement, TabOrganizationSession} from 'chrome://tab-search.top-chrome/tab_search.js'; +import {TabOrganizationError, TabOrganizationState, TabSearchApiProxyImpl, TabSearchSignInBrowserProxyImpl} from 'chrome://tab-search.top-chrome/tab_search.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; import {isVisible} from 'chrome://webui-test/test_util.js'; import {TestTabSearchApiProxy} from './test_tab_search_api_proxy.js'; -import {TestTabSearchSyncBrowserProxy} from './test_tab_search_sync_browser_proxy.js'; +import {TestTabSearchSignInBrowserProxy} from './test_tab_search_sign_in_browser_proxy.js'; suite('TabOrganizationPageTest', () => { let tabOrganizationPage: TabOrganizationPageElement; let tabOrganizationResults: TabOrganizationResultsElement; let testApiProxy: TestTabSearchApiProxy; - let testSyncProxy: TestTabSearchSyncBrowserProxy; + let testSignInProxy: TestTabSearchSignInBrowserProxy; - async function tabOrganizationPageSetup(syncInfo: SyncInfo = { - syncing: true, - syncingHistory: true, - paused: false, - }) { + async function tabOrganizationPageSetup() { testApiProxy = new TestTabSearchApiProxy(); const session = createSession(); testApiProxy.setSession(session); TabSearchApiProxyImpl.setInstance(testApiProxy); - testSyncProxy = new TestTabSearchSyncBrowserProxy(); - testSyncProxy.syncInfo = syncInfo; - TabSearchSyncBrowserProxyImpl.setInstance(testSyncProxy); + testSignInProxy = new TestTabSearchSignInBrowserProxy(); + TabSearchSignInBrowserProxyImpl.setInstance(testSignInProxy); tabOrganizationPage = document.createElement('tab-organization-page'); @@ -48,8 +42,8 @@ testApiProxy.setSession(session); TabSearchApiProxyImpl.setInstance(testApiProxy); - testSyncProxy = new TestTabSearchSyncBrowserProxy(); - TabSearchSyncBrowserProxyImpl.setInstance(testSyncProxy); + testSignInProxy = new TestTabSearchSignInBrowserProxy(); + TabSearchSignInBrowserProxyImpl.setInstance(testSignInProxy); tabOrganizationResults = document.createElement('tab-organization-results'); tabOrganizationResults.name = @@ -319,113 +313,6 @@ assertTrue(refreshButton.innerHTML.includes(rejectSuggestion)); }); - test('Sync required for organization', async () => { - const syncInfo: SyncInfo = { - syncing: false, - syncingHistory: false, - paused: false, - }; - await tabOrganizationPageSetup(syncInfo); - - const notStarted = tabOrganizationPage.shadowRoot!.querySelector( - 'tab-organization-not-started'); - assertTrue(!!notStarted); - assertTrue(isVisible(notStarted)); - - const actionButton = notStarted.shadowRoot!.querySelector('cr-button'); - assertTrue(!!actionButton); - actionButton.click(); - - // The action button should not request tab organization if the user is in - // an invalid sync state. - assertEquals(0, testApiProxy.getCallCount('requestTabOrganization')); - }); - - test('Triggers sync when not syncing', async () => { - const syncInfo: SyncInfo = { - syncing: false, - syncingHistory: true, - paused: false, - }; - await tabOrganizationPageSetup(syncInfo); - - const notStarted = tabOrganizationPage.shadowRoot!.querySelector( - 'tab-organization-not-started'); - assertTrue(!!notStarted); - assertTrue(isVisible(notStarted)); - - const actionButton = notStarted.shadowRoot!.querySelector('cr-button'); - assertTrue(!!actionButton); - actionButton.click(); - - assertEquals(1, testApiProxy.getCallCount('triggerSync')); - }); - - test('Triggers sign in when paused', async () => { - const syncInfo: SyncInfo = { - syncing: true, - syncingHistory: true, - paused: true, - }; - await tabOrganizationPageSetup(syncInfo); - - const notStarted = tabOrganizationPage.shadowRoot!.querySelector( - 'tab-organization-not-started'); - assertTrue(!!notStarted); - assertTrue(isVisible(notStarted)); - - const actionButton = notStarted.shadowRoot!.querySelector('cr-button'); - assertTrue(!!actionButton); - actionButton.click(); - - assertEquals(1, testApiProxy.getCallCount('triggerSignIn')); - }); - - test('Opens settings when not syncing history', async () => { - const syncInfo: SyncInfo = { - syncing: true, - syncingHistory: false, - paused: false, - }; - await tabOrganizationPageSetup(syncInfo); - - const notStarted = tabOrganizationPage.shadowRoot!.querySelector( - 'tab-organization-not-started'); - assertTrue(!!notStarted); - assertTrue(isVisible(notStarted)); - - const actionButton = notStarted.shadowRoot!.querySelector('cr-button'); - assertTrue(!!actionButton); - actionButton.click(); - - assertEquals(1, testApiProxy.getCallCount('openSyncSettings')); - }); - - test('Updates with sync changes', async () => { - await tabOrganizationPageSetup(); - - const notStarted = tabOrganizationPage.shadowRoot!.querySelector( - 'tab-organization-not-started'); - assertTrue(!!notStarted); - assertTrue(isVisible(notStarted)); - - const accountRowSynced = - notStarted.shadowRoot!.querySelector('.account-row'); - assertFalse(!!accountRowSynced); - - testSyncProxy.syncInfo = { - syncing: false, - syncingHistory: false, - paused: false, - }; - webUIListenerCallback('sync-info-changed', testSyncProxy.syncInfo); - await testSyncProxy.whenCalled('getSyncInfo'); - - const accountRowUnsynced = - notStarted.shadowRoot!.querySelector('.account-row'); - assertTrue(!!accountRowUnsynced); - }); - test('Check now action activates on Enter', async () => { await tabOrganizationPageSetup();
diff --git a/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts b/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts index 9609b68..2570988 100644 --- a/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts +++ b/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.ts
@@ -29,10 +29,8 @@ 'setTabIndex', 'startTabGroupTutorial', 'triggerFeedback', - 'triggerSync', 'triggerSignIn', 'openHelpPage', - 'openSyncSettings', 'setUserFeedback', 'showUi', ]); @@ -108,10 +106,6 @@ this.methodCalled('triggerFeedback', [sessionId]); } - triggerSync() { - this.methodCalled('triggerSync'); - } - triggerSignIn() { this.methodCalled('triggerSignIn'); } @@ -120,10 +114,6 @@ this.methodCalled('openHelpPage'); } - openSyncSettings() { - this.methodCalled('openSyncSettings'); - } - setUserFeedback(feedback: UserFeedback) { this.methodCalled('setUserFeedback', [feedback]); }
diff --git a/chrome/test/data/webui/tab_search/test_tab_search_sign_in_browser_proxy.ts b/chrome/test/data/webui/tab_search/test_tab_search_sign_in_browser_proxy.ts new file mode 100644 index 0000000..4bb0a08 --- /dev/null +++ b/chrome/test/data/webui/tab_search/test_tab_search_sign_in_browser_proxy.ts
@@ -0,0 +1,20 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import type {TabSearchSignInBrowserProxy} from 'chrome://tab-search.top-chrome/tab_search.js'; +import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; + +export class TestTabSearchSignInBrowserProxy extends TestBrowserProxy implements + TabSearchSignInBrowserProxy { + constructor() { + super([ + 'getSignInState', + ]); + } + + getSignInState() { + this.methodCalled('getSignInState'); + return Promise.resolve(true); + } +}
diff --git a/chrome/test/data/webui/tab_search/test_tab_search_sync_browser_proxy.ts b/chrome/test/data/webui/tab_search/test_tab_search_sync_browser_proxy.ts deleted file mode 100644 index 1d545bf..0000000 --- a/chrome/test/data/webui/tab_search/test_tab_search_sync_browser_proxy.ts +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import type {AccountInfo, SyncInfo, TabSearchSyncBrowserProxy} from 'chrome://tab-search.top-chrome/tab_search.js'; -import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; - -export class TestTabSearchSyncBrowserProxy extends TestBrowserProxy implements - TabSearchSyncBrowserProxy { - accountInfo: AccountInfo; - syncInfo: SyncInfo; - - constructor() { - super([ - 'getSyncInfo', - 'getAccountInfo', - ]); - - this.accountInfo = { - name: 'Jane Doe', - email: 'testemail@gmail.com', - }; - this.syncInfo = { - syncing: true, - syncingHistory: true, - paused: false, - }; - } - - getSyncInfo() { - this.methodCalled('getSyncInfo'); - return Promise.resolve(this.syncInfo); - } - - getAccountInfo() { - this.methodCalled('getAccountInfo'); - return Promise.resolve(this.accountInfo); - } -}
diff --git a/chromeos/constants/devicetype_unittest.cc b/chromeos/constants/devicetype_unittest.cc index 3c133311..b9d8dd6 100644 --- a/chromeos/constants/devicetype_unittest.cc +++ b/chromeos/constants/devicetype_unittest.cc
@@ -67,7 +67,6 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) TEST(DeviceTypeTest, GetDeviceTypeLacros) { base::test::TaskEnvironment task_environment; - chromeos::ScopedDisableCrosapiForTesting disable_crosapi; { auto params = crosapi::mojom::BrowserInitParams::New(); params->device_type =
diff --git a/chromeos/lacros/lacros_service.cc b/chromeos/lacros/lacros_service.cc index 2c81066..db896c15 100644 --- a/chromeos/lacros/lacros_service.cc +++ b/chromeos/lacros/lacros_service.cc
@@ -854,9 +854,6 @@ } std::optional<uint32_t> LacrosService::CrosapiVersion() const { - if (chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { - return std::nullopt; - } DCHECK(did_bind_receiver_); return chromeos::BrowserParamsProxy::Get()->CrosapiVersion(); } @@ -880,9 +877,6 @@ } int LacrosService::GetInterfaceVersionImpl(base::Token interface_uuid) const { - if (chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { - return -1; - } if (!chromeos::BrowserParamsProxy::Get()->InterfaceVersions()) { return -1; }
diff --git a/chromeos/lacros/lacros_test_helper.cc b/chromeos/lacros/lacros_test_helper.cc index ea4f517..9c1d68a 100644 --- a/chromeos/lacros/lacros_test_helper.cc +++ b/chromeos/lacros/lacros_test_helper.cc
@@ -7,7 +7,7 @@ #include "base/check.h" #include "base/test/test_future.h" #include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h" -#include "chromeos/startup/browser_init_params.h" +#include "chromeos/startup/browser_params_proxy.h" namespace chromeos { namespace { @@ -28,20 +28,10 @@ } } // namespace -ScopedDisableCrosapiForTesting::ScopedDisableCrosapiForTesting() - : disable_crosapi_resetter_( - &BrowserInitParams::is_crosapi_disabled_for_testing_, - true) { - // Ensure that no instance exist, to prevent interference. - CHECK(!LacrosService::Get()); +ScopedLacrosServiceTestHelper::ScopedLacrosServiceTestHelper() { + CHECK(BrowserParamsProxy::IsCrosapiDisabledForTesting()); } -// TODO(crbug.com/1196314): Ensure that no instance exist on destruction, too. -// Currently, browser_tests' shutdown is an exception. -ScopedDisableCrosapiForTesting::~ScopedDisableCrosapiForTesting() = default; - -ScopedLacrosServiceTestHelper::ScopedLacrosServiceTestHelper() = default; - ScopedLacrosServiceTestHelper::~ScopedLacrosServiceTestHelper() = default; bool IsAshVersionAtLeastForTesting(base::Version required_version) {
diff --git a/chromeos/lacros/lacros_test_helper.h b/chromeos/lacros/lacros_test_helper.h index 200cf90..143aa216 100644 --- a/chromeos/lacros/lacros_test_helper.h +++ b/chromeos/lacros/lacros_test_helper.h
@@ -11,22 +11,6 @@ namespace chromeos { -// Disables crosapi while this instance is alive. -// This must be instantiate before LacrosService is instantiated. -// Used only for testing purposes. -class ScopedDisableCrosapiForTesting { - public: - ScopedDisableCrosapiForTesting(); - ScopedDisableCrosapiForTesting(const ScopedDisableCrosapiForTesting&) = - delete; - ScopedDisableCrosapiForTesting& operator=( - const ScopedDisableCrosapiForTesting&) = delete; - ~ScopedDisableCrosapiForTesting(); - - private: - base::AutoReset<bool> disable_crosapi_resetter_; -}; - // Helper for tests to instantiate LacrosService. This should only be // used for unit tests, not browser tests. // Instantiated LacrosService is expected to be accessed via @@ -40,7 +24,6 @@ ~ScopedLacrosServiceTestHelper(); private: - ScopedDisableCrosapiForTesting disable_crosapi_; LacrosService lacros_service_; };
diff --git a/chromeos/startup/README.md b/chromeos/startup/README.md index 58a4cad..97f5cf5 100644 --- a/chromeos/startup/README.md +++ b/chromeos/startup/README.md
@@ -14,3 +14,34 @@ directly. Instead, Lacros code should use `BrowserParamsProxy` which dispatches to either `BrowserInitParams` and `BrowserPostLoginParams` based on whether Lacros was prelaunched at login screen or not. + + +### `BrowserInitParams` in production vs. testing + +In production, Lacros is invoked by Ash with the +`--crosapi-mojo-platform-channel-handle` command line switch pointing to a file +descriptor. This causes Lacros to populate `BrowserInitParams` with Ash-provided +data read from the file. This happens whenever the `BrowserInitParams` are +queried for the first time. + +In testing where Lacros is not invoked by Ash (e.g. Lacros unit and browser +tests) there are two scenarios: + +1) Lacros is invoked without crosapi command line switch. Then + `BrowserInitParams` is created empty. This is the case for example for + `unit_tests` and `browser_tests`. Crosapi is thereby effectively disabled. + +2) Lacros is invoked with crosapi command line switch. Then `BrowserInitParams` + are read from Ash just as in production *unless* there's a call to + `DisableCrosapiForTesting`, in which case the behavior follows that in (1). + (An assertion ensures that `DisableCrosapiForTesting` is called before the + first query of `BrowserInitParams`, if at all). + + Detail: For technical reasons, the command line switch here is not + `--crosapi-mojo-platform-channel-handle` but + `--lacros-mojo-socket-for-testing`. The test runner passes a socket through + which `BrowserTestBase` then requests the + `--crosapi-mojo-platform-channel-handle` file descriptor from Ash. + +Only `lacros_chrome_browsertests` and Lacros `interactive_ui_tests` follow (2), +with only very few uses of `DisableCrosapiForTesting`.
diff --git a/chromeos/startup/browser_init_params.cc b/chromeos/startup/browser_init_params.cc index f9ac18a9..e7ac76f 100644 --- a/chromeos/startup/browser_init_params.cc +++ b/chromeos/startup/browser_init_params.cc
@@ -7,6 +7,8 @@ #include <optional> #include <string> +#include "base/check_is_test.h" +#include "base/command_line.h" #include "chromeos/startup/startup.h" namespace chromeos { @@ -32,17 +34,49 @@ } // namespace +std::optional<bool> BrowserInitParams::is_crosapi_enabled_; + +bool BrowserInitParams::IsCrosapiDisabledForTesting() { + return !IsCrosapiEnabled(); +} + +bool BrowserInitParams::IsCrosapiEnabled() { + if (is_crosapi_enabled_.has_value()) { + return *is_crosapi_enabled_; + } + + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + const bool enabled = + command_line->HasSwitch("crosapi-mojo-platform-channel-handle") || + command_line->HasSwitch("lacros-mojo-socket-for-testing"); + if (!enabled) { + CHECK_IS_TEST(); + } + is_crosapi_enabled_ = enabled; + return enabled; +} + +void BrowserInitParams::DisableCrosapiForTesting() { + CHECK_IS_TEST(); + // TODO(crbug.com/324508902): Strengthen this CHECK condition to + // `!is_crosapi_enabled_.has_value()` when the bug is fixed. + CHECK(!is_crosapi_enabled_.value_or(false)) + << "You are calling DisableCrosapiForTesting too late."; + is_crosapi_enabled_ = false; +} + BrowserInitParams::BrowserInitParams() - : init_params_(is_crosapi_disabled_for_testing_ - ? crosapi::mojom::BrowserInitParams::New() - : ReadStartupBrowserInitParams()) { - if (!init_params_) { - LOG(WARNING) << "BrowserInitParams is not set. " - << "This message should not appear except for testing. " - << "For testing, consider setting " - << "BrowserInitParams::is_crosapi_disabled_for_testing_ " - << "to true if crosapi is not required."; - init_params_ = crosapi::mojom::BrowserInitParams::New(); + : init_params_(IsCrosapiEnabled() + ? ReadStartupBrowserInitParams() + : crosapi::mojom::BrowserInitParams::New()) { + if (IsCrosapiEnabled()) { + CHECK(init_params_) << "crosapi is enabled but BrowserInitParams could not " + "be read. You are probably trying to get or set " + "the BrowserInitParams too early."; + CHECK(init_params_->ash_chrome_version); + } else { + CHECK(init_params_); } } @@ -59,6 +93,15 @@ // static void BrowserInitParams::SetInitParamsForTests( crosapi::mojom::BrowserInitParamsPtr init_params) { + CHECK_IS_TEST(); + if (IsCrosapiEnabled()) { + CHECK(init_params); + CHECK(init_params->ash_chrome_version) + << "crosapi is enabled but the given BrowserInitParams is missing " + "essential data. Make sure to use " + "BrowserInitParams::GetForTests()->Clone() and customize that " + "instead of starting with an empty one"; + } GetInstance()->init_params_ = std::move(init_params); } @@ -75,7 +118,4 @@ return browser_init_params.get(); } -// static -bool BrowserInitParams::is_crosapi_disabled_for_testing_ = false; - } // namespace chromeos
diff --git a/chromeos/startup/browser_init_params.h b/chromeos/startup/browser_init_params.h index a2ab0f8..1163c98 100644 --- a/chromeos/startup/browser_init_params.h +++ b/chromeos/startup/browser_init_params.h
@@ -32,16 +32,23 @@ // Create Mem FD from `init_params_`. static base::ScopedFD CreateStartupData(); - static bool is_crosapi_disabled_for_testing() { - return is_crosapi_disabled_for_testing_; - } + // This will always be false in production. + static bool IsCrosapiDisabledForTesting(); + + // Use sparingly. This should be needed only in exceptional cases. In + // particular, Lacros unit_tests and browser_tests have crosapi disabled by + // default and don't need to call this. + // + // This action cannot be undone, so it must be used only by tests that run in + // separate processes. (However, crosapi is only enabled in such tests + // anyways, hence this is not really a restriction.) + // + // See also README.md. + static void DisableCrosapiForTesting(); private: friend base::NoDestructor<BrowserInitParams>; - // Needs to access |is_crosapi_disabled_for_testing_|. - friend class ScopedDisableCrosapiForTesting; - // Needs to access |Get()|. friend class BrowserParamsProxy; @@ -58,13 +65,11 @@ BrowserInitParams(); ~BrowserInitParams(); - // Tests will set this to |true| which will make all crosapi functionality - // unavailable. Should be set from ScopedDisableCrosapiForTesting always. - // TODO(https://crbug.com/1131722): Ideally we could stub this out or make - // this functional for tests without modifying production code - static bool is_crosapi_disabled_for_testing_; + static bool IsCrosapiEnabled(); - // Parameters passed from ash-chrome. + static std::optional<bool> is_crosapi_enabled_; + + // Parameters passed from ash-chrome (unless crosapi is disabled). crosapi::mojom::BrowserInitParamsPtr init_params_; };
diff --git a/chromeos/startup/browser_params_proxy.cc b/chromeos/startup/browser_params_proxy.cc index e9ab362..f82aae8 100644 --- a/chromeos/startup/browser_params_proxy.cc +++ b/chromeos/startup/browser_params_proxy.cc
@@ -26,8 +26,12 @@ return BrowserPostLoginParams::IsLoggedIn(); } -bool BrowserParamsProxy::IsCrosapiDisabledForTesting() const { - return BrowserInitParams::is_crosapi_disabled_for_testing(); +bool BrowserParamsProxy::IsCrosapiDisabledForTesting() { + return BrowserInitParams::IsCrosapiDisabledForTesting(); +} + +void BrowserParamsProxy::DisableCrosapiForTesting() { + return BrowserInitParams::DisableCrosapiForTesting(); } uint32_t BrowserParamsProxy::CrosapiVersion() const {
diff --git a/chromeos/startup/browser_params_proxy.h b/chromeos/startup/browser_params_proxy.h index 171d87f..961e542 100644 --- a/chromeos/startup/browser_params_proxy.h +++ b/chromeos/startup/browser_params_proxy.h
@@ -25,8 +25,11 @@ // Returns true if the user has logged in, false if not. static bool IsLoggedIn(); + // See documentation in browser_init_params.h. + static bool IsCrosapiDisabledForTesting(); + static void DisableCrosapiForTesting(); + // Init and post-login parameters' accessors are listed starting from here. - bool IsCrosapiDisabledForTesting() const; uint32_t CrosapiVersion() const;
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index 35a4319..62758f42 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -115,6 +115,9 @@ "inputs.VirtualKeyboardHandwriting.floating_lacros@jacuzzi", "inputs.VirtualKeyboardHandwriting.floating_lacros@octopus", + # Failed on LKGM 15770.0.0, fixed on LKGM 15771.0.0 and later. + "filemanager.DrivefsUI", + # READ COMMENT AT TOP BEFORE ADDING NEW TESTS HERE. ]
diff --git a/clank b/clank index 2c1a38e..2d0a791 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 2c1a38e990de645f3a7871f5e3f44558d9d0ad17 +Subproject commit 2d0a791e87f12aa439b145774e2efe96e6d82225
diff --git a/components/metrics/structured/BUILD.gn b/components/metrics/structured/BUILD.gn index 13e696c2..a04e6e97 100644 --- a/components/metrics/structured/BUILD.gn +++ b/components/metrics/structured/BUILD.gn
@@ -12,20 +12,12 @@ sources = [ "event_storage.cc", "event_storage.h", - "key_data.cc", - "key_data.h", - "key_data_file_delegate.cc", - "key_data_file_delegate.h", "key_data_prefs_delegate.cc", "key_data_prefs_delegate.h", - "key_data_provider.cc", - "key_data_provider.h", "key_data_provider_file.cc", "key_data_provider_file.h", "key_data_provider_prefs.cc", "key_data_provider_prefs.h", - "key_util.cc", - "key_util.h", "reporting/structured_metrics_log_metrics.cc", "reporting/structured_metrics_log_metrics.h", "reporting/structured_metrics_reporting_service.cc", @@ -127,6 +119,7 @@ ":proto", ":structured_metrics_validator", "//base", + "//components/metrics/structured/lib", "//components/prefs", "//third_party/metrics_proto", ] @@ -241,13 +234,13 @@ "//base", "//base/test:test_support", "//components/metrics:metrics", + "//components/metrics/structured/lib", ] } source_set("unit_tests") { testonly = true sources = [ - "key_data_file_delegate_unittest.cc", "key_data_prefs_delegate_unittest.cc", "structured_metrics_provider_unittest.cc", "structured_metrics_recorder_unittest.cc", @@ -265,6 +258,7 @@ "//base/test:test_support", "//components/metrics", "//components/metrics:test_support", + "//components/metrics/structured/lib", "//components/metrics/structured/lib:proto", "//components/prefs", "//components/prefs:test_support",
diff --git a/components/metrics/structured/histogram_util.cc b/components/metrics/structured/histogram_util.cc index 381d5df..44ae450 100644 --- a/components/metrics/structured/histogram_util.cc +++ b/components/metrics/structured/histogram_util.cc
@@ -10,10 +10,6 @@ namespace metrics::structured { -void LogInternalError(StructuredMetricsError error) { - UMA_HISTOGRAM_ENUMERATION("UMA.StructuredMetrics.InternalError2", error); -} - void LogEventRecordingState(EventRecordingState state) { UMA_HISTOGRAM_ENUMERATION("UMA.StructuredMetrics.EventRecordingState2", state); @@ -24,10 +20,6 @@ num_events); } -void LogKeyValidation(KeyValidationState state) { - UMA_HISTOGRAM_ENUMERATION("UMA.StructuredMetrics.KeyValidationState", state); -} - void LogNumEventsRecordedBeforeInit(int num_events) { UMA_HISTOGRAM_COUNTS_100("UMA.StructuredMetrics.EventsRecordedBeforeInit", num_events);
diff --git a/components/metrics/structured/histogram_util.h b/components/metrics/structured/histogram_util.h index e0b3679..159f214 100644 --- a/components/metrics/structured/histogram_util.h +++ b/components/metrics/structured/histogram_util.h
@@ -11,29 +11,6 @@ namespace metrics::structured { -// Possible internal errors of the structured metrics system. These are events -// we expect to never see, so only the absolute counts should be looked at, the -// bucket proportion doesn't make sense. These values are persisted to logs. -// Entries should not be renumbered and numeric values should never be reused. -enum class StructuredMetricsError { - kMissingKey = 0, - kWrongKeyLength = 1, - kMissingLastRotation = 2, - kMissingRotationPeriod = 3, - kFailedUintConversion = 4, - kKeyReadError = 5, - kKeyParseError = 6, - kKeyWriteError = 7, - kKeySerializationError = 8, - kEventReadError = 9, - kEventParseError = 10, - kEventWriteError = 11, - kEventSerializationError = 12, - kUninitializedClient = 13, - kInvalidEventParsed = 14, - kMaxValue = kInvalidEventParsed, -}; - // Whether a single event was recorded correctly, or otherwise what error state // occurred. These values are persisted to logs. Entries should not be // renumbered and numeric values should never be reused. @@ -47,24 +24,8 @@ kMaxValue = kLogSizeExceeded, }; -// Describes the action taken by KeyData::ValidateAndGetKey on a particular user -// event key. A key can either be valid with no action taken, missing and so -// created, or out of its rotation period and so re-created. These values are -// persisted to logs. Entries should not be renumbered and numeric values should -// never be reused. -enum class KeyValidationState { - kValid = 0, - kCreated = 1, - kRotated = 2, - kMaxValue = kRotated, -}; - -void LogInternalError(StructuredMetricsError error); - void LogEventRecordingState(EventRecordingState state); -void LogKeyValidation(KeyValidationState state); - // Log how many structured metrics events were contained in a call to // ProvideCurrentSessionData. void LogNumEventsInUpload(int num_events);
diff --git a/components/metrics/structured/key_data_prefs_delegate.cc b/components/metrics/structured/key_data_prefs_delegate.cc index 802482e..541253e0 100644 --- a/components/metrics/structured/key_data_prefs_delegate.cc +++ b/components/metrics/structured/key_data_prefs_delegate.cc
@@ -10,8 +10,8 @@ #include "base/check.h" #include "base/logging.h" #include "base/values.h" -#include "components/metrics/structured/key_data.h" -#include "components/metrics/structured/key_util.h" +#include "components/metrics/structured/lib/key_data.h" +#include "components/metrics/structured/lib/key_util.h" #include "components/metrics/structured/lib/proto/key.pb.h" #include "components/metrics/structured/project_validator.h" #include "components/metrics/structured/structured_metrics_validator.h"
diff --git a/components/metrics/structured/key_data_prefs_delegate.h b/components/metrics/structured/key_data_prefs_delegate.h index 1eb27c9..2837476 100644 --- a/components/metrics/structured/key_data_prefs_delegate.h +++ b/components/metrics/structured/key_data_prefs_delegate.h
@@ -13,7 +13,7 @@ #include "base/memory/raw_ptr.h" #include "base/sequence_checker.h" #include "base/time/time.h" -#include "components/metrics/structured/key_data.h" +#include "components/metrics/structured/lib/key_data.h" #include "components/prefs/pref_service.h" namespace metrics::structured {
diff --git a/components/metrics/structured/key_data_prefs_delegate_unittest.cc b/components/metrics/structured/key_data_prefs_delegate_unittest.cc index 55840c0..2184e34 100644 --- a/components/metrics/structured/key_data_prefs_delegate_unittest.cc +++ b/components/metrics/structured/key_data_prefs_delegate_unittest.cc
@@ -14,8 +14,9 @@ #include "base/test/task_environment.h" #include "base/time/time.h" #include "components/metrics/structured/histogram_util.h" -#include "components/metrics/structured/key_data.h" -#include "components/metrics/structured/key_util.h" +#include "components/metrics/structured/lib/histogram_util.h" +#include "components/metrics/structured/lib/key_data.h" +#include "components/metrics/structured/lib/key_util.h" #include "components/metrics/structured/lib/proto/key.pb.h" #include "components/metrics/structured/structured_metrics_validator.h" #include "components/prefs/pref_registry_simple.h"
diff --git a/components/metrics/structured/key_data_provider_file.cc b/components/metrics/structured/key_data_provider_file.cc index 9fbeac1..96cc7ad 100644 --- a/components/metrics/structured/key_data_provider_file.cc +++ b/components/metrics/structured/key_data_provider_file.cc
@@ -8,8 +8,8 @@ #include "base/functional/bind.h" #include "base/logging.h" -#include "components/metrics/structured/key_data.h" -#include "components/metrics/structured/key_data_file_delegate.h" +#include "components/metrics/structured/lib/key_data.h" +#include "components/metrics/structured/lib/key_data_file_delegate.h" #include "components/metrics/structured/recorder.h" #include "components/metrics/structured/structured_metrics_validator.h"
diff --git a/components/metrics/structured/key_data_provider_file.h b/components/metrics/structured/key_data_provider_file.h index 054239b..7f5c49e7 100644 --- a/components/metrics/structured/key_data_provider_file.h +++ b/components/metrics/structured/key_data_provider_file.h
@@ -8,10 +8,11 @@ #include <memory> #include <optional> +#include "base/barrier_closure.h" #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "components/metrics/structured/key_data_provider.h" +#include "components/metrics/structured/lib/key_data_provider.h" namespace metrics::structured {
diff --git a/components/metrics/structured/key_data_provider_prefs.h b/components/metrics/structured/key_data_provider_prefs.h index be0cf88..b16adde71 100644 --- a/components/metrics/structured/key_data_provider_prefs.h +++ b/components/metrics/structured/key_data_provider_prefs.h
@@ -8,8 +8,8 @@ #include <optional> #include <string_view> -#include "components/metrics/structured/key_data.h" -#include "components/metrics/structured/key_data_provider.h" +#include "components/metrics/structured/lib/key_data.h" +#include "components/metrics/structured/lib/key_data_provider.h" #include "components/prefs/pref_service.h" namespace metrics::structured {
diff --git a/components/metrics/structured/lib/BUILD.gn b/components/metrics/structured/lib/BUILD.gn index c928a7e8..5bff1e20 100644 --- a/components/metrics/structured/lib/BUILD.gn +++ b/components/metrics/structured/lib/BUILD.gn
@@ -9,6 +9,16 @@ # See README.md for more details. source_set("lib") { sources = [ + "histogram_util.cc", + "histogram_util.h", + "key_data.cc", + "key_data.h", + "key_data_file_delegate.cc", + "key_data_file_delegate.h", + "key_data_provider.cc", + "key_data_provider.h", + "key_util.cc", + "key_util.h", "persistent_proto.h", "persistent_proto_internal.cc", "persistent_proto_internal.h", @@ -18,6 +28,7 @@ deps = [ "//base", + "//crypto", "//third_party/protobuf:protobuf_lite", ] } @@ -31,7 +42,10 @@ source_set("unit_tests") { testonly = true - sources = [ "persistent_proto_unittest.cc" ] + sources = [ + "key_data_file_delegate_unittest.cc", + "persistent_proto_unittest.cc", + ] deps = [ ":lib", ":proto",
diff --git a/components/metrics/structured/lib/DEPS b/components/metrics/structured/lib/DEPS index 136b7dc..4185ed6 100644 --- a/components/metrics/structured/lib/DEPS +++ b/components/metrics/structured/lib/DEPS
@@ -9,6 +9,7 @@ include_rules = [ "+base", + "+crypto", "+third_party/protobuf", "+testing/gtest", ]
diff --git a/components/metrics/structured/lib/histogram_util.cc b/components/metrics/structured/lib/histogram_util.cc new file mode 100644 index 0000000..83c18a7c --- /dev/null +++ b/components/metrics/structured/lib/histogram_util.cc
@@ -0,0 +1,19 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/metrics/structured/lib/histogram_util.h" + +#include "base/metrics/histogram_macros.h" + +namespace metrics::structured { + +void LogInternalError(StructuredMetricsError error) { + UMA_HISTOGRAM_ENUMERATION("UMA.StructuredMetrics.InternalError2", error); +} + +void LogKeyValidation(KeyValidationState state) { + UMA_HISTOGRAM_ENUMERATION("UMA.StructuredMetrics.KeyValidationState", state); +} + +} // namespace metrics::structured
diff --git a/components/metrics/structured/lib/histogram_util.h b/components/metrics/structured/lib/histogram_util.h new file mode 100644 index 0000000..9ae8dfe --- /dev/null +++ b/components/metrics/structured/lib/histogram_util.h
@@ -0,0 +1,54 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_METRICS_STRUCTURED_LIB_HISTOGRAM_UTIL_H_ +#define COMPONENTS_METRICS_STRUCTURED_LIB_HISTOGRAM_UTIL_H_ + +namespace metrics::structured { + +// Describes the action taken by KeyData::ValidateAndGetKey on a particular user +// event key. A key can either be valid with no action taken, missing and so +// created, or out of its rotation period and so re-created. These values are +// persisted to logs. Entries should not be renumbered and numeric values should +// never be reused. +enum class KeyValidationState { + kValid = 0, + kCreated = 1, + kRotated = 2, + kMaxValue = kRotated, +}; + +// Possible internal errors of the structured metrics system. These are events +// we expect to never see, so only the absolute counts should be looked at, the +// bucket proportion doesn't make sense. These values are persisted to logs. +// Entries should not be renumbered and numeric values should never be reused. +enum class StructuredMetricsError { + kMissingKey = 0, + kWrongKeyLength = 1, + kMissingLastRotation = 2, + kMissingRotationPeriod = 3, + kFailedUintConversion = 4, + kKeyReadError = 5, + kKeyParseError = 6, + kKeyWriteError = 7, + kKeySerializationError = 8, + kEventReadError = 9, + kEventParseError = 10, + kEventWriteError = 11, + kEventSerializationError = 12, + kUninitializedClient = 13, + kInvalidEventParsed = 14, + kMaxValue = kInvalidEventParsed, +}; + +// Logs an error state in Structured metrics. +void LogInternalError(StructuredMetricsError error); + +// Logs the key validation state. This captures the key state when keys are +// requested to be validated. +void LogKeyValidation(KeyValidationState state); + +} // namespace metrics::structured + +#endif // COMPONENTS_METRICS_STRUCTURED_LIB_HISTOGRAM_UTIL_H_
diff --git a/components/metrics/structured/key_data.cc b/components/metrics/structured/lib/key_data.cc similarity index 95% rename from components/metrics/structured/key_data.cc rename to components/metrics/structured/lib/key_data.cc index 0afae2e..f7af6e7b 100644 --- a/components/metrics/structured/key_data.cc +++ b/components/metrics/structured/lib/key_data.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/metrics/structured/key_data.h" +#include "components/metrics/structured/lib/key_data.h" #include <memory> #include <utility> @@ -15,8 +15,8 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "base/unguessable_token.h" -#include "components/metrics/structured/histogram_util.h" -#include "components/metrics/structured/key_util.h" +#include "components/metrics/structured/lib/histogram_util.h" +#include "components/metrics/structured/lib/key_util.h" #include "crypto/hmac.h" #include "crypto/sha2.h" @@ -157,7 +157,6 @@ // Return the key unless it's the wrong size, in which case return nullopt. const std::string_view key_string = key->key(); if (key_string.size() != kKeySize) { - LogInternalError(StructuredMetricsError::kWrongKeyLength); return std::nullopt; } return key_string;
diff --git a/components/metrics/structured/key_data.h b/components/metrics/structured/lib/key_data.h similarity index 97% rename from components/metrics/structured/key_data.h rename to components/metrics/structured/lib/key_data.h index b6b3b497..d5599160 100644 --- a/components/metrics/structured/key_data.h +++ b/components/metrics/structured/lib/key_data.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_METRICS_STRUCTURED_KEY_DATA_H_ -#define COMPONENTS_METRICS_STRUCTURED_KEY_DATA_H_ +#ifndef COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_H_ +#define COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_H_ #include <memory> #include <optional> @@ -156,4 +156,4 @@ } // namespace metrics::structured -#endif // COMPONENTS_METRICS_STRUCTURED_KEY_DATA_H_ +#endif // COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_H_
diff --git a/components/metrics/structured/key_data_file_delegate.cc b/components/metrics/structured/lib/key_data_file_delegate.cc similarity index 93% rename from components/metrics/structured/key_data_file_delegate.cc rename to components/metrics/structured/lib/key_data_file_delegate.cc index 58a354a..6ccf553 100644 --- a/components/metrics/structured/key_data_file_delegate.cc +++ b/components/metrics/structured/lib/key_data_file_delegate.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/metrics/structured/key_data_file_delegate.h" +#include "components/metrics/structured/lib/key_data_file_delegate.h" #include <utility> @@ -13,8 +13,8 @@ #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" -#include "components/metrics/structured/histogram_util.h" -#include "components/metrics/structured/key_util.h" +#include "components/metrics/structured/lib/histogram_util.h" +#include "components/metrics/structured/lib/key_util.h" #include "components/metrics/structured/lib/persistent_proto.h" #include "components/metrics/structured/lib/proto/key.pb.h"
diff --git a/components/metrics/structured/key_data_file_delegate.h b/components/metrics/structured/lib/key_data_file_delegate.h similarity index 89% rename from components/metrics/structured/key_data_file_delegate.h rename to components/metrics/structured/lib/key_data_file_delegate.h index 5ce597bb..a600659c 100644 --- a/components/metrics/structured/key_data_file_delegate.h +++ b/components/metrics/structured/lib/key_data_file_delegate.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_METRICS_STRUCTURED_KEY_DATA_FILE_DELEGATE_H_ -#define COMPONENTS_METRICS_STRUCTURED_KEY_DATA_FILE_DELEGATE_H_ +#ifndef COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_FILE_DELEGATE_H_ +#define COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_FILE_DELEGATE_H_ #include <memory> #include <optional> @@ -13,7 +13,7 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" -#include "components/metrics/structured/key_data.h" +#include "components/metrics/structured/lib/key_data.h" #include "components/metrics/structured/lib/persistent_proto.h" #include "components/metrics/structured/lib/proto/key.pb.h" @@ -74,4 +74,4 @@ } // namespace metrics::structured -#endif // COMPONENTS_METRICS_STRUCTURED_KEY_DATA_FILE_DELEGATE_H_ +#endif // COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_FILE_DELEGATE_H_
diff --git a/components/metrics/structured/key_data_file_delegate_unittest.cc b/components/metrics/structured/lib/key_data_file_delegate_unittest.cc similarity index 98% rename from components/metrics/structured/key_data_file_delegate_unittest.cc rename to components/metrics/structured/lib/key_data_file_delegate_unittest.cc index 615cfa46..9d1c85de 100644 --- a/components/metrics/structured/key_data_file_delegate_unittest.cc +++ b/components/metrics/structured/lib/key_data_file_delegate_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/metrics/structured/key_data_file_delegate.h" +#include "components/metrics/structured/lib/key_data_file_delegate.h" #include <memory> #include <string> @@ -19,10 +19,8 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "base/values.h" -#include "components/metrics/structured/histogram_util.h" +#include "components/metrics/structured/lib/histogram_util.h" #include "components/metrics/structured/lib/proto/key.pb.h" -#include "components/metrics/structured/recorder.h" -#include "components/prefs/persistent_pref_store.h" #include "testing/gtest/include/gtest/gtest.h" namespace metrics::structured {
diff --git a/components/metrics/structured/key_data_provider.cc b/components/metrics/structured/lib/key_data_provider.cc similarity index 87% rename from components/metrics/structured/key_data_provider.cc rename to components/metrics/structured/lib/key_data_provider.cc index c50790a..246dcb1e 100644 --- a/components/metrics/structured/key_data_provider.cc +++ b/components/metrics/structured/lib/key_data_provider.cc
@@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/metrics/structured/key_data_provider.h" +#include <optional> +#include <string> + +#include "components/metrics/structured/lib/key_data_provider.h" namespace metrics::structured {
diff --git a/components/metrics/structured/key_data_provider.h b/components/metrics/structured/lib/key_data_provider.h similarity index 93% rename from components/metrics/structured/key_data_provider.h rename to components/metrics/structured/lib/key_data_provider.h index 43a2465..8c6b813 100644 --- a/components/metrics/structured/key_data_provider.h +++ b/components/metrics/structured/lib/key_data_provider.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_METRICS_STRUCTURED_KEY_DATA_PROVIDER_H_ -#define COMPONENTS_METRICS_STRUCTURED_KEY_DATA_PROVIDER_H_ +#ifndef COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_PROVIDER_H_ +#define COMPONENTS_METRICS_STRUCTURED_LIB_KEY_DATA_PROVIDER_H_ #include <optional> #include "base/functional/callback_forward.h" #include "base/observer_list.h" #include "base/observer_list_types.h" -#include "components/metrics/structured/key_data.h" +#include "components/metrics/structured/lib/key_data.h" namespace base { class FilePath;
diff --git a/components/metrics/structured/key_util.cc b/components/metrics/structured/lib/key_util.cc similarity index 96% rename from components/metrics/structured/key_util.cc rename to components/metrics/structured/lib/key_util.cc index 148addd9..0157b86 100644 --- a/components/metrics/structured/key_util.cc +++ b/components/metrics/structured/lib/key_util.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/metrics/structured/key_util.h" +#include "components/metrics/structured/lib/key_util.h" #include "base/check_op.h" #include "base/unguessable_token.h"
diff --git a/components/metrics/structured/key_util.h b/components/metrics/structured/lib/key_util.h similarity index 83% rename from components/metrics/structured/key_util.h rename to components/metrics/structured/lib/key_util.h index e55aa211..e22e1d5c 100644 --- a/components/metrics/structured/key_util.h +++ b/components/metrics/structured/lib/key_util.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_METRICS_STRUCTURED_KEY_UTIL_H_ -#define COMPONENTS_METRICS_STRUCTURED_KEY_UTIL_H_ +#ifndef COMPONENTS_METRICS_STRUCTURED_LIB_KEY_UTIL_H_ +#define COMPONENTS_METRICS_STRUCTURED_LIB_KEY_UTIL_H_ #include <optional> #include <string> @@ -29,4 +29,4 @@ } // namespace util } // namespace metrics::structured -#endif // COMPONENTS_METRICS_STRUCTURED_KEY_UTIL_H_ +#endif // COMPONENTS_METRICS_STRUCTURED_LIB_KEY_UTIL_H_
diff --git a/components/metrics/structured/recorder.cc b/components/metrics/structured/recorder.cc index eb268bd..1d355d6 100644 --- a/components/metrics/structured/recorder.cc +++ b/components/metrics/structured/recorder.cc
@@ -10,6 +10,7 @@ #include "base/task/current_thread.h" #include "base/task/sequenced_task_runner.h" #include "components/metrics/structured/histogram_util.h" +#include "components/metrics/structured/lib/histogram_util.h" #include "components/metrics/structured/structured_metrics_features.h" namespace metrics::structured {
diff --git a/components/metrics/structured/structured_metrics_recorder.h b/components/metrics/structured/structured_metrics_recorder.h index 6f3d1a3..2783d61 100644 --- a/components/metrics/structured/structured_metrics_recorder.h +++ b/components/metrics/structured/structured_metrics_recorder.h
@@ -16,8 +16,8 @@ #include "components/metrics/metrics_provider.h" #include "components/metrics/structured/event.h" #include "components/metrics/structured/event_storage.h" -#include "components/metrics/structured/key_data.h" -#include "components/metrics/structured/key_data_provider.h" +#include "components/metrics/structured/lib/key_data.h" +#include "components/metrics/structured/lib/key_data_provider.h" #include "components/metrics/structured/project_validator.h" #include "components/metrics/structured/recorder.h"
diff --git a/components/metrics/structured/test/test_key_data_provider.h b/components/metrics/structured/test/test_key_data_provider.h index 887061380..71bdc37 100644 --- a/components/metrics/structured/test/test_key_data_provider.h +++ b/components/metrics/structured/test/test_key_data_provider.h
@@ -10,7 +10,7 @@ #include <string> #include "base/functional/callback_forward.h" -#include "components/metrics/structured/key_data_provider.h" +#include "components/metrics/structured/lib/key_data_provider.h" namespace base { class FilePath;
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index 96e7e4f..1f27eb87 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -1423,17 +1423,20 @@ auto subtypes = match->subtypes; ExtendMatchSubtypes(*match, &subtypes); - // Count any suggestions that constitute zero-prefix suggestions. - if (subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX_LOCAL_HISTORY) || - subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX_LOCAL_FREQUENT_URLS) || - subtypes.contains( - omnibox::SUBTYPE_ZERO_PREFIX_LOCAL_FREQUENT_QUERIES) || - subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX) || - subtypes.contains(omnibox::SUBTYPE_CLIPBOARD_IMAGE) || - subtypes.contains(omnibox::SUBTYPE_CLIPBOARD_TEXT) || - subtypes.contains(omnibox::SUBTYPE_CLIPBOARD_URL) || - subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX_QUERY_TILE)) { - num_zero_prefix_suggestions_shown++; + if (input_.IsZeroSuggest()) { + result->set_zero_prefix_enabled_in_session(true); + // Count any suggestions that constitute zero-prefix suggestions. + if (subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX_LOCAL_HISTORY) || + subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX_LOCAL_FREQUENT_URLS) || + subtypes.contains( + omnibox::SUBTYPE_ZERO_PREFIX_LOCAL_FREQUENT_QUERIES) || + subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX) || + subtypes.contains(omnibox::SUBTYPE_CLIPBOARD_IMAGE) || + subtypes.contains(omnibox::SUBTYPE_CLIPBOARD_TEXT) || + subtypes.contains(omnibox::SUBTYPE_CLIPBOARD_URL) || + subtypes.contains(omnibox::SUBTYPE_ZERO_PREFIX_QUERY_TILE)) { + num_zero_prefix_suggestions_shown++; + } } auto* available_suggestion = searchbox_stats.add_available_suggestions(); @@ -1473,7 +1476,9 @@ ? result->num_zero_prefix_suggestions_shown_in_session() : num_zero_prefix_suggestions_shown); searchbox_stats.set_zero_prefix_enabled( - searchbox_stats.num_zero_prefix_suggestions_shown() > 0); + omnibox_feature_configs::ReportNumZPSInSession::Get().enabled + ? result->zero_prefix_enabled_in_session() + : searchbox_stats.num_zero_prefix_suggestions_shown() > 0); // Go over all matches and set searchbox stats if the match supports it. for (size_t index = 0; index < result->size(); ++index) {
diff --git a/components/omnibox/browser/autocomplete_controller_unittest.cc b/components/omnibox/browser/autocomplete_controller_unittest.cc index 3582975..f01d3ca 100644 --- a/components/omnibox/browser/autocomplete_controller_unittest.cc +++ b/components/omnibox/browser/autocomplete_controller_unittest.cc
@@ -100,6 +100,7 @@ name, AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED, false, false, traditional_relevance, std::nullopt); match.keyword = u"keyword"; + match.suggestion_group_id = omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST; match.subtypes.emplace(omnibox::SUBTYPE_PERSONAL); match.subtypes.emplace(omnibox::SUBTYPE_ZERO_PREFIX); return match; @@ -627,7 +628,10 @@ #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) } -TEST_F(AutocompleteControllerTest, UpdateResult_NumZPSShownInSession) { +TEST_F(AutocompleteControllerTest, UpdateResult_ZPSEnabledAndShownInSession) { + auto zps_input = FakeAutocompleteController::CreateInput(u""); + zps_input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_CLOBBER); + { SCOPED_TRACE("Zero-prefix suggestions are offered synchronously"); EXPECT_THAT(controller_.SimulateAutocompletePass( @@ -636,11 +640,13 @@ CreatePersonalizedZeroPrefixMatch("zps_1", 1450), CreatePersonalizedZeroPrefixMatch("zps_2", 1449), }, - FakeAutocompleteController::CreateInput(u"")), + zps_input), testing::ElementsAreArray({ "zps_1", "zps_2", })); + // Whether zero-prefix suggestions were enabled in the session is updated. + EXPECT_TRUE(controller_.published_result_.zero_prefix_enabled_in_session()); // The count of zero-prefix suggestions offered in the session is updated. EXPECT_EQ(controller_.published_result_ .num_zero_prefix_suggestions_shown_in_session(), @@ -656,13 +662,14 @@ CreatePersonalizedZeroPrefixMatch("zps_3", 1448), CreatePersonalizedZeroPrefixMatch("zps_4", 1447), }, - FakeAutocompleteController::CreateInput(u"")), + zps_input), testing::ElementsAreArray({ "zps_1", "zps_2", "zps_3", "zps_4", })); + EXPECT_TRUE(controller_.published_result_.zero_prefix_enabled_in_session()); // If zero-prefix suggestions are offered multiple times in the session, the // most recent count is logged. EXPECT_EQ(controller_.published_result_ @@ -675,6 +682,8 @@ // Stop with clear_result=false does not clear the result set or notify // `OnResultChanged()`. EXPECT_FALSE(controller_.published_result_.empty()); + // Whether zero-prefix suggestions were enabled in the session is unchanged. + EXPECT_TRUE(controller_.published_result_.zero_prefix_enabled_in_session()); // The count of zero-prefix suggestions offered in the session is unchanged. EXPECT_EQ(controller_.published_result_ .num_zero_prefix_suggestions_shown_in_session(), @@ -690,6 +699,8 @@ testing::ElementsAreArray({ "search_1", })); + // Whether zero-prefix suggestions were enabled in the session is unchanged. + EXPECT_TRUE(controller_.published_result_.zero_prefix_enabled_in_session()); // The count of zero-prefix suggestions offered in the session is unchanged. EXPECT_EQ(controller_.published_result_ .num_zero_prefix_suggestions_shown_in_session(), @@ -699,9 +710,11 @@ SCOPED_TRACE("Stop with clear_result=true is called due to popup closing"); controller_.Stop(/*clear_result=*/true); // Stop with clear_result=true clears the result set and notifies - // `OnResultChanged()`. The count of zero-prefix suggestions offered in the - // session is also reset. + // `OnResultChanged()`. Whether zero-prefix suggestions were enabled and the + // count of zero-prefix suggestions offered in the session is also reset. EXPECT_TRUE(controller_.published_result_.empty()); + EXPECT_FALSE( + controller_.published_result_.zero_prefix_enabled_in_session()); EXPECT_EQ(controller_.published_result_ .num_zero_prefix_suggestions_shown_in_session(), 0u);
diff --git a/components/omnibox/browser/autocomplete_provider_unittest.cc b/components/omnibox/browser/autocomplete_provider_unittest.cc index ffcaec2..87286ade 100644 --- a/components/omnibox/browser/autocomplete_provider_unittest.cc +++ b/components/omnibox/browser/autocomplete_provider_unittest.cc
@@ -384,7 +384,8 @@ const SuggestionGroupsTestData& test_data); void RunSearchboxStatsTest(const SearchboxStatsTestData* sbs_test_data, - size_t size); + size_t size, + bool input_is_zero_suggest); void RunQuery(const std::string& query, bool allow_exact_keyword_match); @@ -641,8 +642,17 @@ void AutocompleteProviderTest::RunSearchboxStatsTest( const SearchboxStatsTestData* sbs_test_data, - size_t size) { - // Prepare input. + size_t size, + bool input_is_zero_suggest) { + if (input_is_zero_suggest) { + // Prepare the input. + AutocompleteInput input(u"", metrics::OmniboxEventProto::OTHER, + TestingSchemeClassifier()); + input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_CLOBBER); + controller_->input_ = input; + } + + // Prepare the results. const size_t kMaxRelevance = 1000; ACMatches matches; for (size_t i = 0; i < size; ++i) { @@ -1061,7 +1071,7 @@ omnibox::TYPE_NATIVE_CHROME}}; SCOPED_TRACE("No matches"); // Note: We pass 0 here to ignore the dummy data above. - RunSearchboxStatsTest(test_data, 0); + RunSearchboxStatsTest(test_data, 0, /*input_is_zero_suggest=*/false); } // Note: See suggest.proto for the types and subtypes referenced below. @@ -1082,7 +1092,8 @@ searchbox_stats, omnibox::TYPE_NATIVE_CHROME}}; SCOPED_TRACE("One match"); - RunSearchboxStatsTest(test_data, std::size(test_data)); + RunSearchboxStatsTest(test_data, std::size(test_data), + /*input_is_zero_suggest=*/false); } { @@ -1104,7 +1115,8 @@ omnibox::TYPE_ENTITY, {omnibox::SUBTYPE_PERSONAL}}}; SCOPED_TRACE("One match with provider populated subtypes"); - RunSearchboxStatsTest(test_data, std::size(test_data)); + RunSearchboxStatsTest(test_data, std::size(test_data), + /*input_is_zero_suggest=*/false); } { @@ -1143,7 +1155,8 @@ {omnibox::SUBTYPE_ZERO_PREFIX_LOCAL_FREQUENT_QUERIES}}, }; SCOPED_TRACE("Multiple matches in horizontal render group"); - RunSearchboxStatsTest(test_data, std::size(test_data)); + RunSearchboxStatsTest(test_data, std::size(test_data), + /*input_is_zero_suggest=*/true); } { @@ -1216,7 +1229,8 @@ {omnibox::SUBTYPE_ZERO_PREFIX}}, }; SCOPED_TRACE("Multiple matches with horizontal render group"); - RunSearchboxStatsTest(test_data, std::size(test_data)); + RunSearchboxStatsTest(test_data, std::size(test_data), + /*input_is_zero_suggest=*/true); } { @@ -1316,7 +1330,8 @@ {omnibox::SUBTYPE_PERSONAL, omnibox::SUBTYPE_TRENDS}}, }; SCOPED_TRACE("Complex set of matches with repetitive subtypes"); - RunSearchboxStatsTest(test_data, std::size(test_data)); + RunSearchboxStatsTest(test_data, std::size(test_data), + /*input_is_zero_suggest=*/true); } // This test confirms that selection of trivial suggestions does not get @@ -1440,7 +1455,8 @@ omnibox::TYPE_NATIVE_CHROME}, }; SCOPED_TRACE("Trivial and zero-prefix matches"); - RunSearchboxStatsTest(test_data, std::size(test_data)); + RunSearchboxStatsTest(test_data, std::size(test_data), + /*input_is_zero_suggest=*/true); } }
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index a20ccab..4bafdc3d 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -1034,6 +1034,7 @@ void AutocompleteResult::Reset() { ClearMatches(); + zero_prefix_enabled_in_session_ = false; num_zero_prefix_suggestions_shown_in_session_ = 0u; } @@ -1049,6 +1050,8 @@ void AutocompleteResult::Swap(AutocompleteResult* other) { matches_.swap(other->matches_); suggestion_groups_map_.swap(other->suggestion_groups_map_); + std::swap(zero_prefix_enabled_in_session_, + other->zero_prefix_enabled_in_session_); std::swap(num_zero_prefix_suggestions_shown_in_session_, other->num_zero_prefix_suggestions_shown_in_session_); #if BUILDFLAG(IS_ANDROID) @@ -1063,6 +1066,7 @@ matches_ = other.matches_; suggestion_groups_map_ = other.suggestion_groups_map_; + zero_prefix_enabled_in_session_ = other.zero_prefix_enabled_in_session_; num_zero_prefix_suggestions_shown_in_session_ = other.num_zero_prefix_suggestions_shown_in_session_;
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h index fadeb152..a604f21 100644 --- a/components/omnibox/browser/autocomplete_result.h +++ b/components/omnibox/browser/autocomplete_result.h
@@ -231,6 +231,14 @@ return suggestion_groups_map_; } + bool zero_prefix_enabled_in_session() const { + return zero_prefix_enabled_in_session_; + } + + void set_zero_prefix_enabled_in_session(bool enabled) { + zero_prefix_enabled_in_session_ = enabled; + } + size_t num_zero_prefix_suggestions_shown_in_session() const { return num_zero_prefix_suggestions_shown_in_session_; } @@ -424,6 +432,11 @@ // `matches_`. Cleared on `ClearMatches()` or `Reset()`. omnibox::GroupConfigMap suggestion_groups_map_; + // Whether zero-prefix suggestions were enabled in the session (i.e., the + // user could have seen zero-prefix suggestions), regardless of current + // `matches_` - Cleared on `Reset()`. + bool zero_prefix_enabled_in_session_ = false; + // The number of zero-prefix suggestions in the session, regardless of current // `matches_`. Cleared on `Reset()`. size_t num_zero_prefix_suggestions_shown_in_session_ = 0u;
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal index f4aea18..1f827a8 160000 --- a/components/optimization_guide/internal +++ b/components/optimization_guide/internal
@@ -1 +1 @@ -Subproject commit f4aea18550bf707b1d06d65028e7e9edcae7d2c1 +Subproject commit 1f827a8c547d3157e40bbed7e375469c1585d5f7
diff --git a/components/os_crypt/sync/os_crypt_unittest.cc b/components/os_crypt/sync/os_crypt_unittest.cc index 7c4fe89..c7ef1e0 100644 --- a/components/os_crypt/sync/os_crypt_unittest.cc +++ b/components/os_crypt/sync/os_crypt_unittest.cc
@@ -8,8 +8,8 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/functional/bind.h" -#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/threading/thread.h" @@ -219,11 +219,10 @@ // If this test ever breaks do not ignore it as it might result in data loss for // users. TEST_F(OSCryptTestWin, DPAPIHeader) { - std::string plaintext; - std::string ciphertext; - OSCryptMocker::SetLegacyEncryption(true); - crypto::RandBytes(base::WriteInto(&plaintext, 11), 10); + std::string plaintext(10, '\0'); + crypto::RandBytes(base::as_writable_byte_span(plaintext)); + std::string ciphertext; ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext)); using std::string_literals::operator""s;
diff --git a/components/os_crypt/sync/os_crypt_win.cc b/components/os_crypt/sync/os_crypt_win.cc index e955e6b..6a2ee3f 100644 --- a/components/os_crypt/sync/os_crypt_win.cc +++ b/components/os_crypt/sync/os_crypt_win.cc
@@ -5,6 +5,7 @@ #include <windows.h> #include "base/base64.h" +#include "base/containers/span.h" #include "base/feature_list.h" #include "base/logging.h" #include "base/memory/singleton.h" @@ -198,8 +199,8 @@ DCHECK_EQ(kKeyLength, aead.KeyLength()); DCHECK_EQ(kNonceLength, aead.NonceLength()); - std::string nonce; - crypto::RandBytes(base::WriteInto(&nonce, kNonceLength + 1), kNonceLength); + std::string nonce(kNonceLength, '\0'); + crypto::RandBytes(base::as_writable_byte_span(nonce)); if (!aead.Seal(plaintext, nonce, std::string(), ciphertext)) return false; @@ -251,8 +252,8 @@ // If there is no key in the local state, or if DPAPI decryption fails, // generate a new key. - std::string key; - crypto::RandBytes(base::WriteInto(&key, kKeyLength + 1), kKeyLength); + std::string key(kKeyLength, '\0'); + crypto::RandBytes(base::as_writable_byte_span(key)); if (!EncryptAndStoreKey(key, local_state)) { return false;
diff --git a/components/permissions/permission_uma_util.cc b/components/permissions/permission_uma_util.cc index 5563ab8..c2328df 100644 --- a/components/permissions/permission_uma_util.cc +++ b/components/permissions/permission_uma_util.cc
@@ -1075,7 +1075,7 @@ content::WebContents* web_contents, const GURL& requesting_origin) { PermissionsClient::Get()->GetUkmSourceId( - browser_context, web_contents, requesting_origin, + permission_type, browser_context, web_contents, requesting_origin, base::BindOnce(&RecordPermissionUsageUkm, permission_type)); } @@ -1142,7 +1142,7 @@ } PermissionsClient::Get()->GetUkmSourceId( - browser_context, web_contents, requesting_origin, + permission, browser_context, web_contents, requesting_origin, base::BindOnce( &RecordPermissionActionUkm, action, gesture_type, permission, dismiss_count, ignore_count, source_ui, time_to_decision,
diff --git a/components/permissions/permission_uma_util_unittest.cc b/components/permissions/permission_uma_util_unittest.cc index eadd646..022e64f6 100644 --- a/components/permissions/permission_uma_util_unittest.cc +++ b/components/permissions/permission_uma_util_unittest.cc
@@ -853,7 +853,8 @@ simulated_has_source_id_ = source_id; } - void GetUkmSourceId(content::BrowserContext* browser_context, + void GetUkmSourceId(ContentSettingsType permission_type, + content::BrowserContext* browser_context, content::WebContents* web_contents, const GURL& requesting_origin, GetUkmSourceIdCallback callback) override { @@ -862,7 +863,7 @@ std::move(callback).Run(std::nullopt); } else { ukm::SourceId fake_source_id = - ukm::ConvertToSourceId(1, ukm::SourceIdType::NAVIGATION_ID); + ukm::ConvertToSourceId(1, ukm::SourceIdType::NOTIFICATION_ID); std::move(callback).Run(fake_source_id); } }
diff --git a/components/permissions/permissions_client.cc b/components/permissions/permissions_client.cc index 1b86a7e..1f553c9 100644 --- a/components/permissions/permissions_client.cc +++ b/components/permissions/permissions_client.cc
@@ -54,7 +54,8 @@ return false; } -void PermissionsClient::GetUkmSourceId(content::BrowserContext* browser_context, +void PermissionsClient::GetUkmSourceId(ContentSettingsType permission_type, + content::BrowserContext* browser_context, content::WebContents* web_contents, const GURL& requesting_origin, GetUkmSourceIdCallback callback) {
diff --git a/components/permissions/permissions_client.h b/components/permissions/permissions_client.h index d79c94c..8b7c804 100644 --- a/components/permissions/permissions_client.h +++ b/components/permissions/permissions_client.h
@@ -133,13 +133,14 @@ content::BrowserContext* browser_context, const GURL& origin); - // Retrieves the ukm::SourceId (if any) associated with this |browser_context| - // and |web_contents|. |web_contents| may be null. |callback| will be called - // with the result, and may be run synchronously if the result is available - // immediately. + // Retrieves the ukm::SourceId (if any) associated with this + // |permission_type|, |browser_context|, and |web_contents|. |web_contents| + // may be null. |callback| will be called with the result, and may be run + // synchronously if the result is available immediately. using GetUkmSourceIdCallback = - base::OnceCallback<void(std::optional<ukm::SourceId>)>; - virtual void GetUkmSourceId(content::BrowserContext* browser_context, + base::OnceCallback<void(absl::optional<ukm::SourceId>)>; + virtual void GetUkmSourceId(ContentSettingsType permission_type, + content::BrowserContext* browser_context, content::WebContents* web_contents, const GURL& requesting_origin, GetUkmSourceIdCallback callback);
diff --git a/components/permissions/test/test_permissions_client.cc b/components/permissions/test/test_permissions_client.cc index 2ec62dd4..e4318fe 100644 --- a/components/permissions/test/test_permissions_client.cc +++ b/components/permissions/test/test_permissions_client.cc
@@ -81,6 +81,7 @@ } void TestPermissionsClient::GetUkmSourceId( + ContentSettingsType permission_type, content::BrowserContext* browser_context, content::WebContents* web_contents, const GURL& requesting_origin,
diff --git a/components/permissions/test/test_permissions_client.h b/components/permissions/test/test_permissions_client.h index 0599c9a..7091f0e 100644 --- a/components/permissions/test/test_permissions_client.h +++ b/components/permissions/test/test_permissions_client.h
@@ -38,7 +38,8 @@ ObjectPermissionContextBase* GetChooserContext( content::BrowserContext* browser_context, ContentSettingsType type) override; - void GetUkmSourceId(content::BrowserContext* browser_context, + void GetUkmSourceId(ContentSettingsType permission_type, + content::BrowserContext* browser_context, content::WebContents* web_contents, const GURL& requesting_origin, GetUkmSourceIdCallback callback) override;
diff --git a/components/permissions_strings.grdp b/components/permissions_strings.grdp index f46371c..3178394 100644 --- a/components/permissions_strings.grdp +++ b/components/permissions_strings.grdp
@@ -95,10 +95,10 @@ Control and reprogram your MIDI devices </message> <message name="IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT" desc="Permission fragment shown in the permissions bubble when a web page requests access to the computer's microphone."> - Use your microphone + Use your microphones </message> <message name="IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT" desc="Permission fragment shown in the permissions bubble when a web page requests access to the computer's camera."> - Use your camera + Use your cameras </message> <message name="IDS_MEDIA_CAPTURE_CAMERA_PAN_TILT_ZOOM_PERMISSION_FRAGMENT" desc="Permission fragment shown in the permissions prompt when a web page requests access to the computer's camera, including zoom and move."> Use & move your camera
diff --git a/components/permissions_strings_grdp/IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT.png.sha1 b/components/permissions_strings_grdp/IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT.png.sha1 new file mode 100644 index 0000000..b85cd24 --- /dev/null +++ b/components/permissions_strings_grdp/IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT.png.sha1
@@ -0,0 +1 @@ +972029c32944e61ebd37b297fb363aae871199c4 \ No newline at end of file
diff --git a/components/permissions_strings_grdp/IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT.png.sha1 b/components/permissions_strings_grdp/IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT.png.sha1 new file mode 100644 index 0000000..5bb9bdf --- /dev/null +++ b/components/permissions_strings_grdp/IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT.png.sha1
@@ -0,0 +1 @@ +971a228dc10517f8efd32a80d44757b89a8a4215 \ No newline at end of file
diff --git a/components/ukm/ukm_recorder_impl.cc b/components/ukm/ukm_recorder_impl.cc index 5ac9250..738745d 100644 --- a/components/ukm/ukm_recorder_impl.cc +++ b/components/ukm/ukm_recorder_impl.cc
@@ -68,6 +68,7 @@ case ukm::SourceIdObj::Type::DEFAULT: case ukm::SourceIdObj::Type::DEPRECATED_DESKTOP_WEB_APP_ID: case ukm::SourceIdObj::Type::WORKER_ID: + case ukm::SourceIdObj::Type::NOTIFICATION_ID: return false; } } @@ -753,6 +754,7 @@ case SourceIdType::WEB_IDENTITY_ID: case SourceIdType::CHROMEOS_WEBSITE_ID: case SourceIdType::EXTENSION_ID: + case SourceIdType::NOTIFICATION_ID: return UkmConsentType::MSBB; } return UkmConsentType::MSBB; @@ -804,7 +806,8 @@ case ukm::SourceIdObj::Type::NO_URL_ID: case ukm::SourceIdObj::Type::WEB_IDENTITY_ID: case ukm::SourceIdObj::Type::CHROMEOS_WEBSITE_ID: - case ukm::SourceIdObj::Type::EXTENSION_ID: { + case ukm::SourceIdObj::Type::EXTENSION_ID: + case ukm::SourceIdObj::Type::NOTIFICATION_ID: { // Don't keep sources of these types after current report because their // entries are logged only at source creation time. MarkSourceForDeletion(source_id);
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index 3cc4fbe..1192b2cd 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -6,6 +6,7 @@ #include "base/containers/adapters.h" #include "base/feature_list.h" +#include "base/notreached.h" #include "base/strings/stringprintf.h" #include "base/trace_event/traced_value.h" #include "components/download/public/common/download_create_info.h" @@ -196,6 +197,10 @@ return AttributionReportingIssueTypeEnum::WebAndOsHeaders; case blink::mojom::AttributionReportingIssueType::kNoWebOrOsSupport: return AttributionReportingIssueTypeEnum::NoWebOrOsSupport; + case blink::mojom::AttributionReportingIssueType:: + kNavigationRegistrationWithoutTransientUserActivation: + // This issue is not reported from the browser. + NOTREACHED_NORETURN(); } }
diff --git a/content/browser/launch_as_mojo_client_browsertest.cc b/content/browser/launch_as_mojo_client_browsertest.cc index 8fd807e..542959ae 100644 --- a/content/browser/launch_as_mojo_client_browsertest.cc +++ b/content/browser/launch_as_mojo_client_browsertest.cc
@@ -155,6 +155,10 @@ mojo::Remote<mojom::ShellController> shell_controller_; }; +// TODO(http://crbug.com/323984075): This test invokes content_shell in a way +// that is not supported on Lacros (without crosapi data). Figure out what to +// do about that. +#if !BUILDFLAG(IS_CHROMEOS_LACROS) IN_PROC_BROWSER_TEST_F(LaunchAsMojoClientBrowserTest, LaunchAndBindInterface) { // Verifies that we can launch an instance of Content Shell with a Mojo // invitation on the command line and reach the new browser process's exposed @@ -180,6 +184,7 @@ shell_controller->ShutDown(); } +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) // TODO(crbug.com/1259557): This test implementation fundamentally conflicts
diff --git a/content/browser/preloading/preloading_config.cc b/content/browser/preloading/preloading_config.cc index bd9ba4e..4acde79 100644 --- a/content/browser/preloading/preloading_config.cc +++ b/content/browser/preloading/preloading_config.cc
@@ -31,7 +31,7 @@ [{ "preloading_type": "NoStatePrefetch", "preloading_predictor": "LinkRel", - "sampling_likelihood": "0.007925" + "sampling_likelihood": "0.001587" }, { "preloading_type": "NoStatePrefetch", "preloading_predictor": "OmniboxDirectURLInput", @@ -39,27 +39,27 @@ }, { "preloading_type": "Preconnect", "preloading_predictor": "PointerDownOnAnchor", - "sampling_likelihood": "0.000182" + "sampling_likelihood": "0.000037" }, { "preloading_type": "Prefetch", "preloading_predictor": "DefaultSearchEngine", - "sampling_likelihood": "0.022167" + "sampling_likelihood": "0.002909" }, { "preloading_type": "Prefetch", "preloading_predictor": "OmniboxMousePredictor", - "sampling_likelihood": "1.000000" + "sampling_likelihood": "0.125768" }, { "preloading_type": "Prefetch", "preloading_predictor": "OmniboxSearchPredictor", - "sampling_likelihood": "1.000000" + "sampling_likelihood": "0.342295" }, { "preloading_type": "Prefetch", "preloading_predictor": "OmniboxTouchDownPredirector", - "sampling_likelihood": "0.294382" + "sampling_likelihood": "0.063827" }, { "preloading_type": "Prefetch", "preloading_predictor": "SpeculationRules", - "sampling_likelihood": "0.002463" + "sampling_likelihood": "0.000794" }, { "preloading_type": "Prefetch", "preloading_predictor": "SpeculationRulesFromIsolatedWorld", @@ -67,43 +67,43 @@ }, { "preloading_type": "Prerender", "preloading_predictor": "BackButtonHover", - "sampling_likelihood": "0.011186" + "sampling_likelihood": "0.001920" }, { "preloading_type": "Prerender", "preloading_predictor": "BackGestureNavigation", - "sampling_likelihood": "0.364847" + "sampling_likelihood": "0.028777" }, { "preloading_type": "Prerender", "preloading_predictor": "DefaultSearchEngine", - "sampling_likelihood": "0.024857" + "sampling_likelihood": "0.003114" }, { "preloading_type": "Prerender", "preloading_predictor": "MouseBackButton", - "sampling_likelihood": "0.117264" + "sampling_likelihood": "0.041547" }, { "preloading_type": "Prerender", "preloading_predictor": "MouseHoverOnBookmarkBar", - "sampling_likelihood": "0.018748" + "sampling_likelihood": "0.003222" }, { "preloading_type": "Prerender", "preloading_predictor": "MouseHoverOnNewTabPage", - "sampling_likelihood": "0.823005" + "sampling_likelihood": "0.087301" }, { "preloading_type": "Prerender", "preloading_predictor": "OmniboxDirectURLInput", - "sampling_likelihood": "0.009997" + "sampling_likelihood": "0.001662" }, { "preloading_type": "Prerender", "preloading_predictor": "PointerDownOnBookmarkBar", - "sampling_likelihood": "0.058779" + "sampling_likelihood": "0.014170" }, { "preloading_type": "Prerender", "preloading_predictor": "PointerDownOnNewTabPage", - "sampling_likelihood": "1.000000" + "sampling_likelihood": "0.155139" }, { "preloading_type": "Prerender", "preloading_predictor": "SpeculationRules", - "sampling_likelihood": "1.000000" + "sampling_likelihood": "0.494826" }, { "preloading_type": "Prerender", "preloading_predictor": "SpeculationRulesFromIsolatedWorld",
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc index 9569432..ef58033 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
@@ -33,6 +33,9 @@ #include "ui/display/screen.h" #include "ui/events/event_utils.h" #include "ui/events/test/event_generator.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/vector2d.h" #if BUILDFLAG(IS_WIN) #include "content/browser/renderer_host/legacy_render_widget_host_win.h" @@ -304,6 +307,127 @@ EXPECT_TRUE(IsRenderWidgetHostFocused(GetRenderViewHost()->GetWidget())); } +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserTest, + UpdatesCaretBoundsAfterFrameScroll) { + GURL page( + "data:text/html;charset=utf-8," + "<!DOCTYPE html>" + "<html>" + "<body>" + "<style>" + " %23scrollableDiv {" + " height: 10000px;" + " }" + " %23textfield {" + " margin-top: 100px;" + " }" + "</style>" + "<div id=\"scrollableDiv\">" + " <input id=\"textfield\" type=\"text\" value=\"Some editable text\">" + "</div>" + "<script type=\"text/javascript\">" + " function focusTextfield() {" + " document.getElementById('textfield').focus({'preventScroll': true});" + " }" + "</script>" + "</body>" + "</html>"); + EXPECT_TRUE(NavigateToURL(shell(), page)); + GetRenderWidgetHostView()->SetSize(gfx::Size(600, 500)); + + // Focus the textfield and wait for initial caret bounds. + auto* web_contents = shell()->web_contents(); + { + // The caret bounds can have briefly have an invalid zero size value when + // the textfield initially focuses, so wait for non-zero caret size rather + // than waiting for the first caret bounds update. + NonZeroCaretSizeWaiter initial_caret_bounds_waiter(web_contents); + ASSERT_TRUE(ExecJs(web_contents, "focusTextfield();")); + initial_caret_bounds_waiter.Wait(); + } + + const gfx::Rect initial_caret_bounds = + GetRenderWidgetHostView()->GetCaretBounds(); + EXPECT_NE(initial_caret_bounds, gfx::Rect()); + + // Scroll and wait for caret bounds to update. + { + CaretBoundsUpdateWaiter caret_bounds_update_waiter(web_contents); + ASSERT_TRUE(ExecJs(web_contents, "window.scrollBy(0, 50);")); + caret_bounds_update_waiter.Wait(); + } + + EXPECT_EQ(GetRenderWidgetHostView()->GetCaretBounds().x(), + initial_caret_bounds.x()); + EXPECT_LT(GetRenderWidgetHostView()->GetCaretBounds().y(), + initial_caret_bounds.y()); +} + +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserTest, + UpdatesCaretBoundsAfterOverflowScroll) { + GURL page( + "data:text/html;charset=utf-8," + "<!DOCTYPE html>" + "<html>" + "<body>" + "<style>" + " %23container {" + " height: 200px;" + " overflow: scroll;" + " }" + " %23scrollableDiv {" + " height: 1000px;" + " }" + " %23textfield {" + " margin-top: 100px;" + " }" + "</style>" + "<div id=\"container\">" + " <div id=\"scrollableDiv\">" + " <input id=\"textfield\" type=\"text\" value=\"Some editable text\">" + " </div>" + "</div>" + "<script type=\"text/javascript\">" + " function focusTextfield() {" + " document.getElementById('textfield').focus({'preventScroll': true});" + " }" + " function scrollContainerTopBy(dy) {" + " document.getElementById('container').scrollTop += dy;" + " }" + "</script>" + "</body>" + "</html>"); + EXPECT_TRUE(NavigateToURL(shell(), page)); + GetRenderWidgetHostView()->SetSize(gfx::Size(600, 500)); + + // Focus the textfield and wait for initial caret bounds. + auto* web_contents = shell()->web_contents(); + { + // The caret bounds can have briefly have an invalid zero size value when + // the textfield initially focuses, so wait for non-zero caret size rather + // than waiting for the first caret bounds update. + NonZeroCaretSizeWaiter initial_caret_bounds_waiter(web_contents); + ASSERT_TRUE(ExecJs(web_contents, "focusTextfield();")); + initial_caret_bounds_waiter.Wait(); + } + + const gfx::Rect initial_caret_bounds = + GetRenderWidgetHostView()->GetCaretBounds(); + EXPECT_NE(initial_caret_bounds, gfx::Rect()); + + // Scroll and wait for caret bounds to update. + { + CaretBoundsUpdateWaiter caret_bounds_update_waiter(web_contents); + ASSERT_TRUE(ExecJs(web_contents, "scrollContainerTopBy(50);")); + caret_bounds_update_waiter.Wait(); + } + + EXPECT_EQ(GetRenderWidgetHostView()->GetCaretBounds().x(), + initial_caret_bounds.x()); + EXPECT_LT(GetRenderWidgetHostView()->GetCaretBounds().y(), + initial_caret_bounds.y()); +} + class RenderWidgetHostViewAuraDevtoolsBrowserTest : public content::DevToolsProtocolTest { public:
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index a4bba0b..4d8d36e 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -496,12 +496,13 @@ // isolated web apps via the isolated-app:// scheme, and other advanced isolated // app functionality. See https://github.com/reillyeon/isolated-web-apps for a // general overview. -// This also enables support for IWA Controlled Frame, providing the Controlled -// Frame tag to IWA apps. See -// https://github.com/chasephillips/controlled-frame/blob/main/EXPLAINER.md for -// more info. Please don't use this feature flag directly to guard the IWA code. -// Use IsolatedWebAppsPolicy::AreIsolatedWebAppsEnabled() in the browser process -// or check kEnableIsolatedWebAppsInRenderer command line flag in the renderer +// This also enables support for Controlled Frame, providing the Controlled +// Frame tag to IWA apps assuming that Controlled Frame isn't otherwise +// disabled via the kControlledFrame feature. See +// https://github.com/WICG/controlled-frame/blob/main/README.md for more info. +// Please don't use this feature flag directly to guard the IWA code. Use +// IsolatedWebAppsPolicy::AreIsolatedWebAppsEnabled() in the browser process or +// check kEnableIsolatedWebAppsInRenderer command line flag in the renderer // process. BASE_FEATURE(kIsolatedWebApps, "IsolatedWebApps",
diff --git a/content/public/test/DEPS b/content/public/test/DEPS index 0d15af6..abfba8f 100644 --- a/content/public/test/DEPS +++ b/content/public/test/DEPS
@@ -5,7 +5,7 @@ # everywhere. "+chromeos/crosapi/cpp/crosapi_constants.h", "+chromeos/lacros/lacros_service.h", - "+chromeos/lacros/lacros_test_helper.h", + "+chromeos/startup/browser_params_proxy.h", "+chromeos/startup/startup_switches.h", # Tests can use all content/public headers.
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index 501ec5a..b81f943 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -129,7 +129,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) #include "base/files/scoped_file.h" #include "chromeos/crosapi/cpp/crosapi_constants.h" // nogncheck -#include "chromeos/lacros/lacros_test_helper.h" +#include "chromeos/startup/browser_params_proxy.h" #include "chromeos/startup/startup_switches.h" // nogncheck #include "mojo/public/cpp/platform/socket_utils_posix.h" #endif @@ -455,16 +455,14 @@ // For more details, please see: // //chrome/browser/ash/crosapi/test_mojo_connection_manager.h. { - // TODO(crbug.com/1127581): Switch to use |kLacrosMojoSocketForTesting| in - // //ash/constants/ash_switches.h. - // Please refer to the CL comments for why it can't be done now: - // http://crrev.com/c/2402580/2/content/public/test/browser_test_base.cc - std::string socket_path = - command_line->GetSwitchValueASCII("lacros-mojo-socket-for-testing"); - if (socket_path.empty()) { - disable_crosapi_ = - std::make_unique<chromeos::ScopedDisableCrosapiForTesting>(); - } else { + if (!chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { + // TODO(crbug.com/1127581): Switch to use |kLacrosMojoSocketForTesting| in + // //ash/constants/ash_switches.h. + // Please refer to the CL comments for why it can't be done now: + // http://crrev.com/c/2402580/2/content/public/test/browser_test_base.cc + CHECK(command_line->HasSwitch("lacros-mojo-socket-for-testing")); + std::string socket_path = + command_line->GetSwitchValueASCII("lacros-mojo-socket-for-testing"); auto channel = mojo::NamedPlatformChannel::ConnectToServer(socket_path); base::ScopedFD socket_fd = channel.TakePlatformHandle().TakeFD();
diff --git a/content/public/test/browser_test_base.h b/content/public/test/browser_test_base.h index 4f66dbd..c28b0381 100644 --- a/content/public/test/browser_test_base.h +++ b/content/public/test/browser_test_base.h
@@ -45,10 +45,6 @@ class TimeDelta; } // namespace base -namespace chromeos { -class ScopedDisableCrosapiForTesting; -} - namespace ui { class ScopedAnimationDurationScaleMode; } @@ -294,10 +290,6 @@ // not run and report a false positive result. bool set_up_called_ = false; -#if BUILDFLAG(IS_CHROMEOS_LACROS) - std::unique_ptr<chromeos::ScopedDisableCrosapiForTesting> disable_crosapi_; -#endif - std::unique_ptr<storage::QuotaSettings> quota_settings_; std::unique_ptr<NoRendererCrashesAssertion> no_renderer_crashes_assertion_;
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 3f98a5a..c2b4276 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -22,6 +22,7 @@ #include "base/process/kill.h" #include "base/ranges/algorithm.h" #include "base/run_loop.h" +#include "base/scoped_observation.h" #include "base/strings/pattern.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" @@ -135,6 +136,7 @@ #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/geometry/rect.h" #include "ui/latency/latency_info.h" #if !BUILDFLAG(IS_ANDROID) @@ -1247,52 +1249,86 @@ rwhva->OnGestureEvent(&long_tap); } -class BoundingBoxUpdateWaiterImpl : public TextInputManager::Observer { +// Observer which waits for the selection bounds in a RenderWidgetHostViewAura +// to meet some desired conditions. +class SelectionBoundsWaiter : public TextInputManager::Observer { public: - explicit BoundingBoxUpdateWaiterImpl(RenderWidgetHostViewAura* rwhva) - : text_input_manager_(rwhva->GetTextInputManager()), - original_bounding_box_(rwhva->GetSelectionBoundingBox()), - rwhva_(rwhva) { - text_input_manager_->AddObserver(this); + using Predicate = base::RepeatingCallback<bool()>; + + SelectionBoundsWaiter(RenderWidgetHostViewAura* rwhva, Predicate predicate) + : predicate_(std::move(predicate)) { + text_input_manager_observation_.Observe(rwhva->GetTextInputManager()); } - BoundingBoxUpdateWaiterImpl(const BoundingBoxUpdateWaiterImpl&) = delete; - BoundingBoxUpdateWaiterImpl& operator=(const BoundingBoxUpdateWaiterImpl&) = - delete; - virtual ~BoundingBoxUpdateWaiterImpl() { - text_input_manager_->RemoveObserver(this); + SelectionBoundsWaiter(const SelectionBoundsWaiter&) = delete; + SelectionBoundsWaiter& operator=(const SelectionBoundsWaiter&) = delete; + virtual ~SelectionBoundsWaiter() = default; + + // TextInputManager::Observer: + void OnSelectionBoundsChanged( + TextInputManager* text_input_manager, + RenderWidgetHostViewBase* updated_view) override { + if (predicate_.Run()) { + run_loop_.Quit(); + } } void Wait() { run_loop_.Run(); } private: - // TextInputManager::Observer: - void OnSelectionBoundsChanged( - TextInputManager* text_input_manager, - RenderWidgetHostViewBase* updated_view) override { - if (rwhva_->GetSelectionBoundingBox() == original_bounding_box_) { - return; - } - - run_loop_.Quit(); - } - - const raw_ptr<TextInputManager> text_input_manager_; - const gfx::Rect original_bounding_box_; - const raw_ptr<RenderWidgetHostViewAura> rwhva_; - base::RunLoop run_loop_; + Predicate predicate_; + base::ScopedObservation<TextInputManager, TextInputManager::Observer> + text_input_manager_observation_{this}; }; -BoundingBoxUpdateWaiter::BoundingBoxUpdateWaiter(WebContents* web_contents) { - impl_ = std::make_unique<BoundingBoxUpdateWaiterImpl>( +NonZeroCaretSizeWaiter::NonZeroCaretSizeWaiter(WebContents* web_contents) { + RenderWidgetHostViewAura* rwhva = static_cast<content::RenderWidgetHostViewAura*>( - web_contents->GetRenderWidgetHostView())); + web_contents->GetRenderWidgetHostView()); + selection_bounds_waiter_ = std::make_unique<SelectionBoundsWaiter>( + rwhva, base::BindLambdaForTesting([rwhva]() { + return !rwhva->GetCaretBounds().size().IsZero(); + })); +} + +NonZeroCaretSizeWaiter::~NonZeroCaretSizeWaiter() = default; + +void NonZeroCaretSizeWaiter::Wait() { + selection_bounds_waiter_->Wait(); +} + +CaretBoundsUpdateWaiter::CaretBoundsUpdateWaiter(WebContents* web_contents) { + RenderWidgetHostViewAura* rwhva = + static_cast<content::RenderWidgetHostViewAura*>( + web_contents->GetRenderWidgetHostView()); + const gfx::Rect current_caret_bounds = rwhva->GetCaretBounds(); + selection_bounds_waiter_ = std::make_unique<SelectionBoundsWaiter>( + rwhva, base::BindLambdaForTesting([rwhva, current_caret_bounds]() { + return rwhva->GetCaretBounds() != current_caret_bounds; + })); +} + +CaretBoundsUpdateWaiter::~CaretBoundsUpdateWaiter() = default; + +void CaretBoundsUpdateWaiter::Wait() { + selection_bounds_waiter_->Wait(); +} + +BoundingBoxUpdateWaiter::BoundingBoxUpdateWaiter(WebContents* web_contents) { + RenderWidgetHostViewAura* rwhva = + static_cast<content::RenderWidgetHostViewAura*>( + web_contents->GetRenderWidgetHostView()); + const gfx::Rect current_bounding_box = rwhva->GetSelectionBoundingBox(); + selection_bounds_waiter_ = std::make_unique<SelectionBoundsWaiter>( + rwhva, base::BindLambdaForTesting([rwhva, current_bounding_box]() { + return rwhva->GetSelectionBoundingBox() != current_bounding_box; + })); } BoundingBoxUpdateWaiter::~BoundingBoxUpdateWaiter() = default; void BoundingBoxUpdateWaiter::Wait() { - impl_->Wait(); + selection_bounds_waiter_->Wait(); } #endif
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 76b211d..e6b6c09 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -130,7 +130,10 @@ namespace content { -class BoundingBoxUpdateWaiterImpl; +#if defined(USE_AURA) +class SelectionBoundsWaiter; +#endif // defined(USE_AURA) + class BrowserContext; class FileSystemAccessPermissionContext; class FrameTreeNode; @@ -429,6 +432,36 @@ void SimulateLongTapAt(WebContents* web_contents, const gfx::Point& point); +// Can be used to wait for the caret bounds associated with `web_contents` to +// have non-zero size. +class NonZeroCaretSizeWaiter { + public: + explicit NonZeroCaretSizeWaiter(WebContents* web_contents); + NonZeroCaretSizeWaiter(const NonZeroCaretSizeWaiter&) = delete; + NonZeroCaretSizeWaiter& operator=(const NonZeroCaretSizeWaiter&) = delete; + ~NonZeroCaretSizeWaiter(); + + void Wait(); + + private: + std::unique_ptr<SelectionBoundsWaiter> selection_bounds_waiter_; +}; + +// Can be used to wait for an update to the caret bounds associated with +// `web_contents`. +class CaretBoundsUpdateWaiter { + public: + explicit CaretBoundsUpdateWaiter(WebContents* web_contents); + CaretBoundsUpdateWaiter(const CaretBoundsUpdateWaiter&) = delete; + CaretBoundsUpdateWaiter& operator=(const CaretBoundsUpdateWaiter&) = delete; + ~CaretBoundsUpdateWaiter(); + + void Wait(); + + private: + std::unique_ptr<SelectionBoundsWaiter> selection_bounds_waiter_; +}; + // Can be used to wait for updates to the bounding box (i.e. the rectangle // enclosing the selection region) associated with `web_contents`. class BoundingBoxUpdateWaiter { @@ -441,7 +474,7 @@ void Wait(); private: - std::unique_ptr<BoundingBoxUpdateWaiterImpl> impl_; + std::unique_ptr<SelectionBoundsWaiter> selection_bounds_waiter_; }; #endif
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 83826abc..131f0dea 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -787,6 +787,7 @@ "//chromeos/crosapi/cpp:crosapi_constants", "//chromeos/lacros", "//chromeos/lacros:test_support", + "//chromeos/startup", "//chromeos/startup:constants", ] }
diff --git a/content/test/data/forms/form_controls_browsertest_textarea_android.png b/content/test/data/forms/form_controls_browsertest_textarea_android.png index 3c6895fc..5696cb2 100644 --- a/content/test/data/forms/form_controls_browsertest_textarea_android.png +++ b/content/test/data/forms/form_controls_browsertest_textarea_android.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_textarea_chromeos.png b/content/test/data/forms/form_controls_browsertest_textarea_chromeos.png index ed6ed033..1defed5 100644 --- a/content/test/data/forms/form_controls_browsertest_textarea_chromeos.png +++ b/content/test/data/forms/form_controls_browsertest_textarea_chromeos.png Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_textarea_win.png b/content/test/data/forms/form_controls_browsertest_textarea_win.png index 1940e9d..3fd798d 100644 --- a/content/test/data/forms/form_controls_browsertest_textarea_win.png +++ b/content/test/data/forms/form_controls_browsertest_textarea_win.png Binary files differ
diff --git a/content/test/gpu/gpu_tests/test_expectations/cast_streaming_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/cast_streaming_expectations.txt index 02fb72ba..228c75f2 100644 --- a/content/test/gpu/gpu_tests/test_expectations/cast_streaming_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/cast_streaming_expectations.txt
@@ -84,4 +84,5 @@ ################### # Failures/Flakes # ################### + crbug.com/1420075 [ fuchsia-board-astro ] CastStreaming_VP8_1Frame [ RetryOnFailure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 661c8a8..cb944d4 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -342,17 +342,10 @@ crbug.com/1420067 [ fuchsia fuchsia-board-nelson ] Pixel_Video* [ Failure ] crbug.com/1420067 [ fuchsia fuchsia-board-sherlock ] Pixel_Video* [ Failure ] -# Failures on Sherlock -# fuchsia-fyi-sherlock-qemu is using sherlock x64 image. -crbug.com/1268144 [ fuchsia fuchsia-board-qemu-x64 renderer-skia-vulkan ] Pixel_BackgroundImage [ Failure ] -crbug.com/1268144 [ fuchsia fuchsia-board-qemu-x64 renderer-skia-vulkan ] Pixel_SolidColorBackground [ Failure ] # These two tests causes a crash on Swarming. Skipping so that we have a signal for other tests. crbug.com/1268144 [ fuchsia fuchsia-board-sherlock renderer-skia-vulkan ] Pixel_BackgroundImage [ Skip ] crbug.com/1268144 [ fuchsia fuchsia-board-sherlock renderer-skia-vulkan ] Pixel_SolidColorBackground [ Skip ] -# These test renders blank page on the emulator, likely the gpu on the emulator -# missing some features. -crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 renderer-skia-vulkan ] Pixel_WebGLFloat [ Failure ] # Pixel 6 failures. @@ -380,7 +373,6 @@ crbug.com/1517110 [ clang-coverage nvidia-0x2184 nvidia_lt_31.0.15.4601 release-x64 renderer-skia-gl target-cpu-64 win10 ] Pixel_Video_* [ RetryOnFailure ] crbug.com/1517110 [ debug-x64 no-clang-coverage nvidia-0x2184 nvidia_lt_31.0.15.4601 renderer-skia-gl target-cpu-64 win10 ] Pixel_Video_* [ RetryOnFailure ] crbug.com/1517110 [ no-clang-coverage nvidia-0x2184 nvidia_ge_31.0.15.4601 release-x64 renderer-skia-gl target-cpu-64 win10 ] Pixel_Video_* [ RetryOnFailure ] -crbug.com/1517110 [ no-clang-coverage nvidia-0x2184 nvidia_lt_31.0.15.4601 release renderer-skia-gl target-cpu-32 win10 ] Pixel_Video_* [ RetryOnFailure ] # Lacros consistent failures on CrOS devices, skip to save some time @@ -426,8 +418,6 @@ crbug.com/1495573 [ android-pixel-6 renderer-skia-vulkan ] Pixel_Video_MP4_Rounded_Corner [ RetryOnFailure ] # ChromeOS Volteer failures -crbug.com/1516974 [ chromeos cros-chrome chromeos-board-volteer ] Pixel_ScissorTestWithPreserveDrawingBuffer [ Failure ] -crbug.com/1516974 [ chromeos cros-chrome chromeos-board-volteer ] Pixel_WebGLGreenTriangle_NoAA_NoAlpha [ Failure ] crbug.com/1516974 [ chromeos cros-chrome chromeos-board-volteer ] Pixel_WebGLTransparentGreenTriangle_NoAlpha_ImplicitClear [ Failure ] crbug.com/1516977 [ chromeos cros-chrome chromeos-board-volteer ] Pixel_WebGLContextRestored [ Failure ]
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index 21f2a07..4149955d 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -287,10 +287,12 @@ WorkerId{GenerateExtensionIdFromHostId(host_id), rph->GetID(), service_worker_version_id, worker_thread_id}, event_id); - } else if (BackgroundInfo::HasLazyBackgroundPage(extension)) { + } else if (BackgroundInfo::HasBackgroundPage(extension)) { // TODO(crbug.com/1441221): When creating dispatch time metrics for the // DispatchEventToSender event flow, ensure this also handles persistent // background pages. + // Although it's unnecessary to decrement in-flight events for non-lazy + // background pages, we use the logic for event tracking/metrics purposes. callback = base::BindOnce( &EventRouter::DecrementInFlightEventsForRenderFrameHost, weak_factory_.GetWeakPtr(), rph->GetID(), host_id.id, event_id); @@ -1195,6 +1197,8 @@ service_worker_version_id, worker_thread_id}, event_id); } else if (BackgroundInfo::HasBackgroundPage(extension)) { + // Although it's unnecessary to decrement in-flight events for non-lazy + // background pages, we use the logic for event tracking/metrics purposes. callback = base::BindOnce( &EventRouter::DecrementInFlightEventsForRenderFrameHost, weak_factory_.GetWeakPtr(), process->GetID(), extension_id, event_id);
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index 18bf642d1..48c255e 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json
@@ -356,13 +356,13 @@ "chrome://welcome/*", "chrome://vc-background/*", "chrome://app-settings/*", - "chrome://compose/*", "chrome://search-engine-choice/*" ] }, { "channel": "stable", "contexts": ["webui_untrusted"], "matches": [ + "chrome-untrusted://compose/*", "chrome-untrusted://help-app/*", "chrome-untrusted://media-app/*", "chrome-untrusted://mako/*",
diff --git a/gpu/command_buffer/service/dawn_service_serializer.cc b/gpu/command_buffer/service/dawn_service_serializer.cc index 481653fab..53559c9 100644 --- a/gpu/command_buffer/service/dawn_service_serializer.cc +++ b/gpu/command_buffer/service/dawn_service_serializer.cc
@@ -44,6 +44,7 @@ } void* DawnServiceSerializer::GetCmdSpace(size_t size) { + base::AutoLock guard(lock_); // Note: Dawn will never call this function with |size| > // GetMaximumAllocationSize(). DCHECK_LE(put_offset_, kMaxWireBufferSize); @@ -56,7 +57,7 @@ ""); uint32_t next_offset = put_offset_ + static_cast<uint32_t>(size); if (next_offset > buffer_.size()) { - Flush(); + FlushInternal(); // TODO(enga): Keep track of how much command space the application is using // and adjust the buffer size accordingly. @@ -74,9 +75,15 @@ } bool DawnServiceSerializer::Flush() { + base::AutoLock guard(lock_); + FlushInternal(); + return true; +} + +void DawnServiceSerializer::FlushInternal() { if (NeedsFlush()) { TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"), - "DawnServiceSerializer::Flush", "bytes", put_offset_); + "DawnServiceSerializer::Flush", "bytes", put_offset_.load()); bool is_tracing = false; TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.dawn"), @@ -91,10 +98,9 @@ header->return_data_header.trace_id = trace_id; } - client_->HandleReturnData(base::span(buffer_).first(put_offset_)); + client_->HandleReturnData(base::span(buffer_).first(put_offset_.load())); put_offset_ = kDawnReturnCmdsOffset; } - return true; } } // namespace gpu::webgpu
diff --git a/gpu/command_buffer/service/dawn_service_serializer.h b/gpu/command_buffer/service/dawn_service_serializer.h index dbc4bb8..b55b077 100644 --- a/gpu/command_buffer/service/dawn_service_serializer.h +++ b/gpu/command_buffer/service/dawn_service_serializer.h
@@ -7,9 +7,11 @@ #include <dawn/wire/WireClient.h> +#include <atomic> #include <memory> #include "base/memory/raw_ptr.h" +#include "base/synchronization/lock.h" namespace gpu { @@ -27,9 +29,12 @@ bool NeedsFlush() const; private: + void FlushInternal(); + + base::Lock lock_; raw_ptr<DecoderClient, DanglingUntriaged> client_; std::vector<uint8_t> buffer_; - size_t put_offset_; + std::atomic<size_t> put_offset_; }; } // namespace webgpu
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index 8cd9e3d..fa6783b7b 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -307,16 +307,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 123.0.6297.0', + 'description': 'Run with ash-chrome version 123.0.6298.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v123.0.6297.0', - 'revision': 'version:123.0.6297.0', + 'location': 'lacros_version_skew_tests_v123.0.6298.0', + 'revision': 'version:123.0.6298.0', }, ], },
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index 3d883f75..e8519d6e 100644 --- a/infra/config/targets/lacros-version-skew-variants.json +++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@ { "LACROS_VERSION_SKEW_CANARY": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "identifier": "Lacros version skew testing ash canary", "swarming": { "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ] }
diff --git a/internal b/internal index 25029d9..523a084 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 25029d94751c6df826cee247c0d57890c2cedbaa +Subproject commit 523a084bc51377f455f0e042222acbc522a95165
diff --git a/media/audio/apple/audio_auhal.cc b/media/audio/apple/audio_auhal.cc index f517754a..4c28d6a 100644 --- a/media/audio/apple/audio_auhal.cc +++ b/media/audio/apple/audio_auhal.cc
@@ -74,6 +74,78 @@ sizeof(*format)) == noErr; } +// Try map Rls & Rrs channel to Ls & Rs if necessary. +// +// Most of the configurable audio channel layout in Audio MIDI uses Side Left +// (Ls) and Side Right (Rs) as the default surround channel, while some of the +// WAV/FLAC/AAC audios uses Back Left (Rls) and Back Right (Rrs) as default +// surround channel. If we unconditionally treat Rls and Rrs as it is, and if +// Audio MIDI device has no Rls and Rrs channels (only `7.1 Surround` and +// `7.1.4` configuration has Rls & Rrs channel for now), then these two +// channels will be silent. QuickTime is doing something correct, so we +// can do something similar here, the overall logic will be: +// +// 1. If Audio has no Rls & Rrs channels -> Do nothing. +// 2. If Audio has Rls & Rrs channels, and has Ls & Rs channels -> Do nothing. +// 3. If Audio has Rls & Rrs channels, and has no Ls & Rs channels, device has +// Rls & Rrs channels -> Do nothing. +// 4. If Audio has Rls & Rrs channels, and has no Ls & Rs channels, device has +// no Rls & Rrs channels -> Map Rls to Ls, Rrs to Rs. +void MaybeMapRearSurroundChannelToSurroundChannel( + const AudioUnit& audio_unit, + AudioChannelLayout* audio_layout) { + bool maybe_need_mapping = false; + for (UInt32 i = 0; i < audio_layout->mNumberChannelDescriptions; i++) { + AudioChannelLabel label = + audio_layout->mChannelDescriptions[i].mChannelLabel; + // If audio already has Ls or Rs channel, skip. + if (label == kAudioChannelLabel_LeftSurround || + label == kAudioChannelLabel_RightSurround) { + return; + } + if (label == kAudioChannelLabel_RearSurroundLeft || + label == kAudioChannelLabel_RearSurroundRight) { + maybe_need_mapping = true; + } + } + + // If audio has no Rls or Rrs channel, skip. + if (!maybe_need_mapping) { + return; + } + + auto scoped_device_layout = + AudioManagerApple::GetOutputDeviceChannelLayout(audio_unit); + if (!scoped_device_layout) { + return; + } + AudioChannelLayout* device_layout = scoped_device_layout->layout(); + + // If device has Rls or Rrs channel, skip. Since we only do mapping when + // Rls or Rrs channel do not exist. + for (UInt32 i = 0; i < device_layout->mNumberChannelDescriptions; ++i) { + AudioChannelLabel label = + device_layout->mChannelDescriptions[i].mChannelLabel; + if (label == kAudioChannelLabel_RearSurroundLeft || + label == kAudioChannelLabel_RearSurroundRight) { + return; + } + } + + // Map Rls to Ls, Rrs to Rs. + for (UInt32 i = 0; i < audio_layout->mNumberChannelDescriptions; i++) { + AudioChannelLabel label = + audio_layout->mChannelDescriptions[i].mChannelLabel; + if (label == kAudioChannelLabel_RearSurroundLeft) { + audio_layout->mChannelDescriptions[i].mChannelLabel = + kAudioChannelLabel_LeftSurround; + } else if (label == kAudioChannelLabel_RearSurroundRight) { + audio_layout->mChannelDescriptions[i].mChannelLabel = + kAudioChannelLabel_RightSurround; + } + } +} + // Converts |channel_layout| into CoreAudio format and sets up the AUHAL with // our layout information so it knows how to remap the channels. void SetAudioChannelLayout(int channels, @@ -83,21 +155,11 @@ DCHECK_GT(channels, 0); DCHECK_GT(channel_layout, CHANNEL_LAYOUT_UNSUPPORTED); - // On macOS, Audio MIDI only support setup 4 channel layout as - // Quadraphonic(kAudioChannelLayoutTag_Quadraphonic) which equals to - // "CHANNEL_LAYOUT_2_2" in FFMPEG/Chrome. FFMPEG and Chrome will guess - // 4 channel layout as "CHANNEL_LAYOUT_QUAD" which will always result - // in silent channel 3/4 output on Macs. - // - // On Windows, the system also support setup 4 channel layout as - // Quadraphonic(KSAUDIO_SPEAKER_QUAD) which equals to "CHANNEL_LAYOUT_QUAD" - // in FFMPEG/Chrome, so there is not such issue on Windows. - auto input_layout = channels == 4 && channel_layout == CHANNEL_LAYOUT_QUAD - ? CHANNEL_LAYOUT_2_2 - : channel_layout; - auto coreaudio_layout = - ChannelLayoutToAudioChannelLayout(input_layout, channels); + ChannelLayoutToAudioChannelLayout(channel_layout, channels); + + MaybeMapRearSurroundChannelToSurroundChannel(audio_unit, + coreaudio_layout->layout()); OSStatus result = AudioUnitSetProperty( audio_unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input,
diff --git a/media/audio/apple/audio_manager_apple.cc b/media/audio/apple/audio_manager_apple.cc index 1d568e5..8bf580c0 100644 --- a/media/audio/apple/audio_manager_apple.cc +++ b/media/audio/apple/audio_manager_apple.cc
@@ -4,6 +4,11 @@ #include "media/audio/apple/audio_manager_apple.h" +#include <memory> +#include <utility> + +#include "base/apple/osstatus_logging.h" + namespace media { AudioManagerApple::AudioManagerApple(std::unique_ptr<AudioThread> audio_thread, @@ -12,4 +17,69 @@ AudioManagerApple::~AudioManagerApple() = default; +// static +std::unique_ptr<ScopedAudioChannelLayout> +AudioManagerApple::GetOutputDeviceChannelLayout(AudioUnit audio_unit) { + UInt32 size = 0; + // Note: We don't use kAudioDevicePropertyPreferredChannelLayout on the device + // because it is not available on all devices. + OSStatus result = AudioUnitGetPropertyInfo( + audio_unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, + 0, &size, nullptr); + if (result != noErr) { + OSSTATUS_DLOG(ERROR, result) + << "Failed to get property info for AudioUnit channel layout."; + return nullptr; + } + + auto output_layout = std::make_unique<ScopedAudioChannelLayout>(size); + result = AudioUnitGetProperty( + audio_unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, + 0, output_layout->layout(), &size); + if (result != noErr) { + OSSTATUS_LOG(ERROR, result) << "Failed to get AudioUnit channel layout."; + return nullptr; + } + + // We don't want to have to know about all channel layout tags, so force + // system to give us the channel descriptions from the bitmap or tag if + // necessary. + const AudioChannelLayoutTag tag = output_layout->layout()->mChannelLayoutTag; + if (tag == kAudioChannelLayoutTag_UseChannelDescriptions) { + return output_layout; + } + + if (tag == kAudioChannelLayoutTag_UseChannelBitmap) { + result = AudioFormatGetPropertyInfo( + kAudioFormatProperty_ChannelLayoutForBitmap, sizeof(UInt32), + &output_layout->layout()->mChannelBitmap, &size); + } else { + result = + AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag, + sizeof(AudioChannelLayoutTag), &tag, &size); + } + if (result != noErr || !size) { + OSSTATUS_DLOG(ERROR, result) + << "Failed to get AudioFormat property info, size=" << size; + return nullptr; + } + + auto new_layout = std::make_unique<ScopedAudioChannelLayout>(size); + if (tag == kAudioChannelLayoutTag_UseChannelBitmap) { + result = AudioFormatGetProperty( + kAudioFormatProperty_ChannelLayoutForBitmap, sizeof(UInt32), + &output_layout->layout()->mChannelBitmap, &size, new_layout->layout()); + } else { + result = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag, + sizeof(AudioChannelLayoutTag), &tag, &size, + new_layout->layout()); + } + if (result != noErr) { + OSSTATUS_DLOG(ERROR, result) << "Failed to get AudioFormat property."; + return nullptr; + } + + return new_layout; +} + } // namespace media
diff --git a/media/audio/apple/audio_manager_apple.h b/media/audio/apple/audio_manager_apple.h index 4cae91a..441e0a2 100644 --- a/media/audio/apple/audio_manager_apple.h +++ b/media/audio/apple/audio_manager_apple.h
@@ -8,6 +8,7 @@ #include <AudioUnit/AudioUnit.h> #include "media/audio/audio_manager_base.h" +#include "media/base/mac/channel_layout_util_mac.h" #if BUILDFLAG(IS_MAC) #include <CoreAudio/CoreAudio.h> @@ -24,6 +25,11 @@ ~AudioManagerApple() override; + // Retrieve the output channel layout from a given `audio_unit`, Return + // nullptr if failed. + static std::unique_ptr<ScopedAudioChannelLayout> GetOutputDeviceChannelLayout( + AudioUnit audio_unit); + // Apple platform specific implementations overridden by mac and ios. // Manage device capabilities for ambient noise reduction. These functionality // currently implemented on the Mac platform.
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc index 675f49b..0576209 100644 --- a/media/audio/mac/audio_manager_mac.cc +++ b/media/audio/mac/audio_manager_mac.cc
@@ -55,9 +55,7 @@ // Default sample-rate on most Apple hardware. static const int kFallbackSampleRate = 44100; -static bool GetDeviceChannels(AudioUnit audio_unit, - AUElement element, - int* channels); +static bool GetOutputDeviceChannels(AudioUnit audio_unit, int* channels); // Helper method to construct AudioObjectPropertyAddress structure given // property selector and scope. The property element is always set to @@ -369,74 +367,18 @@ return false; } - return GetDeviceChannels(au.audio_unit(), element, channels); + return GetOutputDeviceChannels(au.audio_unit(), channels); } -static bool GetDeviceChannels(AudioUnit audio_unit, - AUElement element, - int* channels) { +static bool GetOutputDeviceChannels(AudioUnit audio_unit, int* channels) { // Attempt to retrieve the channel layout from the AudioUnit. - // - // Note: We don't use kAudioDevicePropertyPreferredChannelLayout on the device - // because it is not available on all devices. - UInt32 size; - Boolean writable; - OSStatus result = AudioUnitGetPropertyInfo( - audio_unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, - element, &size, &writable); - if (result != noErr) { - OSSTATUS_DLOG(ERROR, result) - << "Failed to get property info for AudioUnit channel layout."; - } - - std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[size]); - AudioChannelLayout* layout = - reinterpret_cast<AudioChannelLayout*>(layout_storage.get()); - - result = - AudioUnitGetProperty(audio_unit, kAudioUnitProperty_AudioChannelLayout, - kAudioUnitScope_Output, element, layout, &size); - if (result != noErr) { - OSSTATUS_LOG(ERROR, result) << "Failed to get AudioUnit channel layout."; + std::unique_ptr<ScopedAudioChannelLayout> audio_unit_layout = + AudioManagerApple::GetOutputDeviceChannelLayout(audio_unit); + if (!audio_unit_layout) { + DLOG(ERROR) << "Failed to retrieve output device channel layout."; return false; } - - // We don't want to have to know about all channel layout tags, so force OSX - // to give us the channel descriptions from the bitmap or tag if necessary. - const AudioChannelLayoutTag tag = layout->mChannelLayoutTag; - if (tag != kAudioChannelLayoutTag_UseChannelDescriptions) { - const bool is_bitmap = tag == kAudioChannelLayoutTag_UseChannelBitmap; - const AudioFormatPropertyID fa = - is_bitmap ? kAudioFormatProperty_ChannelLayoutForBitmap - : kAudioFormatProperty_ChannelLayoutForTag; - - if (is_bitmap) { - result = AudioFormatGetPropertyInfo(fa, sizeof(UInt32), - &layout->mChannelBitmap, &size); - } else { - result = AudioFormatGetPropertyInfo(fa, sizeof(AudioChannelLayoutTag), - &tag, &size); - } - if (result != noErr || !size) { - OSSTATUS_DLOG(ERROR, result) - << "Failed to get AudioFormat property info, size=" << size; - return false; - } - - layout_storage.reset(new uint8_t[size]); - layout = reinterpret_cast<AudioChannelLayout*>(layout_storage.get()); - if (is_bitmap) { - result = AudioFormatGetProperty(fa, sizeof(UInt32), - &layout->mChannelBitmap, &size, layout); - } else { - result = AudioFormatGetProperty(fa, sizeof(AudioChannelLayoutTag), &tag, - &size, layout); - } - if (result != noErr) { - OSSTATUS_DLOG(ERROR, result) << "Failed to get AudioFormat property."; - return false; - } - } + AudioChannelLayout* layout = audio_unit_layout->layout(); // There is no channel info for stereo, assume so for mono as well. if (layout->mNumberChannelDescriptions <= 2) {
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc index d4c94d3c0..b79fd5fe 100644 --- a/media/audio/win/core_audio_util_win.cc +++ b/media/audio/win/core_audio_util_win.cc
@@ -56,20 +56,35 @@ case CHANNEL_LAYOUT_STEREO: DVLOG(2) << "CHANNEL_LAYOUT_STEREO=>KSAUDIO_SPEAKER_STEREO"; return KSAUDIO_SPEAKER_STEREO; + case CHANNEL_LAYOUT_2POINT1: + DVLOG(2) << "CHANNEL_LAYOUT_2POINT1=>KSAUDIO_SPEAKER_2POINT1"; + return KSAUDIO_SPEAKER_2POINT1; + case CHANNEL_LAYOUT_SURROUND: + DVLOG(2) << "CHANNEL_LAYOUT_SURROUND=>KSAUDIO_SPEAKER_3POINT0"; + return KSAUDIO_SPEAKER_3POINT0; + case CHANNEL_LAYOUT_3_1: + DVLOG(2) << "CHANNEL_LAYOUT_3_1=>KSAUDIO_SPEAKER_3POINT1"; + return KSAUDIO_SPEAKER_3POINT1; case CHANNEL_LAYOUT_QUAD: DVLOG(2) << "CHANNEL_LAYOUT_QUAD=>KSAUDIO_SPEAKER_QUAD"; return KSAUDIO_SPEAKER_QUAD; case CHANNEL_LAYOUT_4_0: DVLOG(2) << "CHANNEL_LAYOUT_4_0=>KSAUDIO_SPEAKER_SURROUND"; return KSAUDIO_SPEAKER_SURROUND; + case CHANNEL_LAYOUT_5_0: + DVLOG(2) << "CHANNEL_LAYOUT_5_0=>KSAUDIO_SPEAKER_5POINT0"; + return KSAUDIO_SPEAKER_5POINT0; case CHANNEL_LAYOUT_5_1_BACK: DVLOG(2) << "CHANNEL_LAYOUT_5_1_BACK=>KSAUDIO_SPEAKER_5POINT1"; return KSAUDIO_SPEAKER_5POINT1; case CHANNEL_LAYOUT_5_1: DVLOG(2) << "CHANNEL_LAYOUT_5_1=>KSAUDIO_SPEAKER_5POINT1_SURROUND"; return KSAUDIO_SPEAKER_5POINT1_SURROUND; - case CHANNEL_LAYOUT_7_1_WIDE: - DVLOG(2) << "CHANNEL_LAYOUT_7_1_WIDE=>KSAUDIO_SPEAKER_7POINT1"; + case CHANNEL_LAYOUT_7_0: + DVLOG(2) << "CHANNEL_LAYOUT_7_0=>KSAUDIO_SPEAKER_7POINT0"; + return KSAUDIO_SPEAKER_7POINT0; + case CHANNEL_LAYOUT_7_1_WIDE_BACK: + DVLOG(2) << "CHANNEL_LAYOUT_7_1_WIDE_BACK=>KSAUDIO_SPEAKER_7POINT1"; return KSAUDIO_SPEAKER_7POINT1; case CHANNEL_LAYOUT_7_1: DVLOG(2) << "CHANNEL_LAYOUT_7_1=>KSAUDIO_SPEAKER_7POINT1_SURROUND";
diff --git a/media/base/channel_layout.cc b/media/base/channel_layout.cc index f4836f8..704252c 100644 --- a/media/base/channel_layout.cc +++ b/media/base/channel_layout.cc
@@ -100,13 +100,13 @@ { 0 , 1 , 2 , 3 , 4 , 5 , -1 , -1 , -1 , -1 , -1 }, // CHANNEL_LAYOUT_7_0 - { 0 , 1 , 2 , -1 , 5 , 6 , -1 , -1 , -1 , 3 , 4 }, + { 0 , 1 , 2 , -1 , 3 , 4 , -1 , -1 , -1 , 5 , 6 }, // CHANNEL_LAYOUT_7_1 - { 0 , 1 , 2 , 3 , 6 , 7 , -1 , -1 , -1 , 4 , 5 }, + { 0 , 1 , 2 , 3 , 4 , 5 , -1 , -1 , -1 , 6 , 7 }, // CHANNEL_LAYOUT_7_1_WIDE - { 0 , 1 , 2 , 3 , -1 , -1 , 6 , 7 , -1 , 4 , 5 }, + { 0 , 1 , 2 , 3 , -1 , -1 , 4 , 5 , -1 , 6 , 7 }, // CHANNEL_LAYOUT_STEREO_DOWNMIX { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, @@ -118,13 +118,13 @@ { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, // CHANNEL_LAYOUT_4_1 - { 0 , 1 , 2 , 4 , -1 , -1 , -1 , -1 , 3 , -1 , -1 }, + { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , 4 , -1 , -1 }, // CHANNEL_LAYOUT_6_0 - { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , 5 , 3 , 4 }, + { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , 3 , 4 , 5 }, // CHANNEL_LAYOUT_6_0_FRONT - { 0 , 1 , -1 , -1 , -1 , -1 , 4 , 5 , -1 , 2 , 3 }, + { 0 , 1 , -1 , -1 , -1 , -1 , 2 , 3 , -1 , 4 , 5 }, // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR @@ -132,22 +132,22 @@ { 0 , 1 , 2 , -1 , 3 , 4 , -1 , -1 , 5 , -1 , -1 }, // CHANNEL_LAYOUT_6_1 - { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , 6 , 4 , 5 }, + { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , 4 , 5 , 6 }, // CHANNEL_LAYOUT_6_1_BACK { 0 , 1 , 2 , 3 , 4 , 5 , -1 , -1 , 6 , -1 , -1 }, // CHANNEL_LAYOUT_6_1_FRONT - { 0 , 1 , -1 , 6 , -1 , -1 , 4 , 5 , -1 , 2 , 3 }, + { 0 , 1 , -1 , 2 , -1 , -1 , 3 , 4 , -1 , 5 , 6 }, // CHANNEL_LAYOUT_7_0_FRONT - { 0 , 1 , 2 , -1 , -1 , -1 , 5 , 6 , -1 , 3 , 4 }, + { 0 , 1 , 2 , -1 , -1 , -1 , 3 , 4 , -1 , 5 , 6 }, // CHANNEL_LAYOUT_7_1_WIDE_BACK { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , -1 , -1 , -1 }, // CHANNEL_LAYOUT_OCTAGONAL - { 0 , 1 , 2 , -1 , 5 , 6 , -1 , -1 , 7 , 3 , 4 }, + { 0 , 1 , 2 , -1 , 3 , 4 , -1 , -1 , 5 , 6 , 7 }, // CHANNEL_LAYOUT_DISCRETE { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, @@ -156,7 +156,7 @@ { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, // CHANNEL_LAYOUT_4_1_QUAD_SIDE - { 0 , 1 , -1 , 4 , -1 , -1 , -1 , -1 , -1 , 2 , 3 }, + { 0 , 1 , -1 , 2 , -1 , -1 , -1 , -1 , -1 , 3 , 4 }, // CHANNEL_LAYOUT_BITSTREAM { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
diff --git a/media/base/channel_layout.h b/media/base/channel_layout.h index 4a26d0c0..ee5bf64a 100644 --- a/media/base/channel_layout.h +++ b/media/base/channel_layout.h
@@ -48,13 +48,13 @@ // Front L, Front R, Front C, LFE, Back L, Back R CHANNEL_LAYOUT_5_1_BACK = 12, - // Front L, Front R, Front C, Side L, Side R, Back L, Back R + // Front L, Front R, Front C, Back L, Back R, Side L, Side R CHANNEL_LAYOUT_7_0 = 13, - // Front L, Front R, Front C, LFE, Side L, Side R, Back L, Back R + // Front L, Front R, Front C, LFE, Back L, Back R, Side L, Side R CHANNEL_LAYOUT_7_1 = 14, - // Front L, Front R, Front C, LFE, Side L, Side R, Front LofC, Front RofC + // Front L, Front R, Front C, LFE, Front LofC, Front RofC, Side L, Side R CHANNEL_LAYOUT_7_1_WIDE = 15, // Front L, Front R @@ -66,34 +66,34 @@ // Front L, Front R, Front C, LFE CHANNEL_LAYOUT_3_1 = 18, - // Front L, Front R, Front C, Rear C, LFE + // Front L, Front R, Front C, LFE, Back C CHANNEL_LAYOUT_4_1 = 19, - // Front L, Front R, Front C, Side L, Side R, Back C + // Front L, Front R, Front C, Back C, Side L, Side R CHANNEL_LAYOUT_6_0 = 20, - // Front L, Front R, Side L, Side R, Front LofC, Front RofC + // Front L, Front R, Front LofC, Front RofC, Side L, Side R CHANNEL_LAYOUT_6_0_FRONT = 21, - // Front L, Front R, Front C, Rear L, Rear R, Rear C + // Front L, Front R, Front C, Back L, Back R, Back C CHANNEL_LAYOUT_HEXAGONAL = 22, - // Front L, Front R, Front C, LFE, Side L, Side R, Rear Center + // Front L, Front R, Front C, LFE, Back C, Side L, Side R CHANNEL_LAYOUT_6_1 = 23, - // Front L, Front R, Front C, LFE, Back L, Back R, Rear Center + // Front L, Front R, Front C, LFE, Back L, Back R, Back C CHANNEL_LAYOUT_6_1_BACK = 24, - // Front L, Front R, Side L, Side R, Front LofC, Front RofC, LFE + // Front L, Front R, LFE, Front LofC, Front RofC, Side L, Side R CHANNEL_LAYOUT_6_1_FRONT = 25, - // Front L, Front R, Front C, Side L, Side R, Front LofC, Front RofC + // Front L, Front R, Front C, Front LofC, Front RofC, Side L, Side R CHANNEL_LAYOUT_7_0_FRONT = 26, // Front L, Front R, Front C, LFE, Back L, Back R, Front LofC, Front RofC CHANNEL_LAYOUT_7_1_WIDE_BACK = 27, - // Front L, Front R, Front C, Side L, Side R, Rear L, Back R, Back C. + // Front L, Front R, Front C, Back L, Back R, Back C, Side L, Side R CHANNEL_LAYOUT_OCTAGONAL = 28, // Channels are not explicitly mapped to speakers. @@ -106,7 +106,7 @@ // of that. CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC = 30, - // Front L, Front R, Side L, Side R, LFE + // Front L, Front R, LFE, Side L, Side R CHANNEL_LAYOUT_4_1_QUAD_SIDE = 31, // Actual channel layout is specified in the bitstream and the actual channel
diff --git a/media/base/mac/channel_layout_util_mac_unittests.cc b/media/base/mac/channel_layout_util_mac_unittests.cc index b159a0e..7422c55 100644 --- a/media/base/mac/channel_layout_util_mac_unittests.cc +++ b/media/base/mac/channel_layout_util_mac_unittests.cc
@@ -153,19 +153,19 @@ EXPECT_EQ(output_layout->layout()->mChannelDescriptions[3].mChannelFlags, kAudioChannelFlags_AllOff); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[4].mChannelLabel, - kAudioChannelLabel_LeftSurround); + kAudioChannelLabel_RearSurroundLeft); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[4].mChannelFlags, kAudioChannelFlags_AllOff); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[5].mChannelLabel, - kAudioChannelLabel_RightSurround); + kAudioChannelLabel_RearSurroundRight); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[5].mChannelFlags, kAudioChannelFlags_AllOff); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[6].mChannelLabel, - kAudioChannelLabel_RearSurroundLeft); + kAudioChannelLabel_LeftSurround); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[6].mChannelFlags, kAudioChannelFlags_AllOff); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[7].mChannelLabel, - kAudioChannelLabel_RearSurroundRight); + kAudioChannelLabel_RightSurround); EXPECT_EQ(output_layout->layout()->mChannelDescriptions[7].mChannelFlags, kAudioChannelFlags_AllOff); }
diff --git a/media/base/win/mf_helpers.cc b/media/base/win/mf_helpers.cc index a110cac5..1c784d1 100644 --- a/media/base/win/mf_helpers.cc +++ b/media/base/win/mf_helpers.cc
@@ -19,6 +19,7 @@ #include "base/win/windows_version.h" #include "media/base/audio_codecs.h" #include "media/base/audio_decoder_config.h" +#include "media/base/channel_layout.h" #include "media/base/win/mf_helpers.h" #if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO) #include "media/formats/mp4/ac4.h" @@ -302,16 +303,26 @@ return CHANNEL_LAYOUT_MONO; case KSAUDIO_SPEAKER_STEREO: return CHANNEL_LAYOUT_STEREO; + case KSAUDIO_SPEAKER_2POINT1: + return CHANNEL_LAYOUT_2POINT1; + case KSAUDIO_SPEAKER_3POINT0: + return CHANNEL_LAYOUT_SURROUND; + case KSAUDIO_SPEAKER_3POINT1: + return CHANNEL_LAYOUT_3_1; case KSAUDIO_SPEAKER_QUAD: return CHANNEL_LAYOUT_QUAD; case KSAUDIO_SPEAKER_SURROUND: return CHANNEL_LAYOUT_4_0; + case KSAUDIO_SPEAKER_5POINT0: + return CHANNEL_LAYOUT_5_0; case KSAUDIO_SPEAKER_5POINT1: return CHANNEL_LAYOUT_5_1_BACK; case KSAUDIO_SPEAKER_5POINT1_SURROUND: return CHANNEL_LAYOUT_5_1; + case KSAUDIO_SPEAKER_7POINT0: + return CHANNEL_LAYOUT_7_0; case KSAUDIO_SPEAKER_7POINT1: - return CHANNEL_LAYOUT_7_1_WIDE; + return CHANNEL_LAYOUT_7_1_WIDE_BACK; case KSAUDIO_SPEAKER_7POINT1_SURROUND: return CHANNEL_LAYOUT_7_1; case KSAUDIO_SPEAKER_DIRECTOUT:
diff --git a/media/base/win/mf_helpers.h b/media/base/win/mf_helpers.h index 3a517ca..7df1504 100644 --- a/media/base/win/mf_helpers.h +++ b/media/base/win/mf_helpers.h
@@ -110,11 +110,7 @@ // Converts Microsoft's channel configuration to ChannelLayout. // This mapping is not perfect but the best we can do given the current // ChannelLayout enumerator and the Windows-specific speaker configurations -// defined in ksmedia.h. Don't assume that the channel ordering in -// ChannelLayout is exactly the same as the Windows specific configuration. -// As an example: KSAUDIO_SPEAKER_7POINT1_SURROUND is mapped to -// CHANNEL_LAYOUT_7_1 but the positions of Back L, Back R and Side L, Side R -// speakers are different in these two definitions. +// defined in ksmedia.h. MEDIA_EXPORT ChannelLayout ChannelConfigToChannelLayout(ChannelConfig config); // Converts a GUID (little endian) to a bytes array (big endian).
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index f290619..b97950f 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc
@@ -843,12 +843,18 @@ return CHANNEL_LAYOUT_MONO; case AV_CH_LAYOUT_STEREO: return CHANNEL_LAYOUT_STEREO; + case AV_CH_LAYOUT_2POINT1: + return CHANNEL_LAYOUT_2POINT1; case AV_CH_LAYOUT_2_1: return CHANNEL_LAYOUT_2_1; case AV_CH_LAYOUT_SURROUND: return CHANNEL_LAYOUT_SURROUND; + case AV_CH_LAYOUT_3POINT1: + return CHANNEL_LAYOUT_3_1; case AV_CH_LAYOUT_4POINT0: return CHANNEL_LAYOUT_4_0; + case AV_CH_LAYOUT_4POINT1: + return CHANNEL_LAYOUT_4_1; case AV_CH_LAYOUT_2_2: return CHANNEL_LAYOUT_2_2; case AV_CH_LAYOUT_QUAD: @@ -861,20 +867,6 @@ return CHANNEL_LAYOUT_5_0_BACK; case AV_CH_LAYOUT_5POINT1_BACK: return CHANNEL_LAYOUT_5_1_BACK; - case AV_CH_LAYOUT_7POINT0: - return CHANNEL_LAYOUT_7_0; - case AV_CH_LAYOUT_7POINT1: - return CHANNEL_LAYOUT_7_1; - case AV_CH_LAYOUT_7POINT1_WIDE: - return CHANNEL_LAYOUT_7_1_WIDE; - case AV_CH_LAYOUT_STEREO_DOWNMIX: - return CHANNEL_LAYOUT_STEREO_DOWNMIX; - case AV_CH_LAYOUT_2POINT1: - return CHANNEL_LAYOUT_2POINT1; - case AV_CH_LAYOUT_3POINT1: - return CHANNEL_LAYOUT_3_1; - case AV_CH_LAYOUT_4POINT1: - return CHANNEL_LAYOUT_4_1; case AV_CH_LAYOUT_6POINT0: return CHANNEL_LAYOUT_6_0; case AV_CH_LAYOUT_6POINT0_FRONT: @@ -887,14 +879,22 @@ return CHANNEL_LAYOUT_6_1_BACK; case AV_CH_LAYOUT_6POINT1_FRONT: return CHANNEL_LAYOUT_6_1_FRONT; + case AV_CH_LAYOUT_7POINT0: + return CHANNEL_LAYOUT_7_0; case AV_CH_LAYOUT_7POINT0_FRONT: return CHANNEL_LAYOUT_7_0_FRONT; + case AV_CH_LAYOUT_7POINT1: + return CHANNEL_LAYOUT_7_1; + case AV_CH_LAYOUT_7POINT1_WIDE: + return CHANNEL_LAYOUT_7_1_WIDE; #ifdef AV_CH_LAYOUT_7POINT1_WIDE_BACK case AV_CH_LAYOUT_7POINT1_WIDE_BACK: return CHANNEL_LAYOUT_7_1_WIDE_BACK; #endif case AV_CH_LAYOUT_OCTAGONAL: return CHANNEL_LAYOUT_OCTAGONAL; + case AV_CH_LAYOUT_STEREO_DOWNMIX: + return CHANNEL_LAYOUT_STEREO_DOWNMIX; default: // FFmpeg channel_layout is 0 for .wav and .mp3. Attempt to guess layout // based on the channel count.
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc index 1204736b..36f59c23 100644 --- a/media/filters/stream_parser_factory.cc +++ b/media/filters/stream_parser_factory.cc
@@ -388,7 +388,7 @@ static StreamParser* BuildMP4Parser(base::span<const std::string> codecs, MediaLog* media_log) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; bool has_sbr = false; bool has_dv = false;
diff --git a/media/formats/mp2t/mp2t_stream_parser.cc b/media/formats/mp2t/mp2t_stream_parser.cc index aedfe501..d78ba685 100644 --- a/media/formats/mp2t/mp2t_stream_parser.cc +++ b/media/formats/mp2t/mp2t_stream_parser.cc
@@ -37,14 +37,6 @@ namespace { -constexpr int64_t kSampleAESPrivateDataIndicatorAVC = 0x7a617663; -constexpr int64_t kSampleAESPrivateDataIndicatorAAC = 0x61616364; -// TODO(dougsteed). Consider adding support for the following: -// const int64_t kSampleAESPrivateDataIndicatorAC3 = 0x61633364; -// const int64_t kSampleAESPrivateDataIndicatorEAC3 = 0x65633364; - -} // namespace - enum StreamType { // ISO-13818.1 / ITU H.222 Table 2.34 "Stream type assignments" kStreamTypeMpeg1Audio = 0x3, @@ -59,6 +51,57 @@ // kStreamTypeEAC3WithSampleAES = 0xc2, }; +constexpr int64_t kSampleAESPrivateDataIndicatorAVC = 0x7a617663; +constexpr int64_t kSampleAESPrivateDataIndicatorAAC = 0x61616364; +// TODO(dougsteed). Consider adding support for the following: +// const int64_t kSampleAESPrivateDataIndicatorAC3 = 0x61633364; +// const int64_t kSampleAESPrivateDataIndicatorEAC3 = 0x65633364; + +std::optional<base::flat_set<int>> MapAllowedStreamTypes( + std::optional<base::span<const std::string>> allowed_codecs) { + if (!allowed_codecs.has_value()) { + return std::nullopt; + } + base::flat_set<int> allowed_stream_types; + for (const std::string& codec_name : *allowed_codecs) { + switch (StringToVideoCodec(codec_name)) { + case VideoCodec::kH264: + allowed_stream_types.insert(kStreamTypeAVC); + allowed_stream_types.insert(kStreamTypeAVCWithSampleAES); + continue; + case VideoCodec::kUnknown: + // Probably audio. + break; + default: + DLOG(WARNING) << "Unsupported video codec " << codec_name; + continue; + } + + switch (StringToAudioCodec(codec_name)) { + case AudioCodec::kAAC: + allowed_stream_types.insert(kStreamTypeAAC); + allowed_stream_types.insert(kStreamTypeAACWithSampleAES); + continue; + case AudioCodec::kMP3: + allowed_stream_types.insert(kStreamTypeMpeg1Audio); + allowed_stream_types.insert(kStreamTypeMpeg2Audio); + continue; + case AudioCodec::kUnknown: + // Neither audio, nor video. + break; + default: + DLOG(WARNING) << "Unsupported audio codec " << codec_name; + continue; + } + + // Failed to parse as an audio or a video codec. + DLOG(WARNING) << "Unknown codec " << codec_name; + } + return allowed_stream_types; +} + +} // namespace + class PidState { public: enum PidType { @@ -186,48 +229,15 @@ Mp2tStreamParser::BufferQueueWithConfig::~BufferQueueWithConfig() { } -Mp2tStreamParser::Mp2tStreamParser(base::span<const std::string> allowed_codecs, - bool sbr_in_mimetype) - : sbr_in_mimetype_(sbr_in_mimetype), +Mp2tStreamParser::Mp2tStreamParser( + std::optional<base::span<const std::string>> allowed_codecs, + bool sbr_in_mimetype) + : allowed_stream_types_(MapAllowedStreamTypes(allowed_codecs)), + sbr_in_mimetype_(sbr_in_mimetype), selected_audio_pid_(-1), selected_video_pid_(-1), is_initialized_(false), - segment_started_(false) { - for (const std::string& codec_name : allowed_codecs) { - switch (StringToVideoCodec(codec_name)) { - case VideoCodec::kH264: - allowed_stream_types_.insert(kStreamTypeAVC); - allowed_stream_types_.insert(kStreamTypeAVCWithSampleAES); - continue; - case VideoCodec::kUnknown: - // Probably audio. - break; - default: - DLOG(WARNING) << "Unsupported video codec " << codec_name; - continue; - } - - switch (StringToAudioCodec(codec_name)) { - case AudioCodec::kAAC: - allowed_stream_types_.insert(kStreamTypeAAC); - allowed_stream_types_.insert(kStreamTypeAACWithSampleAES); - continue; - case AudioCodec::kMP3: - allowed_stream_types_.insert(kStreamTypeMpeg1Audio); - allowed_stream_types_.insert(kStreamTypeMpeg2Audio); - continue; - case AudioCodec::kUnknown: - // Neither audio, nor video. - break; - default: - DLOG(WARNING) << "Unsupported audio codec " << codec_name; - continue; - } - - // Failed to parse as an audio or a video codec. - DLOG(WARNING) << "Unknown codec " << codec_name; - } -} + segment_started_(false) {} Mp2tStreamParser::~Mp2tStreamParser() = default; @@ -568,7 +578,8 @@ // See https://crbug.com/1169393. // TODO(https://crbug.com/535738): Remove this hack when MSE stream/mime type // checks have been relaxed. - if (allowed_stream_types_.find(stream_type) == allowed_stream_types_.end()) { + if (allowed_stream_types_.has_value() && + !allowed_stream_types_->contains(stream_type)) { DVLOG(1) << "Stream type not allowed for this parser: " << stream_type; return; }
diff --git a/media/formats/mp2t/mp2t_stream_parser.h b/media/formats/mp2t/mp2t_stream_parser.h index dbff1f5c..fc10d41 100644 --- a/media/formats/mp2t/mp2t_stream_parser.h +++ b/media/formats/mp2t/mp2t_stream_parser.h
@@ -12,6 +12,7 @@ #include <memory> #include <set> +#include "base/containers/flat_set.h" #include "base/containers/span.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" @@ -36,8 +37,9 @@ class MEDIA_EXPORT Mp2tStreamParser : public StreamParser { public: - explicit Mp2tStreamParser(base::span<const std::string> allowed_codecs, - bool sbr_in_mimetype); + explicit Mp2tStreamParser( + std::optional<base::span<const std::string>> allowed_codecs, + bool sbr_in_mimetype); Mp2tStreamParser(const Mp2tStreamParser&) = delete; Mp2tStreamParser& operator=(const Mp2tStreamParser&) = delete; @@ -150,8 +152,10 @@ EndMediaSegmentCB end_of_segment_cb_; raw_ptr<MediaLog> media_log_; - // List of allowed stream types for this parser. - std::set<int> allowed_stream_types_; + // List of allowed stream types for this parser. If this set is `nullopt`, + // allowed stream type checking is disabled. An empty set implies no codecs + // are allowed. + std::optional<base::flat_set<int>> allowed_stream_types_; // True when AAC SBR extension is signalled in the mimetype // (mp4a.40.5 in the codecs parameter).
diff --git a/media/formats/mp2t/mp2t_stream_parser_unittest.cc b/media/formats/mp2t/mp2t_stream_parser_unittest.cc index 802c803..042a70c 100644 --- a/media/formats/mp2t/mp2t_stream_parser_unittest.cc +++ b/media/formats/mp2t/mp2t_stream_parser_unittest.cc
@@ -172,9 +172,7 @@ current_audio_config_(), current_video_config_(), capture_buffers(false) { - bool has_sbr = false; - const std::string codecs[] = {"avc1.64001e", "mp3", "aac"}; - parser_ = std::make_unique<Mp2tStreamParser>(codecs, has_sbr); + CreateStrictParser(); } protected: @@ -199,6 +197,17 @@ std::vector<scoped_refptr<StreamParserBuffer>> video_buffer_capture_; bool capture_buffers; + void CreateNonStrictParser() { + bool has_sbr = false; + parser_ = std::make_unique<Mp2tStreamParser>(std::nullopt, has_sbr); + } + + void CreateStrictParser() { + bool has_sbr = false; + const std::string codecs[] = {"avc1.64001e", "mp3", "aac"}; + parser_ = std::make_unique<Mp2tStreamParser>(codecs, has_sbr); + } + void ResetStats() { segment_count_ = 0; config_count_ = 0; @@ -404,6 +413,20 @@ } }; +TEST_F(Mp2tStreamParserTest, NonStrictCodecChecking) { + CreateNonStrictParser(); + InitializeParser(); + ParseMpeg2TsFile("bear-1280x720.ts", 17); + parser_->Flush(); + EXPECT_EQ(audio_frame_count_, 119); + EXPECT_EQ(video_frame_count_, 82); + + // This stream has no mid-stream configuration change. + EXPECT_EQ(config_count_, 1); + EXPECT_EQ(segment_count_, 1); + CreateStrictParser(); +} + TEST_F(Mp2tStreamParserTest, UnalignedAppend17) { // Test small, non-segment-aligned appends. InitializeParser();
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index fac3102..f66632d 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -73,18 +73,19 @@ } // namespace -MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, - bool has_sbr, - bool has_flac, - bool has_iamf, - bool has_dv) +MP4StreamParser::MP4StreamParser( + std::optional<base::flat_set<int>> strict_audio_object_types, + bool has_sbr, + bool has_flac, + bool has_iamf, + bool has_dv) : state_(kWaitingForInit), moof_head_(0), mdat_tail_(0), highest_end_offset_(0), has_audio_(false), has_video_(false), - audio_object_types_(audio_object_types), + strict_audio_object_types_(strict_audio_object_types), has_sbr_(has_sbr), has_flac_(has_flac), has_iamf_(has_iamf), @@ -541,12 +542,14 @@ } #endif // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO) DVLOG(1) << "audio_type 0x" << std::hex << static_cast<int>(audio_type); - if (audio_object_types_.find(audio_type) == audio_object_types_.end()) { - MEDIA_LOG(ERROR, media_log_) - << "audio object type 0x" << std::hex - << static_cast<int>(audio_type) - << " does not match what is specified in the mimetype."; - return false; + if (strict_audio_object_types_.has_value()) { + if (!strict_audio_object_types_->contains(audio_type)) { + MEDIA_LOG(ERROR, media_log_) + << "audio object type 0x" << std::hex + << static_cast<int>(audio_type) + << " does not match what is specified in the mimetype."; + return false; + } } // Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or
diff --git a/media/formats/mp4/mp4_stream_parser.h b/media/formats/mp4/mp4_stream_parser.h index ca0d2d5b..d375586e 100644 --- a/media/formats/mp4/mp4_stream_parser.h +++ b/media/formats/mp4/mp4_stream_parser.h
@@ -12,6 +12,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/containers/flat_set.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "media/base/media_export.h" @@ -33,7 +34,7 @@ class MEDIA_EXPORT MP4StreamParser : public StreamParser { public: - MP4StreamParser(const std::set<int>& audio_object_types, + MP4StreamParser(std::optional<base::flat_set<int>> strict_audio_object_types, bool has_sbr, bool has_flac, bool has_iamf, @@ -165,9 +166,11 @@ bool has_video_; std::set<uint32_t> audio_track_ids_; std::set<uint32_t> video_track_ids_; + // The object types allowed for audio tracks. For FLAC indication, use - // |has_flac_|; - const std::set<int> audio_object_types_; + // |has_flac_|. If this is a nullopt, then strict object type assertion will + // not happen. + const std::optional<base::flat_set<int>> strict_audio_object_types_; const bool has_sbr_; const bool has_flac_; const bool has_iamf_;
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc index 6f1ac07..4918c4ff 100644 --- a/media/formats/mp4/mp4_stream_parser_unittest.cc +++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -81,7 +81,7 @@ : configs_received_(false), lower_bound_(kMaxDecodeTimestamp), verifying_keyframeness_sequence_(false) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kISO_14496_3); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -401,7 +401,7 @@ TEST_F(MP4StreamParserTest, MPEG2_AAC_LC) { InSequence s; - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kISO_13818_7_AAC_LC); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -412,9 +412,19 @@ EXPECT_EQ(audio_decoder_config_.profile(), AudioCodecProfile::kUnknown); } +TEST_F(MP4StreamParserTest, ParsingAACLCNoAudioTypeStrictness) { + InSequence s; + parser_.reset(new MP4StreamParser(std::nullopt, false, false, false, false)); + auto params = GetDefaultInitParametersExpectations(); + params.detected_video_track_count = 0; + InitializeParserWithInitParametersExpectations(params); + ParseMP4File("bear-mpeg2-aac-only_frag.mp4", 512); + EXPECT_EQ(audio_decoder_config_.profile(), AudioCodecProfile::kUnknown); +} + TEST_F(MP4StreamParserTest, MPEG4_XHE_AAC) { InSequence s; // The keyframeness sequence matters for this test. - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kISO_14496_3); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -624,7 +634,7 @@ } TEST_F(MP4StreamParserTest, DemuxingDVProfile5WithDVMimeTypeSourceBuffer) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, true)); @@ -652,7 +662,7 @@ } TEST_F(MP4StreamParserTest, DemuxingDVProfile5WithHEVCMimeTypeSourceBuffer) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -680,7 +690,7 @@ } TEST_F(MP4StreamParserTest, DemuxingDVProfile8WithDVMimeTypeSourceBuffer) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, true)); @@ -708,7 +718,7 @@ } TEST_F(MP4StreamParserTest, DemuxingDVProfile8WithHEVCMimeTypeSourceBuffer) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -740,7 +750,7 @@ } TEST_F(MP4StreamParserTest, DemuxingAC3) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kAC3); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -765,7 +775,7 @@ } TEST_F(MP4StreamParserTest, DemuxingEAC3) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kEAC3); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -790,7 +800,7 @@ } TEST_F(MP4StreamParserTest, DemuxingAc4Ims) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kAC4); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -815,7 +825,7 @@ } TEST_F(MP4StreamParserTest, DemuxingAc4AJoc) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kAC4); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -840,7 +850,7 @@ } TEST_F(MP4StreamParserTest, DemuxingAc4ChannelBasedCoding) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kAC4); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -865,7 +875,7 @@ } TEST_F(MP4StreamParserTest, DemuxingDTS) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kDTS); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -889,7 +899,7 @@ } TEST_F(MP4StreamParserTest, DemuxingDTSE) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kDTSE); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -913,7 +923,7 @@ } TEST_F(MP4StreamParserTest, DemuxingDTSX) { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kDTSX); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false)); @@ -938,7 +948,7 @@ TEST_F(MP4StreamParserTest, Flac) { parser_.reset( - new MP4StreamParser(std::set<int>(), false, true, false, false)); + new MP4StreamParser(base::flat_set<int>(), false, true, false, false)); auto params = GetDefaultInitParametersExpectations(); params.detected_video_track_count = 0; @@ -951,7 +961,7 @@ TEST_F(MP4StreamParserTest, Flac192kHz) { parser_.reset( - new MP4StreamParser(std::set<int>(), false, true, false, false)); + new MP4StreamParser(base::flat_set<int>(), false, true, false, false)); auto params = GetDefaultInitParametersExpectations(); params.detected_video_track_count = 0; @@ -1100,7 +1110,7 @@ : public ::testing::TestWithParam<MatrixRotationTestCaseParam> { public: MP4StreamParserRotationMatrixEvaluatorTest() { - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(kISO_14496_3); parser_.reset( new MP4StreamParser(audio_object_types, false, false, false, false));
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index ffb87ef..e6138b9 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -680,6 +680,16 @@ } } +fuzzer_test("media_h264_decoder_fuzzer") { + sources = [ "h264_decoder_fuzzer.cc" ] + deps = [ + ":gpu", + "//base", + "//media", + ] + seed_corpuses = [ "//media/test/data" ] +} + if (use_av1_hw_decoder) { fuzzer_test("media_av1_decoder_fuzzer") { sources = [ "av1_decoder_fuzzertest.cc" ]
diff --git a/media/gpu/h264_decoder_fuzzer.cc b/media/gpu/h264_decoder_fuzzer.cc new file mode 100644 index 0000000..eacb5df --- /dev/null +++ b/media/gpu/h264_decoder_fuzzer.cc
@@ -0,0 +1,91 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> + +#include "base/numerics/safe_conversions.h" +#include "media/base/decoder_buffer.h" +#include "media/base/video_codecs.h" +#include "media/base/video_types.h" +#include "media/gpu/h264_decoder.h" + +namespace { + +class FakeH264Accelerator : public media::H264Decoder::H264Accelerator { + public: + FakeH264Accelerator() = default; + + FakeH264Accelerator(const FakeH264Accelerator&) = delete; + FakeH264Accelerator& operator=(const FakeH264Accelerator&) = delete; + + ~FakeH264Accelerator() override = default; + + // media::H264Decoder::H264Accelerator + scoped_refptr<media::H264Picture> CreateH264Picture() override { + return new media::H264Picture(); + } + + Status SubmitFrameMetadata(const media::H264SPS* sps, + const media::H264PPS* pps, + const media::H264DPB& dpb, + const media::H264Picture::Vector& ref_pic_listp0, + const media::H264Picture::Vector& ref_pic_listb0, + const media::H264Picture::Vector& ref_pic_listb1, + scoped_refptr<media::H264Picture> pic) override { + return Status::kOk; + } + Status SubmitSlice( + const media::H264PPS* pps, + const media::H264SliceHeader* slice_hdr, + const media::H264Picture::Vector& ref_pic_list0, + const media::H264Picture::Vector& ref_pic_list1, + scoped_refptr<media::H264Picture> pic, + const uint8_t* data, + size_t size, + const std::vector<media::SubsampleEntry>& subsamples) override { + return Status::kOk; + } + Status SubmitDecode(scoped_refptr<media::H264Picture> pic) override { + return Status::kOk; + } + bool OutputPicture(scoped_refptr<media::H264Picture> pic) override { + return true; + } + void Reset() override {} + Status SetStream(base::span<const uint8_t> stream, + const media::DecryptConfig* decrypt_config) override { + return Status::kOk; + } +}; + +} // namespace + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (!size) { + return 0; + } + + media::H264Decoder decoder(std::make_unique<FakeH264Accelerator>(), + media::H264PROFILE_MAIN); + auto external_memory = std::make_unique<media::DecoderBuffer::ExternalMemory>( + base::make_span(data, size)); + scoped_refptr<media::DecoderBuffer> decoder_buffer = + media::DecoderBuffer::FromExternalMemory(std::move(external_memory)); + decoder.SetStream(1, *decoder_buffer); + + size_t retry_count = 0; + while (true) { + switch (decoder.Decode()) { + case media::AcceleratedVideoDecoder::DecodeResult::kConfigChange: + break; + case media::AcceleratedVideoDecoder::DecodeResult::kTryAgain: + if (++retry_count > 3) { + return 0; + } + break; + default: + return 0; + } + } +}
diff --git a/media/muxers/mp4_muxer_delegate_unittest.cc b/media/muxers/mp4_muxer_delegate_unittest.cc index eff907b1..1ca8dbb 100644 --- a/media/muxers/mp4_muxer_delegate_unittest.cc +++ b/media/muxers/mp4_muxer_delegate_unittest.cc
@@ -203,7 +203,7 @@ { // Validate MP4 format. - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(mp4::kISO_14496_3); mp4::MP4StreamParser mp4_stream_parser(audio_object_types, false, false, false, false); @@ -501,7 +501,7 @@ { // Validate MP4 format. - std::set<int> audio_object_types; + base::flat_set<int> audio_object_types; audio_object_types.insert(mp4::kISO_14496_3); mp4::MP4StreamParser mp4_stream_parser(audio_object_types, false, false, false, false);
diff --git a/media/video/h265_parser_fuzzertest.cc b/media/video/h265_parser_fuzzertest.cc index 53bc346..79cd420c 100644 --- a/media/video/h265_parser_fuzzertest.cc +++ b/media/video/h265_parser_fuzzertest.cc
@@ -17,6 +17,8 @@ // Parse until the end of stream/unsupported stream/error in stream is // found. + media::H265SliceHeader shdr; + media::H265SliceHeader prior_shdr; while (true) { media::H265NALU nalu; media::H265SEI sei; @@ -24,8 +26,6 @@ if (res != media::H265Parser::kOk) break; - media::H265SliceHeader shdr; - media::H265SliceHeader prior_shdr; switch (nalu.nal_unit_type) { case media::H265NALU::VPS_NUT: int vps_id;
diff --git a/media/video/vpx_video_encoder.cc b/media/video/vpx_video_encoder.cc index 899deb5eaa..9a7efa30 100644 --- a/media/video/vpx_video_encoder.cc +++ b/media/video/vpx_video_encoder.cc
@@ -5,6 +5,7 @@ #include "media/video/vpx_video_encoder.h" #include <algorithm> +#include <memory> #include <optional> #include "base/logging.h" @@ -76,6 +77,7 @@ "Frame is too large."); config->g_pass = VPX_RC_ONE_PASS; + // libvpx encoding is performed synchronously. config->g_lag_in_frames = 0; config->rc_max_quantizer = 58; // Increase min QP to 12 for vp8 screen sharing; It reduces the encoding @@ -679,7 +681,8 @@ vpx_codec_flags_t flags = key_frame ? VPX_EFLAG_FORCE_KF : 0; int temporal_id = 0; - if (codec_config_.ts_number_layers > 1) { + const bool is_layer_encoding = codec_config_.ts_number_layers > 1; + if (is_layer_encoding) { if (key_frame) temporal_svc_frame_index_ = 0; unsigned int index_in_temp_cycle = @@ -716,7 +719,20 @@ return; } - DrainOutputs(temporal_id, frame->timestamp(), frame->ColorSpace()); + auto output = + GetEncoderOutput(temporal_id, frame->timestamp(), frame->ColorSpace()); + if (is_layer_encoding) { + // If we got an unexpected key frame, |temporal_svc_frame_index_| needs to + // be adjusted, because the next frame should have index 1. + if (output.key_frame) { + temporal_svc_frame_index_ = 0; + } + if (output.size != 0) { + temporal_svc_frame_index_++; + } + } + + output_cb_.Run(std::move(output), {}); std::move(done_cb).Run(EncoderStatus::Codes::kOk); } @@ -819,66 +835,36 @@ return; } - auto vpx_error = vpx_codec_encode(codec_.get(), nullptr, -1, 0, 0, 0); - if (vpx_error != VPX_CODEC_OK) { - auto msg = - LogVpxErrorMessage(codec_.get(), "VPX flushing error", vpx_error); - auto status = EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, msg) - .WithData("vpx_error", vpx_error); - std::move(done_cb).Run(std::move(status)); - return; - } - DrainOutputs(0, std::nullopt, gfx::ColorSpace()); + // The libvpx encoder is operating synchronously and thus doesn't have to + // flush if and only if |g_lag_in_frames| is set to 0. + CHECK_EQ(codec_config_.g_lag_in_frames, 0u); std::move(done_cb).Run(EncoderStatus::Codes::kOk); } -void VpxVideoEncoder::DrainOutputs(int temporal_id, - std::optional<base::TimeDelta> ts, - gfx::ColorSpace color_space) { - const bool flush = !ts.has_value(); - bool dropped_frame = true; +VideoEncoderOutput VpxVideoEncoder::GetEncoderOutput( + int temporal_id, + base::TimeDelta timestamp, + gfx::ColorSpace color_space) const { vpx_codec_iter_t iter = nullptr; const vpx_codec_cx_pkt_t* pkt = nullptr; + VideoEncoderOutput output; + // We don't given timestamps to vpx_codec_encode() that's why + // pkt->data.frame.pts can't be used here. + output.timestamp = timestamp; while ((pkt = vpx_codec_get_cx_data(codec_.get(), &iter))) { if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { - dropped_frame = false; - VideoEncoderOutput result; - result.key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; - - if (result.key_frame) { - // If we got an unexpected key frame, |temporal_svc_frame_index_| needs - // to be adjusted, because the next frame should have index 1. - temporal_svc_frame_index_ = 0; - result.temporal_id = 0; - } else { - result.temporal_id = temporal_id; - } - - // We don't given timestamps to vpx_codec_encode() that's why - // pkt->data.frame.pts can't be used here. - result.timestamp = *ts; - result.color_space = color_space; - result.size = pkt->data.frame.sz; - result.data = std::make_unique<uint8_t[]>(result.size); - memcpy(result.data.get(), pkt->data.frame.buf, result.size); - output_cb_.Run(std::move(result), {}); + // The encoder is operating synchronously. There should be exactly one + // encoded packet, or the frame is dropped. + CHECK_EQ(output.size, 0u); + output.size = pkt->data.frame.sz; + output.data = std::make_unique<uint8_t[]>(output.size); + memcpy(output.data.get(), pkt->data.frame.buf, output.size); + output.key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; + output.temporal_id = output.key_frame ? 0 : temporal_id; + output.color_space = color_space; } } - - if (flush) { - return; - } - - if (dropped_frame) { - VideoEncoderOutput result; - result.timestamp = *ts; - output_cb_.Run(std::move(result), {}); - return; - } - - if (codec_config_.ts_number_layers > 1) { - temporal_svc_frame_index_++; - } + return output; } void VpxVideoEncoder::RecreateVpxImageIfNeeded(vpx_img_fmt fmt,
diff --git a/media/video/vpx_video_encoder.h b/media/video/vpx_video_encoder.h index b5e437d..099a3a2 100644 --- a/media/video/vpx_video_encoder.h +++ b/media/video/vpx_video_encoder.h
@@ -41,9 +41,9 @@ private: base::TimeDelta GetFrameDuration(const VideoFrame& frame); - void DrainOutputs(int temporal_id, - std::optional<base::TimeDelta> ts, - gfx::ColorSpace color_space); + VideoEncoderOutput GetEncoderOutput(int temporal_id, + base::TimeDelta timestamp, + gfx::ColorSpace color_space) const; void RecreateVpxImageIfNeeded(vpx_img_fmt fmt, bool needs_memory); void UpdateEncoderColorSpace();
diff --git a/net/quic/quic_session_pool.cc b/net/quic/quic_session_pool.cc index 098ad85..f0e461e 100644 --- a/net/quic/quic_session_pool.cc +++ b/net/quic/quic_session_pool.cc
@@ -168,7 +168,7 @@ url::SchemeHostPort destination, quic::ParsedQuicVersion quic_version, const ProxyChain& proxy_chain, - const absl::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, + const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, SessionUsage session_usage, PrivacyMode privacy_mode, RequestPriority priority, @@ -504,7 +504,7 @@ const QuicSessionKey& session_key, url::SchemeHostPort destination, quic::ParsedQuicVersion quic_version, - const absl::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, + const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, RequestPriority priority, bool use_dns_aliases, int cert_verify_flags,
diff --git a/net/quic/quic_session_pool.h b/net/quic/quic_session_pool.h index ccfd09cd..be2ee30 100644 --- a/net/quic/quic_session_pool.h +++ b/net/quic/quic_session_pool.h
@@ -151,7 +151,7 @@ url::SchemeHostPort destination, quic::ParsedQuicVersion quic_version, const ProxyChain& proxy_chain, - const absl::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, + const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, SessionUsage session_usage, PrivacyMode privacy_mode, RequestPriority priority, @@ -343,7 +343,7 @@ const QuicSessionKey& session_key, url::SchemeHostPort destination, quic::ParsedQuicVersion quic_version, - const absl::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, + const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag, RequestPriority priority, bool use_dns_aliases, int cert_verify_flags,
diff --git a/net/quic/quic_session_pool_direct_job.cc b/net/quic/quic_session_pool_direct_job.cc index c76d20887..26cd9e2 100644 --- a/net/quic/quic_session_pool_direct_job.cc +++ b/net/quic/quic_session_pool_direct_job.cc
@@ -264,6 +264,7 @@ return rv; } + int QuicSessionPool::DirectJob::DoCreateSessionComplete(int rv) { session_creation_finished_ = true; if (rv != OK) { @@ -423,23 +424,15 @@ } void QuicSessionPool::DirectJob::OnCreateSessionComplete(int rv) { - if (rv != OK) { - DCHECK(!session_); - if (rv == ERR_QUIC_PROTOCOL_ERROR) { - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kCreateSessionFailedAsync); - } - for (QuicSessionRequest* request : requests()) { - request->OnQuicSessionCreationComplete(rv); - } - if (!callback_.is_null()) { - std::move(callback_).Run(rv); - } - return; + if (rv == ERR_QUIC_PROTOCOL_ERROR) { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kCreateSessionFailedAsync); } - DCHECK(session_); - DVLOG(1) << "Created session on network: " << network_; - io_state_ = STATE_CREATE_SESSION_COMPLETE; + if (rv == OK) { + DCHECK(session_); + DVLOG(1) << "Created session on network: " << network_; + } + rv = DoLoop(rv); for (QuicSessionRequest* request : requests()) { @@ -523,4 +516,5 @@ return quic::ParsedQuicVersion::Unsupported(); } + } // namespace net
diff --git a/net/quic/quic_session_pool_test.cc b/net/quic/quic_session_pool_test.cc index 4561da88..83b0a9b 100644 --- a/net/quic/quic_session_pool_test.cc +++ b/net/quic/quic_session_pool_test.cc
@@ -375,7 +375,7 @@ url::SchemeHostPort destination = kDefaultDestination; quic::ParsedQuicVersion quic_version; ProxyChain proxy_chain = ProxyChain::Direct(); - absl::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag = + std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag = TRAFFIC_ANNOTATION_FOR_TESTS; SessionUsage session_usage = SessionUsage::kDestination; PrivacyMode privacy_mode = PRIVACY_MODE_DISABLED;
diff --git a/net/third_party/quiche/src b/net/third_party/quiche/src index bccc7cc..bb4f684 160000 --- a/net/third_party/quiche/src +++ b/net/third_party/quiche/src
@@ -1 +1 @@ -Subproject commit bccc7cc648236d93d8cd4f07c82d7a15a6218bf6 +Subproject commit bb4f68479fd8fa4738339cdcc5782b04b985b72b
diff --git a/sandbox/linux/OWNERS b/sandbox/linux/OWNERS index 29cb7a1..2ac3792 100644 --- a/sandbox/linux/OWNERS +++ b/sandbox/linux/OWNERS
@@ -1,2 +1,3 @@ jorgelo@chromium.org mpdenton@chromium.org +rsesek@chromium.org
diff --git a/services/metrics/public/cpp/ukm_recorder.cc b/services/metrics/public/cpp/ukm_recorder.cc index 41d2d4cd..8448958 100644 --- a/services/metrics/public/cpp/ukm_recorder.cc +++ b/services/metrics/public/cpp/ukm_recorder.cc
@@ -89,6 +89,22 @@ SourceIdType::EXTENSION_ID); } +// static +ukm::SourceId UkmRecorder::GetSourceIdForNotificationPermission( + base::PassKey<ChromePermissionsClient>, + const GURL& origin) { + return UkmRecorder::GetSourceIdFromScopeImpl(origin, + SourceIdType::NOTIFICATION_ID); +} + +// static +ukm::SourceId UkmRecorder::GetSourceIdForNotificationEvent( + base::PassKey<PlatformNotificationServiceImpl>, + const GURL& origin) { + return UkmRecorder::GetSourceIdFromScopeImpl(origin, + SourceIdType::NOTIFICATION_ID); +} + void UkmRecorder::RecordOtherURL(ukm::SourceIdObj source_id, const GURL& url) { UpdateSourceURL(source_id.ToInt64(), url); }
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h index 1f835fb..c78fa3b 100644 --- a/services/metrics/public/cpp/ukm_recorder.h +++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -17,9 +17,11 @@ #include "services/metrics/public/mojom/ukm_interface.mojom-forward.h" #include "url/gurl.h" +class ChromePermissionsClient; class DIPSNavigationHandle; class DIPSService; class PermissionUmaUtil; +class PlatformNotificationServiceImpl; namespace apps { class WebsiteMetrics; @@ -141,6 +143,19 @@ base::PassKey<apps::WebsiteMetrics>, const GURL& chromeos_website_url); + // Gets a new SourceId of NOTIFICATION_ID type. This should only be + // used for recording Permission UKM events related to persistent and + // nonpersistent notifications. `origin` is the domain that uses the Push API. + static SourceId GetSourceIdForNotificationPermission( + base::PassKey<ChromePermissionsClient>, + const GURL& origin); + + // Gets a new SourceId of NOTIFICATION_ID type. This should only be used + // for recording persistent and nonpersistent notification UKM events. + static SourceId GetSourceIdForNotificationEvent( + base::PassKey<PlatformNotificationServiceImpl>, + const GURL& origin); + // This method should be called when the system is about to shutdown, but // `UkmRecorder` is still available to record metrics. // Calls `OnStartingShutdown` on each observer from `observers_`.
diff --git a/services/metrics/public/cpp/ukm_source.cc b/services/metrics/public/cpp/ukm_source.cc index 035d2355..77aa22d 100644 --- a/services/metrics/public/cpp/ukm_source.cc +++ b/services/metrics/public/cpp/ukm_source.cc
@@ -66,6 +66,8 @@ return SourceType::CHROMEOS_WEBSITE_ID; case SourceIdType::EXTENSION_ID: return SourceType::EXTENSION_ID; + case SourceIdType::NOTIFICATION_ID: + return SourceType::NOTIFICATION_ID; } }
diff --git a/services/metrics/public/cpp/ukm_source_id.cc b/services/metrics/public/cpp/ukm_source_id.cc index ed7c07a..b693d582 100644 --- a/services/metrics/public/cpp/ukm_source_id.cc +++ b/services/metrics/public/cpp/ukm_source_id.cc
@@ -113,6 +113,8 @@ return "CHROMEOS_WEBSITE_ID"; case SourceIdObj::Type::EXTENSION_ID: return "EXTENSION_ID"; + case SourceIdObj::Type::NOTIFICATION_ID: + return "NOTIFICATION_ID"; } }
diff --git a/services/metrics/public/cpp/ukm_source_id.h b/services/metrics/public/cpp/ukm_source_id.h index 4af9acc..91f18ea 100644 --- a/services/metrics/public/cpp/ukm_source_id.h +++ b/services/metrics/public/cpp/ukm_source_id.h
@@ -90,8 +90,16 @@ // Some criteria (e.g. checking if it's a synced extension) will be applied // when recording metrics with this type. EXTENSION_ID = 12, + // Source ID type for service-worker triggered persisted notification + // events. + // Notification events may occur in the background and an associated URL is + // not necessarily present in the browsing history. A new source of this + // type and associated events are expected to be recorded within the same + // report + // interval; it will not be kept in memory between different reports. + NOTIFICATION_ID = 13, - kMaxValue = EXTENSION_ID, + kMaxValue = NOTIFICATION_ID, }; // Default constructor has the invalid value.
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 6ce7499f..19cf30ad 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5311,9 +5311,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5323,8 +5323,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": { @@ -5467,9 +5467,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5479,8 +5479,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index b8711799..f498a05 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -20464,9 +20464,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20476,8 +20476,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": { @@ -20614,9 +20614,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20626,8 +20626,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index f1a8481..914161b 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -41453,9 +41453,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41464,8 +41464,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": { @@ -41603,9 +41603,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41614,8 +41614,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": { @@ -42935,9 +42935,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -42946,8 +42946,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": { @@ -43085,9 +43085,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -43096,8 +43096,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 23e4ce5..7490f1c 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -16507,12 +16507,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16522,8 +16522,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": { @@ -16683,12 +16683,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 123.0.6297.0", + "description": "Run with ash-chrome version 123.0.6298.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16698,8 +16698,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6297.0", - "revision": "version:123.0.6297.0" + "location": "lacros_version_skew_tests_v123.0.6298.0", + "revision": "version:123.0.6298.0" } ], "dimensions": {
diff --git a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter index 62db514..fc44ec8 100644 --- a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter +++ b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter
@@ -57,3 +57,9 @@ -TabDragging/DetachToBrowserTabDragControllerTest.SelectTabDuringDrag/2 -TabDragging/DetachToBrowserTabDragControllerTest.TabDragContextOwnsDraggedTabs/0 -TabDragging/DetachToBrowserTabDragControllerTest.TabDragContextOwnsDraggedTabs/2 + +# TODO(b/324465984) These tests are failing because of an issue with the skew +# roller. They're using a new testing API which requires support from a version +# of Ash > 121.0.6167.16. Remove this once the skew roller is fixed and a more +# recent version of Ash lands in the skew tests. +-TabDragging/DetachToBrowserInSeparateDisplayTabDragControllerTest.DragTabToWindowInSeparateDisplay/*
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 8cd9e3d..fa6783b7b 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -307,16 +307,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 123.0.6297.0', + 'description': 'Run with ash-chrome version 123.0.6298.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6297.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6298.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v123.0.6297.0', - 'revision': 'version:123.0.6297.0', + 'location': 'lacros_version_skew_tests_v123.0.6298.0', + 'revision': 'version:123.0.6298.0', }, ], },
diff --git a/testing/libfuzzer/OWNERS b/testing/libfuzzer/OWNERS index a173923..f084f05 100644 --- a/testing/libfuzzer/OWNERS +++ b/testing/libfuzzer/OWNERS
@@ -1,10 +1,9 @@ titouan@chromium.org -pgrace@chromium.org ahijazi@chromium.org paulsemel@chromium.org pmeuleman@chromium.org +tiszka@chromium.org adetaylor@chromium.org #{LAST_RESORT_SUGGESTION} bookholt@chromium.org #{LAST_RESORT_SUGGESTION} -tiszka@chromium.org #{LAST_RESORT_SUGGESTION} metzman@chromium.org #{LAST_RESORT_SUGGESTION}
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index c59cc328..fd333d1 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -17840,6 +17840,27 @@ ] } ], + "SharedStorageAPIEnableWALForDatabase": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "fuchsia", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "EnableWAL", + "enable_features": [ + "SharedStorageAPIEnableWALForDatabase" + ] + } + ] + } + ], "SharedStorageWorkletThreadImplementation": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index e784b1e..cb7d3cc 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit e784b1ec822888844ec60abcf50d169f0347f6cf +Subproject commit cb7d3cc206d6a4165c0012d78387b714b55a0556
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index c3a9c45a..a01baca 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1228,11 +1228,6 @@ &kLCPCriticalPathPredictor, "lcpp_image_load_priority", LcppResourceLoadPriority::kVeryHigh, &lcpp_resource_load_priorities}; -const base::FeatureParam<LcppResourceLoadPriority> - kLCPCriticalPathPredictorInfluencerScriptLoadPriority{ - &kLCPCriticalPathPredictor, "lcpp_script_load_priority", - LcppResourceLoadPriority::kVeryHigh, &lcpp_resource_load_priorities}; - const base::FeatureParam<bool> kLCPCriticalPathPredictorEnableElementLocatorPerformanceImprovements{ &kLCPCriticalPathPredictor, "lcpp_enable_perf_improvements", true}; @@ -1246,11 +1241,25 @@ "LCPScriptObserver", base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam<LcppResourceLoadPriority> + kLCPScriptObserverScriptLoadPriority{ + &kLCPScriptObserver, "lcpscriptobserver_script_load_priority", + LcppResourceLoadPriority::kVeryHigh, &lcpp_resource_load_priorities}; + +const base::FeatureParam<LcppResourceLoadPriority> + kLCPScriptObserverImageLoadPriority{ + &kLCPScriptObserver, "lcpscriptobserver_image_load_priority", + LcppResourceLoadPriority::kVeryHigh, &lcpp_resource_load_priorities}; + const base::FeatureParam<int> kLCPScriptObserverMaxUrlLength{ - &kLCPScriptObserver, "lcpp_max_url_length", 1024}; + &kLCPScriptObserver, "lcpscriptobserver_script_max_url_length", 1024}; const base::FeatureParam<int> kLCPScriptObserverMaxUrlCountPerOrigin{ - &kLCPScriptObserver, "lcpp_max_url_count_per_origin", 5}; + &kLCPScriptObserver, "lcpscriptobserver_script_max_url_count_per_origin", + 5}; + +const base::FeatureParam<bool> kLCPScriptObserverAdjustImageLoadPriority{ + &kLCPScriptObserver, "lcpscriptobserver_adjust_image_load_priority", false}; BASE_FEATURE(kLCPPAutoPreconnectLcpOrigin, "LCPPAutoPreconnectLcpOrigin",
diff --git a/third_party/blink/common/loader/lcp_critical_path_predictor_util.cc b/third_party/blink/common/loader/lcp_critical_path_predictor_util.cc index d0bca58..14ed75c 100644 --- a/third_party/blink/common/loader/lcp_critical_path_predictor_util.cc +++ b/third_party/blink/common/loader/lcp_critical_path_predictor_util.cc
@@ -24,4 +24,12 @@ blink::features::kLCPPAutoPreconnectLcpOrigin); } +bool LcppScriptObserverEnabled() { + return base::FeatureList::IsEnabled(blink::features::kLCPScriptObserver) || + (base::FeatureList::IsEnabled( + features::kLowPriorityAsyncScriptExecution) && + features::kLowPriorityAsyncScriptExecutionExcludeLcpInfluencersParam + .Get()); +} + } // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index fd25b8a7..dd4fc02 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -690,10 +690,6 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<LcppResourceLoadPriority> kLCPCriticalPathPredictorImageLoadPriority; -// The ResourceLoadPriority for scripts that are expected to be LCP influencers. -BLINK_COMMON_EXPORT extern const base::FeatureParam<LcppResourceLoadPriority> - kLCPCriticalPathPredictorInfluencerScriptLoadPriority; - // Enables LCPP ElementLocator performance improvements BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> kLCPCriticalPathPredictorEnableElementLocatorPerformanceImprovements; @@ -706,6 +702,14 @@ // the LCP element. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLCPScriptObserver); +// The ResourceLoadPriority for scripts that are expected to be LCP influencers. +BLINK_COMMON_EXPORT extern const base::FeatureParam<LcppResourceLoadPriority> + kLCPScriptObserverScriptLoadPriority; + +// The ResourceLoadPriority for images that are expected to LCP elements. +BLINK_COMMON_EXPORT extern const base::FeatureParam<LcppResourceLoadPriority> + kLCPScriptObserverImageLoadPriority; + // The maximum URL count for LCPP. BLINK_COMMON_EXPORT extern const base::FeatureParam<int> kLCPScriptObserverMaxUrlCountPerOrigin; @@ -714,6 +718,10 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<int> kLCPScriptObserverMaxUrlLength; +// Enable ResourceLoadPriority changes for all HTMLImageElement loaded images. +BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> + kLCPScriptObserverAdjustImageLoadPriority; + // If enabled, LCP image origin is predicted and preconnected automatically. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLCPPAutoPreconnectLcpOrigin);
diff --git a/third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h b/third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h index c8f563b..7056cbc6 100644 --- a/third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h +++ b/third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h
@@ -10,6 +10,7 @@ namespace blink { BLINK_COMMON_EXPORT bool LcppEnabled(); +BLINK_COMMON_EXPORT bool LcppScriptObserverEnabled(); } // namespace blink
diff --git a/third_party/blink/public/mojom/devtools/inspector_issue.mojom b/third_party/blink/public/mojom/devtools/inspector_issue.mojom index d4c618a..86618ffb 100644 --- a/third_party/blink/public/mojom/devtools/inspector_issue.mojom +++ b/third_party/blink/public/mojom/devtools/inspector_issue.mojom
@@ -91,6 +91,7 @@ kInvalidRegisterOsTriggerHeader, kWebAndOsHeaders, kNoWebOrOsSupport, + kNavigationRegistrationWithoutTransientUserActivation, }; struct AttributionReportingIssueDetails {
diff --git a/third_party/blink/renderer/core/editing/dom_selection.cc b/third_party/blink/renderer/core/editing/dom_selection.cc index 798fe21..b9eed89 100644 --- a/third_party/blink/renderer/core/editing/dom_selection.cc +++ b/third_party/blink/renderer/core/editing/dom_selection.cc
@@ -100,20 +100,6 @@ return Selection().GetSelectionInDOMTree().IsBaseFirst(); } -// TODO(tkent): Following four functions based on VisibleSelection should be -// removed. -static Position AnchorPosition(const VisibleSelection& selection) { - Position anchor = - selection.IsBaseFirst() ? selection.Start() : selection.End(); - return anchor.ParentAnchoredEquivalent(); -} - -static Position FocusPosition(const VisibleSelection& selection) { - Position focus = - selection.IsBaseFirst() ? selection.End() : selection.Start(); - return focus.ParentAnchoredEquivalent(); -} - Node* DOMSelection::anchorNode() const { if (Range* range = PrimaryRangeOrNull()) { if (!DomWindow() || IsBaseFirstInSelection()) @@ -548,7 +534,7 @@ EphemeralRange DOMSelection::CreateRangeFromSelectionEditor() const { const VisibleSelection& selection = GetVisibleSelection(); - const Position& anchor = blink::AnchorPosition(selection); + const Position& anchor = selection.Base().ParentAnchoredEquivalent(); if (IsSelectionOfDocument() && !anchor.AnchorNode()->IsInShadowTree()) return FirstEphemeralRangeOf(selection); @@ -556,7 +542,7 @@ if (!anchor_node) // crbug.com/595100 return EphemeralRange(); - const Position& focus = FocusPosition(selection); + const Position& focus = selection.Extent().ParentAnchoredEquivalent(); const Position shadow_adjusted_focus = Position(ShadowAdjustedNode(focus), ShadowAdjustedOffset(focus)); const Position shadow_adjusted_anchor =
diff --git a/third_party/blink/renderer/core/editing/frame_selection_test.cc b/third_party/blink/renderer/core/editing/frame_selection_test.cc index d7310bc..c842391c 100644 --- a/third_party/blink/renderer/core/editing/frame_selection_test.cc +++ b/third_party/blink/renderer/core/editing/frame_selection_test.cc
@@ -35,6 +35,8 @@ #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/testing/fake_display_item_client.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/vector2d.h" namespace blink { @@ -1396,6 +1398,33 @@ frame_view->FrameToDocument(Selection().AbsoluteUnclippedBounds())); } +TEST_F(FrameSelectionTest, AbosluteSelectionBoundsAfterScroll) { + SetBodyContent( + "<style>" + " html, body { height: 2000px; }" + "</style>" + "<div style='height:1000px;'>" + " <p style='margin-top:100px; font-size:30px'>text</p>" + "</div>"); + Selection().SelectAll(); + + gfx::Rect initial_anchor, initial_focus; + Selection().ComputeAbsoluteBounds(initial_anchor, initial_focus); + + // Scroll 50px down. + const int scroll_offset = 50; + GetDocument().View()->LayoutViewport()->SetScrollOffset( + ScrollOffset(0, scroll_offset), mojom::blink::ScrollType::kProgrammatic); + + // Check absolute selection bounds are updated. + gfx::Rect anchor_after_scroll, focus_after_scroll; + Selection().ComputeAbsoluteBounds(anchor_after_scroll, focus_after_scroll); + EXPECT_EQ(anchor_after_scroll, + initial_anchor - gfx::Vector2d(0, scroll_offset)); + EXPECT_EQ(focus_after_scroll, + initial_focus - gfx::Vector2d(0, scroll_offset)); +} + TEST_F(FrameSelectionTest, SelectionContainsBidiBoundary) { InsertStyleElement("div{font:10px/10px Ahem}"); // Rendered as abcFED
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader.cc b/third_party/blink/renderer/core/frame/attribution_src_loader.cc index 5d49715..f4ce11dd 100644 --- a/third_party/blink/renderer/core/frame/attribution_src_loader.cc +++ b/third_party/blink/renderer/core/frame/attribution_src_loader.cc
@@ -39,6 +39,7 @@ #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/conversions/attribution_data_host.mojom-blink.h" #include "third_party/blink/public/mojom/conversions/conversions.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" @@ -84,6 +85,8 @@ using ::attribution_reporting::mojom::SourceType; using ::network::mojom::AttributionReportingEligibility; +using mojom::blink::AttributionReportingIssueType; + // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class AttributionSrcRequestStatus {
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc index ae63ba1..4221de5 100644 --- a/third_party/blink/renderer/core/html/html_image_element.cc +++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/html/html_image_element.h" +#include "third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h" #include "third_party/blink/renderer/core/css/css_property_names.h" @@ -120,7 +121,7 @@ is_changed_shortly_after_mouseover_(false), is_auto_sized_(false), is_predicted_lcp_element_(false) { - if (base::FeatureList::IsEnabled(features::kLCPScriptObserver)) { + if (blink::LcppScriptObserverEnabled()) { if (LocalFrame* frame = document.GetFrame()) { if (LCPCriticalPathPredictor* lcpp = frame->GetLCPP()) { if (LCPScriptObserver* script_observer = lcpp->lcp_script_observer()) {
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc index d1b8ceb..f28b1f5 100644 --- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc +++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
@@ -187,6 +187,8 @@ namespace { +using mojom::blink::AttributionReportingIssueType; + protocol::Audits::AttributionReportingIssueType BuildAttributionReportingIssueType(AttributionReportingIssueType type) { switch (type) { @@ -239,11 +241,12 @@ } // namespace -void AuditsIssue::ReportAttributionIssue(ExecutionContext* execution_context, - AttributionReportingIssueType type, - Element* element, - const String& request_id, - const String& invalid_parameter) { +void AuditsIssue::ReportAttributionIssue( + ExecutionContext* execution_context, + AttributionReportingIssueType type, + Element* element, + const String& request_id, + const String& invalid_parameter) { auto details = protocol::Audits::AttributionReportingIssueDetails::create() .setViolationType(BuildAttributionReportingIssueType(type)) .build();
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h index cecce24..6c23774 100644 --- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h +++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
@@ -47,24 +47,6 @@ kNoCorsRedirectModeNotFollow, }; -enum class AttributionReportingIssueType { - kPermissionPolicyDisabled, - kUntrustworthyReportingOrigin, - kInsecureContext, - kInvalidRegisterSourceHeader, - kInvalidRegisterTriggerHeader, - kSourceAndTriggerHeaders, - kSourceIgnored, - kTriggerIgnored, - kOsSourceIgnored, - kOsTriggerIgnored, - kInvalidRegisterOsSourceHeader, - kInvalidRegisterOsTriggerHeader, - kWebAndOsHeaders, - kNoWebOrOsSupport, - kNavigationRegistrationWithoutTransientUserActivation, -}; - enum class SharedArrayBufferIssueType { kTransferIssue, kCreationIssue, @@ -124,11 +106,12 @@ WTF::String failedParameter, std::optional<base::UnguessableToken> issue_id); - static void ReportAttributionIssue(ExecutionContext* execution_context, - AttributionReportingIssueType type, - Element* element, - const String& request_id, - const String& invalid_parameter); + static void ReportAttributionIssue( + ExecutionContext* execution_context, + mojom::blink::AttributionReportingIssueType type, + Element* element, + const String& request_id, + const String& invalid_parameter); static void ReportSharedArrayBufferIssue( ExecutionContext* execution_context,
diff --git a/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc b/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc index aefefccd..000970b0 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc +++ b/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc
@@ -529,9 +529,10 @@ TextOffsetMap offset_map; String transformed = layout_text->TransformAndSecureText(original, offset_map); - DCHECK_EQ(layout_text->TransformedText(), transformed); + CHECK_EQ(layout_text->TransformedText().length(), transformed.length()); const Vector<unsigned> length_map = TransformedString::CreateLengthMap( original.length(), transformed.length(), offset_map); + CHECK(transformed.length() == length_map.size() || length_map.size() == 0); AppendText(TransformedString(layout_text->TransformedText(), {length_map.data(), length_map.size()}), *layout_text);
diff --git a/third_party/blink/renderer/core/layout/inline/transformed_string.cc b/third_party/blink/renderer/core/layout/inline/transformed_string.cc index 50f40aaa..7127097 100644 --- a/third_party/blink/renderer/core/layout/inline/transformed_string.cc +++ b/third_party/blink/renderer/core/layout/inline/transformed_string.cc
@@ -62,6 +62,9 @@ if (length_map_.empty()) { return TransformedString(sub_view); } + CHECK_EQ(view_.length(), length_map_.size()); + CHECK_LE(start, view_.length()); + CHECK_LE(start + length, view_.length()); return TransformedString(sub_view, length_map_.subspan(start, length)); }
diff --git a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc index 4e258e10..f6d546a 100644 --- a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc +++ b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc
@@ -30,7 +30,7 @@ host_(frame.DomWindow()), task_runner_(frame.GetTaskRunner(TaskType::kInternalLoading)) { CHECK(LcppEnabled()); - if (base::FeatureList::IsEnabled(features::kLCPScriptObserver)) { + if (blink::LcppScriptObserverEnabled()) { lcp_script_observer_ = MakeGarbageCollected<LCPScriptObserver>(frame_); } } @@ -210,7 +210,7 @@ } } - if (base::FeatureList::IsEnabled(features::kLCPScriptObserver)) { + if (blink::LcppScriptObserverEnabled()) { if (const HTMLImageElement* image_element = DynamicTo<HTMLImageElement>(lcp_element)) { auto& creators = image_element->creator_scripts();
diff --git a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_script_observer.cc b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_script_observer.cc index 43dde3f..320c158 100644 --- a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_script_observer.cc +++ b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_script_observer.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_script_observer.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" namespace blink { @@ -67,7 +68,7 @@ LCPScriptObserver::LCPScriptObserver(LocalFrame* local_root) : local_root_(local_root) { - CHECK(base::FeatureList::IsEnabled(features::kLCPScriptObserver)); + CHECK(blink::LcppScriptObserverEnabled()); local_root_->GetProbeSink()->AddLCPScriptObserver(this); }
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc index ac8d45b..7a00436 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -843,37 +843,19 @@ )HTML"); ForceFullCompositingUpdate(); - // The scrolling contents layer is fully marked as pan-y. + // The outer layer (not scrollable) will be fully marked as pan-y (100x100) + // and the scrollable layer will only have the contents marked as pan-y + // (50x150). const auto* scrolling_contents_layer = ScrollingContentsLayerByDOMElementId("scrollable"); cc::Region region = scrolling_contents_layer->touch_action_region().GetRegionForTouchAction( TouchAction::kPanY | TouchAction::kInternalNotWritable); - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - EXPECT_EQ(scrolling_contents_layer->bounds(), gfx::Size(100, 150)); - EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 100, 150)); - } else { - // When HitTestOpaqueness is not enabled, the scrolling contents layer - // contains only the drawable contents due to the lack of the hit test - // data for the whole scrolling contents. - EXPECT_EQ(scrolling_contents_layer->bounds(), gfx::Size(50, 150)); - EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 50, 150)); - } + EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 50, 150)); - const auto* container_layer = LayerByDOMElementId("scrollable"); + const auto* container_layer = MainFrameScrollingContentsLayer(); region = container_layer->touch_action_region().GetRegionForTouchAction( TouchAction::kPanY | TouchAction::kInternalNotWritable); - EXPECT_EQ(region.bounds(), gfx::Rect()); - // TODO(crbug.com/324285520): Do we need touch action data in a ScrollHitTest - // layer? - EXPECT_EQ(container_layer->bounds(), gfx::Size(100, 100)); - - // The area of the scroller (8,8 100x100) in the main frame scrolling - // contents layer is also marked as pan-y. - const auto* main_frame_scrolling_layer = MainFrameScrollingContentsLayer(); - region = - main_frame_scrolling_layer->touch_action_region().GetRegionForTouchAction( - TouchAction::kPanY | TouchAction::kInternalNotWritable); EXPECT_EQ(region.bounds(), gfx::Rect(8, 8, 100, 100)); }
diff --git a/third_party/blink/renderer/core/paint/block_painter_test.cc b/third_party/blink/renderer/core/paint/block_painter_test.cc index 6446c06d..c38e47ab 100644 --- a/third_party/blink/renderer/core/paint/block_painter_test.cc +++ b/third_party/blink/renderer/core/paint/block_painter_test.cc
@@ -659,10 +659,7 @@ scroller->FirstFragment().PaintProperties()->ScrollTranslation(); scroll_hit_test_data.scroll_hit_test_rect = gfx::Rect(0, 0, 100, 100); HitTestData scrolled_hit_test_data; - scrolled_hit_test_data.touch_action_rects = { - {RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? gfx::Rect(0, 0, 200, 100) - : gfx::Rect(0, 0, 200, 50)}}; + scrolled_hit_test_data.touch_action_rects = {{gfx::Rect(0, 0, 200, 50)}}; const auto& paint_chunks = ContentPaintChunks(); EXPECT_THAT( @@ -677,17 +674,11 @@ 1, 1, PaintChunk::Id(scroller->Id(), DisplayItem::kScrollHitTest), scroller->FirstFragment().LocalBorderBoxProperties(), &scroll_hit_test_data, gfx::Rect(0, 0, 100, 100)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(scroller->Id(), - RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? kScrollingBackgroundChunkType - : kClippedContentsBackgroundChunkType), - scroller->FirstFragment().ContentsProperties(), - &scrolled_hit_test_data, - RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? gfx::Rect(0, 0, 200, 100) - : gfx::Rect(0, 0, 200, 50)))); + IsPaintChunk(1, 1, + PaintChunk::Id(scroller->Id(), + kClippedContentsBackgroundChunkType), + scroller->FirstFragment().ContentsProperties(), + &scrolled_hit_test_data, gfx::Rect(0, 0, 200, 50)))); const auto& scroller_paint_chunk = paint_chunks[1]; // The hit test rect for the scroller itself should not be scrolled.
diff --git a/third_party/blink/renderer/core/paint/box_fragment_painter.cc b/third_party/blink/renderer/core/paint/box_fragment_painter.cc index 9ac3710..3b05112 100644 --- a/third_party/blink/renderer/core/paint/box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/box_fragment_painter.cc
@@ -476,21 +476,14 @@ // We need to call PaintObject twice: one for painting background in the // border box space, and the other for painting background in the scrolling // contents space. - const LayoutBox& box = To<LayoutBox>(*box_fragment_.GetLayoutObject()); - auto paint_location = box.GetBackgroundPaintLocation(); + auto paint_location = To<LayoutBox>(*box_fragment_.GetLayoutObject()) + .GetBackgroundPaintLocation(); if (!(paint_location & kBackgroundPaintInBorderBoxSpace)) info.SetSkipsBackground(true); PaintObject(info, paint_offset); info.SetSkipsBackground(false); - if ((RuntimeEnabledFeatures::HitTestOpaquenessEnabled() && - // We need to record hit test data for the scrolling contents. - box.ScrollsOverflow()) || - (paint_location & kBackgroundPaintInContentsSpace)) { - if (!(paint_location & kBackgroundPaintInContentsSpace)) { - DCHECK(RuntimeEnabledFeatures::HitTestOpaquenessEnabled()); - info.SetSkipsBackground(true); - } + if (paint_location & kBackgroundPaintInContentsSpace) { // If possible, paint overflow controls before scrolling background to // make it easier to merge scrolling background and scrolling contents // into the same layer. The function checks if it's appropriate to paint @@ -500,9 +493,7 @@ info.SetIsPaintingBackgroundInContentsSpace(true); PaintObject(info, paint_offset); info.SetIsPaintingBackgroundInContentsSpace(false); - info.SetSkipsBackground(false); } - if (ShouldPaintDescendantBlockBackgrounds(original_phase)) info.phase = PaintPhase::kDescendantBlockBackgroundsOnly; } @@ -1072,12 +1063,7 @@ } Element* element = DynamicTo<Element>(layout_object.GetNode()); - if (element && element->GetRegionCaptureCropId() && - // TODO(wangxianzhu): This is to avoid the side-effect of - // HitTestOpaqueness on region capture data. Verify if the side-effect - // really matters. - !(paint_info.IsPaintingBackgroundInContentsSpace() && - paint_info.ShouldSkipBackground())) { + if (element && element->GetRegionCaptureCropId()) { paint_info.context.GetPaintController().RecordRegionCaptureData( *background_client, *(element->GetRegionCaptureCropId()), ToPixelSnappedRect(paint_rect));
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc index af8f8c6..7180477 100644 --- a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -389,13 +389,6 @@ .SetShouldDoFullPaintInvalidationWithoutLayoutChange( PaintInvalidationReason::kBackground); } - - if (background_invalidation_type == BackgroundInvalidationType::kNone && - box_.ScrollsOverflow() && - box_.PreviousScrollableOverflowRect() != box_.ScrollableOverflowRect()) { - // We need to re-record the hit test data for scrolling contents. - context_.painting_layer->SetNeedsRepaint(); - } } void BoxPaintInvalidator::InvalidatePaint() {
diff --git a/third_party/blink/renderer/core/paint/box_painter_test.cc b/third_party/blink/renderer/core/paint/box_painter_test.cc index a18170f..981599b 100644 --- a/third_party/blink/renderer/core/paint/box_painter_test.cc +++ b/third_party/blink/renderer/core/paint/box_painter_test.cc
@@ -214,13 +214,10 @@ 2, 2, PaintChunk::Id(container.Id(), DisplayItem::kScrollHitTest), container.FirstFragment().LocalBorderBoxProperties(), &scroll_hit_test_data, gfx::Rect(0, 0, 200, 200)), - IsPaintChunk( - 2, 3, - PaintChunk::Id(container.Id(), - RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? kScrollingBackgroundChunkType - : kClippedContentsBackgroundChunkType), - scrolling_contents_properties))); + IsPaintChunk(2, 3, + PaintChunk::Id(container.Id(), + kClippedContentsBackgroundChunkType), + scrolling_contents_properties))); // We always create scroll node for the root layer. const auto& root_transform =
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc index b952085..948f22a 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -834,15 +834,13 @@ return layers.empty() ? nullptr : layers[0]; } - const cc::Layer* CcLayerByOwnerNode(Node* node) { - return CcLayerByOwnerNodeId(RootCcLayer(), node->GetDomNodeId()); - } - - const cc::Layer* CcLayerForIFrameContent(Document* iframe_doc) { - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - return CcLayerByOwnerNode(iframe_doc); + const cc::Layer* CcLayerByOwnerNodeId(Node* node) { + DOMNodeId id = node->GetDomNodeId(); + for (auto& layer : RootCcLayer()->children()) { + if (layer->debug_info() && layer->debug_info()->owner_node_id == id) + return layer.get(); } - return CcLayerByOwnerNode(iframe_doc->documentElement()); + return nullptr; } Element* GetElementById(const char* id) { @@ -1968,7 +1966,8 @@ Compositor().BeginFrame(); Document* iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("iframe"))->contentDocument(); - auto* layer = CcLayerForIFrameContent(iframe_doc); + Node* owner_node = iframe_doc->documentElement(); + auto* layer = CcLayerByOwnerNodeId(owner_node); EXPECT_TRUE(layer); EXPECT_EQ(layer->bounds(), gfx::Size(300, 150)); } @@ -1990,7 +1989,8 @@ Document* iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("iframe"))->contentDocument(); - EXPECT_TRUE(CcLayerForIFrameContent(iframe_doc)); + Node* owner_node = iframe_doc->documentElement(); + EXPECT_TRUE(CcLayerByOwnerNodeId(owner_node)); } // An iframe that is cross-origin to the parent should be composited. This test @@ -2016,12 +2016,13 @@ Document* iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("main_iframe")) ->contentDocument(); - EXPECT_TRUE(CcLayerByOwnerNode(iframe_doc)); + EXPECT_TRUE(CcLayerByOwnerNodeId(iframe_doc)); iframe_doc = To<HTMLFrameOwnerElement>( iframe_doc->getElementById(AtomicString("child_iframe"))) ->contentDocument(); - EXPECT_TRUE(CcLayerForIFrameContent(iframe_doc)); + Node* owner_node = iframe_doc->documentElement(); + EXPECT_TRUE(CcLayerByOwnerNodeId(owner_node)); } // Initially the iframe is cross-origin and should be composited. After changing @@ -2043,7 +2044,8 @@ Document* iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("iframe"))->contentDocument(); - EXPECT_TRUE(CcLayerForIFrameContent(iframe_doc)); + Node* owner_node = iframe_doc->documentElement(); + EXPECT_TRUE(CcLayerByOwnerNodeId(owner_node)); NonThrowableExceptionState exception_state; GetDocument().setDomain(String("origin-a.com"), exception_state); @@ -2055,7 +2057,8 @@ iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("iframe"))->contentDocument(); - EXPECT_FALSE(CcLayerForIFrameContent(iframe_doc)); + owner_node = iframe_doc->documentElement(); + EXPECT_FALSE(CcLayerByOwnerNodeId(owner_node)); } // This test sets up nested frames with domains A -> B -> A. Initially, the @@ -2082,12 +2085,13 @@ Document* iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("main_iframe")) ->contentDocument(); - EXPECT_TRUE(CcLayerByOwnerNode(iframe_doc)); + EXPECT_TRUE(CcLayerByOwnerNodeId(iframe_doc)); iframe_doc = To<HTMLFrameOwnerElement>( iframe_doc->getElementById(AtomicString("child_iframe"))) ->contentDocument(); - EXPECT_TRUE(CcLayerForIFrameContent(iframe_doc)); + Node* owner_node = iframe_doc->documentElement(); + EXPECT_TRUE(CcLayerByOwnerNodeId(owner_node)); auto* main_iframe_element = To<HTMLIFrameElement>( GetDocument().getElementById(AtomicString("main_iframe"))); @@ -2107,12 +2111,13 @@ UpdateAllLifecyclePhases(); iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("main_iframe")) ->contentDocument(); - EXPECT_FALSE(CcLayerByOwnerNode(iframe_doc)); + EXPECT_FALSE(CcLayerByOwnerNodeId(iframe_doc)); iframe_doc = To<HTMLFrameOwnerElement>( iframe_doc->getElementById(AtomicString("child_iframe"))) ->contentDocument(); - EXPECT_FALSE(CcLayerForIFrameContent(iframe_doc)); + owner_node = iframe_doc->documentElement(); + EXPECT_FALSE(CcLayerByOwnerNodeId(owner_node)); } // Regression test for https://crbug.com/1095167. Render surfaces require that @@ -2341,7 +2346,8 @@ // containing document. Document* iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("iframe"))->contentDocument(); - auto* iframe_layer = CcLayerForIFrameContent(iframe_doc); + Node* owner_node = iframe_doc->documentElement(); + auto* iframe_layer = CcLayerByOwnerNodeId(owner_node); ASSERT_TRUE(iframe_layer); auto* iframe_transform_node = GetTransformNode(iframe_layer); EXPECT_TRUE(iframe_transform_node); @@ -2365,7 +2371,7 @@ Compositor().BeginFrame(); // Ensure that the toplevel is marked as a visible root. - auto* toplevel_layer = CcLayerByOwnerNode(&GetDocument()); + auto* toplevel_layer = CcLayerByOwnerNodeId(&GetDocument()); ASSERT_TRUE(toplevel_layer); auto* toplevel_transform_node = GetTransformNode(toplevel_layer); ASSERT_TRUE(toplevel_transform_node); @@ -2375,7 +2381,8 @@ // Ensure that the iframe is marked as a visible root. Document* iframe_doc = To<HTMLFrameOwnerElement>(GetElementById("iframe"))->contentDocument(); - auto* iframe_layer = CcLayerForIFrameContent(iframe_doc); + Node* owner_node = iframe_doc->documentElement(); + auto* iframe_layer = CcLayerByOwnerNodeId(owner_node); ASSERT_TRUE(iframe_layer); auto* iframe_transform_node = GetTransformNode(iframe_layer); ASSERT_TRUE(iframe_transform_node); @@ -2389,7 +2396,7 @@ UpdateAllLifecyclePhases(); - iframe_layer = CcLayerForIFrameContent(iframe_doc); + iframe_layer = CcLayerByOwnerNodeId(owner_node); ASSERT_TRUE(iframe_layer); iframe_transform_node = GetTransformNode(iframe_layer); ASSERT_TRUE(iframe_transform_node);
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc index 337aca22..a6e1c7ce 100644 --- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc +++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
@@ -230,13 +230,10 @@ 1, 1, PaintChunk::Id(container.Id(), DisplayItem::kScrollHitTest), container.FirstFragment().LocalBorderBoxProperties(), &container_scroll_hit_test, gfx::Rect(0, 0, 200, 200)), - IsPaintChunk( - 1, 3, - PaintChunk::Id(container.Id(), - RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? kScrollingBackgroundChunkType - : kClippedContentsBackgroundChunkType), - container.FirstFragment().ContentsProperties()))); + IsPaintChunk(1, 3, + PaintChunk::Id(container.Id(), + kClippedContentsBackgroundChunkType), + container.FirstFragment().ContentsProperties()))); container.GetScrollableArea()->SetScrollOffset( ScrollOffset(4000, 4000), mojom::blink::ScrollType::kProgrammatic); @@ -261,13 +258,10 @@ 1, 1, PaintChunk::Id(container.Id(), DisplayItem::kScrollHitTest), container.FirstFragment().LocalBorderBoxProperties(), &container_scroll_hit_test, gfx::Rect(0, 0, 200, 200)), - IsPaintChunk( - 1, 3, - PaintChunk::Id(container.Id(), - RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? kScrollingBackgroundChunkType - : kClippedContentsBackgroundChunkType), - container.FirstFragment().ContentsProperties()))); + IsPaintChunk(1, 3, + PaintChunk::Id(container.Id(), + kClippedContentsBackgroundChunkType), + container.FirstFragment().ContentsProperties()))); } TEST_P(PaintControllerPaintTest, ScrollHitTestOrder) { @@ -548,13 +542,10 @@ 2, 2, PaintChunk::Id(container.Id(), DisplayItem::kScrollHitTest), container.FirstFragment().LocalBorderBoxProperties(), &container_scroll_hit_test, gfx::Rect(0, 0, 200, 200)), - IsPaintChunk( - 2, 3, - PaintChunk::Id(container.Id(), - RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? kScrollingBackgroundChunkType - : kClippedContentsBackgroundChunkType), - container.FirstFragment().ContentsProperties()), + IsPaintChunk(2, 3, + PaintChunk::Id(container.Id(), + kClippedContentsBackgroundChunkType), + container.FirstFragment().ContentsProperties()), IsPaintChunk( 3, 4, PaintChunk::Id(pos_z_child.Layer()->Id(),
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc index 88f2d97..f338c557 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -170,17 +170,10 @@ auto* filler_layer = To<LayoutBoxModelObject>(filler)->Layer(); auto chunks = ContentPaintChunks(); - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 6); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 4, 2); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 5, 1); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 6, 1); - } else { - EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1); - } + EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5); + EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2); + EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1); + EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1); auto container_properties = container->FirstFragment().LocalBorderBoxProperties(); @@ -190,65 +183,31 @@ container->FirstFragment().PaintProperties()->ScrollTranslation(); scroll_hit_test.scroll_hit_test_rect = gfx::Rect(0, 0, 150, 150); - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - EXPECT_THAT( - chunks, - ElementsAre( - VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON, - IsPaintChunk( - 1, 1, - PaintChunk::Id(container_layer->Id(), DisplayItem::kLayerChunk), - container_properties, nullptr, gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(container->Id(), DisplayItem::kScrollHitTest), - container_properties, &scroll_hit_test, - gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(container->Id(), kScrollingBackgroundChunkType), - content_properties, nullptr, gfx::Rect(0, 0, 300, 400)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(content_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 0, 200, 100)), - IsPaintChunk(1, 1, - PaintChunk::Id(inner_content_layer->Id(), - DisplayItem::kLayerChunk), - content_properties, nullptr, - gfx::Rect(0, 0, 100, 100)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(filler_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 100, 300, 300)))); - } else { - EXPECT_THAT( - chunks, - ElementsAre( - VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON, - IsPaintChunk( - 1, 1, - PaintChunk::Id(container_layer->Id(), DisplayItem::kLayerChunk), - container_properties, nullptr, gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(container->Id(), DisplayItem::kScrollHitTest), - container_properties, &scroll_hit_test, - gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(content_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 0, 200, 100)), - IsPaintChunk(1, 1, - PaintChunk::Id(inner_content_layer->Id(), - DisplayItem::kLayerChunk), - content_properties, nullptr, - gfx::Rect(0, 0, 100, 100)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(filler_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 100, 300, 300)))); - } + EXPECT_THAT( + chunks, + ElementsAre( + VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON, + IsPaintChunk( + 1, 1, + PaintChunk::Id(container_layer->Id(), DisplayItem::kLayerChunk), + container_properties, nullptr, gfx::Rect(0, 0, 150, 150)), + IsPaintChunk( + 1, 1, + PaintChunk::Id(container->Id(), DisplayItem::kScrollHitTest), + container_properties, &scroll_hit_test, + gfx::Rect(0, 0, 150, 150)), + IsPaintChunk( + 1, 1, + PaintChunk::Id(content_layer->Id(), DisplayItem::kLayerChunk), + content_properties, nullptr, gfx::Rect(0, 0, 200, 100)), + IsPaintChunk(1, 1, + PaintChunk::Id(inner_content_layer->Id(), + DisplayItem::kLayerChunk), + content_properties, nullptr, gfx::Rect(0, 0, 100, 100)), + IsPaintChunk( + 1, 1, + PaintChunk::Id(filler_layer->Id(), DisplayItem::kLayerChunk), + content_properties, nullptr, gfx::Rect(0, 100, 300, 300)))); To<HTMLElement>(inner_content->GetNode()) ->setAttribute( @@ -269,75 +228,37 @@ kBackgroundType))); chunks = ContentPaintChunks(); - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 6); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 4, 2); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 5, 1); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 6, 1); + EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5); + EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2); + EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1); + EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1); - EXPECT_THAT( - ContentPaintChunks(), - ElementsAre( - VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON, - IsPaintChunk( - 1, 1, - PaintChunk::Id(container_layer->Id(), DisplayItem::kLayerChunk), - container_properties, nullptr, gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(container->Id(), DisplayItem::kScrollHitTest), - container_properties, &scroll_hit_test, - gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(container->Id(), kScrollingBackgroundChunkType), - content_properties, nullptr, gfx::Rect(0, 0, 300, 400)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(content_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 0, 200, 100)), - IsPaintChunk(1, 2, - PaintChunk::Id(inner_content_layer->Id(), - DisplayItem::kLayerChunk), - content_properties, nullptr, - gfx::Rect(0, 100, 100, 100)), - IsPaintChunk( - 2, 2, - PaintChunk::Id(filler_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 100, 300, 300)))); - } else { - EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1); - EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1); - - EXPECT_THAT( - ContentPaintChunks(), - ElementsAre( - VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON, - IsPaintChunk( - 1, 1, - PaintChunk::Id(container_layer->Id(), DisplayItem::kLayerChunk), - container_properties, nullptr, gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(container->Id(), DisplayItem::kScrollHitTest), - container_properties, &scroll_hit_test, - gfx::Rect(0, 0, 150, 150)), - IsPaintChunk( - 1, 1, - PaintChunk::Id(content_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 0, 200, 100)), - IsPaintChunk(1, 2, - PaintChunk::Id(inner_content_layer->Id(), - DisplayItem::kLayerChunk), - content_properties, nullptr, - gfx::Rect(0, 100, 100, 100)), - IsPaintChunk( - 2, 2, - PaintChunk::Id(filler_layer->Id(), DisplayItem::kLayerChunk), - content_properties, nullptr, gfx::Rect(0, 100, 300, 300)))); - } + EXPECT_THAT( + ContentPaintChunks(), + ElementsAre( + VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON, + IsPaintChunk( + 1, 1, + PaintChunk::Id(container_layer->Id(), DisplayItem::kLayerChunk), + container_properties, nullptr, gfx::Rect(0, 0, 150, 150)), + IsPaintChunk( + 1, 1, + PaintChunk::Id(container->Id(), DisplayItem::kScrollHitTest), + container_properties, &scroll_hit_test, + gfx::Rect(0, 0, 150, 150)), + IsPaintChunk( + 1, 1, + PaintChunk::Id(content_layer->Id(), DisplayItem::kLayerChunk), + content_properties, nullptr, gfx::Rect(0, 0, 200, 100)), + IsPaintChunk(1, 2, + PaintChunk::Id(inner_content_layer->Id(), + DisplayItem::kLayerChunk), + content_properties, nullptr, + gfx::Rect(0, 100, 100, 100)), + IsPaintChunk( + 2, 2, + PaintChunk::Id(filler_layer->Id(), DisplayItem::kLayerChunk), + content_properties, nullptr, gfx::Rect(0, 100, 300, 300)))); } TEST_P(PaintLayerPainterTest, CachedSubsequenceOnCullRectChange) {
diff --git a/third_party/blink/renderer/core/paint/view_painter.cc b/third_party/blink/renderer/core/paint/view_painter.cc index c0a6d218..3736dac 100644 --- a/third_party/blink/renderer/core/paint/view_painter.cc +++ b/third_party/blink/renderer/core/paint/view_painter.cc
@@ -74,21 +74,13 @@ if (layout_view_.StyleRef().Visibility() != EVisibility::kVisible) return; + bool has_hit_test_data = + ObjectPainter(layout_view_).ShouldRecordSpecialHitTestData(paint_info); bool painting_background_in_contents_space = paint_info.IsPaintingBackgroundInContentsSpace(); - bool paints_hit_test_data = - (RuntimeEnabledFeatures::HitTestOpaquenessEnabled() && - painting_background_in_contents_space) || - ObjectPainter(layout_view_).ShouldRecordSpecialHitTestData(paint_info); Element* element = DynamicTo<Element>(layout_view_.GetNode()); - bool paints_region_capture_data = - element && element->GetRegionCaptureCropId() && - // TODO(wangxianzhu): This is to avoid the side-effect of - // HitTestOpaqueness on region capture data. Verify if the side-effect - // really matters. - !(painting_background_in_contents_space && - paint_info.ShouldSkipBackground()); + bool has_region_capture_data = element && element->GetRegionCaptureCropId(); bool paints_scroll_hit_test = !painting_background_in_contents_space && layout_view_.FirstFragment().PaintProperties()->Scroll(); @@ -99,8 +91,8 @@ } return false; }(); - if (!layout_view_.HasBoxDecorationBackground() && !paints_hit_test_data && - !paints_scroll_hit_test && !paints_region_capture_data && + if (!layout_view_.HasBoxDecorationBackground() && !has_hit_test_data && + !paints_scroll_hit_test && !has_region_capture_data && !is_represented_via_pseudo_elements) { return; } @@ -202,13 +194,13 @@ *background_client, painted_separate_backdrop, painted_separate_effect); } - if (paints_hit_test_data) { + if (has_hit_test_data) { ObjectPainter(layout_view_) .RecordHitTestData(paint_info, pixel_snapped_background_rect, *background_client); } - if (paints_region_capture_data) { + if (has_region_capture_data) { BoxPainter(layout_view_) .RecordRegionCaptureData(paint_info, PhysicalRect(pixel_snapped_background_rect),
diff --git a/third_party/blink/renderer/core/paint/view_painter_test.cc b/third_party/blink/renderer/core/paint/view_painter_test.cc index 8d0360ad..23557ed 100644 --- a/third_party/blink/renderer/core/paint/view_painter_test.cc +++ b/third_party/blink/renderer/core/paint/view_painter_test.cc
@@ -231,13 +231,7 @@ EXPECT_THAT( ContentPaintChunks(), ElementsAre(IsPaintChunk( - 1, 1, - RuntimeEnabledFeatures::HitTestOpaquenessEnabled() - ? PaintChunk::Id(view->GetScrollableArea() - ->GetScrollingBackgroundDisplayItemClient() - .Id(), - DisplayItem::kDocumentBackground) - : PaintChunk::Id(html->Layer()->Id(), DisplayItem::kLayerChunk), + 1, 1, PaintChunk::Id(html->Layer()->Id(), DisplayItem::kLayerChunk), scrolling_properties, &scrolling_hit_test_data, gfx::Rect(0, 0, 800, 3000)))); }
diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc b/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc index c4a96d6..8e77dba 100644 --- a/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc +++ b/third_party/blink/renderer/core/scheduler_integration_tests/frame_throttling_test.cc
@@ -554,16 +554,11 @@ auto* frame_element = To<HTMLIFrameElement>( GetDocument().getElementById(AtomicString("frame"))); - auto* frame_doc = frame_element->contentDocument(); - auto* frame_view = frame_doc->View(); + auto* frame_view = frame_element->contentDocument()->View(); EXPECT_FALSE(frame_view->CanThrottleRendering()); auto* root_layer = WebView().MainFrameImpl()->GetFrameView()->RootCcLayer(); EXPECT_EQ(0u, CcLayersByDOMElementId(root_layer, "container").size()); - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - EXPECT_TRUE(CcLayerByOwnerNodeId(root_layer, frame_doc->GetDomNodeId())); - } else { - EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "inner_frame").size()); - } + EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "inner_frame").size()); // First make the child hidden to enable throttling, and composite // the container. @@ -575,11 +570,7 @@ CompositeFrame(); EXPECT_TRUE(frame_view->CanThrottleRendering()); EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "container").size()); - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - EXPECT_TRUE(CcLayerByOwnerNodeId(root_layer, frame_doc->GetDomNodeId())); - } else { - EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "inner_frame").size()); - } + EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "inner_frame").size()); // Then bring it back on-screen, and decomposite container. container_element->setAttribute(kStyleAttr, g_empty_atom); @@ -588,11 +579,7 @@ CompositeFrame(); EXPECT_FALSE(frame_view->CanThrottleRendering()); EXPECT_EQ(0u, CcLayersByDOMElementId(root_layer, "container").size()); - if (RuntimeEnabledFeatures::HitTestOpaquenessEnabled()) { - EXPECT_TRUE(CcLayerByOwnerNodeId(root_layer, frame_doc->GetDomNodeId())); - } else { - EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "inner_frame").size()); - } + EXPECT_EQ(1u, CcLayersByDOMElementId(root_layer, "inner_frame").size()); } TEST_P(FrameThrottlingTest, MutatingThrottledFrameDoesNotCauseAnimation) {
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 2c9bb5dc..033dd0e8 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.cc +++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h" #include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h" @@ -275,8 +276,7 @@ static const bool exclude_lcp_influencers = features::kLowPriorityAsyncScriptExecutionExcludeLcpInfluencersParam .Get(); - if (exclude_lcp_influencers && - base::FeatureList::IsEnabled(features::kLCPScriptObserver)) { + if (exclude_lcp_influencers && LcppScriptObserverEnabled()) { if (LCPCriticalPathPredictor* lcpp = top_document.GetFrame()->GetLCPP()) { if (lcpp->IsLcpInfluencerScript(GetResource()->Url())) { return false;
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.cc b/third_party/blink/renderer/core/scroll/scrollable_area.cc index e4ce59e..a6de1b6906 100644 --- a/third_party/blink/renderer/core/scroll/scrollable_area.cc +++ b/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -42,6 +42,7 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/animation/scroll_timeline.h" #include "third_party/blink/renderer/core/css/properties/longhands.h" +#include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" @@ -711,6 +712,9 @@ if (offset_changed && GetLayoutBox() && GetLayoutBox()->GetFrameView()) { GetLayoutBox()->GetFrameView()->GetLayoutShiftTracker().NotifyScroll( scroll_type, delta); + // FrameSelection caches visual selection information which needs to be + // invalidated after scrolling. + GetLayoutBox()->GetFrameView()->GetFrame().Selection().MarkCacheDirty(); } GetScrollAnimator().SetCurrentOffset(offset);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 652f980..a9cc7db 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -46,6 +46,7 @@ #include "services/network/public/cpp/request_mode.h" #include "services/network/public/mojom/url_loader_factory.mojom-blink.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/loader/lcp_critical_path_predictor_util.h" #include "third_party/blink/public/common/mime_util/mime_util.h" #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h" #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h" @@ -517,26 +518,49 @@ } // LCP Critical Path Predictor identified resources get a priority boost. - if ((is_potentially_lcp_element || is_potentially_lcp_influencer) && - !features::kLCPCriticalPathPredictorDryRun.Get()) { + if (LcppEnabled()) { + bool should_modify_request_priority = false; features::LcppResourceLoadPriority preferred_priority = - is_potentially_lcp_element - ? features::kLCPCriticalPathPredictorImageLoadPriority.Get() - : features::kLCPCriticalPathPredictorInfluencerScriptLoadPriority - .Get(); + features::LcppResourceLoadPriority::kMedium; - ++potentially_lcp_resource_priority_boosts_; + if (is_potentially_lcp_element) { + // Adjust priority of LCP image request. + if (base::FeatureList::IsEnabled(features::kLCPCriticalPathPredictor) && + !features::kLCPCriticalPathPredictorDryRun.Get()) { + should_modify_request_priority = true; + preferred_priority = + features::kLCPCriticalPathPredictorImageLoadPriority.Get(); + } - switch (preferred_priority) { - case features::LcppResourceLoadPriority::kMedium: - priority = std::max(priority, ResourceLoadPriority::kMedium); - break; - case features::LcppResourceLoadPriority::kHigh: - priority = std::max(priority, ResourceLoadPriority::kHigh); - break; - case features::LcppResourceLoadPriority::kVeryHigh: - priority = std::max(priority, ResourceLoadPriority::kVeryHigh); - break; + if (base::FeatureList::IsEnabled(features::kLCPScriptObserver) && + features::kLCPScriptObserverAdjustImageLoadPriority.Get()) { + should_modify_request_priority = true; + preferred_priority = + features::kLCPScriptObserverImageLoadPriority.Get(); + } + } + + if (is_potentially_lcp_influencer && + base::FeatureList::IsEnabled(features::kLCPScriptObserver)) { + // Adjust priority of LCP influencing script request. + should_modify_request_priority = true; + preferred_priority = features::kLCPScriptObserverScriptLoadPriority.Get(); + } + + if (should_modify_request_priority) { + ++potentially_lcp_resource_priority_boosts_; + + switch (preferred_priority) { + case features::LcppResourceLoadPriority::kMedium: + priority = std::max(priority, ResourceLoadPriority::kMedium); + break; + case features::LcppResourceLoadPriority::kHigh: + priority = std::max(priority, ResourceLoadPriority::kHigh); + break; + case features::LcppResourceLoadPriority::kVeryHigh: + priority = std::max(priority, ResourceLoadPriority::kVeryHigh); + break; + } } }
diff --git a/third_party/blink/renderer/platform/testing/find_cc_layer.cc b/third_party/blink/renderer/platform/testing/find_cc_layer.cc index 93bf473d..e7bcd5e5 100644 --- a/third_party/blink/renderer/platform/testing/find_cc_layer.cc +++ b/third_party/blink/renderer/platform/testing/find_cc_layer.cc
@@ -63,19 +63,6 @@ return CcLayerByCcElementId(const_cast<cc::Layer*>(root), element_id); } -cc::Layer* CcLayerByOwnerNodeId(cc::Layer* root, DOMNodeId id) { - for (auto& layer : root->children()) { - if (layer->debug_info() && layer->debug_info()->owner_node_id == id) { - return layer.get(); - } - } - return nullptr; -} - -const cc::Layer* CcLayerByOwnerNodeId(const cc::Layer* root, DOMNodeId id) { - return CcLayerByOwnerNodeId(const_cast<cc::Layer*>(root), id); -} - cc::Layer* ScrollingContentsCcLayerByScrollElementId( cc::Layer* root, const CompositorElementId& scroll_element_id) {
diff --git a/third_party/blink/renderer/platform/testing/find_cc_layer.h b/third_party/blink/renderer/platform/testing/find_cc_layer.h index fbcad9e..c64dff3 100644 --- a/third_party/blink/renderer/platform/testing/find_cc_layer.h +++ b/third_party/blink/renderer/platform/testing/find_cc_layer.h
@@ -36,10 +36,6 @@ const cc::Layer* CcLayerByCcElementId(const cc::Layer* root, const CompositorElementId&); -cc::Layer* CcLayerByOwnerNodeId(cc::Layer* root, DOMNodeId); - -const cc::Layer* CcLayerByOwnerNodeId(const cc::Layer* root, DOMNodeId); - cc::Layer* ScrollingContentsCcLayerByScrollElementId( cc::Layer* root, const CompositorElementId& scroll_element_id);
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite b/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite index 2f68756..6ad2491 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite +++ b/third_party/blink/web_tests/FlagExpectations/enable-skia-graphite
@@ -36,6 +36,7 @@ crbug.com/1518086 external/wpt/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 virtual/view-transition/external/wpt/css/css-view-transitions/pseudo-with-classes-new-with-class-old-without.html [ Failure ] crbug.com/626703 virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-group.html [ Failure ] crbug.com/626703 virtual/view-transition/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-group.html [ Failure ] crbug.com/626703 virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index a6b38ec..e1013a6 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2573,6 +2573,11 @@ crbug.com/626703 external/wpt/css/printing/table-overflow-quirks-frameset-crash-print.html [ Crash Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Win11-arm64 ] external/wpt/html/cross-origin-embedder-policy/credentialless/fetch.https.window.html [ Timeout ] +crbug.com/626703 external/wpt/webrtc/RTCRtpReceiver-getStats.https.html [ Skip Timeout ] +crbug.com/626703 external/wpt/webrtc/RTCRtpSender-getStats.https.html [ Skip Timeout ] +crbug.com/626703 [ Win11-arm64 ] external/wpt/webtransport/echo-large-bidirectional-streams.https.any.worker.html [ Timeout ] +crbug.com/626703 [ Win11-arm64 ] virtual/shared-storage-fenced-frame-mparch/external/wpt/shared-storage/shared-storage-writable-service-worker-fetch.tentative.https.sub.html [ Failure Timeout ] crbug.com/626703 [ Win11-arm64 ] virtual/keepalive-in-browser-migration/external/wpt/xhr/send-redirect-bogus-sync.htm [ Timeout ] crbug.com/626703 external/wpt/css/css-backgrounds/background-position-negative-percentage-comparison-002.html [ Failure ] crbug.com/626703 external/wpt/svg/text/reftests/first-letter.svg [ Failure ]
diff --git a/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.png b/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.png index 6e3e1aa..dd307e379 100644 --- a/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.png +++ b/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt b/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt index 3769f1e..69cd9119 100644 --- a/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt +++ b/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [785, 3700], "transform": 1 },
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt index f9bc3ed..9c55152 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt
@@ -27,7 +27,9 @@ }, { "name": "LayoutNGBlockFlow (positioned) DIV class='overflow fixed'", - "bounds": [785, 1000], + "bounds": [100, 1000], + "contentsOpaque": true, + "backgroundColor": "#0000FF", "transform": 1 }, {
diff --git a/third_party/blink/web_tests/compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective-expected.txt b/third_party/blink/web_tests/compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective-expected.txt index ad7e5442..7d9613b5 100644 --- a/third_party/blink/web_tests/compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective-expected.txt
@@ -32,12 +32,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [185, 290], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='child first'", "bounds": [60, 200], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt b/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt index 3ba755d2..4a640d15 100644 --- a/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
@@ -23,14 +23,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV id='scroller'", - "position": [1, 1], - "bounds": [100, 180], - "drawsContent": false, - "backfaceVisibility": "hidden", - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='fixed'", "position": [60, 60], "bounds": [80, 80],
diff --git a/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt b/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt index bd047c9..3c7daf3 100644 --- a/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt
@@ -23,8 +23,10 @@ "contentsOpaque": true }, { - "name": "LayoutNGBlockFlow DIV class='scroller'", - "bounds": [305, 1224], + "name": "LayoutNGBlockFlow (relative positioned) DIV class='column'", + "position": [10, 10], + "bounds": [284, 1204], + "contentsOpaque": true, "backgroundColor": "#C0C0C0" } ]
diff --git a/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt index ebba1fd..020b860 100644 --- a/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -14,6 +14,12 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'", + "position": [2, 6], + "bounds": [85, 136], + "transform": 2 + }, + { "name": "HorizontalScrollbar", "position": [10, 97], "bounds": [104, 257] @@ -26,12 +32,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'", - "position": [2, 2], - "bounds": [85, 144], - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned'", "position": [35, 10], "bounds": [199, 105] @@ -70,8 +70,8 @@ }, { "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute-grandchildren' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [105, 144], + "position": [2, 6], + "bounds": [105, 136], "transform": 4 }, { @@ -95,12 +95,6 @@ "transform": 5 }, { - "name": "LayoutNGBlockFlow DIV id='container-absolute-not-contained' class='overflow'", - "position": [2, 2], - "bounds": [85, 144], - "transform": 6 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-not-contained' class='positionAbsolute positioned'", "position": [275, 10], "bounds": [199, 105] @@ -119,6 +113,12 @@ "transform": 7 }, { + "name": "LayoutNGBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'", + "position": [2, 6], + "bounds": [85, 136], + "transform": 8 + }, + { "name": "HorizontalScrollbar", "position": [2, 87], "bounds": [100, 15], @@ -132,12 +132,6 @@ "transform": 7 }, { - "name": "LayoutNGBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'", - "position": [2, 2], - "bounds": [85, 144], - "transform": 8 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned'", "position": [395, 75], "bounds": [80, 40], @@ -180,8 +174,8 @@ }, { "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute-sibling-grandchildren' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [105, 144], + "position": [2, 6], + "bounds": [105, 136], "transform": 10 }, { @@ -204,22 +198,14 @@ "transform": 11 }, { - "name": "LayoutNGBlockFlow DIV id='container-absolute-sibling-not-contained' class='overflow'", - "position": [2, 2], - "bounds": [85, 144], - "transform": 12 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling-not-contained' class='positionAbsolute positioned'", "position": [155, 130], "bounds": [199, 105] }, { "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled'", - "position": [6, 90], - "bounds": [75, 24], - "contentsOpaque": true, - "backgroundColor": "#0000FF", + "position": [6, 34], + "bounds": [75, 80], "transform": 12 }, { @@ -249,9 +235,9 @@ "bounds": [137, 104] }, { - "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute-sibling' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [105, 144], + "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling' class='positionAbsolute positioned'", + "position": [6, 34], + "bounds": [101, 80], "transform": 14 }, { @@ -281,9 +267,9 @@ "bounds": [104, 137] }, { - "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [105, 144], + "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute' class='positionAbsolute positioned'", + "position": [6, 34], + "bounds": [101, 80], "transform": 16 }, { @@ -308,8 +294,8 @@ }, { "name": "LayoutNGBlockFlow (positioned) DIV id='container-fixed-sibling-grandchildren' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [85, 144], + "position": [2, 6], + "bounds": [85, 136], "transform": 18 }, { @@ -348,25 +334,17 @@ "transform": 20 }, { - "name": "LayoutNGBlockFlow (positioned) DIV id='container-fixed-sibling' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [85, 144], - "transform": 21 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-fixed-sibling' class='positionFixed positioned'", "bounds": [80, 40], "contentsOpaque": true, "backgroundColor": "#800080", - "transform": 22 + "transform": 21 }, { "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled'", - "position": [6, 90], - "bounds": [75, 24], - "contentsOpaque": true, - "backgroundColor": "#0000FF", - "transform": 21 + "position": [6, 34], + "bounds": [75, 80], + "transform": 22 }, { "name": "LayoutNGBlockFlow (positioned) DIV id='container-fixed-grandchildren' class='positionAbsolute overflow'", @@ -390,8 +368,8 @@ }, { "name": "LayoutNGBlockFlow (positioned) DIV id='container-fixed-grandchildren' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [85, 144], + "position": [2, 6], + "bounds": [85, 136], "transform": 24 }, { @@ -430,25 +408,17 @@ "transform": 26 }, { - "name": "LayoutNGBlockFlow (positioned) DIV id='container-fixed' class='positionAbsolute overflow'", - "position": [2, 2], - "bounds": [85, 144], - "transform": 27 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-fixed' class='positionFixed positioned'", "bounds": [80, 40], "contentsOpaque": true, "backgroundColor": "#800080", - "transform": 28 + "transform": 27 }, { "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled'", - "position": [6, 90], - "bounds": [75, 24], - "contentsOpaque": true, - "backgroundColor": "#0000FF", - "transform": 27 + "position": [6, 34], + "bounds": [75, 80], + "transform": 28 }, { "name": "LayoutNGBlockFlow (positioned) DIV id='sibling-absolute-sibling-grandchildren-not-contained' class='positionFixed sibling'", @@ -532,7 +502,7 @@ "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled onTop'", "position": [6, 6], "bounds": [75, 136], - "transform": 21 + "transform": 22 }, { "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled onTop'", @@ -544,7 +514,7 @@ "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled onTop'", "position": [6, 6], "bounds": [75, 136], - "transform": 27 + "transform": 28 }, { "name": "VerticalScrollbar", @@ -745,6 +715,15 @@ }, { "id": 21, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [155, 315, 0, 1] + ] + }, + { + "id": 22, "parent": 20, "transform": [ [1, 0, 0, 0], @@ -754,15 +733,6 @@ ] }, { - "id": 22, - "transform": [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [155, 315, 0, 1] - ] - }, - { "id": 23, "transform": [ [1, 0, 0, 0], @@ -801,6 +771,15 @@ }, { "id": 27, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [395, 315, 0, 1] + ] + }, + { + "id": 28, "parent": 26, "transform": [ [1, 0, 0, 0], @@ -810,15 +789,6 @@ ] }, { - "id": 28, - "transform": [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [395, 315, 0, 1] - ] - }, - { "id": 29, "transform": [ [1, 0, 0, 0],
diff --git a/third_party/blink/web_tests/compositing/scrollbars/composited-overlay-scrollbars-with-scrollbar-color-expected.txt b/third_party/blink/web_tests/compositing/scrollbars/composited-overlay-scrollbars-with-scrollbar-color-expected.txt index 3a82d86..1b0fb89 100644 --- a/third_party/blink/web_tests/compositing/scrollbars/composited-overlay-scrollbars-with-scrollbar-color-expected.txt +++ b/third_party/blink/web_tests/compositing/scrollbars/composited-overlay-scrollbars-with-scrollbar-color-expected.txt
@@ -15,11 +15,17 @@ { "name": "LayoutNGBlockFlow DIV id='outer'", "position": [1, 1], - "bounds": [400, 602], + "bounds": [400, 500], + "drawsContent": false, "transform": 1 }, { "name": "LayoutNGBlockFlow DIV id='inner'", + "bounds": [102, 102], + "transform": 2 + }, + { + "name": "LayoutNGBlockFlow DIV id='inner'", "position": [1, 1], "bounds": [100, 100], "drawsContent": false,
diff --git a/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.png b/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.png index fd384bd2..7500557 100644 --- a/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.png +++ b/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.txt b/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.txt index 1ee3546..a94e897 100644 --- a/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.txt +++ b/third_party/blink/web_tests/compositing/scrollbars/nested-overlay-scrollbars-expected.txt
@@ -14,10 +14,9 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV id='outer'", - "position": [2, 2], - "bounds": [400, 704], - "transform": 2 + "name": "LayoutNGBlockFlow (positioned) DIV id='inner'", + "bounds": [204, 204], + "transform": 3 }, { "name": "LayoutNGBlockFlow (positioned) DIV id='inner'", @@ -29,7 +28,14 @@ { "name": "LayoutNGBlockFlow (positioned) DIV id='inner'", "position": [2, 2], - "bounds": [5000, 9000], + "bounds": [2000, 9000], + "transform": 3 + }, + { + "name": "LayoutNGBlockFlow (positioned) DIV id='spacer'", + "position": [2, 2002], + "bounds": [5000, 1000], + "drawsContent": false, "transform": 3 }, {
diff --git a/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt b/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt index 07cab82..506d1dc0 100644 --- a/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt +++ b/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt
@@ -33,7 +33,7 @@ "transform": 2 }, { - "name": "LayoutNGBlockFlow DIV", + "name": "LayoutNGBlockFlow (relative positioned) DIV", "bounds": [285, 1000], "contentsOpaque": true, "backgroundColor": "#ADD8E6",
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 f10ea1d..b2d728f 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
@@ -161992,6 +161992,19 @@ {} ] ], + "multicol-fill-balance-029.html": [ + "837141bd0593716c5b5fb46ef3f68efb4aaf077e", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "multicol-fill-balance-nested-000.html": [ "5e466df8077545b4d6474389d296bc26c5b28b86", [ @@ -237917,6 +237930,19 @@ } ] ], + "class-specificity.html": [ + "55de2ec3884c174a4978be193fde2220fb0c5164", + [ + null, + [ + [ + "/css/css-view-transitions/class-specificity-ref.html", + "==" + ] + ], + {} + ] + ], "content-smaller-than-box-size.html": [ "d2b8f63ca068ffc744b7b1a7b0ca8d1c25a32854", [ @@ -291907,7 +291933,7 @@ } }, "DIR_METADATA": [ - "90ae077137c9b3993cb978aa35719ab986a16f3d", + "6cbcf6fcc7a6934be10ad0c19859f0bcdd5169ca", [] ], "FileReader": { @@ -292043,7 +292069,7 @@ }, "IndexedDB": { "DIR_METADATA": [ - "fd463f526deb09c01c207280281f0916e362cb3a", + "ba37f8208671e49f54067071896d46ad25ad8f85", [] ], "META.yml": [ @@ -292123,7 +292149,7 @@ ], "WebCryptoAPI": { "DIR_METADATA": [ - "d048f385de5c03d1e61db0bb0a67c3fc3e78e33a", + "9524f8ead3d8f9d2645e2a2cb12b0f2f89a0283a", [] ], "META.yml": [ @@ -292591,7 +292617,7 @@ [] ], "DIR_METADATA": [ - "caea56d67a654fb8b15e43a1b0eab7e413a88177", + "22cfa46b2f5ffb1fa3db78d07e69585ff3c48e8d", [] ], "META.yml": [ @@ -292751,7 +292777,7 @@ [] ], "DIR_METADATA": [ - "caea56d67a654fb8b15e43a1b0eab7e413a88177", + "22cfa46b2f5ffb1fa3db78d07e69585ff3c48e8d", [] ], "META.yml": [ @@ -293585,7 +293611,7 @@ }, "background-fetch": { "DIR_METADATA": [ - "7950c4dd3b7cfec535e3f6b50ad175bcf4306653", + "00b3667937a21dbbd3b54f06d23157ce72fa2e0a", [] ], "META.yml": [ @@ -293679,7 +293705,7 @@ }, "battery-status": { "DIR_METADATA": [ - "54f06e6c8d511931b441399b1e47092601b80cd9", + "fa5fe8a7b8a32af4f0a7fd263bff08955c6bd57d", [] ], "META.yml": [ @@ -294069,7 +294095,7 @@ }, "clear-site-data": { "DIR_METADATA": [ - "f070ceb51ea0821263c460d1372a090076cba928", + "da9cab8ad438c0b30ab8537a9da51f7345f7def6", [] ], "META.yml": [ @@ -294121,7 +294147,7 @@ }, "client-hints": { "DIR_METADATA": [ - "8fb918d73800b63618e1334894180edd5fe67fb1", + "b61d0e7dc0285e1ddb71faeb844f3fddf9807a0a", [] ], "META.yml": [ @@ -295441,7 +295467,7 @@ }, "compute-pressure": { "DIR_METADATA": [ - "866fe18e3429ef9da9ba99d79d4b542efeb7d147", + "84eada454f76c911fecb599c57547c9254615461", [] ], "OWNERS": [ @@ -295517,7 +295543,7 @@ }, "contacts": { "DIR_METADATA": [ - "00a602c2a0354a48c5cd803982b4f5a315828a90", + "4f90941a61a60c8950b228e6498713e9b6393f83", [] ], "META.yml": [ @@ -295597,7 +295623,7 @@ }, "content-security-policy": { "DIR_METADATA": [ - "3978889a17ef79b1fc3cd4439f8289b49cc6c9d2", + "afb7c1def9e72ff0434de9e7df2570c6fc961f0a", [] ], "META.yml": [ @@ -297709,7 +297735,7 @@ }, "cookie-store": { "DIR_METADATA": [ - "2d1e4e3e2f3bdb3cbc142d17a8ed3f5e08a34238", + "e3f78621264b6d32d7c8baeba34ba0e245d83458", [] ], "META.yml": [ @@ -297757,7 +297783,7 @@ }, "cookies": { "DIR_METADATA": [ - "5bfb93a27c7eff04e12c781490299d92b5d251bd", + "6816daf9256ea5a0ca0871a16d623ed31cae3391", [] ], "META.yml": [ @@ -298071,13 +298097,13 @@ }, "core-aam": { "DIR_METADATA": [ - "803582c48bb6a7ce275ce6dffaef5f172d12cfc6", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ] }, "cors": { "DIR_METADATA": [ - "6f7db9f1903cf820990d8c18a0bc673b6bbdad40", + "b8c8e48dccf37bca36a1fb7bee2ac662768f35a6", [] ], "META.yml": [ @@ -298448,7 +298474,7 @@ [] ], "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -305489,7 +305515,7 @@ } }, "DIR_METADATA": [ - "c41ee089b8e083540febdab0fb23c1c8bafbbfc5", + "38c4cd0efc94eb8941cf45405784304d216b6aab", [] ], "README.md": [ @@ -305506,7 +305532,7 @@ [] ], "DIR_METADATA": [ - "12a5b0640db68c21567548a4542814ae563e3230", + "9e975836343f290b261804bc4b15cbf616b018d7", [] ], "META.yml": [ @@ -305848,7 +305874,7 @@ }, "css-align": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -306052,7 +306078,7 @@ }, "css-anchor-position": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "WEB_FEATURES.yml": [ @@ -306071,10 +306097,6 @@ "6ac93ee7a49bb2d31902ed9afdc0f4f4bd432f09", [] ], - "anchor-position-auto-003-expected.txt": [ - "3c133b4e49254d3d91c06be88bf675b6827f7f4f", - [] - ], "anchor-position-multicol-003-expected.txt": [ "7f03f52a900220153e28834fdbb2cca9f2d99da5", [] @@ -306146,7 +306168,7 @@ [] ], "DIR_METADATA": [ - "849d9c0f45574344e9c71d57c57cdb030cd7205d", + "8ea8b499efa75b870181f1f6eadf3aa765603855", [] ], "Document-getAnimations.tentative-expected.txt": [ @@ -306290,7 +306312,7 @@ }, "css-backgrounds": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -308410,7 +308432,7 @@ }, "css-box": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -308638,7 +308660,7 @@ }, "css-break": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -310054,7 +310076,7 @@ }, "css-contain": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -310311,7 +310333,7 @@ ], "container-queries": { "DIR_METADATA": [ - "2fa113f5f777ecbc33fcb295316c42fd7dfa8f71", + "b7dc9730f956fd4eda032aeeef33e920110545ee", [] ], "WEB_FEATURES.yml": [ @@ -312388,7 +312410,7 @@ }, "css-display": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -312596,7 +312618,7 @@ }, "css-easing": { "DIR_METADATA": [ - "849d9c0f45574344e9c71d57c57cdb030cd7205d", + "8ea8b499efa75b870181f1f6eadf3aa765603855", [] ], "META.yml": [ @@ -312620,7 +312642,7 @@ }, "css-fill-stroke": { "DIR_METADATA": [ - "aeb9395befd7af9295ff79f2a97d85da49320d75", + "23b65fc8f89f5ba15ff74a1e87f5bb1faffe1352", [] ], "META.yml": [ @@ -312636,7 +312658,7 @@ }, "css-flexbox": { "DIR_METADATA": [ - "e51f58e0dd2d33f85b8907874dab7a2afbd5224c", + "660b8c13ffbf14e5460f4f0c1eff016a2e07a881", [] ], "META.yml": [ @@ -314840,7 +314862,7 @@ }, "css-font-loading": { "DIR_METADATA": [ - "79a21decd5a038b674382ce2c897a53fb471f13f", + "1abfaf02dc5ff5f1ae04d981c9595326078f54e5", [] ], "META.yml": [ @@ -314902,7 +314924,7 @@ }, "css-fonts": { "DIR_METADATA": [ - "79a21decd5a038b674382ce2c897a53fb471f13f", + "1abfaf02dc5ff5f1ae04d981c9595326078f54e5", [] ], "META.yml": [ @@ -322494,7 +322516,7 @@ }, "css-grid": { "DIR_METADATA": [ - "0a52f7cafb7518ceb6f9a00a65377c7910e7cba2", + "8ff2dfc2bd4e1a8e4c2ce2d83347bab21e27b239", [] ], "META.yml": [ @@ -325338,7 +325360,7 @@ }, "css-inline": { "DIR_METADATA": [ - "d7542b2d18dbe34bd58c0ae8721b27f4bc134f76", + "51348ef089d5a8b4a54a07ddc701500237fd94eb", [] ], "META.yml": [ @@ -325612,7 +325634,7 @@ }, "css-layout-api": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -326192,7 +326214,7 @@ }, "css-logical": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -326282,7 +326304,7 @@ }, "css-masking": { "DIR_METADATA": [ - "3bd51be2ecdace0a79f51401df6803cb4d0d8beb", + "0dfef80521e06207d84f383c466f84b725226a40", [] ], "META.yml": [ @@ -327172,7 +327194,7 @@ }, "css-multicol": { "DIR_METADATA": [ - "d7aaf3d206d9205a622667caad552dbbbe3db583", + "19a8f8ddd5a15bb5661eac37d91f4f96dc66747d", [] ], "META.yml": [ @@ -328306,7 +328328,7 @@ }, "css-overflow": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -328840,7 +328862,7 @@ }, "css-overscroll-behavior": { "DIR_METADATA": [ - "913fe32f2a162e65713812b39ce842da97ab2189", + "5139078a147d01a3b4abfbca662e439539352f22", [] ], "META.yml": [ @@ -328850,7 +328872,7 @@ }, "css-page": { "DIR_METADATA": [ - "444bfd257b407e5443e23403f0209147a2c570d1", + "558bab8adc0265a4370657df61bad4751502e5a9", [] ], "META.yml": [ @@ -329598,7 +329620,7 @@ }, "css-position": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -330954,7 +330976,7 @@ }, "css-rhythm": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "parsing": { @@ -330978,7 +331000,7 @@ }, "css-ruby": { "DIR_METADATA": [ - "abc2fd0b20698d7c05bc9be576fd9fb853a14501", + "d883c1fdde11f4047da00a462512b0f2051340b6", [] ], "META.yml": [ @@ -331368,7 +331390,7 @@ }, "css-scroll-anchoring": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -331416,7 +331438,7 @@ }, "css-scroll-snap": { "DIR_METADATA": [ - "913fe32f2a162e65713812b39ce842da97ab2189", + "5139078a147d01a3b4abfbca662e439539352f22", [] ], "META.yml": [ @@ -331508,7 +331530,7 @@ }, "css-scroll-snap-2": { "DIR_METADATA": [ - "913fe32f2a162e65713812b39ce842da97ab2189", + "5139078a147d01a3b4abfbca662e439539352f22", [] ], "resources": { @@ -331560,7 +331582,7 @@ }, "css-scrollbars": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -331808,7 +331830,7 @@ }, "css-shapes": { "DIR_METADATA": [ - "2a197612af0b04fa4f2a3b0aeee84598813b9ac1", + "1cd8252c31b31677c9faae54d3918c1aa41c9638", [] ], "META.yml": [ @@ -332652,7 +332674,7 @@ }, "css-sizing": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -333512,7 +333534,7 @@ }, "css-tables": { "DIR_METADATA": [ - "b0e995291a114006c858e0e729f9004547f8fd37", + "96713364d9283e0d61e3618028156e5ac8069c9a", [] ], "META.yml": [ @@ -333810,7 +333832,7 @@ }, "css-text": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -337820,7 +337842,7 @@ }, "css-text-decor": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -338574,7 +338596,7 @@ [] ], "DIR_METADATA": [ - "0c19f2542ada4b1e9ab5661d9555fd3cc1c828f2", + "1ccb381510827bf921b5cd82f64832d9a9f145fb", [] ], "META.yml": [ @@ -340026,7 +340048,7 @@ }, "css-transitions": { "DIR_METADATA": [ - "849d9c0f45574344e9c71d57c57cdb030cd7205d", + "8ea8b499efa75b870181f1f6eadf3aa765603855", [] ], "KeyframeEffect-getKeyframes.tentative-expected.txt": [ @@ -340770,7 +340792,7 @@ }, "css-ui": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "META.yml": [ @@ -342862,7 +342884,7 @@ [] ], "DIR_METADATA": [ - "92f4c431c19b1194009c9b591111f3ee70a34522", + "6b3fe4d05f3e015b933a583232fedb6f9e65d8a6", [] ], "WEB_FEATURES.yml": [ @@ -342909,6 +342931,10 @@ "c47b31e4d5a3a2121bf8191c1e612b5a5f2f1663", [] ], + "class-specificity-ref.html": [ + "5c882ada040ec700eda008e016d0a1827e31d368", + [] + ], "content-object-fit-fill-ref.html": [ "b86e0a95a172bcc191f17d954b2cf6bd710a1fd1", [] @@ -343504,7 +343530,7 @@ }, "css-writing-modes": { "DIR_METADATA": [ - "6d01f16a1c7c74fc298cf2730ecf4026e206ca04", + "509b85e788247f8eb8d15f98be34a2079bd7e294", [] ], "META.yml": [ @@ -346594,7 +346620,7 @@ }, "filter-effects": { "DIR_METADATA": [ - "3bd51be2ecdace0a79f51401df6803cb4d0d8beb", + "0dfef80521e06207d84f383c466f84b725226a40", [] ], "META.yml": [ @@ -347396,7 +347422,7 @@ }, "geometry": { "DIR_METADATA": [ - "7b5b42f0644d3bf645c8a419c626c7992e15eae7", + "bf8bf7ef91a3c5c8db4c2bb317a7f28be4db6cae", [] ], "META.yml": [ @@ -347746,7 +347772,7 @@ }, "printing": { "DIR_METADATA": [ - "444bfd257b407e5443e23403f0209147a2c570d1", + "558bab8adc0265a4370657df61bad4751502e5a9", [] ], "OWNERS": [ @@ -348924,12 +348950,12 @@ "mozilla": { "mozilla-central-reftests": { "DIR_METADATA": [ - "97e2659bf8cff713dc731eec03ac942794cc5fd2", + "5e354710d3b40f776065d9eadb2feb229fb8a225", [] ], "flexbox": { "DIR_METADATA": [ - "e51f58e0dd2d33f85b8907874dab7a2afbd5224c", + "660b8c13ffbf14e5460f4f0c1eff016a2e07a881", [] ], "OWNERS": [ @@ -348939,7 +348965,7 @@ }, "shapes1": { "DIR_METADATA": [ - "2a197612af0b04fa4f2a3b0aeee84598813b9ac1", + "1cd8252c31b31677c9faae54d3918c1aa41c9638", [] ] }, @@ -348971,7 +348997,7 @@ }, "custom-elements": { "DIR_METADATA": [ - "70523b2671d129a214c5b1660a887430fdf24c38", + "da4ec085247a73295cfd55a20b7d5589f4f09246", [] ], "Document-createElement-customized-builtins-expected.txt": [ @@ -349173,7 +349199,7 @@ }, "device-memory": { "DIR_METADATA": [ - "49afa4246ce1f9872f63629d058a6fb0a9bb8898", + "51daa9d1f9980472f510632b968dfdbc827ad069", [] ], "META.yml": [ @@ -349187,7 +349213,7 @@ }, "direct-sockets": { "DIR_METADATA": [ - "b9d644b2b52ab0c94b02de0ccb94c2a5708155be", + "e168aa3489d82b455687f96e7e256ebef77b94c0", [] ], "META.yml": [ @@ -349799,7 +349825,7 @@ }, "dom": { "DIR_METADATA": [ - "c899c23a6f6d5f830eaf301f1b099c7400697746", + "f9a56cc928857bcba3fde2d0b7c11cc679b5d417", [] ], "META.yml": [ @@ -349905,7 +349931,7 @@ }, "scrolling": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "OWNERS": [ @@ -350459,7 +350485,7 @@ }, "domparsing": { "DIR_METADATA": [ - "5a884ce65add9a794aa76a284a9f7c6328837d3c", + "49ea5cdbba15cd5a86e7c3d560ca92798e581465", [] ], "DOMParser-parseFromString-xml-expected.txt": [ @@ -350519,7 +350545,7 @@ }, "domxpath": { "DIR_METADATA": [ - "5a884ce65add9a794aa76a284a9f7c6328837d3c", + "49ea5cdbba15cd5a86e7c3d560ca92798e581465", [] ], "META.yml": [ @@ -350567,7 +350593,7 @@ }, "dpub-aam": { "DIR_METADATA": [ - "803582c48bb6a7ce275ce6dffaef5f172d12cfc6", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ], "META.yml": [ @@ -350577,7 +350603,7 @@ }, "dpub-aria": { "DIR_METADATA": [ - "803582c48bb6a7ce275ce6dffaef5f172d12cfc6", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ], "META.yml": [ @@ -350601,7 +350627,7 @@ }, "editing": { "DIR_METADATA": [ - "df514395075eba326bc9cc0f767e30f7fd298d59", + "b02baf2b975aae8fbe87db8500b9905575c44a9f", [] ], "META.yml": [ @@ -351627,7 +351653,7 @@ }, "element-timing": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -351703,7 +351729,7 @@ }, "encoding": { "DIR_METADATA": [ - "1856ad29fa833ed89056471d00f06fc5b83cca1e", + "c4133b0ddece7ac66c2aa5f306b2eb17c9d47c4d", [] ], "META.yml": [ @@ -352773,7 +352799,7 @@ }, "encrypted-media": { "DIR_METADATA": [ - "b2d54848137f71e991f587b6a9c2c10c7c9ed490", + "2fa48e26bc85cc184fbf2d2594022f22376d97dd", [] ], "META.yml": [ @@ -353117,7 +353143,7 @@ }, "entries-api": { "DIR_METADATA": [ - "3fe14ca40e52343cd7f7a3478f3f8b770e2e2ce0", + "16b976ab451500a09882e7fda75b8bf2f4af2acc", [] ], "META.yml": [ @@ -353189,7 +353215,7 @@ }, "event-timing": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -353229,7 +353255,7 @@ }, "eventsource": { "DIR_METADATA": [ - "7db289519cc9a2f553de565b2d6efaada4cfbaee", + "8e8b91ddda00a87040e7cf7c38025c98ffc2968e", [] ], "META.yml": [ @@ -353403,7 +353429,7 @@ }, "feature-policy": { "DIR_METADATA": [ - "6764282f2a3b50937eddd107a9f626b99766d1d6", + "9a5e0775d4e3bac1fb4223a9d8889bdde19319c6", [] ], "META.yml": [ @@ -353681,7 +353707,7 @@ }, "fenced-frame": { "DIR_METADATA": [ - "8c8f7d738ac69e05d9d64833808488b8074eb238", + "80d1ce82d8b1b50a92823c3cc8a1df61127fd05b", [] ], "README.md": [ @@ -354541,7 +354567,7 @@ }, "fetch": { "DIR_METADATA": [ - "7576a20a63e1e4a132ffa7bcd4727416fb0460e8", + "31ad696e5b3b222730440a3fd7277ff0aa88aac9", [] ], "META.yml": [ @@ -355406,7 +355432,7 @@ }, "corb": { "DIR_METADATA": [ - "086a544b71cbb52cd5add472e1bc35916c1a71a1", + "60d71a6305f9c7a4d32c6d6e23c52c3ff86044a1", [] ], "OWNERS": [ @@ -355598,7 +355624,7 @@ }, "cross-origin-resource-policy": { "DIR_METADATA": [ - "086a544b71cbb52cd5add472e1bc35916c1a71a1", + "60d71a6305f9c7a4d32c6d6e23c52c3ff86044a1", [] ], "OWNERS": [ @@ -356629,7 +356655,7 @@ }, "file-system-access": { "DIR_METADATA": [ - "3fe14ca40e52343cd7f7a3478f3f8b770e2e2ce0", + "16b976ab451500a09882e7fda75b8bf2f4af2acc", [] ], "META.yml": [ @@ -357107,7 +357133,7 @@ }, "font-access": { "DIR_METADATA": [ - "c72979d5cee8d80d814524f24cb99b8c5b164692", + "453e8964f0fb3116ab83c8bf43aae7af0e95729b", [] ], "OWNERS": [ @@ -358103,7 +358129,7 @@ }, "fs": { "DIR_METADATA": [ - "12cf0e36d35303a5936a5a1f0fba87083b219262", + "16b976ab451500a09882e7fda75b8bf2f4af2acc", [] ], "META.yml": [ @@ -358293,7 +358319,7 @@ }, "fullscreen": { "DIR_METADATA": [ - "1652c4fa811abc3de5100db23c1e35ff86f5d20d", + "9231eb5bf517e390a361b2a66a1aa807b165670f", [] ], "META.yml": [ @@ -358377,7 +358403,7 @@ }, "gamepad": { "DIR_METADATA": [ - "4f543fde4f6384f3e2dd959cc5cb697981c3e9d2", + "8cac0a9f585ea681683966eb2e7041447aa6faf6", [] ], "META.yml": [ @@ -358411,7 +358437,7 @@ }, "generic-sensor": { "DIR_METADATA": [ - "caea56d67a654fb8b15e43a1b0eab7e413a88177", + "22cfa46b2f5ffb1fa3db78d07e69585ff3c48e8d", [] ], "META.yml": [ @@ -358451,7 +358477,7 @@ }, "geolocation-API": { "DIR_METADATA": [ - "1fb69db5e8b213d5076cf202a51b3e92d192c471", + "e20089c8e5f1c6f06bfaa2177ac3905cbe89f5a1", [] ], "META.yml": [ @@ -358491,7 +358517,7 @@ }, "geolocation-sensor": { "DIR_METADATA": [ - "caea56d67a654fb8b15e43a1b0eab7e413a88177", + "22cfa46b2f5ffb1fa3db78d07e69585ff3c48e8d", [] ], "GeolocationSensor-disabled-by-feature-policy.https-expected.txt": [ @@ -358555,7 +358581,7 @@ }, "graphics-aam": { "DIR_METADATA": [ - "44396ee85cd0abfe885866f20a0f64d5b61eb8c5", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ], "META.yml": [ @@ -358565,7 +358591,7 @@ }, "graphics-aria": { "DIR_METADATA": [ - "44396ee85cd0abfe885866f20a0f64d5b61eb8c5", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ], "META.yml": [ @@ -358575,7 +358601,7 @@ }, "gyroscope": { "DIR_METADATA": [ - "caea56d67a654fb8b15e43a1b0eab7e413a88177", + "22cfa46b2f5ffb1fa3db78d07e69585ff3c48e8d", [] ], "Gyroscope-disabled-by-feature-policy.https.html.headers": [ @@ -358607,7 +358633,7 @@ }, "hr-time": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -358667,7 +358693,7 @@ }, "html": { "DIR_METADATA": [ - "83562e71cd20d551852247d15c9573d68078bb17", + "80e019d94891585c88cab66335aa3a4a7953b722", [] ], "META.yml": [ @@ -358680,7 +358706,7 @@ ], "anonymous-iframe": { "DIR_METADATA": [ - "a1a39b2ec27a6984e710b48b3478e2da2979bd15", + "aefe36ceb35d80b7321e8fbae910e74a8b0e6b2f", [] ], "fenced-frame-bypass.tentative.https.window-expected.txt": [ @@ -358717,12 +358743,12 @@ "browsers": { "browsing-the-web": { "DIR_METADATA": [ - "7f2331a3c7a9ee714fa7dc7ef99d85d4c9875f78", + "a95e8282333741e60e6c60e17dedc5d37d6fe74e", [] ], "back-forward-cache": { "DIR_METADATA": [ - "27e202f1dd9f77ec5704168b248a9a8fdd62f7d7", + "25a99cf75a9c7c561ca6fc54c2e908e524a0f0ae", [] ], "README.md": [ @@ -359651,7 +359677,7 @@ }, "history": { "DIR_METADATA": [ - "d1616e608283fd58960d220a0c41adaffaab43b8", + "6a5a4e506745134ef1923f18d8d60dff0db9339a", [] ], "joint-session-history": { @@ -360019,7 +360045,7 @@ }, "offline": { "DIR_METADATA": [ - "572fffe4d37f43eeb09e2238c4f1b19540adeb98", + "64b6100d95b31245ff9a771a792a65db2a922ea3", [] ], "changestonetworkingmodel": { @@ -360081,7 +360107,7 @@ }, "origin": { "DIR_METADATA": [ - "a19d4eeecc75654a46966efa7badc560e5ebc3e1", + "4b3272cebd1b67dca68efcb1078a74ab4eadde12", [] ], "cross-origin-objects": { @@ -360419,7 +360445,7 @@ }, "sandboxing": { "DIR_METADATA": [ - "1545c0cd3269bb1cf0aea96953deb81729f96d47", + "e8afad2413e607029d81b9e95fafd3c363902dd3", [] ], "inner-iframe.html": [ @@ -361026,7 +361052,7 @@ }, "canvas": { "DIR_METADATA": [ - "ab76b6227db42798d91c09a8f9f772f64ae67d9c", + "2ce9a46f05ee2614aff69c66d621b20bcb93b396", [] ], "META.yml": [ @@ -363502,7 +363528,7 @@ }, "capability-delegation": { "DIR_METADATA": [ - "4315492acc29e0a504bc5293b4f7de6560bde28f", + "1e6300806fa1d60c270698a2adc69c1047a8cdbe", [] ], "resources": { @@ -363518,7 +363544,7 @@ }, "cross-origin-embedder-policy": { "DIR_METADATA": [ - "02e1e27f9856a51cbb836be0da5c94a024c9f96b", + "3b21e94ee860dce2a04f515fb0432dbedfdbc89d", [] ], "META.yml": [ @@ -363896,7 +363922,7 @@ }, "cross-origin-opener-policy": { "DIR_METADATA": [ - "0fbc9925cf1cba4a314fee38b2e76026cf021657", + "71b31a9ac09e02f15e408a5b862a9a9e4c43268d", [] ], "META.yml": [ @@ -365032,7 +365058,7 @@ [] ], "utils.js": [ - "9a890ab685c675ee5baca618ce5d85b367761760", + "8a9a537e96df89a2944d62dcc2915b8a51796fd5", [] ] } @@ -365050,7 +365076,7 @@ }, "editing": { "DIR_METADATA": [ - "df514395075eba326bc9cc0f767e30f7fd298d59", + "b02baf2b975aae8fbe87db8500b9905575c44a9f", [] ], "activation": { @@ -368583,7 +368609,7 @@ "interaction": { "focus": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "OWNERS": [ @@ -368804,7 +368830,7 @@ "non-replaced-elements": { "flow-content-0": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "div-align-ref.html": [ @@ -368870,7 +368896,7 @@ ], "lists": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "TODO-lists.html": [ @@ -368935,14 +368961,14 @@ [] ], "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ] } }, "tables": { "DIR_METADATA": [ - "4f37329faad59e57da0239577be1f4216e54cd0a", + "c8909f2b9c86237b881f6f2465f13e4fb1ce162f", [] ], "colgroup_valign-ref.xhtml": [ @@ -369074,7 +369100,7 @@ }, "the-fieldset-and-legend-elements": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "META.yml": [ @@ -369258,7 +369284,7 @@ }, "the-frameset-and-frame-elements": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "reference": { @@ -369288,7 +369314,7 @@ }, "the-hr-element-0": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "align-ref.html": [ @@ -369368,7 +369394,7 @@ "replaced-elements": { "attributes-for-embedded-content-and-images": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "img-aspect-ratio-expected.txt": [ @@ -369452,7 +369478,7 @@ }, "embedded-content-rendering-rules": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "canvas-fallback-ref.html": [ @@ -369474,7 +369500,7 @@ }, "images": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "blocked-by-csp-ref.html": [ @@ -369595,7 +369621,7 @@ }, "the-details-element": { "DIR_METADATA": [ - "df439d2a81c457f7988c5a7f458343bc277fd049", + "72387ccff958b7a6fea9972a4f0cedad09e83c03", [] ], "details-display-property-is-ignored-ref.html": [ @@ -369808,7 +369834,7 @@ }, "select": { "DIR_METADATA": [ - "9a1c39ffa1cc8fd0e858ced30bdee0405f14be67", + "c8ba5e73831c7af891acb9ba7fd72d83926a78c9", [] ] }, @@ -369862,7 +369888,7 @@ }, "the-base-element": { "DIR_METADATA": [ - "b302b2d63e0743df407f4e38626936cb7fbdc7c1", + "fcaa81db5f93d5eaee17ffb04ea5ce4b13ea421e", [] ], "base-data-expected.txt": [ @@ -369884,7 +369910,7 @@ }, "the-link-element": { "DIR_METADATA": [ - "bd63d0f587f37e7af822a01cff5751f2799d4ec0", + "bfdbe5913d3b90f505ae594d16d62bcf8dc91f24", [] ], "all": [ @@ -370118,7 +370144,7 @@ }, "media-elements": { "DIR_METADATA": [ - "672ea355b505d0280084c26506ff98a640bfb36e", + "6b6e7c9b9bfe0b1e97d09f49850840f0ab755115", [] ], "autoplay-allowed-by-feature-policy.https.sub.html.headers": [ @@ -370642,7 +370668,7 @@ }, "the-audio-element": { "DIR_METADATA": [ - "4a4d0c998e0d0b772051919750136bd0ff91f2fc", + "0a1bdecc9eb0aa602f7f560964939d957e8cc52b", [] ], "audio_content-ref.htm": [ @@ -370652,7 +370678,7 @@ }, "the-canvas-element": { "DIR_METADATA": [ - "ab76b6227db42798d91c09a8f9f772f64ae67d9c", + "2ce9a46f05ee2614aff69c66d621b20bcb93b396", [] ], "imagedata-expected.txt": [ @@ -370726,7 +370752,7 @@ }, "the-embed-element": { "DIR_METADATA": [ - "41cb89f8902d75fd47ba0e9bab7a774bdb7335b1", + "23ebfecc93a139823e907a1e82dcc5d75d841690", [] ], "embed-hidden-attribute-ref.html": [ @@ -370752,13 +370778,13 @@ }, "the-frame-element": { "DIR_METADATA": [ - "1fdab2993377d969915d6c53cf299494eb6ea27c", + "16b6d7c9f7dd414631d9a1f3f7781d456e48b7a4", [] ] }, "the-iframe-element": { "DIR_METADATA": [ - "54bf5e2d38634747e0098bf3318a1b8c95011f33", + "ec28560a3120e8de48e517b75c1f1d4c1df8429a", [] ], "change_child.html": [ @@ -371362,7 +371388,7 @@ }, "the-video-element": { "DIR_METADATA": [ - "4069fda1d1abc9cfa3172454d234e485eac0d33a", + "399cf2aa213438f79a37707a56cb751b07da869e", [] ], "video-poster-shown-preload-auto-ref.html": [ @@ -371385,7 +371411,7 @@ }, "forms": { "DIR_METADATA": [ - "47ef0b4add5234a8dd1947589b2023ae19937187", + "a1a17b487752c8c1f6a78294533c03fbf088d2a6", [] ], "META.yml": [ @@ -371414,7 +371440,7 @@ }, "form-submission-0": { "DIR_METADATA": [ - "216811a6b87c1aadebaeed1a292aba36d3d9cb25", + "8744800ee36273cc28c4804ad9554d7eb9de1c77", [] ], "enctypes-helper.js": [ @@ -371466,7 +371492,7 @@ }, "form-submission-target": { "DIR_METADATA": [ - "216811a6b87c1aadebaeed1a292aba36d3d9cb25", + "8744800ee36273cc28c4804ad9554d7eb9de1c77", [] ], "form-target-iframe-helper.py": [ @@ -371516,7 +371542,7 @@ }, "the-button-element": { "DIR_METADATA": [ - "7f4667d5d230f86997119c19665fec5234a0aec6", + "4881f7e9eece3beb376c2b42cd4ad7e9c6a4413c", [] ], "button-activate-frame.html": [ @@ -371534,13 +371560,13 @@ }, "the-datalist-element": { "DIR_METADATA": [ - "2ec1cb8c2fbd413a2b158d041c2595ebdf7547c9", + "d4bdb2a6271c098b3f5cd52d4b47c90e220a5825", [] ] }, "the-fieldset-element": { "DIR_METADATA": [ - "880fbeebd89d0a4e670b691f2900d41a2f5ef30e", + "66c747a5b5224140e9bcae06106116307db2157c", [] ], "accessibility": { @@ -371678,7 +371704,7 @@ }, "the-label-element": { "DIR_METADATA": [ - "90f14b62ceaa4f9e5cf1d55828c16dd11d61966d", + "f16207d340f6ae6875949a274bdc4742194e1625", [] ], "iframe-label-attributes.html": [ @@ -371692,13 +371718,13 @@ }, "the-legend-element": { "DIR_METADATA": [ - "880fbeebd89d0a4e670b691f2900d41a2f5ef30e", + "66c747a5b5224140e9bcae06106116307db2157c", [] ] }, "the-meter-element": { "DIR_METADATA": [ - "4e6647688ef56831da0d51393ad03aafca8f7db3", + "09bf11ef4c5459e8edd2f436b36d675375bd00bc", [] ], "meter-min-rendering-ref.html": [ @@ -371708,13 +371734,13 @@ }, "the-optgroup-element": { "DIR_METADATA": [ - "9a1c39ffa1cc8fd0e858ced30bdee0405f14be67", + "c8ba5e73831c7af891acb9ba7fd72d83926a78c9", [] ] }, "the-option-element": { "DIR_METADATA": [ - "9a1c39ffa1cc8fd0e858ced30bdee0405f14be67", + "c8ba5e73831c7af891acb9ba7fd72d83926a78c9", [] ], "dynamic-content-change-rendering-ref.html": [ @@ -371728,19 +371754,19 @@ }, "the-output-element": { "DIR_METADATA": [ - "92fcea609bc899be614fbf094527324d0fa03d15", + "5f96515e41ec80c00c0fd4075b1a4f15c274879d", [] ] }, "the-progress-element": { "DIR_METADATA": [ - "db9a278eac4943e267462d0e6ba785d5fc32a0c7", + "bffb9a7a62945645e3e2afdbdca700c5018f2e96", [] ] }, "the-select-element": { "DIR_METADATA": [ - "9a1c39ffa1cc8fd0e858ced30bdee0405f14be67", + "c8ba5e73831c7af891acb9ba7fd72d83926a78c9", [] ], "reset-algorithm-rendering-ref.html": [ @@ -371753,7 +371779,7 @@ [] ], "stylable-select-styles.css": [ - "726380f940d2e32b390269afca9617c88e3bb251", + "a7e9a87cdfa96a56cd82da56e78717efb4b0c966", [] ] }, @@ -371768,7 +371794,7 @@ }, "the-selectlist-element": { "DIR_METADATA": [ - "973a72f0c76ce10096fcd255f83c0cec54cf69fa", + "53ce4c9e0b1b1bbeae0ccf5375622d4cc5e1f9f3", [] ], "button-type-selectlist-appearance-ref.html": [ @@ -371876,7 +371902,7 @@ }, "the-textarea-element": { "DIR_METADATA": [ - "ccd3628d451d3fcf7ab70d815c2bb6716f66dea5", + "67b102f814349e5a672d01449796307ee7a37316", [] ], "multiline-placeholder-ref.html": [ @@ -372030,7 +372056,7 @@ }, "the-details-element": { "DIR_METADATA": [ - "df439d2a81c457f7988c5a7f458343bc277fd049", + "72387ccff958b7a6fea9972a4f0cedad09e83c03", [] ], "details-add-summary-ref.html": [ @@ -372046,7 +372072,7 @@ }, "the-dialog-element": { "DIR_METADATA": [ - "12964ec475f8051987f0e0b3b21da40c24deb907", + "dbd93e12e34bc8a6fded50ec431c10193276b701", [] ], "WEB_FEATURES.yml": [ @@ -372206,7 +372232,7 @@ }, "the-summary-element": { "DIR_METADATA": [ - "df439d2a81c457f7988c5a7f458343bc277fd049", + "72387ccff958b7a6fea9972a4f0cedad09e83c03", [] ] } @@ -372335,7 +372361,7 @@ }, "popovers": { "DIR_METADATA": [ - "84360244f4fef37b9d80991df49dc030e0744d5f", + "643fadf00993764164f913173d081f0fb781ebbb", [] ], "WEB_FEATURES.yml": [ @@ -374281,7 +374307,7 @@ }, "tabular-data": { "DIR_METADATA": [ - "0888feef801b9eae64055d36616c459b6ae263e5", + "a50bbad8a217186ed1f52615cdce6d92bc77dce2", [] ], "META.yml": [ @@ -374296,7 +374322,7 @@ "text-level-semantics": { "the-a-element": { "DIR_METADATA": [ - "c830afebf42164fda5c66cdb1ca4f34d31dd44b3", + "ce0c8aa742a2b0ff6b8d07802f95d181c04c9d02", [] ], "a-download-404.py": [ @@ -374434,7 +374460,7 @@ }, "syntax": { "DIR_METADATA": [ - "ef1ead61c0a42f90fbb5f2c2e4a51380ac651ccc", + "9defd5b2f11fab493420e8e6a90f37a4a5e5bcb6", [] ], "charset": { @@ -375736,7 +375762,7 @@ }, "the-xhtml-syntax": { "DIR_METADATA": [ - "a7b9f49c7d02fd94ca00a167f1213052e36bc5fb", + "e4d35e1ea7db3074420192430a8fd24384ddb8e8", [] ], "parsing-xhtml-documents": { @@ -375792,7 +375818,7 @@ }, "user-activation": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -375845,7 +375871,7 @@ "webappapis": { "animation-frames": { "DIR_METADATA": [ - "b3548e292a5c44cb66e004f343a63ff0823c7525", + "3ebd4ca7994eabac158da14f99c3454780e943a7", [] ] }, @@ -375992,7 +376018,7 @@ }, "html-unsafe-methods": { "DIR_METADATA": [ - "359e0a1c4901bb9deaf88f94b4e04cccf9a2235e", + "3954de55ef246a5e85592fadb0055a85ba005371", [] ], "resources": { @@ -376457,7 +376483,7 @@ }, "html-aam": { "DIR_METADATA": [ - "44396ee85cd0abfe885866f20a0f64d5b61eb8c5", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ], "META.yml": [ @@ -376471,7 +376497,7 @@ }, "html-media-capture": { "DIR_METADATA": [ - "9d6cfb7ba022d236a5be2a0fedf3b44367b1b071", + "d4bb4ac4b9187864a168c35f55bf51465f2e1a06", [] ], "META.yml": [ @@ -376551,7 +376577,7 @@ }, "imagebitmap-renderingcontext": { "DIR_METADATA": [ - "43096d5e3f23002dc54a8181361f88d4bcce822f", + "549d477488a8cd8f5425eee3c7ecb8d35464c326", [] ], "META.yml": [ @@ -376565,7 +376591,7 @@ [] ], "DIR_METADATA": [ - "9b0121386d1d5435a8420caea934ef0d59a826aa", + "03f4b4ad9b9145a88413664de8c7b2341b0b85fa", [] ], "META.yml": [ @@ -377257,7 +377283,7 @@ "testdriver": { "actions": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "OWNERS": [ @@ -377359,7 +377385,7 @@ }, "input-events": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -378647,7 +378673,7 @@ }, "intersection-observer": { "DIR_METADATA": [ - "aab9ded40a44aa888745a4a544ff6b6874015624", + "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], "META.yml": [ @@ -378899,7 +378925,7 @@ }, "keyboard-map": { "DIR_METADATA": [ - "21c3f0496c6abe11737266979e496e58726edf83", + "f5a8ef9fcbc1324cd1c7fe685ab5ca1c6f63c3f6", [] ], "META.yml": [ @@ -378927,7 +378953,7 @@ }, "largest-contentful-paint": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -378975,7 +379001,7 @@ }, "layout-instability": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -379337,7 +379363,7 @@ }, "longtask-timing": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -379385,7 +379411,7 @@ }, "magnetometer": { "DIR_METADATA": [ - "caea56d67a654fb8b15e43a1b0eab7e413a88177", + "22cfa46b2f5ffb1fa3db78d07e69585ff3c48e8d", [] ], "META.yml": [ @@ -381275,7 +381301,7 @@ }, "mediacapture-insertable-streams": { "DIR_METADATA": [ - "563fa6720ba3a89d6ad8add86cd903465fe456f2", + "433a390634c6a8e750aaae8e8888c16adb296b1d", [] ], "META.yml": [ @@ -381381,7 +381407,7 @@ }, "mediacapture-record": { "DIR_METADATA": [ - "6d96e9ae712a1fc39291ba9f92ea94fbb3c2ea00", + "95af59abd1a79a3f96f30743c5ea787afc25ae08", [] ], "META.yml": [ @@ -381433,7 +381459,7 @@ }, "mediacapture-streams": { "DIR_METADATA": [ - "914b263a9ad0c34d7a2d75c935a1addc64e60045", + "433a390634c6a8e750aaae8e8888c16adb296b1d", [] ], "GUM-deny.https-expected.txt": [ @@ -381653,7 +381679,7 @@ }, "mixed-content": { "DIR_METADATA": [ - "370f0a1242d9a04c2e96bedc07e3fff2e0da50d7", + "1b162928708ea1f75425a7063d6ebfd6616105e4", [] ], "META.yml": [ @@ -382229,7 +382255,7 @@ }, "navigation-timing": { "DIR_METADATA": [ - "c907af0b21f16fa5683875467904fd498879089c", + "25862ba2b4cd6effa5c1ac2c151e196077ba3f86", [] ], "META.yml": [ @@ -382451,7 +382477,7 @@ }, "orientation-event": { "DIR_METADATA": [ - "dc60f5a939a7938b5df7b0a1671c6b2d408139fe", + "2e439f2f1c0f5bcc773804a3bd9711efdb93436b", [] ], "META.yml": [ @@ -382487,7 +382513,7 @@ [] ], "DIR_METADATA": [ - "caea56d67a654fb8b15e43a1b0eab7e413a88177", + "22cfa46b2f5ffb1fa3db78d07e69585ff3c48e8d", [] ], "META.yml": [ @@ -382529,7 +382555,7 @@ }, "page-visibility": { "DIR_METADATA": [ - "ad88c7283bfa1315fe5d8d47084a600d4fa4c588", + "945d3913671d593f7c70b121223d76837b819fa8", [] ], "META.yml": [ @@ -382577,7 +382603,7 @@ }, "paint-timing": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -382631,7 +382657,7 @@ }, "payment-handler": { "DIR_METADATA": [ - "d1e9bdd8e19ae45f3f7f2893100012a80e9d7b44", + "360c6927a5d51b1e6fa589afc8507dd8d462a437", [] ], "META.yml": [ @@ -382723,7 +382749,7 @@ }, "payment-method-basic-card": { "DIR_METADATA": [ - "d1e9bdd8e19ae45f3f7f2893100012a80e9d7b44", + "360c6927a5d51b1e6fa589afc8507dd8d462a437", [] ], "META.yml": [ @@ -382741,7 +382767,7 @@ }, "payment-method-id": { "DIR_METADATA": [ - "d1e9bdd8e19ae45f3f7f2893100012a80e9d7b44", + "360c6927a5d51b1e6fa589afc8507dd8d462a437", [] ], "META.yml": [ @@ -382759,7 +382785,7 @@ }, "payment-request": { "DIR_METADATA": [ - "d1e9bdd8e19ae45f3f7f2893100012a80e9d7b44", + "360c6927a5d51b1e6fa589afc8507dd8d462a437", [] ], "META.yml": [ @@ -382869,7 +382895,7 @@ }, "performance-timeline": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -383023,7 +383049,7 @@ }, "permissions-policy": { "DIR_METADATA": [ - "6764282f2a3b50937eddd107a9f626b99766d1d6", + "9a5e0775d4e3bac1fb4223a9d8889bdde19319c6", [] ], "META.yml": [ @@ -383533,7 +383559,7 @@ }, "picture-in-picture": { "DIR_METADATA": [ - "d18b4d5206bdc6de4c562d7002cfd19bb52b9e68", + "2848df5083857a860a27b87457766bfee1bb228e", [] ], "META.yml": [ @@ -383799,7 +383825,7 @@ }, "pointerevents": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -383893,7 +383919,7 @@ }, "pointerlock": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -383907,7 +383933,7 @@ }, "preload": { "DIR_METADATA": [ - "0eda2ab480bb6f4fb6aa21b32505add40dfc9f54", + "9fd2956443224ad3a11731bca782dd855e216142", [] ], "META.yml": [ @@ -384175,7 +384201,7 @@ }, "presentation-api": { "DIR_METADATA": [ - "886ef51d7b5fa1a88bcaf59acfc56265b4b732d3", + "3eec6d938f788c607f9030fcae431e55dae6b47a", [] ], "META.yml": [ @@ -384335,7 +384361,7 @@ }, "quirks": { "DIR_METADATA": [ - "c41ee089b8e083540febdab0fb23c1c8bafbbfc5", + "38c4cd0efc94eb8941cf45405784304d216b6aab", [] ], "META.yml": [ @@ -385053,7 +385079,7 @@ ] }, "DIR_METADATA": [ - "97c04a7da7988985f213888de90ceb99d53a2d2f", + "f1d29c3bf1b433e390f52e831e9fca46b04d62d6", [] ], "META.yml": [ @@ -385867,7 +385893,7 @@ }, "remote-playback": { "DIR_METADATA": [ - "4bbb82d3a9c1eb024eaa6577bd467a99d038123a", + "03d258a59320854ca3feb8b90d0b81727e96b2dd", [] ], "META.yml": [ @@ -386029,7 +386055,7 @@ }, "requestidlecallback": { "DIR_METADATA": [ - "188cb769c8116c13d402e4e304d763b0c6087dbd", + "e85f220758bdd61bae3c88298ee1620ebafea394", [] ], "META.yml": [ @@ -386101,7 +386127,7 @@ [] ], "DIR_METADATA": [ - "931e51bc45c9d2b60007e45aad0bb2bb63b82762", + "98756eed92aff5d953cacb3b9963ac213c842d84", [] ], "META.yml": [ @@ -386853,7 +386879,7 @@ }, "sanitizer-api": { "DIR_METADATA": [ - "c1c57ff93ec12d1699f3f75ef46bc941df6e93f0", + "d54fad0ddb22c364ef82d5b06d64fbbc345212ce", [] ], "META.yml": [ @@ -386907,7 +386933,7 @@ }, "scheduler": { "DIR_METADATA": [ - "c451247ee94cd356c5b9b16f3f11bf44abac0919", + "b1e1ab51974c9cbe46d3b4d876e1cb7b7fb4764c", [] ], "META.yml": [ @@ -386925,7 +386951,7 @@ }, "screen-capture": { "DIR_METADATA": [ - "e5ad3abb40f534b400469e2c7e1bf22a9bdc5e1a", + "e93c1ac7c5b2c9ca0c8122b8eadf37b3bf43bed1", [] ], "META.yml": [ @@ -386951,7 +386977,7 @@ }, "screen-orientation": { "DIR_METADATA": [ - "726cc0038d469c7904537d0d8c92f66229fa34e4", + "747d0ddf80a3321ffad6856560137476a551ce35", [] ], "META.yml": [ @@ -387175,7 +387201,7 @@ }, "scroll-to-text-fragment": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -387279,7 +387305,7 @@ }, "secure-contexts": { "DIR_METADATA": [ - "bfec72293a64b00de9850a9f25222e91c86ef1aa", + "1f59bfc499e36be1e4b3e3ae27708acfba12b825", [] ], "META.yml": [ @@ -387427,7 +387453,7 @@ }, "selection": { "DIR_METADATA": [ - "c8c1b8eba51e7469644730155ce541a27776cbfe", + "25eea5bb6a6a1c107ad0a01001a5f0b6cee4cb1e", [] ], "META.yml": [ @@ -387577,7 +387603,7 @@ }, "server-timing": { "DIR_METADATA": [ - "0a9aa94aac4ec920912f69b55cde725f3f8fc78a", + "2d7f3dfdc5052c716b0a56edce2f0684b6180f85", [] ], "META.yml": [ @@ -388331,7 +388357,7 @@ }, "service-workers": { "DIR_METADATA": [ - "870c4d33d576efa9415f5f1f77f593bc1fac35ca", + "d52b3f7d9baf1daa46a3ef122d5d50e3f165cb4b", [] ], "META.yml": [ @@ -388344,7 +388370,7 @@ ], "cache-storage": { "DIR_METADATA": [ - "049926d70493335c0502f9f567536d90c31afb61", + "c727bca735fdc4298e2517f162a8156a588e49e0", [] ], "META.yml": [ @@ -390463,7 +390489,7 @@ }, "shadow-dom": { "DIR_METADATA": [ - "ab2d7cb4c4ae84d18301995b2cb9584dd040cd25", + "940ee2c1ebe2bf0563aa83cc94b5582f8795b479", [] ], "META.yml": [ @@ -390831,6 +390857,10 @@ "a475ee4f96ebdba21095eae2ecf98e524d344d72", [] ], + "credentials-test-helper.py": [ + "81a988e3581f0567a29a58b7303f124c5cc5e38e", + [] + ], "delete-key.https.html": [ "41595f3ee3868a1e7fa1f866bcc8936de16f5cbd", [] @@ -391843,7 +391873,7 @@ }, "storage": { "DIR_METADATA": [ - "e2269a82f197486d5e37db2fe294a4a40a056e91", + "9f57b8eb7d13433c726dcd3775a6b5a8febeb366", [] ], "META.yml": [ @@ -391915,7 +391945,7 @@ }, "storage-access-api": { "DIR_METADATA": [ - "1da7c78a0f02e4a4a10aaf1e7da005be04c4fa75", + "d9cdeb078674a7a09266de8b41a6f3a5a4a558dd", [] ], "META.yml": [ @@ -391995,7 +392025,7 @@ }, "streams": { "DIR_METADATA": [ - "3376bf31c0f931846fe7a0144837d5f8c8b7854b", + "8fe190dc70e8a1ef7d989388293972dc0277808f", [] ], "META.yml": [ @@ -392599,7 +392629,7 @@ }, "subresource-integrity": { "DIR_METADATA": [ - "a19d4eeecc75654a46966efa7badc560e5ebc3e1", + "4b3272cebd1b67dca68efcb1078a74ab4eadde12", [] ], "META.yml": [ @@ -392663,7 +392693,7 @@ }, "svg": { "DIR_METADATA": [ - "e66538f202184551183384a925fc9c76d0b25062", + "8c4bb5a5af3e4235eeb6fae14af464fe16a6164e", [] ], "META.yml": [ @@ -393905,7 +393935,7 @@ }, "svg-aam": { "DIR_METADATA": [ - "803582c48bb6a7ce275ce6dffaef5f172d12cfc6", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ], "META.yml": [ @@ -393955,7 +393985,7 @@ }, "touch-events": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -393991,7 +394021,7 @@ }, "trusted-types": { "DIR_METADATA": [ - "a19d4eeecc75654a46966efa7badc560e5ebc3e1", + "4b3272cebd1b67dca68efcb1078a74ab4eadde12", [] ], "META.yml": [ @@ -394141,7 +394171,7 @@ }, "uievents": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -394491,7 +394521,7 @@ }, "upgrade-insecure-requests": { "DIR_METADATA": [ - "a19d4eeecc75654a46966efa7badc560e5ebc3e1", + "4b3272cebd1b67dca68efcb1078a74ab4eadde12", [] ], "META.yml": [ @@ -394847,7 +394877,7 @@ }, "url": { "DIR_METADATA": [ - "7db289519cc9a2f553de565b2d6efaada4cfbaee", + "8e8b91ddda00a87040e7cf7c38025c98ffc2968e", [] ], "IdnaTestV2.window-expected.txt": [ @@ -395025,7 +395055,7 @@ }, "user-timing": { "DIR_METADATA": [ - "17e24c0942c8113028f9267cb32724f45d651c53", + "e1a0e70f54c6a2b32e056562aba8680ed9465d9b", [] ], "META.yml": [ @@ -395057,7 +395087,7 @@ }, "vibration": { "DIR_METADATA": [ - "dc10621ad5f761c6dd6dd29e4d848115e7d138b9", + "e3e50e15209e52bf06a9e77b5f56ec354ecc1784", [] ], "META.yml": [ @@ -395077,7 +395107,7 @@ }, "virtual-keyboard": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -395095,7 +395125,7 @@ }, "visual-viewport": { "DIR_METADATA": [ - "71b1a71b1fc10f62a9c9b29c86269a4b75f64892", + "5f3ed792088ab2ebde6d2cff982ed0ff3978c748", [] ], "META.yml": [ @@ -395117,7 +395147,7 @@ }, "wai-aria": { "DIR_METADATA": [ - "803582c48bb6a7ce275ce6dffaef5f172d12cfc6", + "c536c667a8d5dbeea8a1de059c919a3ed9ba4336", [] ], "META.yml": [ @@ -395165,7 +395195,7 @@ }, "wasm": { "DIR_METADATA": [ - "62bf56d0945188c5d5c3d9896e4d65859355bfae", + "4b909b680ad9a6427138483665e3f32dbcb093f7", [] ], "META.yml": [ @@ -395867,7 +395897,7 @@ }, "web-animations": { "DIR_METADATA": [ - "849d9c0f45574344e9c71d57c57cdb030cd7205d", + "8ea8b499efa75b870181f1f6eadf3aa765603855", [] ], "META.yml": [ @@ -396539,7 +396569,7 @@ }, "web-locks": { "DIR_METADATA": [ - "fdf5b1166c3fa35cc2d40c4a118e9fdc5a6f5bdd", + "154e22b5b088f616f6728986a0c31986eb435f43", [] ], "META.yml": [ @@ -396601,7 +396631,7 @@ }, "web-nfc": { "DIR_METADATA": [ - "a6a4d266d010fd64d202bfdfe2f20423d26ad9a3", + "627969dbb18a0953bbec6fc2d0e7bebe367b4b68", [] ], "META.yml": [ @@ -396671,7 +396701,7 @@ [] ], "DIR_METADATA": [ - "f74af73c5aa293b815a36f5a5d402b721203fdec", + "21b16eeff4248021978819aed5ef78de5ac6b694", [] ], "META.yml": [ @@ -397025,7 +397055,7 @@ }, "webauthn": { "DIR_METADATA": [ - "9b2a65804f6cef4528f335c826530320b9991c57", + "4587771a9e7b7840842b3f294adcadbf37ab073c", [] ], "META.yml": [ @@ -397272,7 +397302,7 @@ ], "tests": { "DIR_METADATA": [ - "6f03308a1ae0de450984d9420a35e50d9c0a50a3", + "d1fdc95bb61bac6035daf0840aa82b91c0639bb0", [] ], "__init__.py": [ @@ -398393,7 +398423,7 @@ }, "webhid": { "DIR_METADATA": [ - "5ef1de28cfb2d526e5dac080f6d60ab33314b7f0", + "b0539f275812c26ac08422b4abeb097286fdd93f", [] ], "META.yml": [ @@ -398523,7 +398553,7 @@ }, "webmessaging": { "DIR_METADATA": [ - "b431244896dbcdb96e0199478d7289603f79cfd1", + "9c4c47b1f615728aded280900be2a89052862775", [] ], "META.yml": [ @@ -399239,7 +399269,7 @@ }, "webrtc": { "DIR_METADATA": [ - "e5ad3abb40f534b400469e2c7e1bf22a9bdc5e1a", + "e93c1ac7c5b2c9ca0c8122b8eadf37b3bf43bed1", [] ], "META.yml": [ @@ -399474,7 +399504,7 @@ [] ], "webrtc-test-helpers.sub.js": [ - "48882b30ccc263c6fb72e9e910d3dbe9f06d8141", + "8a46302668a2d6d443728122942bbef0cfe9a5f8", [] ] }, @@ -399895,7 +399925,7 @@ [] ], "DIR_METADATA": [ - "64adb78363ab700eb76a5518e4af14c9d459cb00", + "8f6200917d040466c08a12f834d305343127bcf1", [] ], "META.yml": [ @@ -400425,7 +400455,7 @@ }, "webstorage": { "DIR_METADATA": [ - "ce4f4b22854c2392fcf49fa0a523e1161a0dc60b", + "72c4c8fd00c5f08cddd3d525b75fb6bd31d6d51c", [] ], "META.yml": [ @@ -400703,7 +400733,7 @@ }, "webusb": { "DIR_METADATA": [ - "5a176d6b781915288dcb5e978d45e02d071acee7", + "8aa2b3ee5e5b2368e09b878c6b5bd7b17ef4d4ef", [] ], "META.yml": [ @@ -400787,7 +400817,7 @@ }, "webvtt": { "DIR_METADATA": [ - "9d51636449fb3e2f34ba125067982b378d209613", + "af661f0095d99a64ae3555fb35ab6c3b80b3faea", [] ], "META.yml": [ @@ -402797,7 +402827,7 @@ }, "webxr": { "DIR_METADATA": [ - "88aee7ea4e6d785271b82c45fffb161567924a98", + "014bf0909d4e057ea53863976a83bcae490865de", [] ], "META.yml": [ @@ -402925,7 +402955,7 @@ }, "workers": { "DIR_METADATA": [ - "be0381fa0cac6832c90c06a64d8468be654aadf6", + "b93f1971cbecb4d09043593e84191f7b8d2052f3", [] ], "META.yml": [ @@ -404175,7 +404205,7 @@ }, "worklets": { "DIR_METADATA": [ - "be0381fa0cac6832c90c06a64d8468be654aadf6", + "b93f1971cbecb4d09043593e84191f7b8d2052f3", [] ], "META.yml": [ @@ -404335,7 +404365,7 @@ }, "x-frame-options": { "DIR_METADATA": [ - "ba32a64a1254123a1b9e35d9485d28f74b4c1e57", + "7ce99aa674ffbf48c34b20d98c947d504884794c", [] ], "META.yml": [ @@ -404371,7 +404401,7 @@ }, "xhr": { "DIR_METADATA": [ - "8b3df48a61563c79c82abb42dfc16bebe9a8927f", + "9c5bfd99ab4ba2e747a038d8284033717b11a88c", [] ], "META.yml": [ @@ -427774,7 +427804,7 @@ ] ], "clipboard-item.https.html": [ - "b50a1c97d746168fd4166726ead0964faa03aa39", + "7e148703a2679286d563053904d3accc820900a9", [ null, {} @@ -441789,34 +441819,6 @@ {} ] ], - "anchor-position-auto-001.html": [ - "b5e19522b00d8327e2eb1da96a2714ff2c62c60b", - [ - null, - {} - ] - ], - "anchor-position-auto-002.html": [ - "1c86fe2e4678f5fc7600d16f6580b24b60117330", - [ - null, - {} - ] - ], - "anchor-position-auto-003.html": [ - "33ef58b2af4692f071596aa005f4e72954d6c04f", - [ - null, - {} - ] - ], - "anchor-position-auto-004.html": [ - "befd5fcff068d7af8d9b9a1a658eddfb3008b55d", - [ - null, - {} - ] - ], "anchor-position-borders-001.html": [ "1e2ecbc909cee0f9f301481c12ab6a8fc9b4ff0c", [ @@ -457890,6 +457892,15 @@ } }, "css-page": { + "cssom": { + "page-001.html": [ + "2f6b4dde0500cf7ef40b2187708539523472d33a", + [ + null, + {} + ] + ] + }, "inheritance.html": [ "565287bce50fa46fdc17cf438ff9eeb2862106a7", [ @@ -472864,6 +472875,13 @@ {} ] ], + "variables-animation-math-functions-tentative.html": [ + "7c33d6cfa364efcad60ab224a926686ba6279b47", + [ + null, + {} + ] + ], "variables-substitute-guaranteed-invalid.html": [ "4abfe28d1f21b2891599543b3972b26fbd15b77e", [ @@ -476505,7 +476523,7 @@ ] ], "display-mode.html": [ - "e6633de856c5f438e47ebe1d05b1593753948fbf", + "4ade16799f9db32f502df643f33094e5a2552e70", [ null, {} @@ -476773,6 +476791,13 @@ {} ] ], + "offset-rotate-interpolation-math-functions-tentative.html": [ + "34e0abf2b0debc151c85d439c649de60b47ab5d2", + [ + null, + {} + ] + ], "offset-rotate-interpolation.html": [ "55845108ebf5f3c42a8b0532121199136160d695", [ @@ -501436,6 +501461,15 @@ } ] ], + "modal-dialog-interrupt-paint.html": [ + "011311a03a37df4e33e6b3a67d9c07ea2776843c", + [ + null, + { + "testdriver": true + } + ] + ], "mousedown.html": [ "35a07faeb1bcaaadb0ca606f8948004b45a115ae", [ @@ -563587,7 +563621,7 @@ ] ], "the-anchor-attribute-003.tentative.html": [ - "fe4657aabb33e63f58d7b623d1fd27d55e38b7c6", + "ec2d8d5ead9673e307350bc7346a5f3b971a391b", [ null, {} @@ -563936,196 +563970,196 @@ ] ], "element-render-blocking-001.tentative.html": [ - "9624b41a194946794fc17c71f66fb4cc2ec6abe1", + "36567f9d54adea41a703b23adac438e160f397cf", [ null, {} ] ], "element-render-blocking-002.tentative.html": [ - "ab0fd511156bc9edb89fe9350d87a000616f2438", + "3c907597f7ac35b84e29ccd37627499c347f511a", [ null, {} ] ], "element-render-blocking-003.tentative.html": [ - "eb3a347a6ebbb7b05a5e3bb7905c9098bf755c51", + "2858798a35f58e1152b7047c35359878d1820ecc", [ null, {} ] ], "element-render-blocking-004.tentative.html": [ - "2c50f2d362a54c8252f92222a71025301222aa9f", + "f45f5587204674691349f298f9367204233aa235", [ null, {} ] ], "element-render-blocking-005.tentative.html": [ - "04cdab467deff3f8880855592cd5724d064b3371", + "098a3c57676cc88788a23efa0818e00b9a8e6344", [ null, {} ] ], "element-render-blocking-006.tentative.html": [ - "1c9da255a622503c2f2bb74fc98876938bce19e1", + "223e42109e5c65985e0aec2b0c24ef8f1d810d15", [ null, {} ] ], "element-render-blocking-007.tentative.html": [ - "df8f9ae3d1258194088f4b8cbadbf2eee9b85500", + "9aa0aeea79834833ff0151227723c1a6c17e06e2", [ null, {} ] ], "element-render-blocking-008.tentative.html": [ - "c2458a0bab31244de67c707d32b2669a5aaa746a", + "e671dda19c43b44d3f065b8de0e68f7326e88aba", [ null, {} ] ], "element-render-blocking-009.tentative.html": [ - "d765ac8a5d3c9b742fa9b24d3401d6c1ff098a08", + "8498816ea5c435cce0ea3d597b7f0b381d73d7f6", [ null, {} ] ], "element-render-blocking-010.tentative.html": [ - "7ef6a1baf35b460791ac54b8891dc3e019aaee85", + "ef6f709012e4bd4bb222b8cc74317abdbc40768f", [ null, {} ] ], "element-render-blocking-011.tentative.html": [ - "31df9b068c01b5a149941f24d619898f6b926301", + "dee82d8c5950c16360d2ff799393a50bed1f7a95", [ null, {} ] ], "element-render-blocking-012.tentative.html": [ - "8f2594d25903a60911f89d7eb6a39968ca2e9d82", + "4110e54c5f20420d8da783d21e43d2f9961aed5a", [ null, {} ] ], "element-render-blocking-013.tentative.html": [ - "9d65bd96b73189f4fafbbcd59261261e0f154fb9", + "ecd97be86a6633daf0d03f86f231de295abee459", [ null, {} ] ], "element-render-blocking-014.tentative.html": [ - "d042b96b64370c1ad08cd235729a2c0e6abb597e", + "ea8948de42dec015384aa2bd7a13edb283b6d522", [ null, {} ] ], "element-render-blocking-015.tentative.html": [ - "f7ac0b1015d79635d83fced00cbcb8c7c5e6400b", + "a775ee417403ab3fef3635194ff1d62b4c335266", [ null, {} ] ], "element-render-blocking-016.tentative.html": [ - "d32a0468e79b4109607d920ec72279ae0af0e0d6", + "8968c5dacd329537b9d7c1d0d0ce38786077f583", [ null, {} ] ], "element-render-blocking-017.tentative.html": [ - "d3a6046cbb37f90b3bf5721f1799f8df313d06c7", + "2d3b5747216f50902714bff725cddf50ec7556c0", [ null, {} ] ], "element-render-blocking-018.tentative.html": [ - "0d7402201accb05ce81636be43057128cfaf976b", + "76e6394b5b16586de768ad553c671b8594d0635e", [ null, {} ] ], "element-render-blocking-019.tentative.html": [ - "fea9e3a2b21821722eb956beac19acfb44721034", + "80a7019edc4beb272ef65d7cd1d28f88fb18a813", [ null, {} ] ], "element-render-blocking-020.tentative.html": [ - "7fc0fe19bbae57d15b5a8bbc27cfb6400661114b", + "10019c943f402c91c0ca07efefe462d5bc6ece48", [ null, {} ] ], "element-render-blocking-021.tentative.html": [ - "29430349f04689578cc7e5f90ba86ef77626bde5", + "1ca2114689a6cdbc961c9eecd1fa4e328117d431", [ null, {} ] ], "element-render-blocking-022.tentative.html": [ - "6548c9ec4df21169af9c97dfa30acf49acb1c95a", + "5dfbcac30a4c065a888f5ea804ba306758d83e6c", [ null, {} ] ], "element-render-blocking-023.tentative.html": [ - "c3661bcaa6a9c3b2e6fc64dc937c73688041a43d", + "8fe8b6a8c8e30f05250c2ca569f5b4d938bed71c", [ null, {} ] ], "element-render-blocking-024.tentative.html": [ - "c98022cfeabef10171061432168274eb81324834", + "19e4020fb769bb59053a6a64cc1c499583044c73", [ null, {} ] ], "element-render-blocking-025.tentative.html": [ - "29868b92cbc76a7f9b6da3e645e02c0701f5e31b", + "689ae69f452d421b66554c8e547ca95f5f269af9", [ null, {} ] ], "element-render-blocking-026.tentative.html": [ - "dc23211b8b00d2011592dd529bd554670456acc5", + "6abfc43b8b237b3f8f0f6474d36fcce1c3aaac52", [ null, {} ] ], "element-render-blocking-027.tentative.html": [ - "5b8a5eb24d5e973a25ca8fbf594f85f006ba7a06", + "56f88e0fc2b773f74afb86e306f42a1aa39d9c1b", [ null, {} ] ], "element-render-blocking-028.tentative.html": [ - "57ba3d602602d59f55bdaa34d18eeb06254e826a", + "a64d542c4ac7ef97a2e3427dabe485519da97518", [ null, {} @@ -564686,6 +564720,15 @@ {} ] ] + }, + "writing-suggestions": { + "writingsuggestions.html": [ + "49e75000d3eb9cb828fb5e702010a6bd555c73b7", + [ + null, + {} + ] + ] } }, "focus": { @@ -625777,7 +625820,7 @@ ] ], "modifying-selection-with-non-primary-mouse-button.tentative.html": [ - "cb2e44295a9405e8a247bcc0aa9760e42a0b8286", + "79fc52ac7dbfa75884cef22017e89df1f38a9e4c", [ "selection/contenteditable/modifying-selection-with-non-primary-mouse-button.tentative.html?middle", { @@ -631267,6 +631310,48 @@ {} ] ], + "same-origin-add-module-credentials-include.tentative.https.sub.html": [ + "a9082661a8b6cee451e7258b154631e2d1f1831d", + [ + null, + {} + ] + ], + "same-origin-add-module-credentials-omit.tentative.https.sub.html": [ + "a5945725c010950aaacf5e252ffc4ebdb096158f", + [ + null, + {} + ] + ], + "same-origin-add-module-credentials-same-origin.tentative.https.sub.html": [ + "aea76264384afffe37da04e919e843d554a87637", + [ + null, + {} + ] + ], + "same-origin-create-worklet-credentials-include.tentative.https.sub.html": [ + "2e1d9cf723562416844c1ee550073b7bac4ee2d7", + [ + null, + {} + ] + ], + "same-origin-create-worklet-credentials-omit.tentative.https.sub.html": [ + "ef90c02d6434a6b472e618e3f3d95ad7e4d08775", + [ + null, + {} + ] + ], + "same-origin-create-worklet-credentials-same-origin.tentative.https.sub.html": [ + "6d9fd7c1362a06930df2f71d3c2fbd193e2746d4", + [ + null, + {} + ] + ], "select-url-keep-alive.tentative.https.sub.html": [ "f3755538b9d4b23e026fec85c161cb730531d4dc", [ @@ -671649,7 +671734,7 @@ ] ], "RTCRtpReceiver-getStats.https.html": [ - "d9344b176e39dcb697d11b70a626706f4b794445", + "bfa82b979c08bdbe056f82e2b6eb5449a716b063", [ null, { @@ -671683,7 +671768,7 @@ ] ], "RTCRtpSender-getStats.https.html": [ - "797365e9f4e89b649839fb9b7bc8a19b879df672", + "5c27af2134a033dc0bffdca9909afe12ea375183", [ null, { @@ -672730,10 +672815,12 @@ ] ], "RTCRtpParameters-codec.html": [ - "cce2c1661f7d7761da12d2ee4ba7be1446fcfe9b", + "5fc1401badf49d6fbc2f46c9936b3711cd3c2466", [ null, - {} + { + "timeout": "long" + } ] ], "RTCRtpReceiver-jitterBufferTarget-stats.html": [
diff --git a/third_party/blink/web_tests/external/wpt/selection/contenteditable/modifying-selection-with-non-primary-mouse-button.tentative.html b/third_party/blink/web_tests/external/wpt/selection/contenteditable/modifying-selection-with-non-primary-mouse-button.tentative.html index cb2e442..79fc52a 100644 --- a/third_party/blink/web_tests/external/wpt/selection/contenteditable/modifying-selection-with-non-primary-mouse-button.tentative.html +++ b/third_party/blink/web_tests/external/wpt/selection/contenteditable/modifying-selection-with-non-primary-mouse-button.tentative.html
@@ -128,6 +128,11 @@ resetEditor(); editor.focus(); selection.collapse(span1.firstChild, 2); + let contextmenuFired = false; + function onContextMenu() { + contextmenuFired = true; + } + document.addEventListener("contextmenu", onContextMenu, {capture: true}); let actions = new test_driver.Actions(); await actions .pointerMove(0, 0) @@ -137,13 +142,26 @@ .pointerUp({button: getButtonType(actions)}) .keyUp("\uE008") .send(); + document.removeEventListener("contextmenu", onContextMenu, {capture: true}); - assert_equals(selection.anchorNode, span1.firstChild, - "Selection#anchorNode should keep in the first <span> element"); - assert_equals(selection.anchorOffset, 2, - "Selection#anchorNode should keep at 2 of the first <span> element"); - assert_equals(selection.focusNode, span2.firstChild, - `Selection#focusNode should be in the second <span> element which was clicked by ${button} button`); + if (button != "secondary" || contextmenuFired) { + assert_equals(selection.anchorNode, span1.firstChild, + "Selection#anchorNode should keep in the first <span> element"); + assert_equals(selection.anchorOffset, 2, + "Selection#anchorNode should keep at 2 of the first <span> element"); + assert_equals(selection.focusNode, span2.firstChild, + `Selection#focusNode should be in the second <span> element which was clicked by ${button} button`); + } else { + // Special case for Firefox. Firefox users can forcibly open context menu + // with pressing shift key. In this case, users may want the secondary + // button click to work as without Shift key press. + assert_true(selection.isCollapsed, + `Selection should be collapsed after ${button} button click because contextmenu was not opened with Shift key`); + assert_equals(selection.focusNode, span2.firstChild, + `Selection should be collapsed in the second <span> element which was clicked by ${ + button + } button because contextmenu was not opened with Shift key`); + } }, `Shift + ${button} click should extend the selection`); promise_test(async () => {
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https.html index d9344b17..bfa82b9 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https.html
@@ -23,7 +23,8 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(callee); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const statsReport = await receiver.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'inbound-rtp')); }, 'receiver.getStats() via addTransceiver should return stats report containing inbound-rtp stats'); @@ -40,8 +41,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(callee); const receiver = callee.getReceivers()[0]; + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const statsReport = await receiver.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'inbound-rtp')); }, 'receiver.getStats() via addTrack should return stats report containing inbound-rtp stats'); @@ -58,8 +60,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(callee); const [receiver] = callee.getReceivers(); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const [transceiver] = callee.getTransceivers(); const statsPromiseFirst = receiver.getStats(); transceiver.stop(); @@ -81,8 +84,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(callee); const [receiver] = callee.getReceivers(); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const statsReportFirst = await receiver.getStats(); callee.close(); const statsReportSecond = await receiver.getStats(); @@ -102,8 +106,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(callee); const receiver = callee.getReceivers()[0]; + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const statsReport = await receiver.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'candidate-pair')); assert_true(!![...statsReport.values()].find(({type}) => type === 'local-candidate'));
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https.html index 797365e9..5c27af2 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https.html
@@ -21,7 +21,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(caller); + const [ receiver ] = callee.getReceivers(); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const statsReport = await sender.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'outbound-rtp')); }, 'sender.getStats() via addTransceiver should return stats report containing outbound-rtp stats'); @@ -38,7 +40,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(caller); + const [ receiver ] = callee.getReceivers(); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const statsReport = await sender.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'outbound-rtp')); }, 'sender.getStats() via addTrack should return stats report containing outbound-rtp stats'); @@ -55,7 +59,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(caller); + const [ receiver ] = callee.getReceivers(); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const [sender] = caller.getSenders(); const [transceiver] = caller.getTransceivers(); @@ -78,7 +84,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(callee); + const [ receiver ] = callee.getReceivers(); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const [sender] = caller.getSenders(); const statsReportFirst = await sender.getStats(); caller.close(); @@ -99,7 +107,9 @@ exchangeIceCandidates(caller, callee); await exchangeOfferAnswer(caller, callee); - await listenToConnected(caller); + const [ receiver ] = callee.getReceivers(); + // Wait for RTP + await new Promise(r => receiver.track.onunmute = r); const statsReport = await sender.getStats(); assert_true(!![...statsReport.values()].find(({type}) => type === 'candidate-pair')); assert_true(!![...statsReport.values()].find(({type}) => type === 'local-candidate'));
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/resources/webrtc-test-helpers.sub.js b/third_party/blink/web_tests/external/wpt/webrtc/resources/webrtc-test-helpers.sub.js index 48882b30..8a46302 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/resources/webrtc-test-helpers.sub.js +++ b/third_party/blink/web_tests/external/wpt/webrtc/resources/webrtc-test-helpers.sub.js
@@ -62,18 +62,18 @@ // Opens a new WebRTC connection. async function openWebRTC(remoteContextHelper) { await remoteContextHelper.executeScript(async (sessionDesc, candidate) => { - const testRTCPeerConnection = new RTCPeerConnection(); - await testRTCPeerConnection.setRemoteDescription(sessionDesc); - await testRTCPeerConnection.addIceCandidate(candidate); + window.testRTCPeerConnection = new RTCPeerConnection(); + await window.testRTCPeerConnection.setRemoteDescription(sessionDesc); + await window.testRTCPeerConnection.addIceCandidate(candidate); }, [sessionDesc, candidate]); } // Opens a new WebRTC connection and then close it. async function openThenCloseWebRTC(remoteContextHelper) { await remoteContextHelper.executeScript(async (sessionDesc, candidate) => { - const testRTCPeerConnection = new RTCPeerConnection(); - await testRTCPeerConnection.setRemoteDescription(sessionDesc); - await testRTCPeerConnection.addIceCandidate(candidate); - testRTCPeerConnection.close(); + window.testRTCPeerConnection = new RTCPeerConnection(); + await window.testRTCPeerConnection.setRemoteDescription(sessionDesc); + await window.testRTCPeerConnection.addIceCandidate(candidate); + window.testRTCPeerConnection.close(); }, [sessionDesc, candidate]); }
diff --git a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt index fe17b4c..02a8f64 100644 --- a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt +++ b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt
@@ -10,17 +10,17 @@ nestedContent: layer(140x10) has hit test rect (0,0 140x10) nestedContent: layer(256x72) has hit test rect (0,30 256x12) -overflowwithhandler: layer(256x116) has hit test rect (-1,-1 258x118) overflowwithhandler: layer(250x20) has hit test rect (0,0 250x10) +overflowwithhandler: layer(256x116) has hit test rect (0,0 256x116) overflowwithhandler: layer(250x20) has hit test rect (0,10 70x10) overflowwithhandler: layer(273x112) has hit test rect (0,10 273x52) -overflowwithborder: layer(263x124) has hit test rect (-6,-6 275x136) overflowwithborder: layer(250x20) has hit test rect (0,0 250x10) +overflowwithborder: layer(255x116) has hit test rect (0,0 255x116) overflowwithborder: layer(250x20) has hit test rect (0,10 240x10) overflowwithborder: layer(769x881) has hit test rect (5,349 290x70) withTransform: layer(271x12) has hit test rect (0,0 271x12) -withTransform: layer(282x77) has hit test rect (0,13 273x14) +withTransform: layer(273x77) has hit test rect (0,13 273x14)
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/fast/overflow/overflow-update-transform-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/fast/overflow/overflow-update-transform-expected.png new file mode 100644 index 0000000..fab310bb --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/fast/overflow/overflow-update-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.png b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.png new file mode 100644 index 0000000..fd5051a1 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/virtual/prefer_compositing_to_lcd_text/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt b/third_party/blink/web_tests/flag-specific/highdpi/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt index 74e7c32..ecfbdde 100644 --- a/third_party/blink/web_tests/flag-specific/highdpi/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt +++ b/third_party/blink/web_tests/flag-specific/highdpi/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [762, 774], "backgroundColor": "#0000FF", "transform": 1
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt b/third_party/blink/web_tests/flag-specific/highdpi/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt deleted file mode 100644 index 822e231..0000000 --- a/third_party/blink/web_tests/flag-specific/highdpi/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt +++ /dev/null
@@ -1,73 +0,0 @@ -{ - "layers": [ - { - "name": "LayoutView #document", - "bounds": [600, 250], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [0, 0, 600, 250] - ] - }, - { - "name": "LayoutNGBlockFlow HTML", - "bounds": [600, 8], - "drawsContent": false - } - ] -} -{ - "layers": [ - { - "name": "LayoutView #document", - "bounds": [400, 250], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [0, 0, 400, 250] - ] - }, - { - "name": "LayoutNGBlockFlow HTML", - "bounds": [400, 8], - "drawsContent": false - } - ] -} -{ - "layers": [ - { - "name": "LayoutView #document", - "bounds": [400, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [0, 0, 400, 600] - ] - }, - { - "name": "LayoutNGBlockFlow HTML", - "bounds": [400, 8], - "drawsContent": false - } - ] -} -{ - "layers": [ - { - "name": "LayoutView #document", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [0, 0, 800, 600] - ] - }, - { - "name": "LayoutNGBlockFlow HTML", - "bounds": [800, 8], - "drawsContent": false - } - ] -} -
diff --git a/third_party/blink/web_tests/http/tests/resources/prevent-bfcache.js b/third_party/blink/web_tests/http/tests/resources/prevent-bfcache.js index 5b1301e..2a261a2 100644 --- a/third_party/blink/web_tests/http/tests/resources/prevent-bfcache.js +++ b/third_party/blink/web_tests/http/tests/resources/prevent-bfcache.js
@@ -7,7 +7,11 @@ // page. The function should be async even if it doesn't seem necessary, so that // if we need to change how it blocks in the future to something async, we will // not need to update all callers. -let bc; async function preventBFCache() { - bc = new BroadcastChannel("blocker"); + await new Promise(resolve => { + // Use a random UUID as the (highly likely) unique lock name. + navigator.locks.request(Math.random(), () => { + resolve(); + }); + }); }
diff --git a/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt index 04cbc5de..d2198c89 100644 --- a/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [800, 5016], "transform": 1 }
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/composited-overlay-scrollbars-scrollbar-color-repaint-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/composited-overlay-scrollbars-scrollbar-color-repaint-expected.txt index 3a82d86..1b0fb89 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/composited-overlay-scrollbars-scrollbar-color-repaint-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/composited-overlay-scrollbars-scrollbar-color-repaint-expected.txt
@@ -15,11 +15,17 @@ { "name": "LayoutNGBlockFlow DIV id='outer'", "position": [1, 1], - "bounds": [400, 602], + "bounds": [400, 500], + "drawsContent": false, "transform": 1 }, { "name": "LayoutNGBlockFlow DIV id='inner'", + "bounds": [102, 102], + "transform": 2 + }, + { + "name": "LayoutNGBlockFlow DIV id='inner'", "position": [1, 1], "bounds": [100, 100], "drawsContent": false,
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.png b/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.png index f6743d9..dc85ee8 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.png +++ b/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt index 86c90ee..e5c14c3 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt
@@ -13,7 +13,7 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV", + "name": "LayoutNGBlockFlow DIV id='target'", "bounds": [200, 200], "backgroundColor": "#00800080", "invalidations": [
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt index 5f25487..dfb74a5 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt
@@ -20,7 +20,10 @@ }, { "name": "LayoutNGBlockFlow DIV id='target'", - "bounds": [100, 210], + "position": [0, 80], + "bounds": [50, 50], + "contentsOpaque": true, + "backgroundColor": "#0000FF", "transform": 2 } ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt index 115bd31a..dc0883d2 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt
@@ -33,14 +33,6 @@ "drawsContent": false, "backfaceVisibility": "hidden", "transform": 1 - }, - { - "name": "LayoutNGBlockFlow (relative positioned) DIV id='container'", - "position": [1, 1], - "bounds": [100, 430], - "drawsContent": false, - "backfaceVisibility": "hidden", - "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt index 2b6fe7bd..10fa8f2 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt
@@ -14,6 +14,13 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='scroller'", + "position": [1, 26], + "bounds": [185, 1000], + "drawsContent": false, + "transform": 2 + }, + { "name": "HorizontalScrollbar", "position": [1, 186], "bounds": [200, 15], @@ -25,13 +32,6 @@ "bounds": [15, 185], "contentsOpaque": true, "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV id='scroller'", - "position": [1, 1], - "bounds": [185, 1025], - "drawsContent": false, - "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.png b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.png index e56a6ab..b29e8db5 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.png +++ b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt index 7572f4d..8efbb8a 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt
@@ -13,6 +13,14 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='scroller'", + "bounds": [185, 1200], + "invalidations": [ + [0, 0, 185, 200] + ], + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [0, 185], "bounds": [200, 15], @@ -24,14 +32,6 @@ "bounds": [15, 185], "contentsOpaque": true, "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV id='scroller'", - "bounds": [185, 1200], - "invalidations": [ - [0, 0, 185, 200] - ], - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-expected.txt b/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-expected.txt index 2d72e89..208e273 100644 --- a/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-expected.txt
@@ -29,13 +29,6 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrollable'", - "position": [1, 1], - "bounds": [795, 1491], - "drawsContent": false, - "transform": 4 - }, - { "name": "LayoutNGBlockFlow (relative positioned) DIV id='transform'", "bounds": [200, 200], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html b/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html index d326bb4..ade0fff9 100644 --- a/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html +++ b/third_party/blink/web_tests/paint/invalidation/repaint-overlay/layers-overlay.html
@@ -84,13 +84,6 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrollable'", - "position": [1, 1], - "bounds": [795, 1491], - "drawsContent": false, - "transform": 4 - }, - { "name": "LayoutNGBlockFlow (relative positioned) DIV id='transform'", "bounds": [200, 200], "contentsOpaque": true, @@ -196,13 +189,6 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrollable'", - "position": [1, 1], - "bounds": [795, 1491], - "drawsContent": false, - "transform": 4 - }, - { "name": "LayoutNGBlockFlow (relative positioned) DIV id='transform'", "bounds": [200, 200], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt index 4e950eac..f53b136f 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt
@@ -27,11 +27,9 @@ }, { "name": "LayoutNGBlockFlow DIV id='scroller'", - "bounds": [10000, 385], + "bounds": [10000, 200], + "contentsOpaque": true, "backgroundColor": "#008000", - "invalidations": [ - [0, 0, 10000, 200] - ], "transform": 1 } ],
diff --git a/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt index 64f9acc..822e231 100644 --- a/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt
@@ -10,8 +10,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [600, 250], + "name": "LayoutNGBlockFlow HTML", + "bounds": [600, 8], "drawsContent": false } ] @@ -28,8 +28,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [400, 250], + "name": "LayoutNGBlockFlow HTML", + "bounds": [400, 8], "drawsContent": false } ] @@ -46,8 +46,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [400, 600], + "name": "LayoutNGBlockFlow HTML", + "bounds": [400, 8], "drawsContent": false } ] @@ -64,8 +64,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [800, 600], + "name": "LayoutNGBlockFlow HTML", + "bounds": [800, 8], "drawsContent": false } ]
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/text/input-disabled-state-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/text/input-disabled-state-expected.png index 202c2c2..fca14fba 100644 --- a/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/text/input-disabled-state-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/text/input-disabled-state-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-expected.png index 9c50e8bc..e44e08f 100644 --- a/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-quirks-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-quirks-expected.png index 6190496..7f4e916 100644 --- a/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-quirks-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/forms/textarea/basic-textareas-quirks-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/bugzilla-6473-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/bugzilla-6473-expected.txt deleted file mode 100644 index 72432d79..0000000 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/bugzilla-6473-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "layers": [ - { - "name": "Scrolling background of LayoutView #document", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [8, 152, 784, 20], - [8, 136, 784, 20], - [8, 16, 661, 100] - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/scrolling-without-painting-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/scrolling-without-painting-expected.png index ad8c5f90..24dcc6f 100644 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/scrolling-without-painting-expected.png +++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/scrolling-without-painting-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/updating-scrolling-content-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/updating-scrolling-content-expected.png index cd9bd54..4b512b5 100644 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/updating-scrolling-content-expected.png +++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/compositing/updating-scrolling-content-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.png index 2b604b3..6aaf628 100644 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.png +++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png index 4ad4882..673824a 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png +++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt index ecf0b99..c99fa95 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [508, 516], "backgroundColor": "#0000FF", "transform": 1
diff --git a/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt index ecf0b99..c99fa95 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [508, 516], "backgroundColor": "#0000FF", "transform": 1
diff --git a/third_party/blink/web_tests/platform/mac/compositing/iframes/invisible-nested-iframe-show-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/iframes/invisible-nested-iframe-show-expected.txt index 6169ab5e..12359218 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/iframes/invisible-nested-iframe-show-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/iframes/invisible-nested-iframe-show-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [285, 192], "backgroundColor": "#C0C0C0", "transform": 1
diff --git a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt index 255ae4b..5218f2a2 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-in-fixed-overflow-expected.txt
@@ -27,7 +27,9 @@ }, { "name": "LayoutNGBlockFlow (positioned) DIV class='overflow fixed'", - "bounds": [785, 1000], + "bounds": [100, 1000], + "contentsOpaque": true, + "backgroundColor": "#0000FF", "transform": 1 }, {
diff --git a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt index 2f917b3..3eb107c 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -16,6 +16,12 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'", + "position": [1, 1], + "bounds": [285, 800], + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [1, 286], "bounds": [300, 15], @@ -29,12 +35,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'", - "position": [1, 1], - "bounds": [285, 800], - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='fixed lime box'", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/content-gains-scrollbars-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/content-gains-scrollbars-expected.txt index 63754ca..12811299 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/content-gains-scrollbars-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/content-gains-scrollbars-expected.txt
@@ -26,12 +26,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [85, 200], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='vertical' class='content tall'", "bounds": [10, 200], "drawsContent": false, @@ -57,12 +51,6 @@ "transform": 2 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 85], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='horizontal' class='content wide'", "bounds": [200, 10], "drawsContent": false, @@ -101,12 +89,6 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 200], - "drawsContent": false, - "transform": 3 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='both' class='content wide tall'", "bounds": [200, 200], "drawsContent": false,
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt index da8aa1c..e6d1d06 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -13,6 +13,13 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV class='scroller'", + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#C0C0C0", + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [0, 285], "bounds": [285, 15], @@ -31,13 +38,6 @@ "position": [285, 285], "bounds": [15, 15], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV class='scroller'", - "bounds": [1000, 1000], - "contentsOpaque": true, - "backgroundColor": "#C0C0C0", - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-scrollbar-layers-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-scrollbar-layers-expected.txt index 297a77a..a5951e0 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-scrollbar-layers-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-scrollbar-layers-expected.txt
@@ -26,12 +26,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [85, 200], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='content tall'", "bounds": [10, 200], "drawsContent": false, @@ -57,12 +51,6 @@ "transform": 2 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 85], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='content wide'", "bounds": [200, 10], "drawsContent": false, @@ -101,12 +89,6 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 200], - "drawsContent": false, - "transform": 3 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='content wide tall'", "bounds": [200, 200], "drawsContent": false,
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt index 44bc053..a49cadd9 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
@@ -23,14 +23,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV id='scroller'", - "position": [1, 1], - "bounds": [100, 180], - "drawsContent": false, - "backfaceVisibility": "hidden", - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='fixed'", "bounds": [80, 80], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt index 2347f45..406dc10 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt
@@ -26,10 +26,11 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV", - "bounds": [585, 500], + "name": "LayoutNGBlockFlow (relative positioned) DIV", + "position": [0, 100], + "bounds": [585, 400], "invalidations": [ - [400, 100, 20, 20] + [400, 0, 20, 20] ], "transform": 1 }
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt b/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt index d5b25d4..9e46c07 100644 --- a/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt +++ b/third_party/blink/web_tests/platform/mac/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
@@ -20,12 +20,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV id='inner'", - "bounds": [285, 1000], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow DIV id='content'", "bounds": [285, 1000], "transform": 1
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/text/input-disabled-state-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/text/input-disabled-state-expected.png index e13312d..134893d8 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/text/input-disabled-state-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/text/input-disabled-state-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-expected.png index 5ab0ddc6..aed0a5f 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png index 0c37a88..8a25ad4 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-update-transform-expected.png b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-update-transform-expected.png index d4dc57d..696b202 100644 --- a/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-update-transform-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-update-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/bugzilla-6473-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/bugzilla-6473-expected.txt index 6f1bed4..1594a37 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/bugzilla-6473-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/bugzilla-6473-expected.txt
@@ -7,8 +7,7 @@ "backgroundColor": "#FFFFFF", "invalidations": [ [8, 146, 784, 18], - [8, 130, 784, 18], - [8, 16, 667, 95] + [8, 130, 784, 18] ] } ]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt index 67e0509..53f2b8c 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt
@@ -29,7 +29,7 @@ ] }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [285, 216], "invalidations": [ [0, 0, 285, 216]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt index d36ceee..82d98a9 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt
@@ -26,7 +26,7 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV", + "name": "LayoutNGBlockFlow (relative positioned) DIV", "bounds": [585, 400], "invalidations": [ [400, 0, 50, 50],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt index 28aa13e..d9e17eb 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
@@ -26,12 +26,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned) DIV", - "bounds": [185, 1000], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow DIV id='foo2'", "bounds": [150, 1000], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt index 1d3600299c..f85324ee 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
@@ -13,6 +13,16 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='container'", + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#008000", + "invalidations": [ + [0, 0, 1000, 1000] + ], + "transform": 2 + }, + { "name": "HorizontalScrollbar", "position": [0, 285], "bounds": [385, 15], @@ -31,16 +41,6 @@ "position": [385, 285], "bounds": [15, 15], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV id='container'", - "bounds": [1000, 1000], - "contentsOpaque": true, - "backgroundColor": "#008000", - "invalidations": [ - [0, 0, 1000, 1000] - ], - "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt index c5d24929..6a20f9d 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt
@@ -39,12 +39,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV id='container'", - "bounds": [3000, 3000], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt index a7dc253..a920f83 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt
@@ -27,7 +27,7 @@ }, { "name": "LayoutNGBlockFlow (children-inline) PRE id='scroller'", - "bounds": [185, 615], + "bounds": [47, 615], "invalidations": [ [0, 0, 47, 615] ],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt index 7b416b2..c95bf3d2 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt
@@ -16,19 +16,6 @@ "transform": 1 }, { - "name": "HorizontalScrollbar", - "position": [0, 485], - "bounds": [800, 15], - "transform": 1 - }, - { - "name": "VerticalScrollbar", - "position": [785, 0], - "bounds": [15, 485], - "contentsOpaque": true, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow DIV", "bounds": [785, 1340], "invalidations": [ @@ -41,6 +28,19 @@ [52, 18, 45, 18] ], "transform": 1 + }, + { + "name": "HorizontalScrollbar", + "position": [0, 485], + "bounds": [800, 15], + "transform": 1 + }, + { + "name": "VerticalScrollbar", + "position": [785, 0], + "bounds": [15, 485], + "contentsOpaque": true, + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt index 7eb9ac3..505d3ac 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt
@@ -27,7 +27,7 @@ }, { "name": "LayoutNGBlockFlow (children-inline) DIV id='container'", - "bounds": [185, 234], + "bounds": [75, 234], "invalidations": [ [0, 216, 75, 18], [0, 198, 75, 18],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt index 749f297..023e69f 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt
@@ -17,6 +17,12 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='container'", + "position": [5, 5], + "bounds": [400, 400], + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [5, 190], "bounds": [185, 15], @@ -35,12 +41,6 @@ "position": [190, 190], "bounds": [15, 15], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV id='container'", - "position": [5, 5], - "bounds": [400, 400], - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt index 8af7c96..245c92d 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt
@@ -14,7 +14,7 @@ }, { "name": "LayoutNGBlockFlow DIV id='target'", - "bounds": [784, 1027], + "bounds": [100, 1027], "transform": 1 } ],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/line-flow-with-floats-9-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/line-flow-with-floats-9-expected.txt index 5e6c20d..f03e4e7 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/line-flow-with-floats-9-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/line-flow-with-floats-9-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [485, 606], "invalidations": [ [0, 0, 485, 606]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt index 285230c..2edc5e7 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt
@@ -36,9 +36,10 @@ }, { "name": "LayoutNGBlockFlow DIV id='scroller'", - "bounds": [185, 350], + "position": [0, 16], + "bounds": [185, 334], "invalidations": [ - [0, 0, 185, 350] + [0, 0, 185, 334] ], "transform": 1 }
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt index bc26bde..f7b98e7 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt
@@ -14,6 +14,15 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV class='container'", + "position": [1, 1], + "bounds": [2100, 100], + "invalidations": [ + [2000, 0, 100, 100] + ], + "transform": 2 + }, + { "name": "HorizontalScrollbar", "position": [1, 186], "bounds": [285, 15], @@ -25,15 +34,6 @@ "position": [286, 1], "bounds": [15, 200], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV class='container'", - "position": [1, 1], - "bounds": [2100, 185], - "invalidations": [ - [2000, 0, 100, 100] - ], - "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt index fbc2489..8e9fbac 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt
@@ -14,6 +14,15 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV class='container'", + "position": [1, 1], + "bounds": [2100, 100], + "invalidations": [ + [0, 0, 100, 100] + ], + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [1, 186], "bounds": [285, 15], @@ -25,15 +34,6 @@ "position": [286, 1], "bounds": [15, 200], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV class='container'", - "position": [1, 1], - "bounds": [2100, 185], - "invalidations": [ - [0, 0, 100, 100] - ], - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt index b26a78e..9a21d37 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt
@@ -14,6 +14,15 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV class='vertical-rl container'", + "position": [1, 1], + "bounds": [2100, 100], + "invalidations": [ + [0, 0, 100, 100] + ], + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [1, 186], "bounds": [285, 15], @@ -25,15 +34,6 @@ "position": [286, 1], "bounds": [15, 200], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV class='vertical-rl container'", - "position": [1, 1], - "bounds": [2100, 185], - "invalidations": [ - [0, 0, 100, 100] - ], - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/raster-under-invalidation-checking-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/raster-under-invalidation-checking-expected.txt index b9eb545..337ab60 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/raster-under-invalidation-checking-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/raster-under-invalidation-checking-expected.txt
@@ -969,7 +969,7 @@ }, { "name": "LayoutNGBlockFlow DIV id='scroller'", - "bounds": [4000, 20060], + "bounds": [4000, 20000], "invalidations": [ [40, 10010, 60, 40] ],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt index aa4e8da8..d9966282 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt
@@ -33,10 +33,11 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned) DIV id='transformed'", - "bounds": [1050, 1050], + "name": "LayoutNGBlockFlow (relative positioned) DIV id='relative'", + "position": [50, 50], + "bounds": [1000, 1000], "invalidations": [ - [100, 150, 100, 100] + [50, 100, 100, 100] ], "transform": 2 }
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/iframe-scrollbar-hover-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/iframe-scrollbar-hover-expected.txt index 60ed6b8..d2d91db 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/iframe-scrollbar-hover-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/iframe-scrollbar-hover-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [185, 316], "drawsContent": false, "transform": 1
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt index 448414e..c61c8ca 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -13,13 +13,6 @@ "transform": 1 }, { - "name": "VerticalScrollbar", - "position": [769, 0], - "bounds": [15, 300], - "contentsOpaque": true, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow DIV id='outerDiv'", "bounds": [769, 700], "transform": 2 @@ -31,6 +24,13 @@ "transform": 3 }, { + "name": "LayoutNGBlockFlow DIV id='innerDiv'", + "bounds": [300, 800], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 4 + }, + { "name": "VerticalScrollbar", "position": [754, 0], "bounds": [15, 400], @@ -38,9 +38,11 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow DIV id='innerDiv'", - "bounds": [754, 800], - "transform": 4 + "name": "VerticalScrollbar", + "position": [769, 0], + "bounds": [15, 300], + "contentsOpaque": true, + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt index fca30d6..93ace43 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
@@ -40,18 +40,18 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV class='scroller'", - "position": [5, 5], - "bounds": [285, 290], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='icon'", "bounds": [40, 40], "contentsOpaque": true, "backgroundColor": "#FFDDBB", "transform": 3 + }, + { + "name": "LayoutNGBlockFlow (relative positioned) DIV class='list'", + "position": [25, 25], + "bounds": [180, 250], + "drawsContent": false, + "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt index 8544e60..4c4010a 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt
@@ -21,9 +21,10 @@ }, { "name": "LayoutNGBlockFlow (children-inline) DIV id='t'", - "bounds": [65, 198], + "position": [0, 162], + "bounds": [44, 36], "invalidations": [ - [0, 162, 44, 36] + [0, 0, 44, 36] ], "transform": 2 }
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt index 448414e..c61c8ca 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -13,13 +13,6 @@ "transform": 1 }, { - "name": "VerticalScrollbar", - "position": [769, 0], - "bounds": [15, 300], - "contentsOpaque": true, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow DIV id='outerDiv'", "bounds": [769, 700], "transform": 2 @@ -31,6 +24,13 @@ "transform": 3 }, { + "name": "LayoutNGBlockFlow DIV id='innerDiv'", + "bounds": [300, 800], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 4 + }, + { "name": "VerticalScrollbar", "position": [754, 0], "bounds": [15, 400], @@ -38,9 +38,11 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow DIV id='innerDiv'", - "bounds": [754, 800], - "transform": 4 + "name": "VerticalScrollbar", + "position": [769, 0], + "bounds": [15, 300], + "contentsOpaque": true, + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/resize-scrollable-iframe-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/resize-scrollable-iframe-expected.txt index e422b36..a520c3e 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/resize-scrollable-iframe-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/resize-scrollable-iframe-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [1008, 1016], "drawsContent": false, "transform": 1
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt index 5ac04e3..f636d082 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt
@@ -13,6 +13,12 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='target'", + "bounds": [400, 400], + "drawsContent": false, + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [0, 185], "bounds": [85, 15], @@ -34,12 +40,6 @@ [0, 0, 15, 15] ], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV id='target'", - "bounds": [400, 400], - "drawsContent": false, - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt index 2f4117b7..857f9922 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt
@@ -7,8 +7,8 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [1000, 600] + "name": "LayoutNGBlockFlow HTML", + "bounds": [1000, 252] }, { "name": "LayoutNGBlockFlow DIV id='container'", @@ -18,6 +18,13 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='container'", + "position": [1, 1], + "bounds": [2000, 2000], + "drawsContent": false, + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [1, 186], "bounds": [185, 15], @@ -39,13 +46,6 @@ [0, 0, 15, 15] ], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV id='container'", - "position": [1, 1], - "bounds": [2000, 2000], - "drawsContent": false, - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt index e510f32..bc7f98a9 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt
@@ -13,6 +13,12 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV", + "bounds": [150, 300], + "drawsContent": false, + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [0, 85], "bounds": [85, 15], @@ -31,12 +37,6 @@ "position": [85, 85], "bounds": [15, 15], "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV", - "bounds": [150, 300], - "drawsContent": false, - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt index 3e80898..05261d6 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
@@ -13,6 +13,13 @@ "transform": 2 }, { + "name": "LayoutNGBlockFlow MAT id='scroller'", + "position": [0, 18], + "bounds": [345, 2000], + "drawsContent": false, + "transform": 3 + }, + { "name": "VerticalScrollbar", "position": [345, 0], "bounds": [15, 640], @@ -20,12 +27,6 @@ "transform": 2 }, { - "name": "LayoutNGBlockFlow MAT id='scroller'", - "bounds": [345, 2018], - "drawsContent": false, - "transform": 3 - }, - { "name": "LayoutNGBlockFlow (sticky positioned, children-inline) DIV id='sticky'", "bounds": [345, 18], "transform": 4
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt index 9874980..f155145b 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt
@@ -27,9 +27,19 @@ "transform": 1 }, { - "name": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'", + "name": "LayoutNGBlockFlow (relative positioned) DIV class='relative red'", "position": [2, 2], - "bounds": [950, 450], + "bounds": [450, 450], + "contentsOpaque": true, + "backgroundColor": "#FF0000", + "transform": 2 + }, + { + "name": "LayoutNGBlockFlow (positioned) DIV class='absolute green'", + "position": [502, 2], + "bounds": [450, 450], + "contentsOpaque": true, + "backgroundColor": "#008000", "transform": 2 } ],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt index e213f6f..6f8c494 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
@@ -28,9 +28,19 @@ "transform": 2 }, { - "name": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'", + "name": "LayoutNGBlockFlow (relative positioned) DIV class='relative red'", "position": [2, 2], - "bounds": [950, 450], + "bounds": [450, 450], + "contentsOpaque": true, + "backgroundColor": "#FF0000", + "transform": 3 + }, + { + "name": "LayoutNGBlockFlow (positioned) DIV class='absolute green'", + "position": [502, 2], + "bounds": [450, 450], + "contentsOpaque": true, + "backgroundColor": "#008000", "transform": 3 }, {
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt index c511804..1ac9ffc 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -13,13 +13,6 @@ "transform": 1 }, { - "name": "VerticalScrollbar", - "position": [769, 0], - "bounds": [15, 300], - "contentsOpaque": true, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow DIV id='outerDiv'", "bounds": [769, 700], "transform": 2 @@ -31,6 +24,11 @@ "transform": 3 }, { + "name": "LayoutNGBlockFlow DIV id='innerDiv'", + "bounds": [306, 810], + "transform": 4 + }, + { "name": "VerticalScrollbar", "position": [754, 0], "bounds": [15, 400], @@ -38,9 +36,11 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow DIV id='innerDiv'", - "bounds": [754, 810], - "transform": 4 + "name": "VerticalScrollbar", + "position": [769, 0], + "bounds": [15, 300], + "contentsOpaque": true, + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt index c511804..1ac9ffc 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -13,13 +13,6 @@ "transform": 1 }, { - "name": "VerticalScrollbar", - "position": [769, 0], - "bounds": [15, 300], - "contentsOpaque": true, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow DIV id='outerDiv'", "bounds": [769, 700], "transform": 2 @@ -31,6 +24,11 @@ "transform": 3 }, { + "name": "LayoutNGBlockFlow DIV id='innerDiv'", + "bounds": [306, 810], + "transform": 4 + }, + { "name": "VerticalScrollbar", "position": [754, 0], "bounds": [15, 400], @@ -38,9 +36,11 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow DIV id='innerDiv'", - "bounds": [754, 810], - "transform": 4 + "name": "VerticalScrollbar", + "position": [769, 0], + "bounds": [15, 300], + "contentsOpaque": true, + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/text-match-document-change-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/text-match-document-change-expected.txt index 1a0958ce..aa34951f 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/text-match-document-change-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/text-match-document-change-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [285, 1052], "invalidations": [ [8, 26, 256, 36]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-expected.txt index 64f9acc..822e231 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-expected.txt
@@ -10,8 +10,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [600, 250], + "name": "LayoutNGBlockFlow HTML", + "bounds": [600, 8], "drawsContent": false } ] @@ -28,8 +28,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [400, 250], + "name": "LayoutNGBlockFlow HTML", + "bounds": [400, 8], "drawsContent": false } ] @@ -46,8 +46,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [400, 600], + "name": "LayoutNGBlockFlow HTML", + "bounds": [400, 8], "drawsContent": false } ] @@ -64,8 +64,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [800, 600], + "name": "LayoutNGBlockFlow HTML", + "bounds": [800, 8], "drawsContent": false } ]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-generated-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-generated-expected.txt index 64f9acc..822e231 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-generated-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-generated-expected.txt
@@ -10,8 +10,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [600, 250], + "name": "LayoutNGBlockFlow HTML", + "bounds": [600, 8], "drawsContent": false } ] @@ -28,8 +28,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [400, 250], + "name": "LayoutNGBlockFlow HTML", + "bounds": [400, 8], "drawsContent": false } ] @@ -46,8 +46,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [400, 600], + "name": "LayoutNGBlockFlow HTML", + "bounds": [400, 8], "drawsContent": false } ] @@ -64,8 +64,8 @@ ] }, { - "name": "Scrolling background of LayoutView #document", - "bounds": [800, 600], + "name": "LayoutNGBlockFlow HTML", + "bounds": [800, 8], "drawsContent": false } ]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-scrolling-contents-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-scrolling-contents-expected.txt index 66d92ae..b9da11c 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-scrolling-contents-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/window-resize/window-resize-background-image-fixed-scrolling-contents-expected.txt
@@ -10,7 +10,7 @@ ] }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [585, 3016], "drawsContent": false }, @@ -34,7 +34,7 @@ ] }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [385, 3016], "drawsContent": false }, @@ -58,7 +58,7 @@ ] }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [385, 3016], "drawsContent": false }, @@ -82,7 +82,7 @@ ] }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [785, 3016], "drawsContent": false },
diff --git a/third_party/blink/web_tests/platform/mac/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/mac/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt index d9ce637..135e8c9 100644 --- a/third_party/blink/web_tests/platform/mac/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt +++ b/third_party/blink/web_tests/platform/mac/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt
@@ -15,11 +15,17 @@ { "name": "LayoutNGBlockFlow DIV id='outer'", "position": [1, 1], - "bounds": [400, 602], + "bounds": [400, 500], + "drawsContent": false, "transform": 1 }, { "name": "LayoutNGBlockFlow DIV id='inner'", + "bounds": [102, 102], + "transform": 2 + }, + { + "name": "LayoutNGBlockFlow DIV id='inner'", "position": [1, 1], "bounds": [100, 100], "drawsContent": false,
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png index 12f7e23..b224558 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt b/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt index 147236e..d418fde 100644 --- a/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [508, 516], "backgroundColor": "#0000FF", "transform": 1
diff --git a/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt b/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt index 147236e..d418fde 100644 --- a/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt
@@ -7,7 +7,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Scrolling background of LayoutView #document", + "name": "LayoutNGBlockFlow HTML", "bounds": [508, 516], "backgroundColor": "#0000FF", "transform": 1
diff --git a/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt index f71f3a7a..227d6d4 100644 --- a/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -16,6 +16,12 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'", + "position": [1, 1], + "bounds": [285, 800], + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [1, 286], "bounds": [300, 15], @@ -29,12 +35,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'", - "position": [1, 1], - "bounds": [285, 800], - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='fixed lime box'", "position": [10, 100], "bounds": [100, 100],
diff --git a/third_party/blink/web_tests/platform/win/compositing/overflow/content-gains-scrollbars-expected.txt b/third_party/blink/web_tests/platform/win/compositing/overflow/content-gains-scrollbars-expected.txt index 3130a44..3f78ad3 100644 --- a/third_party/blink/web_tests/platform/win/compositing/overflow/content-gains-scrollbars-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/overflow/content-gains-scrollbars-expected.txt
@@ -26,12 +26,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [85, 200], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='vertical' class='content tall'", "bounds": [10, 200], "drawsContent": false, @@ -57,12 +51,6 @@ "transform": 2 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 85], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='horizontal' class='content wide'", "bounds": [200, 10], "drawsContent": false, @@ -102,12 +90,6 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 200], - "drawsContent": false, - "transform": 3 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV id='both' class='content wide tall'", "bounds": [200, 200], "drawsContent": false,
diff --git a/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt index 0a79633..53d0152 100644 --- a/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -13,6 +13,13 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV class='scroller'", + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#C0C0C0", + "transform": 1 + }, + { "name": "HorizontalScrollbar", "position": [0, 285], "bounds": [285, 15], @@ -32,13 +39,6 @@ "bounds": [15, 15], "contentsOpaque": true, "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV class='scroller'", - "bounds": [1000, 1000], - "contentsOpaque": true, - "backgroundColor": "#C0C0C0", - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-scrollbar-layers-expected.txt b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-scrollbar-layers-expected.txt index 02f0c31..aa80a7e 100644 --- a/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-scrollbar-layers-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-scrollbar-layers-expected.txt
@@ -26,12 +26,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [85, 200], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='content tall'", "bounds": [10, 200], "drawsContent": false, @@ -57,12 +51,6 @@ "transform": 2 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 85], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='content wide'", "bounds": [200, 10], "drawsContent": false, @@ -102,12 +90,6 @@ "transform": 3 }, { - "name": "LayoutNGBlockFlow (positioned, children-inline) DIV class='container'", - "bounds": [200, 200], - "drawsContent": false, - "transform": 3 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV class='content wide tall'", "bounds": [200, 200], "drawsContent": false,
diff --git a/third_party/blink/web_tests/platform/win/compositing/overflow/universal-accelerated-overflow-scroll-expected.png b/third_party/blink/web_tests/platform/win/compositing/overflow/universal-accelerated-overflow-scroll-expected.png index 94c97f2..7161ab5 100644 --- a/third_party/blink/web_tests/platform/win/compositing/overflow/universal-accelerated-overflow-scroll-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/overflow/universal-accelerated-overflow-scroll-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/text/input-disabled-state-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/text/input-disabled-state-expected.png index e7943cd1..8e7ee92 100644 --- a/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/text/input-disabled-state-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/text/input-disabled-state-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-expected.png index 1eb382b..ccbe6db 100644 --- a/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-quirks-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-quirks-expected.png index 57921ed..8d9c0bb 100644 --- a/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-quirks-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/forms/textarea/basic-textareas-quirks-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/bugzilla-6473-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/bugzilla-6473-expected.txt index 55d892ce..537ff88 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/bugzilla-6473-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/bugzilla-6473-expected.txt
@@ -7,8 +7,7 @@ "backgroundColor": "#FFFFFF", "invalidations": [ [8, 152, 784, 20], - [8, 136, 784, 20], - [8, 16, 626, 100] + [8, 136, 784, 20] ] } ]
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt index 2970a09..28b6727 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
@@ -13,6 +13,16 @@ "transform": 1 }, { + "name": "LayoutNGBlockFlow DIV id='container'", + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#008000", + "invalidations": [ + [0, 0, 1000, 1000] + ], + "transform": 2 + }, + { "name": "HorizontalScrollbar", "position": [0, 285], "bounds": [385, 15], @@ -32,16 +42,6 @@ "bounds": [15, 15], "contentsOpaque": true, "transform": 1 - }, - { - "name": "LayoutNGBlockFlow DIV id='container'", - "bounds": [1000, 1000], - "contentsOpaque": true, - "backgroundColor": "#008000", - "invalidations": [ - [0, 0, 1000, 1000] - ], - "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt index cea750e..1773cdb45 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer-expected.txt
@@ -40,12 +40,6 @@ "transform": 1 }, { - "name": "LayoutNGBlockFlow DIV id='container'", - "bounds": [3000, 3000], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutNGBlockFlow (positioned) DIV", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt index e73b549..518c8e4 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/composited-overflow-local-background-removed-expected.txt
@@ -36,9 +36,10 @@ }, { "name": "LayoutNGBlockFlow DIV id='scroller'", - "bounds": [185, 352], + "position": [0, 16], + "bounds": [185, 336], "invalidations": [ - [0, 0, 185, 352] + [0, 0, 185, 336] ], "transform": 1 }
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/raster-under-invalidation-checking-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/raster-under-invalidation-checking-expected.txt index af0cd403..6544ff4 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/raster-under-invalidation-checking-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/raster-under-invalidation-checking-expected.txt
@@ -970,7 +970,7 @@ }, { "name": "LayoutNGBlockFlow DIV id='scroller'", - "bounds": [4000, 20060], + "bounds": [4000, 20000], "invalidations": [ [40, 10010, 60, 40] ],
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png index b2e3be0..b5ca916 100644 --- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png +++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/autofill/autofilled-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/scrollbars/overlay-scrollbar-over-child-layer-nested.html b/third_party/blink/web_tests/scrollbars/overlay-scrollbar-over-child-layer-nested.html index 3b3d1a97..7253fcb6 100644 --- a/third_party/blink/web_tests/scrollbars/overlay-scrollbar-over-child-layer-nested.html +++ b/third_party/blink/web_tests/scrollbars/overlay-scrollbar-over-child-layer-nested.html
@@ -1,5 +1,4 @@ <!DOCTYPE html> -<meta name="fuzzy" content="maxDifference=0-255;totalPixels=0-3"> <script> if (window.internals) internals.useMockOverlayScrollbars();
diff --git a/third_party/blink/web_tests/scrollbars/overlay-scrollbars-with-scrollbar-color-expected.txt b/third_party/blink/web_tests/scrollbars/overlay-scrollbars-with-scrollbar-color-expected.txt index 3a82d86..1b0fb89 100644 --- a/third_party/blink/web_tests/scrollbars/overlay-scrollbars-with-scrollbar-color-expected.txt +++ b/third_party/blink/web_tests/scrollbars/overlay-scrollbars-with-scrollbar-color-expected.txt
@@ -15,11 +15,17 @@ { "name": "LayoutNGBlockFlow DIV id='outer'", "position": [1, 1], - "bounds": [400, 602], + "bounds": [400, 500], + "drawsContent": false, "transform": 1 }, { "name": "LayoutNGBlockFlow DIV id='inner'", + "bounds": [102, 102], + "transform": 2 + }, + { + "name": "LayoutNGBlockFlow DIV id='inner'", "position": [1, 1], "bounds": [100, 100], "drawsContent": false,
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.png b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.png index f6dd657b..d7e5a72 100644 --- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.png +++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt index d9ce637..135e8c9 100644 --- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt +++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbars-within-overflow-scroll-expected.txt
@@ -15,11 +15,17 @@ { "name": "LayoutNGBlockFlow DIV id='outer'", "position": [1, 1], - "bounds": [400, 602], + "bounds": [400, 500], + "drawsContent": false, "transform": 1 }, { "name": "LayoutNGBlockFlow DIV id='inner'", + "bounds": [102, 102], + "transform": 2 + }, + { + "name": "LayoutNGBlockFlow DIV id='inner'", "position": [1, 1], "bounds": [100, 100], "drawsContent": false,
diff --git a/third_party/catapult b/third_party/catapult index d80f7d1..99cae58 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit d80f7d1ae4c6c010ecc8e660588f33f5768cb177 +Subproject commit 99cae5876c51001792d8225f77579eb537188490
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index 1cdf052..d5d8b1b 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit 1cdf05204cf5365bcb63fd8b306750b054be5c73 +Subproject commit d5d8b1bb4ddbde9f4752ca8ae28543a31b64e211
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index cb3c970..f12c052 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit cb3c970179dfea108e67796c202f519068d1d48f +Subproject commit f12c052fc715d18e765fe3f78fdb3584a14baf4b
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index ba8834932..eba6d72 100644 --- a/third_party/metrics_proto/README.chromium +++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Metrics Protos Short Name: metrics_proto URL: This is the canonical public repository -Version: 600904906 -Date: 2024-01-23 UTC +Version: 597734888 +Date: 2024-01-12 UTC License: BSD License File: LICENSE Shipped: yes
diff --git a/third_party/metrics_proto/ukm/source.proto b/third_party/metrics_proto/ukm/source.proto index 2388d41f..0b4eaec8 100644 --- a/third_party/metrics_proto/ukm/source.proto +++ b/third_party/metrics_proto/ukm/source.proto
@@ -27,6 +27,7 @@ WEB_IDENTITY_ID = 10; CHROMEOS_WEBSITE_ID = 11; EXTENSION_ID = 12; + NOTIFICATION_ID = 13; } // Android Activity Type defined by
diff --git a/third_party/pdfium b/third_party/pdfium index aad37f1..64571d5 160000 --- a/third_party/pdfium +++ b/third_party/pdfium
@@ -1 +1 @@ -Subproject commit aad37f1a2976c5379b8a2aba60a330d7aba55164 +Subproject commit 64571d5d1f1eb7e91b7237b37d7bffecebb77981
diff --git a/third_party/skia b/third_party/skia index c653705..d503bc9c 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit c653705482bc2a85d42e19cb441ce5e250d81e39 +Subproject commit d503bc9c6e46b399fe7f89057c21b7c393ccd845
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index d8fc430..52f57ac 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit d8fc43000b3e5e924679432724228bf75695ca27 +Subproject commit 52f57acdf69e747b0cea3c458a6ec6467dcb6d8a
diff --git a/tools/codeql/queries/bad_message_no_return.ql b/tools/codeql/queries/bad_message_no_return.ql new file mode 100644 index 0000000..eb859046 --- /dev/null +++ b/tools/codeql/queries/bad_message_no_return.ql
@@ -0,0 +1,51 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import cpp +import lib.Chromium + +/** + * @name potential ReceivedBadMessage call without return. + * @description Detects instances where bad_message::ReceivedBadMessage + * is called and not immediately followed by a return statement. + * @kind problem + * @problem.severity warning + * @id cpp/report-bad-message-without-return + */ + +class BadMessageCall extends FunctionCall { + BadMessageCall() { + + // bad_message::ReceivedBadMessage + this.getTarget().hasQualifiedName("bad_message", "ReceivedBadMessage") or + + // content::bad_message::ReceivedBadMessage + this.getTarget().hasQualifiedName("content::bad_message", "ReceivedBadMessage") + } +} + +from BadMessageCall call, Function f +where + Chromium::isChromiumCode(call) and + + call.getEnclosingFunction() = f and + + // Ignore any calls with a returnStatement in the same enclosing block. + not exists(ReturnStmt returnStmt | + call.getEnclosingBlock() = returnStmt.getEnclosingBlock() + ) and + + // Ignore any calls with a returnStatement immediately after in the block + exists(Stmt stmtAfterCall | + stmtAfterCall.getEnclosingFunction() = f and + stmtAfterCall.getLocation().getStartLine() > call.getLocation().getStartLine() and + not stmtAfterCall instanceof ReturnStmt and + not exists(ReturnStmt returnBetween | + returnBetween.getEnclosingFunction() = f and + returnBetween.getLocation().getStartLine() > call.getLocation().getStartLine() and + returnBetween.getLocation().getStartLine() < stmtAfterCall.getLocation().getStartLine() + ) + ) +select call, + call.getLocation().getFile().getRelativePath() + ":" + call.getLocation().getStartLine().toString()
diff --git a/tools/codeql/queries/lib/Chromium.qll b/tools/codeql/queries/lib/Chromium.qll new file mode 100644 index 0000000..41bd981 --- /dev/null +++ b/tools/codeql/queries/lib/Chromium.qll
@@ -0,0 +1,47 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import cpp +import semmle.code.cpp.dataflow.DataFlow + +module Chromium { + predicate isChromiumCode(Element e) { isChromiumPath(e.getFile()) } + + predicate isChromiumPath(Container c) { + exists(string path | + path = c.getAbsolutePath() and + not path.matches("%buildtools%") and + not path.matches("%include/c++%") and + not path.matches("/usr/include%") and + not path.matches("%native_client%") + ) + } + + predicate isUbiquitousChromiumPath(Container c) { + exists(string path | + path = c.getAbsolutePath() and + not path.matches("%ios_internal%") and + not path.matches("%ios%") and + not path.matches("%android_webview%") and + not path.matches("%chromecast%") + ) + } + + predicate isUbiquitousChromiumCode(Element e) { + isChromiumPath(e.getFile()) and + isUbiquitousChromiumPath(e.getFile()) + } + + predicate isBlinkCode(Element e) { + isChromiumCode(e.getFile()) and + isBlinkPath(e.getFile()) + } + + predicate isBlinkPath(Container c) { + exists(string path | + path = c.getAbsolutePath() and + path.matches("%third_party/blink%") + ) + } +}
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 5b732a3..5ee9c00 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -841,6 +841,10 @@ "META": {"join": 2, "sizes": {"includes": [20]}}, "includes": [5880], }, + "<(SHARED_INTERMEDIATE_DIR)/ash/webui/print_preview_cros/resources/resources.grd": { + "META": {"sizes": {"includes": [50]}}, + "includes": [5885], + }, "<(SHARED_INTERMEDIATE_DIR)/ash/webui/sample_system_web_app_ui/resources/trusted/resources.grd": { "META": {"sizes": {"includes": [50],}}, "includes": [5900],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index dc07b6cd..bdf212f 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -18600,6 +18600,7 @@ <int value="-950411190" label="WebViewCpuAffinityRestrictToLittleCores:enabled"/> <int value="-950384924" label="OmniboxDisableInstantExtendedLimit:enabled"/> + <int value="-949956361" label="ControlledFrame:disabled"/> <int value="-949178861" label="enable-new-avatar-menu"/> <int value="-948930847" label="EnableOopPrintDrivers:enabled"/> <int value="-948684341" label="OmniboxBlurWithEscape:enabled"/> @@ -20948,6 +20949,7 @@ <int value="138995035" label="SafeBrowsingAsyncRealTimeCheck:enabled"/> <int value="139569991" label="SharingDeviceExpiration:disabled"/> <int value="139603247" label="AudioHFPMicSRToggle:disabled"/> + <int value="139974547" label="ControlledFrame:enabled"/> <int value="140257184" label="ChromeOSAmbientModeNewUrl:enabled"/> <int value="140427435" label="OmniboxReportSearchboxStats:enabled"/> <int value="140778694"
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index a9937d75..88db87b 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -974,7 +974,7 @@ <owner>clank-app-team@google.com</owner> <summary> Records the primary display (screen) size in tens of inches with 0.2 inches - (2 units) granularity, during deferred startup. The display size is not + (2 units) granularity, during deferred startup. The re-enabled size is not affected by Android N multi-window mode. </summary> </histogram> @@ -1028,27 +1028,35 @@ </histogram> <histogram name="Android.DownloadManager.OpenSource.Audio" - enum="AndroidDownloadOpenSource" expires_after="2023-07-09"> + enum="AndroidDownloadOpenSource" expires_after="2024-05-31"> <owner>shaktisahu@chromium.org</owner> <owner>clank-downloads@google.com</owner> - <summary>Records how users open audio download files on Android.</summary> + <summary> + Records how users open audio download files on Android. This histogram was + previously expired on 2023-07-09, and was re-enabled on 2024-02-12. + </summary> </histogram> <histogram name="Android.DownloadManager.OpenSource.Other" - enum="AndroidDownloadOpenSource" expires_after="2023-06-25"> + enum="AndroidDownloadOpenSource" expires_after="2024-05-31"> <owner>shaktisahu@chromium.org</owner> <owner>clank-downloads@google.com</owner> <summary> Records the entry point for users opening downloaded files on Android, that - are not audio nor video. + are not audio nor video. Records how users open audio download files on + Android. This histogram was previously expired on 2023-06-25, and was + re-enabled on 2024-02-12. </summary> </histogram> <histogram name="Android.DownloadManager.OpenSource.Video" - enum="AndroidDownloadOpenSource" expires_after="2023-06-25"> + enum="AndroidDownloadOpenSource" expires_after="2024-05-31"> <owner>shaktisahu@chromium.org</owner> <owner>clank-downloads@google.com</owner> - <summary>Records how users open video download files on Android.</summary> + <summary> + Records how users open video download files on Android. This histogram was + previously expired on 2023-06-25, and was re-enabled on 2024-02-12. + </summary> </histogram> <histogram name="Android.DownloadManager.ServiceStopped.DownloadForeground" @@ -1089,11 +1097,13 @@ </histogram> <histogram name="Android.DownloadPage.OpenSource" - enum="AndroidDownloadOpenSource" expires_after="2023-04-23"> + enum="AndroidDownloadOpenSource" expires_after="2024-05-31"> <owner>qinmin@chromium.org</owner> <owner>clank-downloads@google.com</owner> <summary> - Records the entry point for users opening the download page on Android. + Records the entry point for users opening the download page on Android. This + histogram was previously expired on 2023-04-23, and was re-enabled on + 2024-02-12. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml index c6dd95b..7efc9cd1 100644 --- a/tools/metrics/histograms/metadata/arc/histograms.xml +++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -1536,6 +1536,26 @@ <summary>Records the style of an Arc notification when it's created.</summary> </histogram> +<histogram + name="Arc.NotificationView.{ChildView}.{FadeType}.AnimationSmoothness" + units="%" expires_after="2024-06-01"> + <owner>shuminghao@google.com</owner> + <owner>arc-framework@google.com</owner> + <summary> + Relative smoothness of the fade animation of {ChildView} inside a + notification view. 100% represents ideally smooth 60 frames per second. + Emitted when the fade in/out animation is completed. + </summary> + <token key="ChildView"> + <variant name="CollapsedSummaryView"/> + <variant name="ContentView"/> + </token> + <token key="FadeType"> + <variant name="FadeIn"/> + <variant name="FadeOut"/> + </token> +</histogram> + <histogram name="Arc.OptInAction" enum="ArcOptInAction" expires_after="2024-06-30"> <owner>mhasank@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/ash/enums.xml b/tools/metrics/histograms/metadata/ash/enums.xml index 3cf3042..500fdc6 100644 --- a/tools/metrics/histograms/metadata/ash/enums.xml +++ b/tools/metrics/histograms/metadata/ash/enums.xml
@@ -441,6 +441,12 @@ <int value="2" label="Delete file"/> </enum> +<enum name="ClassroomUserAction"> + <int value="0" label="Assignment list selected"/> + <int value="1" label="Header icon pressed"/> + <int value="2" label="Student assignment pressed"/> +</enum> + <enum name="DataFetchEventSource"> <int value="0" label="PostLoginFullRestore"/> <int value="1" label="Overview"/> @@ -1819,6 +1825,7 @@ <int value="2" label="Session exit due to window destruction"/> <int value="3" label="Session exit due to shutdown"/> <int value="4" label="Session exit due to unspecified reasons"/> + <int value="5" label="Session exit due to converting to tablet mode"/> </enum> <enum name="SplitViewSwapWindowsSource"> @@ -1832,6 +1839,18 @@ <int value="2" label="Went back on the home screen"/> </enum> +<enum name="TasksUserAction"> + <int value="0" label="Active task list changed"/> + <int value="1" label="Task marked complete"/> + <int value="2" label="Task marked incomplete"/> + <int value="3" label="Add task started"/> + <int value="4" label="Modify task started"/> + <int value="5" label="Header button clicked"/> + <int value="6" label="Add new task button clicked"/> + <int value="7" label="Footer button clicked"/> + <int value="8" label="Edit in Google Tasks button clicked"/> +</enum> + <enum name="TimeManagementGlanceablesFeatureStatus"> <int value="0" label="Disabled"/> <int value="1" label="Enabled - trusted tester"/>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 05f1689..fc593a09 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -3664,6 +3664,16 @@ </summary> </histogram> +<histogram name="Ash.Glanceables.TimeManagement.Classroom.UserAction" + enum="ClassroomUserAction" expires_after="2024-12-31"> + <owner>tbarzic@google.com</owner> + <owner>chromeos-launcher@google.com</owner> + <summary> + User actions performed in the Time Management Glanceables bubble for Google + Classroom + </summary> +</histogram> + <histogram name="Ash.Glanceables.TimeManagement.FeatureStatus" enum="TimeManagementGlanceablesFeatureStatus" expires_after="2024-12-31"> <owner>amitrokhin@google.com</owner> @@ -3759,6 +3769,16 @@ </summary> </histogram> +<histogram name="Ash.Glanceables.TimeManagement.Tasks.UserAction" + enum="TasksUserAction" expires_after="2024-12-31"> + <owner>tbarzic@google.com</owner> + <owner>chromeos-launcher@google.com</owner> + <summary> + User actions performed in the Time Management Glanceables bubble for Google + Tasks + </summary> +</histogram> + <histogram name="Ash.Glanceables.TimeManagement.TasksCountInDefaultTaskList" units="tasks" expires_after="2024-12-31"> <owner>amitrokhin@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/help_app/histograms.xml b/tools/metrics/histograms/metadata/help_app/histograms.xml index 95cac56..d9e1ac7 100644 --- a/tools/metrics/histograms/metadata/help_app/histograms.xml +++ b/tools/metrics/histograms/metadata/help_app/histograms.xml
@@ -23,7 +23,7 @@ <histograms> <histogram name="Discover.SearchConcept.ReadStatus" - enum="HelpAppSearchConceptReadStatus" expires_after="2024-03-24"> + enum="HelpAppSearchConceptReadStatus" expires_after="2025-03-24"> <owner>chenjih@google.com</owner> <owner>tby@chromium.org</owner> <owner>showoff-eng@google.com</owner> @@ -37,7 +37,7 @@ </histogram> <histogram name="Discover.SearchConcept.WriteStatus" - enum="HelpAppSearchConceptWriteStatus" expires_after="2024-03-24"> + enum="HelpAppSearchConceptWriteStatus" expires_after="2025-03-24"> <owner>chenjih@google.com</owner> <owner>tby@chromium.org</owner> <owner>showoff-eng@google.com</owner> @@ -62,7 +62,7 @@ </histogram> <histogram name="Discover.SearchHandler.SearchResultStatus" - enum="HelpAppSearchHandlerSearchResultStatus" expires_after="2024-03-24"> + enum="HelpAppSearchHandlerSearchResultStatus" expires_after="2025-03-24"> <owner>chenjih@google.com</owner> <owner>tby@chromium.org</owner> <owner>zufeng@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml index d7cbe888..9f25bbdc 100644 --- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -4525,6 +4525,7 @@ <suffix name="OsUrlHandler" label="OsUrlHandler"/> <suffix name="Personalization" label="Personalization"/> <suffix name="PrintManagement" label="PrintManagement"/> + <suffix name="PrintPreviewCrOS" label="Print Preview CrOS"/> <suffix name="Projector" label="Projector"/> <suffix name="Sample" label="Sample"/> <suffix name="Scanning" label="Scanning"/>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml index 1cd4c9ce..27d3fe432 100644 --- a/tools/metrics/histograms/metadata/ios/histograms.xml +++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -3810,7 +3810,7 @@ </histogram> <histogram name="IOS.Variations.FirstRun.SeedApplicationStage" - enum="VariationsFirstRunSeedApplicationStage" expires_after="2024-07-01"> + enum="VariationsFirstRunSeedApplicationStage" expires_after="2024-09-26"> <owner>ginnyhuang@chromium.org</owner> <owner>huitingyu@google.com</owner> <owner>bling-get-set-up@google.com</owner> @@ -3826,7 +3826,7 @@ </histogram> <histogram name="IOS.Variations.FirstRun.SeedFetchResult" - enum="VariationsSeedFetchResult" expires_after="2024-03-26"> + enum="VariationsSeedFetchResult" expires_after="2024-09-26"> <owner>ginnyhuang@chromium.org</owner> <owner>bling-get-set-up@google.com</owner> <summary> @@ -3837,7 +3837,7 @@ </histogram> <histogram name="IOS.Variations.FirstRun.SeedFetchTime" units="ms" - expires_after="2024-08-04"> + expires_after="2024-09-26"> <owner>ginnyhuang@chromium.org</owner> <owner>bling-get-set-up@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml index bec4441..287d5f1 100644 --- a/tools/metrics/histograms/metadata/net/histograms.xml +++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -341,7 +341,7 @@ </histogram> <histogram name="HttpCache.AddTransactionToEntry" units="ms" - expires_after="2024-03-24"> + expires_after="2024-08-13"> <owner>bashi@chromium.org</owner> <owner>net-dev@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml index d0063f9..727ee4a7 100644 --- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml +++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -130,7 +130,7 @@ </variants> <histogram name="SegmentationPlatform.AdaptiveToolbar.SegmentSelected.Startup" - enum="AdaptiveToolbarButtonVariant" expires_after="2024-06-30"> + enum="AdaptiveToolbarButtonVariant" expires_after="2025-06-30"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -141,7 +141,7 @@ <histogram name="SegmentationPlatform.AdaptiveToolbar.SegmentSelection.Computed" - enum="AdaptiveToolbarButtonVariant" expires_after="2024-04-28"> + enum="AdaptiveToolbarButtonVariant" expires_after="2025-04-28"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -151,7 +151,7 @@ </histogram> <histogram name="SegmentationPlatform.AdaptiveToolbar.SegmentSwitched" - enum="AdaptiveToolbarSegmentSwitch" expires_after="2024-06-30"> + enum="AdaptiveToolbarSegmentSwitch" expires_after="2025-06-30"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -163,7 +163,7 @@ <histogram name="SegmentationPlatform.ClassificationRequest.TotalDuration.{SegmentationKey}" - units="ms" expires_after="2024-06-30"> + units="ms" expires_after="2025-06-30"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -180,7 +180,7 @@ <histogram name="SegmentationPlatform.DefaultModelDelivery.Metadata.FeatureCount.{SegmentationModel}" - units="features" expires_after="2024-08-14"> + units="features" expires_after="2025-08-14"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -195,7 +195,7 @@ <histogram name="SegmentationPlatform.DefaultModelDelivery.Metadata.Validation.{ValidationPhase}.{SegmentationModel}" - enum="SegmentationPlatformValidationResult" expires_after="2024-08-14"> + enum="SegmentationPlatformValidationResult" expires_after="2025-08-14"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -211,7 +211,7 @@ </histogram> <histogram name="SegmentationPlatform.DefaultModelDelivery.Received" - enum="SegmentationPlatformSegmentationModel" expires_after="2024-08-14"> + enum="SegmentationPlatformSegmentationModel" expires_after="2025-08-14"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -225,7 +225,7 @@ <histogram name="SegmentationPlatform.DefaultModelDelivery.SaveResult.{SegmentationModel}" - enum="BooleanSuccess" expires_after="2024-08-14"> + enum="BooleanSuccess" expires_after="2025-08-14"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -240,7 +240,7 @@ <histogram name="SegmentationPlatform.DefaultModelDelivery.SegmentIdMatches.{SegmentationModel}" - enum="BooleanYesNo" expires_after="2024-08-14"> + enum="BooleanYesNo" expires_after="2025-08-14"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -254,7 +254,7 @@ </histogram> <histogram name="SegmentationPlatform.DeviceCountByOsType.{OsType}" - units="devices" expires_after="2024-10-01"> + units="devices" expires_after="2025-10-01"> <owner>junzou@chromium.org</owner> <owner>ssid@chromium.org</owner> <owner>chrome-segmentation-team@google.com</owner> @@ -282,7 +282,7 @@ <histogram name="SegmentationPlatform.FeatureProcessing.Error.{SegmentationModel}" enum="SegmentationPlatformFeatureProcessingError" - expires_after="2024-10-01"> + expires_after="2025-10-01"> <owner>haileywang@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -295,7 +295,7 @@ </histogram> <histogram name="SegmentationPlatform.Init.CreationToInitializationLatency" - units="ms" expires_after="2024-08-04"> + units="ms" expires_after="2025-08-04"> <owner>ssid@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -306,7 +306,7 @@ <histogram name="SegmentationPlatform.Init.ModelUpdatedTimeDifferenceInDays.{SegmentID}" - units="days" expires_after="2024-10-01"> + units="days" expires_after="2025-10-01"> <owner>haileywang@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -320,7 +320,7 @@ <histogram name="SegmentationPlatform.Init.ProcessCreationToServiceCreationLatency" - units="ms" expires_after="2024-06-30"> + units="ms" expires_after="2025-06-30"> <owner>ssid@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -330,7 +330,7 @@ </histogram> <histogram name="SegmentationPlatform.Maintenance.CleanupSignalSuccessCount" - units="signals" expires_after="2024-10-01"> + units="signals" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -344,7 +344,7 @@ <histogram name="SegmentationPlatform.Maintenance.CompactionResult.{SignalType}" - enum="BooleanSuccess" expires_after="2024-10-01"> + enum="BooleanSuccess" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -358,7 +358,7 @@ </histogram> <histogram name="SegmentationPlatform.Maintenance.SignalIdentifierCount" - units="ids" expires_after="2024-10-01"> + units="ids" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -371,7 +371,7 @@ </histogram> <histogram name="SegmentationPlatform.ModelAvailability.{SegmentationModel}" - enum="SegmentationModelAvailability" expires_after="2024-10-01"> + enum="SegmentationModelAvailability" expires_after="2025-10-01"> <owner>ssid@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -390,7 +390,7 @@ <histogram name="SegmentationPlatform.ModelDelivery.DeleteResult.{SegmentationModel}" - enum="BooleanSuccess" expires_after="2024-10-01"> + enum="BooleanSuccess" expires_after="2025-10-01"> <owner>salg@chromium.org</owner> <owner>ssid@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -406,7 +406,7 @@ <histogram name="SegmentationPlatform.ModelDelivery.HasMetadata.{SegmentationModel}" - enum="BooleanYesNo" expires_after="2024-10-01"> + enum="BooleanYesNo" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -422,7 +422,7 @@ <histogram name="SegmentationPlatform.ModelDelivery.Metadata.FeatureCount.{SegmentationModel}" - units="features" expires_after="2024-10-01"> + units="features" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -438,7 +438,7 @@ <histogram name="SegmentationPlatform.ModelDelivery.Metadata.Validation.{ValidationPhase}.{SegmentationModel}" - enum="SegmentationPlatformValidationResult" expires_after="2024-10-01"> + enum="SegmentationPlatformValidationResult" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -455,7 +455,7 @@ </histogram> <histogram name="SegmentationPlatform.ModelDelivery.Received" - enum="SegmentationPlatformSegmentationModel" expires_after="2024-06-30"> + enum="SegmentationPlatformSegmentationModel" expires_after="2025-06-30"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -470,7 +470,7 @@ <histogram name="SegmentationPlatform.ModelDelivery.SaveResult.{SegmentationModel}" - enum="BooleanSuccess" expires_after="2024-10-01"> + enum="BooleanSuccess" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -486,7 +486,7 @@ <histogram name="SegmentationPlatform.ModelDelivery.SegmentIdMatches.{SegmentationModel}" - enum="BooleanYesNo" expires_after="2024-10-01"> + enum="BooleanYesNo" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -502,7 +502,7 @@ <histogram name="SegmentationPlatform.ModelExecution.DefaultProvider.Status.{SegmentationModel}" - enum="SegmentationPlatformModelExecutionStatus" expires_after="2024-10-01"> + enum="SegmentationPlatformModelExecutionStatus" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -516,7 +516,7 @@ <histogram name="SegmentationPlatform.ModelExecution.Duration.FeatureProcessing.{SegmentationModel}" - units="ms" expires_after="2024-10-01"> + units="ms" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -531,7 +531,7 @@ <histogram name="SegmentationPlatform.ModelExecution.Duration.Model.{SegmentationModel}.{ModelExecutionStatus}" - units="ms" expires_after="2024-10-01"> + units="ms" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -548,7 +548,7 @@ <histogram name="SegmentationPlatform.ModelExecution.Duration.Total.{SegmentationModel}.{ModelExecutionStatus}" - units="ms" expires_after="2024-10-01"> + units="ms" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -567,7 +567,7 @@ <histogram name="SegmentationPlatform.ModelExecution.Result.{Index}.{SegmentationModel}" - units="score" expires_after="2024-10-01"> + units="score" expires_after="2025-10-01"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -583,7 +583,7 @@ <histogram name="SegmentationPlatform.ModelExecution.Result.{SegmentationModel}" - units="score" expires_after="2024-10-01"> + units="score" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -599,7 +599,7 @@ <histogram name="SegmentationPlatform.ModelExecution.SaveResult.{SegmentationModel}" - enum="BooleanSuccess" expires_after="2024-10-01"> + enum="BooleanSuccess" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -615,7 +615,7 @@ <histogram name="SegmentationPlatform.ModelExecution.Status.{SegmentationModel}" - enum="SegmentationPlatformModelExecutionStatus" expires_after="2024-10-01"> + enum="SegmentationPlatformModelExecutionStatus" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -642,7 +642,7 @@ <histogram name="SegmentationPlatform.ModelExecution.ZeroValuePercent.{SegmentationModel}" - units="%" expires_after="2024-10-01"> + units="%" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -657,7 +657,7 @@ <histogram name="SegmentationPlatform.SegmentInfoDatabase.ProtoDBUpdateResult.{SegmentationKey}" - enum="BooleanSuccess" expires_after="2024-10-01"> + enum="BooleanSuccess" expires_after="2025-10-01"> <owner>salg@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -674,7 +674,7 @@ <histogram name="SegmentationPlatform.SegmentSelectionOnDemand.Duration.{SegmentationKey}.{SelectedSegment}" - units="ms" expires_after="2024-10-01"> + units="ms" expires_after="2025-10-01"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -696,7 +696,7 @@ </histogram> <histogram name="SegmentationPlatform.SelectionFailedReason" - enum="SegmentationSelectionFailureReason" expires_after="2024-02-05"> + enum="SegmentationSelectionFailureReason" expires_after="2025-02-05"> <owner>ssid@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -707,7 +707,7 @@ </histogram> <histogram name="SegmentationPlatform.SelectionFailedReason.{SegmentationKey}" - enum="SegmentationSelectionFailureReason" expires_after="2024-10-01"> + enum="SegmentationSelectionFailureReason" expires_after="2025-10-01"> <owner>ssid@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -725,7 +725,7 @@ <histogram name="SegmentationPlatform.SignalDatabase.GetSamples.DatabaseEntryCount" - units="entries" expires_after="2024-10-01"> + units="entries" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -740,7 +740,7 @@ </histogram> <histogram name="SegmentationPlatform.SignalDatabase.GetSamples.Result" - enum="BooleanSuccess" expires_after="2024-05-26"> + enum="BooleanSuccess" expires_after="2025-05-26"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -753,7 +753,7 @@ </histogram> <histogram name="SegmentationPlatform.SignalDatabase.GetSamples.SampleCount" - units="samples" expires_after="2024-10-01"> + units="samples" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -768,7 +768,7 @@ </histogram> <histogram name="SegmentationPlatform.Signals.ListeningCount.{SignalType}" - units="signals" expires_after="2024-10-01"> + units="signals" expires_after="2025-10-01"> <owner>nyquist@chromium.org</owner> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -781,7 +781,7 @@ </histogram> <histogram name="SegmentationPlatform.StructuredMetrics.TooManyTensors.Count" - units="tensors" expires_after="2024-10-01"> + units="tensors" expires_after="2025-10-01"> <owner>qinmin@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -792,7 +792,7 @@ </histogram> <histogram name="SegmentationPlatform.SyncSessions.RecordTabCountAtSyncUpdate" - units="tabs" expires_after="2024-06-30"> + units="tabs" expires_after="2025-06-30"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -802,7 +802,7 @@ </histogram> <histogram name="SegmentationPlatform.SyncSessions.TabsCountAtStartup" - units="tabs" expires_after="2024-06-30"> + units="tabs" expires_after="2025-06-30"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -813,7 +813,7 @@ <histogram name="SegmentationPlatform.SyncSessions.TimeFromStartupToFirstSyncUpdate" - units="ms" expires_after="2024-06-30"> + units="ms" expires_after="2025-06-30"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -825,7 +825,7 @@ </histogram> <histogram name="SegmentationPlatform.SyncSessions.TimeFromStartupToSyncUpdate" - units="ms" expires_after="2024-10-01"> + units="ms" expires_after="2025-10-01"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -839,7 +839,7 @@ <histogram name="SegmentationPlatform.SyncSessions.TimeFromTabLoadedToSyncUpdate" - units="ms" expires_after="2024-06-30"> + units="ms" expires_after="2025-06-30"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -853,7 +853,7 @@ <histogram name="SegmentationPlatform.SyncSessions.{TimeInterval}TabCountAtFirstSyncUpdate" - units="tabs" expires_after="2024-06-30"> + units="tabs" expires_after="2025-06-30"> <owner>ritikagup@google.com</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -874,7 +874,7 @@ <histogram name="SegmentationPlatform.TrainingDataCollectionEvents.{SegmentationModel}" enum="SegmentationPlatformTrainingDataCollectionEvent" - expires_after="2024-10-01"> + expires_after="2025-10-01"> <owner>ssid@chromium.org</owner> <owner>qinmin@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> @@ -887,7 +887,7 @@ </histogram> <histogram name="SegmentationPlatform.{BooleanModel}.SegmentSwitched" - enum="SegmentationBooleanSegmentSwitch" expires_after="2024-10-01"> + enum="SegmentationBooleanSegmentSwitch" expires_after="2025-10-01"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -900,7 +900,7 @@ <histogram name="SegmentationPlatform.{SegmentationKey}.PostProcessing.TopLabel.Computed" - units="index" expires_after="2024-10-01"> + units="index" expires_after="2025-10-01"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -914,7 +914,7 @@ <histogram name="SegmentationPlatform.{SegmentationKey}.PostProcessing.TopLabel.Switched" - units="index" expires_after="2024-10-01"> + units="index" expires_after="2025-10-01"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary> @@ -928,7 +928,7 @@ <histogram name="SegmentationPlatform.{SegmentationKey}.SegmentSelection.Computed2" - enum="SegmentationPlatformSegmentationModel" expires_after="2024-10-01"> + enum="SegmentationPlatformSegmentationModel" expires_after="2025-10-01"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-segmentation-platform@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/signin/enums.xml b/tools/metrics/histograms/metadata/signin/enums.xml index ede12f47..b45edb3 100644 --- a/tools/metrics/histograms/metadata/signin/enums.xml +++ b/tools/metrics/histograms/metadata/signin/enums.xml
@@ -714,6 +714,11 @@ reverted to the initial state: signed out in the profile but keeping the account on the web only. </int> + <int value="31" label="IdleTimeout policy triggered signout"> + The enterprise policy IdleTimeout was set, and the IdleTimeoutActions list + value included `sign_out`. When the user has been idle for the time + specified in the policy value, they will be signed out. + </int> </enum> <enum name="SigninSSOIdentityListRequestCacheState">
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 2946154..06a4b1b 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,7 +6,7 @@ }, "win": { "hash": "a783ab3fdb019ab9f920723578ff14b5c3247ccf", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/958abadb3d3c8914fe0a50ae84b5ad7551a60cf9/trace_processor_shell.exe" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/e01c38d714f4d55c7ef67aa9414c69479b051b38/trace_processor_shell.exe" }, "linux_arm": { "hash": "46739eeb4b8f2a65a8a0aac57743767e6407f7bb",
diff --git a/tools/search_engine_choice/search_engine_icons_utils.py b/tools/search_engine_choice/search_engine_icons_utils.py index a09a604..14070af 100644 --- a/tools/search_engine_choice/search_engine_icons_utils.py +++ b/tools/search_engine_choice/search_engine_icons_utils.py
@@ -47,7 +47,6 @@ Returns the set of used engines. by checking which engines are used in `template_url_prepopulate_data.cc`. """ - print('Populating used engines set') used_engines = set() SE_NAME_REGEX = re.compile(r'.*SearchEngineTier::[A-Za-z]+, &(.+)},') with open(src_dir + config_file_path, 'r',
diff --git a/tools/typescript/definitions/chrome_test.d.ts b/tools/typescript/definitions/chrome_test.d.ts index 80042b2..79f45323 100644 --- a/tools/typescript/definitions/chrome_test.d.ts +++ b/tools/typescript/definitions/chrome_test.d.ts
@@ -10,6 +10,7 @@ export function assertEq<T>(expected: T, actual: T, message?: string): void; export function assertFalse(value: boolean, message?: string): void; export function assertTrue(value: boolean, message?: string): asserts value; + export function checkDeepEq<T>(value: T, actual: T): boolean; export function fail(message?: string): never; export function runTests(tests: Array<() => void>): void; export function runWithUserGesture(callback: () => void): void;
diff --git a/ui/compositor/debug_utils.cc b/ui/compositor/debug_utils.cc index 95cd13e..330f425 100644 --- a/ui/compositor/debug_utils.cc +++ b/ui/compositor/debug_utils.cc
@@ -91,7 +91,8 @@ if (!layer->rounded_corner_radii().IsEmpty()) { *out << "\n" << property_indent_str; - *out << "rounded-corners-radii" << layer->rounded_corner_radii().ToString(); + *out << "rounded-corners-radii: " + << layer->rounded_corner_radii().ToString(); } const ui::Layer* mask = const_cast<ui::Layer*>(layer)->layer_mask_layer();
diff --git a/ui/file_manager/base/js/convert_to_ts.py b/ui/file_manager/base/js/convert_to_ts.py index a632612..ebcfaba 100644 --- a/ui/file_manager/base/js/convert_to_ts.py +++ b/ui/file_manager/base/js/convert_to_ts.py
@@ -26,6 +26,10 @@ r'@private|@protected|@override' ) +TESTCASE_NAMESPACE = re.compile(r"testcase\.(.*) =( async)? \(\) => {") +IMPORT_TESTCASE = re.compile(r"import {testcase} from '../testcase.js';") +ARROW_FUNCTION_CLOSE_BRACE = re.compile(r"^};$") + # Matching:` this.bla;`` or `private this.bla;` NON_INITIALIZED_PROP = re.compile(r'\s+this\.[\w_]+;') # Matching: this.bla = 'anything'; @@ -77,6 +81,10 @@ lines.append(line) continue + # Don't include testcase import. + if IMPORT_TESTCASE.match(line): + continue + # Fully commented out line, ignores inline comment. if is_comment(line): if ts_ignoring: @@ -96,6 +104,7 @@ lines.append(line) processing_comment = False + processing_arrow_function = False idx = -1 while (idx < len(lines) - 1): idx += 1 @@ -123,6 +132,19 @@ if not is_jsdoc_star(line): processing_comment = False + # Arrow functions end with a ';' after their closing brace, remove it. + if processing_arrow_function and ARROW_FUNCTION_CLOSE_BRACE.match( + line): + lines[idx] = "}\n" + processing_arrow_function = False + continue + + # Rewrite testcase imports to exports instead. + match = TESTCASE_NAMESPACE.search(line) + if match: + processing_arrow_function = True + lines[idx] = f"export async function {match.group(1)}() " "{\n" + # Remove the lines marked for deletion. remove_lines(lines) return lines @@ -636,8 +658,8 @@ # Process as `file_names.gni` to remove the .js file and add it to # the `ts_files = ` section. if b == _INTEGRATION_TESTS_ROOT.joinpath('BUILD.gn'): - new_build_file = process_file_names_gni(js_path.absolute(), b) - replace_file(b, new_build_file) + new_build_file = process_file_names_gni(js_path.absolute(), b) + replace_file(b, new_build_file) # Only process file_names.gni for Files app and Image Loader. if js_path_abs_str.startswith((str(_FILES_APP_ROOT),
diff --git a/ui/file_manager/base/js/tests/testing_convert_to_ts.js b/ui/file_manager/base/js/tests/testing_convert_to_ts.js index e97fe3e..3a80544 100644 --- a/ui/file_manager/base/js/tests/testing_convert_to_ts.js +++ b/ui/file_manager/base/js/tests/testing_convert_to_ts.js
@@ -11,6 +11,7 @@ import {ColorChangeUpdater} from 'chrome://resources/cr_components/color_change_listener/colors_css_updater.js'; import {FileManagerBaseInterface} from '../../../file_manager/externs/background/file_manager_base.js'; +import {testcase} from '../testcase.js'; // @ts-ignore: error TS2314: Generic type 'Array<T>' requires 1 type @@ -146,3 +147,12 @@ return show; } } + +testcase.functionShouldBeRewrittenAndAsyncAdded = () => { + // The function name should be rewritten as well as the trailing semicolon + // along with a new async specifier added. +}; + +testcase.functionShouldBeRewritten = async () => { + // The function name should be rewritten as well as the trailing semicolon. +};
diff --git a/ui/file_manager/base/js/tests/testing_convert_to_ts_expected.js.txt b/ui/file_manager/base/js/tests/testing_convert_to_ts_expected.js.txt index e5d9fd6..a57b275 100644 --- a/ui/file_manager/base/js/tests/testing_convert_to_ts_expected.js.txt +++ b/ui/file_manager/base/js/tests/testing_convert_to_ts_expected.js.txt
@@ -120,3 +120,12 @@ return show; } } + +export async function functionShouldBeRewrittenAndAsyncAdded() { + // The function name should be rewritten as well as the trailing semicolon + // along with a new async specifier added. +} + +export async function functionShouldBeRewritten() { + // The function name should be rewritten as well as the trailing semicolon. +}
diff --git a/ui/file_manager/integration_tests/BUILD.gn b/ui/file_manager/integration_tests/BUILD.gn index 4af927c..34be576 100644 --- a/ui/file_manager/integration_tests/BUILD.gn +++ b/ui/file_manager/integration_tests/BUILD.gn
@@ -13,9 +13,7 @@ # File Manager. "file_manager/background.js", - "file_manager/breadcrumbs.js", "file_manager/context_menu.js", - "file_manager/copy_between_windows.js", "file_manager/create_new_folder.js", "file_manager/crostini.js", "file_manager/directory_tree_context_menu.js", @@ -23,33 +21,18 @@ "file_manager/dlp_enterprise_connectors.js", "file_manager/drive_specific.js", "file_manager/file_dialog.js", - "file_manager/file_display.js", - "file_manager/file_list.js", "file_manager/file_transfer_connector.js", "file_manager/folder_shortcuts.js", - "file_manager/format_dialog.js", "file_manager/gear_menu.js", - "file_manager/grid_view.js", - "file_manager/guest_os.js", "file_manager/holding_space.js", "file_manager/install_linux_package_dialog.js", - "file_manager/keyboard_operations.js", - "file_manager/metadata.js", "file_manager/metrics.js", - "file_manager/my_files.js", - "file_manager/office.js", - "file_manager/providers.js", - "file_manager/quick_view.js", "file_manager/recents.js", "file_manager/restore_prefs.js", "file_manager/search.js", - "file_manager/sort_columns.js", "file_manager/tab_index.js", - "file_manager/tasks.js", "file_manager/test_data.js", - "file_manager/toolbar.js", "file_manager/transfer.js", - "file_manager/zip_files.js", # Page Objects. "file_manager/page_objects/directory_tree.js", @@ -67,14 +50,13 @@ # "file_manager/background.ts", - # "file_manager/breadcrumbs.ts", - + "file_manager/breadcrumbs.ts", "file_manager/choose_entry.ts", "file_manager/choose_entry_const.ts", # "file_manager/context_menu.ts", - # "file_manager/copy_between_windows.ts", + "file_manager/copy_between_windows.ts", # "file_manager/create_new_folder.ts", @@ -92,9 +74,9 @@ # "file_manager/file_dialog.ts", - # "file_manager/file_display.ts", + "file_manager/file_display.ts", - # "file_manager/file_list.ts", + "file_manager/file_list.ts", # "file_manager/file_transfer_connector.ts", @@ -102,42 +84,35 @@ # "file_manager/folder_shortcuts.ts", - # "file_manager/format_dialog.ts", + "file_manager/format_dialog.ts", # "file_manager/gear_menu.ts", - # "file_manager/grid_view.ts", + "file_manager/grid_view.ts", - # "file_manager/guest_os.ts", + "file_manager/guest_os.ts", # "file_manager/holding_space.ts", # "file_manager/install_linux_package_dialog.ts", - # "file_manager/keyboard_operations.ts", - + "file_manager/keyboard_operations.ts", "file_manager/manage_dialog.ts", - - # "file_manager/metadata.ts", + "file_manager/metadata.ts", # "file_manager/metrics.ts", - # "file_manager/my_files.ts", - + "file_manager/my_files.ts", "file_manager/navigation.ts", - - # "file_manager/office.ts", - + "file_manager/office.ts", "file_manager/open_audio_media_app.ts", "file_manager/open_files_in_web_drive.ts", "file_manager/open_image_media_app.ts", "file_manager/open_media_app.ts", "file_manager/open_sniffed_files.ts", "file_manager/open_video_media_app.ts", - - # "file_manager/providers.ts", - - # "file_manager/quick_view.ts", + "file_manager/providers.ts", + "file_manager/quick_view.ts", # "file_manager/recents.ts", @@ -146,24 +121,22 @@ # "file_manager/search.ts", "file_manager/share.ts", - - # "file_manager/sort_columns.ts", + "file_manager/sort_columns.ts", # "file_manager/tab_index.ts", - # "file_manager/tasks.ts", + "file_manager/tasks.ts", # "file_manager/test_data.ts", - # "file_manager/toolbar.ts", + "file_manager/toolbar.ts", # "file_manager/transfer.ts", "file_manager/trash.ts", - "file_manager/traverse.ts", - # "file_manager/zip_files.ts", + "file_manager/zip_files.ts", # Page Objects. # "file_manager/page_objects/directory_tree.ts",
diff --git a/ui/file_manager/integration_tests/file_manager/breadcrumbs.js b/ui/file_manager/integration_tests/file_manager/breadcrumbs.ts similarity index 82% rename from ui/file_manager/integration_tests/file_manager/breadcrumbs.js rename to ui/file_manager/integration_tests/file_manager/breadcrumbs.ts index 9b604a9..c3581a0 100644 --- a/ui/file_manager/integration_tests/file_manager/breadcrumbs.js +++ b/ui/file_manager/integration_tests/file_manager/breadcrumbs.ts
@@ -5,8 +5,8 @@ * @fileoverview Tests that breadcrumbs work. */ +import type {ElementObject} from '../prod/file_manager/shared_types.js'; import {createNestedTestFolders, ENTRIES, getCaller, getUserActionCount, pending, repeatUntil, RootPath, sendTestMessage, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -15,12 +15,8 @@ return 'xf-breadcrumb'; } -// @ts-ignore: error TS4111: Property 'breadcrumbsNavigate' comes from an index -// signature, so it must be accessed with ['breadcrumbsNavigate']. -testcase.breadcrumbsNavigate = async () => { +export async function breadcrumbsNavigate() { const files = [ENTRIES.hello, ENTRIES.photos]; - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); const breadcrumbsTag = await getBreadcrumbTagName(); @@ -34,22 +30,17 @@ appId, [breadcrumbsTag, 'button:nth-last-of-type(2)']); // Wait for the contents of Downloads to load again. - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. await remoteCall.waitForFiles(appId, TestEntryInfo.getExpectedRows(files)); // A user action should have been recorded for the breadcrumbs. chrome.test.assertEq( 1, await getUserActionCount('FileBrowser.ClickBreadcrumbs')); -}; +} /** * Tests that Downloads is translated in the breadcrumbs. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsDownloadsTranslation' comes -// from an index signature, so it must be accessed with -// ['breadcrumbsDownloadsTranslation']. -testcase.breadcrumbsDownloadsTranslation = async () => { +export async function breadcrumbsDownloadsTranslation() { // Switch UI to Portuguese (Portugal). await sendTestMessage({name: 'switchLanguage', language: 'pt-PT'}); @@ -74,14 +65,12 @@ // Wait and check breadcrumb translation. await remoteCall.waitUntilCurrentDirectoryIsChanged( appId, '/Os meus ficheiros/Transferências/photos'); -}; +} /** * Tests that the breadcrumbs correctly render a short (3 component) path. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsRenderShortPath' comes from an -// index signature, so it must be accessed with ['breadcrumbsRenderShortPath']. -testcase.breadcrumbsRenderShortPath = async () => { +export async function breadcrumbsRenderShortPath() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(1); @@ -100,9 +89,7 @@ const breadcrumbElement = await remoteCall.waitForElement(appId, [breadcrumbsTag]); const path = breadcrumb.slice(1); // remove leading "/" char - // @ts-ignore: error TS4111: Property 'path' comes from an index signature, so - // it must be accessed with ['path']. - chrome.test.assertEq(path, breadcrumbElement.attributes.path); + chrome.test.assertEq(path, breadcrumbElement.attributes['path']); // Check: some of the main breadcrumb buttons should be visible. const buttons = [breadcrumbsTag, 'button']; @@ -123,16 +110,13 @@ // Check: the breadcrumb elider button should not exist. const eliderButton = [breadcrumbsTag, '[elider]']; await remoteCall.waitForElementLost(appId, eliderButton); -}; +} /** * Tests that short breadcrumbs paths (of 4 or fewer components) should not * be rendered elided. The elider button not exist. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsEliderButtonNotExist' comes -// from an index signature, so it must be accessed with -// ['breadcrumbsEliderButtonNotExist']. -testcase.breadcrumbsEliderButtonNotExist = async () => { +export async function breadcrumbsEliderButtonNotExist() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(2); @@ -151,9 +135,7 @@ const breadcrumbElement = await remoteCall.waitForElement(appId, [breadcrumbsTag]); const path = breadcrumb.slice(1); // remove leading "/" char - // @ts-ignore: error TS4111: Property 'path' comes from an index signature, so - // it must be accessed with ['path']. - chrome.test.assertEq(path, breadcrumbElement.attributes.path); + chrome.test.assertEq(path, breadcrumbElement.attributes['path']); // Check: all of the main breadcrumb buttons should be visible. const buttons = [breadcrumbsTag, 'button']; @@ -176,14 +158,12 @@ // Check: the breadcrumb elider button should not exist. const eliderButton = [breadcrumbsTag, '[elider]']; await remoteCall.waitForElementLost(appId, eliderButton); -}; +} /** * Tests that the breadcrumbs correctly render a long (5 component) path. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsRenderLongPath' comes from an -// index signature, so it must be accessed with ['breadcrumbsRenderLongPath']. -testcase.breadcrumbsRenderLongPath = async () => { +export async function breadcrumbsRenderLongPath() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(3); @@ -202,9 +182,7 @@ const breadcrumbElement = await remoteCall.waitForElement(appId, [breadcrumbsTag]); const path = breadcrumb.slice(1); // remove leading "/" char - // @ts-ignore: error TS4111: Property 'path' comes from an index signature, so - // it must be accessed with ['path']. - chrome.test.assertEq(path, breadcrumbElement.attributes.path); + chrome.test.assertEq(path, breadcrumbElement.attributes['path']); // Check: some of the main breadcrumb buttons should be visible. const buttons = [breadcrumbsTag, 'button[id]']; @@ -225,15 +203,13 @@ // Check: the breadcrumb elider button should be shown. const eliderButton = [breadcrumbsTag, '[elider]']; await remoteCall.waitForElement(appId, eliderButton); -}; +} /** * Tests that clicking a main breadcumb button makes the app navigate and * update the breadcrumb to that item. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsMainButtonClick' comes from an -// index signature, so it must be accessed with ['breadcrumbsMainButtonClick']. -testcase.breadcrumbsMainButtonClick = async () => { +export async function breadcrumbsMainButtonClick() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(2); @@ -252,9 +228,7 @@ const breadcrumbElement = await remoteCall.waitForElement(appId, [breadcrumbsTag]); const path = breadcrumb.slice(1); // remove leading "/" char - // @ts-ignore: error TS4111: Property 'path' comes from an index signature, so - // it must be accessed with ['path']. - chrome.test.assertEq(path, breadcrumbElement.attributes.path); + chrome.test.assertEq(path, breadcrumbElement.attributes['path']); // Click the "second" main breadcrumb button (2nd path component). await remoteCall.waitAndClickElement( @@ -263,16 +237,13 @@ // Check: the breadcrumb path should be updated due to navigation. await remoteCall.waitForElement( appId, [`${breadcrumbsTag}[path="My files/Downloads"]`]); -}; +} /** * Tests that an Enter key on a main breadcumb button item makes the app * navigate and update the breadcrumb to that item. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsMainButtonEnterKey' comes from -// an index signature, so it must be accessed with -// ['breadcrumbsMainButtonEnterKey']. -testcase.breadcrumbsMainButtonEnterKey = async () => { +export async function breadcrumbsMainButtonEnterKey() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(2); @@ -291,9 +262,7 @@ const breadcrumbElement = await remoteCall.waitForElement(appId, [breadcrumbsTag]); const path = breadcrumb.slice(1); // remove leading "/" char - // @ts-ignore: error TS4111: Property 'path' comes from an index signature, so - // it must be accessed with ['path']. - chrome.test.assertEq(path, breadcrumbElement.attributes.path); + chrome.test.assertEq(path, breadcrumbElement.attributes['path']); // Send an Enter key to the "second" main breadcrumb button. const secondButton = [breadcrumbsTag, 'button[id="second"]']; @@ -304,16 +273,13 @@ // Check: the breadcrumb path should be updated due to navigation. await remoteCall.waitForElement( appId, [`${breadcrumbsTag}[path="My files/Downloads"]`]); -}; +} /** * Tests that a breadcrumbs elider button click opens its drop down menu and * that clicking the button again, closes the drop down menu. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsEliderButtonClick' comes from -// an index signature, so it must be accessed with -// ['breadcrumbsEliderButtonClick']. -testcase.breadcrumbsEliderButtonClick = async () => { +export async function breadcrumbsEliderButtonClick() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(3); @@ -358,16 +324,13 @@ // Check: the focus should return to the elider button. await remoteCall.waitForElement(appId, eliderFocus); -}; +} /** * Tests that pressing Enter key on the breadcrumbs elider button opens its * drop down menu, then pressing Escape key closes the drop down menu. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsEliderButtonKeyboard' comes -// from an index signature, so it must be accessed with -// ['breadcrumbsEliderButtonKeyboard']. -testcase.breadcrumbsEliderButtonKeyboard = async () => { +export async function breadcrumbsEliderButtonKeyboard() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(4); @@ -420,16 +383,13 @@ // Check: the focus should return to the elider button. await remoteCall.waitForElement(appId, eliderFocus); -}; +} /** * Tests that clicking outside the elider button drop down menu makes that * drop down menu close. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsEliderMenuClickOutside' comes -// from an index signature, so it must be accessed with -// ['breadcrumbsEliderMenuClickOutside']. -testcase.breadcrumbsEliderMenuClickOutside = async () => { +export async function breadcrumbsEliderMenuClickOutside() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(5); @@ -457,16 +417,13 @@ // Check: the elider button drop-down menu should close. await remoteCall.waitForElementLost(appId, menu); -}; +} /** * Tests that clicking an elider button drop down menu item makes the app * navigate and update the breadcrumb to that item. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsEliderMenuItemClick' comes -// from an index signature, so it must be accessed with -// ['breadcrumbsEliderMenuItemClick']. -testcase.breadcrumbsEliderMenuItemClick = async () => { +export async function breadcrumbsEliderMenuItemClick() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(3); @@ -485,9 +442,7 @@ const breadcrumbElement = await remoteCall.waitForElement(appId, [breadcrumbsTag]); const path = breadcrumb.slice(1); // remove leading "/" char - // @ts-ignore: error TS4111: Property 'path' comes from an index signature, so - // it must be accessed with ['path']. - chrome.test.assertEq(path, breadcrumbElement.attributes.path); + chrome.test.assertEq(path, breadcrumbElement.attributes['path']); // Click the breadcrumb elider button when it appears. const eliderButton = [breadcrumbsTag, '[elider]']; @@ -517,16 +472,13 @@ // Check: the breadcrumb path should be updated due to navigation. await remoteCall.waitForElement( appId, [`${breadcrumbsTag}[path="My files/Downloads"]`]); -}; +} /** * Tests that a <shift>-Tab key on the elider button drop down menu closes * the menu and focuses button#first to the left of the elider button. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsEliderMenuItemTabLeft' comes -// from an index signature, so it must be accessed with -// ['breadcrumbsEliderMenuItemTabLeft']. -testcase.breadcrumbsEliderMenuItemTabLeft = async () => { +export async function breadcrumbsEliderMenuItemTabLeft() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(3); @@ -561,16 +513,13 @@ // Check: the "first" main button should be focused. await remoteCall.waitForElement( appId, [breadcrumbsTag, 'button[id="first"]:focus']); -}; +} /** * Tests that a Tab key on the elider button drop down menu closes the menu * and focuses button#second to the right of the elider button. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsEliderMenuItemTabRight' comes -// from an index signature, so it must be accessed with -// ['breadcrumbsEliderMenuItemTabRight']. -testcase.breadcrumbsEliderMenuItemTabRight = async () => { +export async function breadcrumbsEliderMenuItemTabRight() { // Build an array of nested folder test entries. const nestedFolderTestEntries = createNestedTestFolders(3); @@ -604,17 +553,14 @@ // Check: the "second" main button should be focused. await remoteCall.waitForElement( appId, [breadcrumbsTag, 'button[id="second"]:focus']); -}; +} /** * Tests that when the breadcrumbs + action bar buttons exceed the available * viewport width, their width is updated to fit the space instead of exceeding * the viewport and having some of the action bar buttons not visible. */ -// @ts-ignore: error TS4111: Property 'breadcrumbsDontExceedAvailableViewport' -// comes from an index signature, so it must be accessed with -// ['breadcrumbsDontExceedAvailableViewport']. -testcase.breadcrumbsDontExceedAvailableViewport = async () => { +export async function breadcrumbsDontExceedAvailableViewport() { const nestedFolderTestEntries = createNestedTestFolders(2); // Open FilesApp on Downloads containing the test entries. @@ -628,14 +574,12 @@ // Get the spacer with between breadcrumbs and action bar buttons, this // indicates the available space we can resize the window before the text in // the breadcrumb is clamped. - const spacerWidth = await remoteCall.waitForElementStyles( + const spacerWidth: ElementObject = await remoteCall.waitForElementStyles( appId, 'div.dialog-header > .spacer', ['width']); // Shrink the window by the available spacer width -10px to ensure the // breadcrumbs don't start clamping text. - // @ts-ignore: error TS18048: 'spacerWidth.renderedWidth' is possibly - // 'undefined'. - const newWindowWidth = outerWidth - spacerWidth.renderedWidth + 10; + const newWindowWidth = outerWidth - spacerWidth.renderedWidth! + 10; chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( 'resizeWindow', appId, [newWindowWidth, outerHeight])); @@ -657,19 +601,19 @@ // to the directory the below calculation occurs prior to the relayout // happening, repeat until the values agree with each other. const caller = getCaller(); - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const actualDialogHeaderWidth = await remoteCall.waitForElementStyles( appId, 'div.dialog-header', ['width']); - if (expectedDialogHeaderWidth.renderedWidth !== + if (expectedDialogHeaderWidth.renderedWidth === actualDialogHeaderWidth.renderedWidth) { - return pending( - caller, 'Expected dialog header width is %s, got %s', - expectedDialogHeaderWidth.renderedWidth, - actualDialogHeaderWidth.renderedWidth); + return; } + return pending( + caller, 'Expected dialog header width is %s, got %s', + expectedDialogHeaderWidth.renderedWidth, + actualDialogHeaderWidth.renderedWidth); }); -}; +} /** * Test that navigating back from a sub-folder in Google Drive> Shared With Me @@ -677,10 +621,7 @@ * Internally Shared With Me uses some of the Drive Search code, this confused * the DirectoryModel clearing the search state in the Store. */ -// @ts-ignore: error TS4111: Property 'breadcrumbNavigateBackToSharedWithMe' -// comes from an index signature, so it must be accessed with -// ['breadcrumbNavigateBackToSharedWithMe']. -testcase.breadcrumbNavigateBackToSharedWithMe = async () => { +export async function breadcrumbNavigateBackToSharedWithMe() { // Open Files app on Drive containing "Shared with me" file entries. const sharedSubFolderName = ENTRIES.sharedWithMeDirectory.nameText; const appId = await setupAndWaitUntilReady( @@ -707,4 +648,4 @@ // Wait until the breadcrumb path is updated. await remoteCall.waitUntilCurrentDirectoryIsChanged(appId, '/Shared with me'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/copy_between_windows.js b/ui/file_manager/integration_tests/file_manager/copy_between_windows.ts similarity index 75% rename from ui/file_manager/integration_tests/file_manager/copy_between_windows.js rename to ui/file_manager/integration_tests/file_manager/copy_between_windows.ts index f078876..614ca45a 100644 --- a/ui/file_manager/integration_tests/file_manager/copy_between_windows.js +++ b/ui/file_manager/integration_tests/file_manager/copy_between_windows.ts
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {addEntries, ENTRIES, RootPath, sendTestMessage, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {openNewWindow, remoteCall} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -15,12 +14,12 @@ /** * Opens two window of given root paths. - * @param {string} rootPath1 Root path of the first window. - * @param {string} rootPath2 Root path of the second window. - * @return {Promise<[string, string]>} Promise fulfilled with an array - * containing two window IDs. + * @param rootPath1 Root path of the first window. + * @param rootPath2 Root path of the second window. + * @return Promise fulfilled with an array containing two window IDs. */ -async function openTwoWindows(rootPath1, rootPath2) { +async function openTwoWindows( + rootPath1: string, rootPath2: string): Promise<[string, string]> { const windowIds = await Promise.all([openNewWindow(rootPath1), openNewWindow(rootPath2)]); @@ -33,15 +32,15 @@ /** * Copies a file between two windows. - * @param {string} window1 ID of the source window. - * @param {string} window2 ID of the destination window. - * @param {TestEntryInfo} file Test entry info to be copied. - * @param {?TestEntryInfo} alreadyPresentFile Test entry info for file that - * should already exist. - * @return {Promise<void>} Promise fulfilled on success. + * @param window1 ID of the source window. + * @param window2 ID of the destination window. + * @param file Test entry info to be copied. + * @param alreadyPresentFile Test entry info for file that should already exist. + * @return Promise fulfilled on success. */ async function copyBetweenWindows( - window1, window2, file, alreadyPresentFile = null) { + window1: string, window2: string, file: TestEntryInfo, + alreadyPresentFile: null|TestEntryInfo = null): Promise<void> { if (!file || !file.nameText) { chrome.test.assertTrue(false, 'copyBetweenWindows invalid file name'); } @@ -61,20 +60,13 @@ if (alreadyPresentFile) { expectedFiles.push(alreadyPresentFile.getExpectedRow()); } - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // boolean; }' is not assignable to parameter of type '{ orderCheck: boolean | - // null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(window2, expectedFiles, flag); } /** * Tests file copy+paste from Drive to Downloads. */ -// @ts-ignore: error TS4111: Property 'copyBetweenWindowsDriveToLocal' comes -// from an index signature, so it must be accessed with -// ['copyBetweenWindowsDriveToLocal']. -testcase.copyBetweenWindowsDriveToLocal = async () => { +export async function copyBetweenWindowsDriveToLocal() { // Open two Files app windows. const [window1, window2] = await openTwoWindows(RootPath.DOWNLOADS, RootPath.DRIVE); @@ -90,15 +82,12 @@ // Copy Drive hello file to Downloads. await copyBetweenWindows(window2, window1, ENTRIES.hello, ENTRIES.photos); -}; +} /** * Tests file copy+paste from Downloads to Drive. */ -// @ts-ignore: error TS4111: Property 'copyBetweenWindowsLocalToDrive' comes -// from an index signature, so it must be accessed with -// ['copyBetweenWindowsLocalToDrive']. -testcase.copyBetweenWindowsLocalToDrive = async () => { +export async function copyBetweenWindowsLocalToDrive() { // Open two Files app windows. const [window1, window2] = await openTwoWindows(RootPath.DOWNLOADS, RootPath.DRIVE); @@ -114,15 +103,12 @@ // Copy Downloads hello file to Drive. await copyBetweenWindows(window1, window2, ENTRIES.hello, ENTRIES.photos); -}; +} /** * Tests file copy+paste from Drive to USB. */ -// @ts-ignore: error TS4111: Property 'copyBetweenWindowsDriveToUsb' comes from -// an index signature, so it must be accessed with -// ['copyBetweenWindowsDriveToUsb']. -testcase.copyBetweenWindowsDriveToUsb = async () => { +export async function copyBetweenWindowsDriveToUsb() { // Add photos to Downloads. await addEntries(['local'], [ENTRIES.photos]); @@ -155,15 +141,12 @@ // Check Drive hello file, copy it to USB. await copyBetweenWindows(window2, window1, ENTRIES.hello); -}; +} /** * Tests file copy+paste from Downloads to USB. */ -// @ts-ignore: error TS4111: Property 'copyBetweenWindowsLocalToUsb' comes from -// an index signature, so it must be accessed with -// ['copyBetweenWindowsLocalToUsb']. -testcase.copyBetweenWindowsLocalToUsb = async () => { +export async function copyBetweenWindowsLocalToUsb() { // Add photos to Drive. await addEntries(['drive'], [ENTRIES.photos]); @@ -196,15 +179,12 @@ // Check Downloads hello file, copy it to USB. await copyBetweenWindows(window2, window1, ENTRIES.hello); -}; +} /** * Tests file copy+paste from USB to Drive. */ -// @ts-ignore: error TS4111: Property 'copyBetweenWindowsUsbToDrive' comes from -// an index signature, so it must be accessed with -// ['copyBetweenWindowsUsbToDrive']. -testcase.copyBetweenWindowsUsbToDrive = async () => { +export async function copyBetweenWindowsUsbToDrive() { // Add photos to Downloads. await addEntries(['local'], [ENTRIES.photos]); @@ -236,15 +216,12 @@ // Check USB hello file, copy it to Drive. await copyBetweenWindows(window1, window2, ENTRIES.hello); -}; +} /** * Tests file copy+paste from USB to Downloads. */ -// @ts-ignore: error TS4111: Property 'copyBetweenWindowsUsbToLocal' comes from -// an index signature, so it must be accessed with -// ['copyBetweenWindowsUsbToLocal']. -testcase.copyBetweenWindowsUsbToLocal = async () => { +export async function copyBetweenWindowsUsbToLocal() { // Add photos to Drive. await addEntries(['drive'], [ENTRIES.photos]); @@ -277,4 +254,4 @@ // Check USB hello file, copy it to Downloads. await copyBetweenWindows(window1, window2, ENTRIES.hello); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/file_display.js b/ui/file_manager/integration_tests/file_manager/file_display.ts similarity index 69% rename from ui/file_manager/integration_tests/file_manager/file_display.js rename to ui/file_manager/integration_tests/file_manager/file_display.ts index b9f9ad33..ed1a6807 100644 --- a/ui/file_manager/integration_tests/file_manager/file_display.js +++ b/ui/file_manager/integration_tests/file_manager/file_display.ts
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {type ElementObject} from '../prod/file_manager/shared_types.js'; import {addEntries, ENTRIES, RootPath, sendTestMessage, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {IGNORE_APP_ERRORS, isSinglePartitionFormat, openNewWindow, remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -13,10 +13,10 @@ * Checks if the files initially added by the C++ side are displayed, and * that files subsequently added are also displayed. * - * @param {string} path Path to be tested, Downloads or Drive. - * @param {!Array<!TestEntryInfo>} defaultEntries Default file entries. + * @param path Path to be tested, Downloads or Drive. + * @param defaultEntries Default file entries. */ -async function fileDisplay(path, defaultEntries) { +async function fileDisplay(path: string, defaultEntries: TestEntryInfo[]) { // Open Files app on the given |path| with default file entries. const appId = await setupAndWaitUntilReady(path); @@ -36,21 +36,16 @@ /** * Tests files display in Downloads. */ -// @ts-ignore: error TS4111: Property 'fileDisplayDownloads' comes from an index -// signature, so it must be accessed with ['fileDisplayDownloads']. -testcase.fileDisplayDownloads = () => { +export async function fileDisplayDownloads() { return fileDisplay(RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET); -}; +} /** * Tests opening the files app navigating to a local folder. Uses * platform_util::OpenItem, a call to an API distinct from the one commonly used * in other tests for the same operation. */ -// @ts-ignore: error TS4111: Property 'fileDisplayLaunchOnLocalFolder' comes -// from an index signature, so it must be accessed with -// ['fileDisplayLaunchOnLocalFolder']. -testcase.fileDisplayLaunchOnLocalFolder = async () => { +export async function fileDisplayLaunchOnLocalFolder() { // Add a file to Downloads. await addEntries(['local'], [ENTRIES.photos]); @@ -68,17 +63,14 @@ // The API used to launch the Files app does not set the IN_TEST flag to true: // error when attempting to retrieve Web Store access token. return IGNORE_APP_ERRORS; -}; +} /** * Tests opening the files app navigating to a local folder. Uses * platform_util::OpenItem, a call to an API distinct from the one commonly used * in other tests for the same operation. */ -// @ts-ignore: error TS4111: Property 'fileDisplayLaunchOnLocalFile' comes from -// an index signature, so it must be accessed with -// ['fileDisplayLaunchOnLocalFile']. -testcase.fileDisplayLaunchOnLocalFile = async () => { +export async function fileDisplayLaunchOnLocalFile() { // Add a file to Downloads. await addEntries(['local'], [ENTRIES.hello, ENTRIES.world]); @@ -100,16 +92,14 @@ // The API used to launch the Files app does not set the IN_TEST flag to true: // error when attempting to retrieve Web Store access token. return IGNORE_APP_ERRORS; -}; +} /** * Tests opening the files app navigating to the My Drive folder. Uses * platform_util::OpenItem, a call to an API distinct from the one commonly used * in other tests for the same operation. */ -// @ts-ignore: error TS4111: Property 'fileDisplayLaunchOnDrive' comes from an -// index signature, so it must be accessed with ['fileDisplayLaunchOnDrive']. -testcase.fileDisplayLaunchOnDrive = async () => { +export async function fileDisplayLaunchOnDrive() { // Open Files app on the Drive directory. await sendTestMessage({name: 'launchAppOnDrive'}); @@ -123,23 +113,19 @@ // The API used to launch the Files app does not set the IN_TEST flag to true: // error when attempting to retrieve Web Store access token. return IGNORE_APP_ERRORS; -}; +} /** * Tests files display in Google Drive. */ -// @ts-ignore: error TS4111: Property 'fileDisplayDrive' comes from an index -// signature, so it must be accessed with ['fileDisplayDrive']. -testcase.fileDisplayDrive = () => { +export async function fileDisplayDrive() { return fileDisplay(RootPath.DRIVE, BASIC_DRIVE_ENTRY_SET); -}; +} /** * Tests file display rendering in offline Google Drive. */ -// @ts-ignore: error TS4111: Property 'fileDisplayDriveOffline' comes from an -// index signature, so it must be accessed with ['fileDisplayDriveOffline']. -testcase.fileDisplayDriveOffline = async () => { +export async function fileDisplayDriveOffline() { const driveFiles = [ENTRIES.hello, ENTRIES.pinned, ENTRIES.photos, ENTRIES.testDocument]; @@ -156,10 +142,10 @@ // Check: the hello.txt file only should be rendered 'offline'. chrome.test.assertEq(1, elements.length); - chrome.test.assertEq(0, elements[0].text.indexOf('hello.txt')); + chrome.test.assertEq(0, elements[0]!.text.indexOf('hello.txt')); // Check: hello.txt must have 'offline' CSS render style (opacity). - chrome.test.assertEq('0.38', elements[0].styles.opacity); + chrome.test.assertEq('0.38', elements[0]!.styles.opacity); // Retrieve file entries that are 'available offline' (not dimmed). // Use "first-child" here because opacity for offline only applies on the @@ -172,11 +158,10 @@ // Check: these files should have 'available offline' CSS style. chrome.test.assertEq(3, elements.length); - // @ts-ignore: error TS7006: Parameter 'fileName' implicitly has an 'any' - // type. - function checkRenderedInAvailableOfflineStyle(element, fileName) { - chrome.test.assertEq(0, element.text.indexOf(fileName)); - chrome.test.assertEq('1', element.styles.opacity); + function checkRenderedInAvailableOfflineStyle( + element: ElementObject, fileName: string) { + chrome.test.assertEq(0, element.text!.indexOf(fileName)); + chrome.test.assertEq('1', element.styles!['opacity']); } // Directories are shown as 'available offline'. @@ -187,13 +172,13 @@ // Pinned files are shown as 'available offline'. checkRenderedInAvailableOfflineStyle(elements[2], 'pinned'); -}; +} /** * Tests file display rendering in online Google Drive. - * @param {string} appId the id for the window to check the file display. + * @param appId the id for the window to check the file display. */ -async function checkDriveOnlineDisplay(appId) { +async function checkDriveOnlineDisplay(appId: string) { // Retrieve all file list row entries. const fileEntry = '#file-list .table-row'; const elements = await remoteCall.callRemoteTestUtil( @@ -209,24 +194,19 @@ /** * Tests file display rendering in online Google Drive. */ -// @ts-ignore: error TS4111: Property 'fileDisplayDriveOnline' comes from an -// index signature, so it must be accessed with ['fileDisplayDriveOnline']. -testcase.fileDisplayDriveOnline = async () => { +export async function fileDisplayDriveOnline() { // Open Files app on Drive. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], BASIC_DRIVE_ENTRY_SET); await checkDriveOnlineDisplay(appId); -}; +} /** * Tests file display rendering in online Google Drive when opening via OpenItem * function. */ -// @ts-ignore: error TS4111: Property 'fileDisplayDriveOnlineNewWindow' comes -// from an index signature, so it must be accessed with -// ['fileDisplayDriveOnlineNewWindow']. -testcase.fileDisplayDriveOnlineNewWindow = async () => { +export async function fileDisplayDriveOnlineNewWindow() { // Open Files app on the Drive directory. await addEntries(['drive'], BASIC_DRIVE_ENTRY_SET); await sendTestMessage({name: 'launchAppOnDrive'}); @@ -235,21 +215,17 @@ const appId = await remoteCall.waitForWindow(); // Wait for Files app to finish loading. - // @ts-ignore: error TS2345: Argument of type 'boolean' is not assignable to - // parameter of type '(arg0: Object) => boolean | Object'. await remoteCall.waitFor('isFileManagerLoaded', appId, true); await checkDriveOnlineDisplay(appId); -}; +} /** * Tests files display in the "Computers" section of Google Drive. Testing that * we can navigate to folders inside /Computers also has the side effect of * testing that the breadcrumbs are working. */ -// @ts-ignore: error TS4111: Property 'fileDisplayComputers' comes from an index -// signature, so it must be accessed with ['fileDisplayComputers']. -testcase.fileDisplayComputers = async () => { +export async function fileDisplayComputers() { // Open Files app on Drive with Computers registered. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], COMPUTERS_ENTRY_SET); @@ -263,15 +239,13 @@ // Navigate to a subdirectory under a Computer Root. await directoryTree.navigateToPath('/Computers/Computer A/A'); -}; +} /** * Tests files display in an MTP volume. */ -// @ts-ignore: error TS4111: Property 'fileDisplayMtp' comes from an index -// signature, so it must be accessed with ['fileDisplayMtp']. -testcase.fileDisplayMtp = async () => { +export async function fileDisplayMtp() { const MTP_VOLUME_TYPE = 'mtp'; // Open Files app on local downloads. @@ -286,19 +260,13 @@ // Verify the MTP file list. const files = TestEntryInfo.getExpectedRows(BASIC_FAKE_ENTRY_SET); - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); -}; +} /** * Tests files display in a removable USB volume. */ -// @ts-ignore: error TS4111: Property 'fileDisplayUsb' comes from an index -// signature, so it must be accessed with ['fileDisplayUsb']. -testcase.fileDisplayUsb = async () => { +export async function fileDisplayUsb() { const USB_VOLUME_TYPE = 'removable'; // Open Files app on local downloads. @@ -313,19 +281,13 @@ // Verify the USB file list. const files = TestEntryInfo.getExpectedRows(BASIC_FAKE_ENTRY_SET); - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); -}; +} /** * Tests files display on a removable USB volume with and without partitions. */ -// @ts-ignore: error TS4111: Property 'fileDisplayUsbPartition' comes from an -// index signature, so it must be accessed with ['fileDisplayUsbPartition']. -testcase.fileDisplayUsbPartition = async () => { +export async function fileDisplayUsbPartition() { // Open Files app on local downloads. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -380,17 +342,14 @@ const childVolumeType = directoryTree.getItemVolumeType(itemEntries[0]); chrome.test.assertTrue('removable' !== childVolumeType); } -}; +} /** * Tests that the file system type is properly displayed in the type * column. Checks that the entries can be properly sorted by type. * crbug.com/973743 */ -// @ts-ignore: error TS4111: Property 'fileDisplayUsbPartitionSort' comes from -// an index signature, so it must be accessed with -// ['fileDisplayUsbPartitionSort']. -testcase.fileDisplayUsbPartitionSort = async () => { +export async function fileDisplayUsbPartitionSort() { // Open Files app on local downloads. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -408,10 +367,6 @@ ['partition-1', '--', 'ntfs'], ]; const options = {orderCheck: true, ignoreLastModifiedTime: true}; - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: boolean; - // ignoreLastModifiedTime: boolean; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | null | - // undefined; ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, expectedRows, options); // Sort by type in ascending order. @@ -428,10 +383,6 @@ ['partition-1', '--', 'ntfs'], ['partition-3', '--', 'vfat'], ]; - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: boolean; - // ignoreLastModifiedTime: boolean; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | null | - // undefined; ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, expectedRows, options); // Sort by type in descending order. @@ -448,21 +399,14 @@ ['partition-1', '--', 'ntfs'], ['partition-2', '--', 'ext4'], ]; - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: boolean; - // ignoreLastModifiedTime: boolean; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | null | - // undefined; ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, expectedRows, options); -}; +} /** * Tests display of partitions in file list after mounting a removable USB * volume. */ -// @ts-ignore: error TS4111: Property 'fileDisplayPartitionFileTable' comes from -// an index signature, so it must be accessed with -// ['fileDisplayPartitionFileTable']. -testcase.fileDisplayPartitionFileTable = async () => { +export async function fileDisplayPartitionFileTable() { // Open Files app on local downloads. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -482,17 +426,18 @@ const partitionTwo = await remoteCall.waitForElement( appId, '#file-list [file-name="partition-2"] .type'); chrome.test.assertEq('ext4', partitionTwo.text); -}; +} /** * Searches for a string in Downloads and checks that the correct results * are displayed. * - * @param {string} searchTerm The string to search for. - * @param {!Array<!TestEntryInfo>} expectedResults The results set. + * @param searchTerm The string to search for. + * @param expectedResults The results set. * */ -async function searchDownloads(searchTerm, expectedResults) { +async function searchDownloads( + searchTerm: string, expectedResults: TestEntryInfo[]) { // Open Files app on local downloads. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -513,30 +458,24 @@ } /** - * Tests case-senstive search for an entry in Downloads. + * Tests case-sensitive search for an entry in Downloads. */ -// @ts-ignore: error TS4111: Property 'fileSearch' comes from an index -// signature, so it must be accessed with ['fileSearch']. -testcase.fileSearch = () => { +export async function fileSearch() { return searchDownloads('hello', [ENTRIES.hello]); -}; +} /** * Tests case-insenstive search for an entry in Downloads. */ -// @ts-ignore: error TS4111: Property 'fileSearchCaseInsensitive' comes from an -// index signature, so it must be accessed with ['fileSearchCaseInsensitive']. -testcase.fileSearchCaseInsensitive = () => { +export async function fileSearchCaseInsensitive() { return searchDownloads('HELLO', [ENTRIES.hello]); -}; +} /** * Tests searching for a string doesn't match anything in Downloads and that * there are no displayed items that match the search string. */ -// @ts-ignore: error TS4111: Property 'fileSearchNotFound' comes from an index -// signature, so it must be accessed with ['fileSearchNotFound']. -testcase.fileSearchNotFound = async () => { +export async function fileSearchNotFound() { const searchTerm = 'blahblah'; const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -553,16 +492,13 @@ 'fakeEvent', appId, ['#search-box cr-input', 'input']); await remoteCall.waitForFiles(appId, []); -}; +} /** * Tests Files app opening without errors when there isn't Downloads which is * the default volume. */ -// @ts-ignore: error TS4111: Property 'fileDisplayWithoutDownloadsVolume' comes -// from an index signature, so it must be accessed with -// ['fileDisplayWithoutDownloadsVolume']. -testcase.fileDisplayWithoutDownloadsVolume = async () => { +export async function fileDisplayWithoutDownloadsVolume() { // Ensure no volumes are mounted. chrome.test.assertEq('0', await sendTestMessage({name: 'getVolumesCount'})); @@ -576,17 +512,13 @@ chrome.test.assertTrue(!!appId, 'failed to open new window'); // Wait for Files app to finish loading. - // @ts-ignore: error TS2345: Argument of type 'boolean' is not assignable to - // parameter of type '(arg0: Object) => boolean | Object'. await remoteCall.waitFor('isFileManagerLoaded', appId, true); -}; +} /** * Tests Files app opening without errors when there are no volumes at all. */ -// @ts-ignore: error TS4111: Property 'fileDisplayWithoutVolumes' comes from an -// index signature, so it must be accessed with ['fileDisplayWithoutVolumes']. -testcase.fileDisplayWithoutVolumes = async () => { +export async function fileDisplayWithoutVolumes() { // Ensure no volumes are mounted. chrome.test.assertEq('0', await sendTestMessage({name: 'getVolumesCount'})); @@ -595,20 +527,15 @@ chrome.test.assertTrue(!!appId, 'failed to open new window'); // Wait for Files app to finish loading. - // @ts-ignore: error TS2345: Argument of type 'boolean' is not assignable to - // parameter of type '(arg0: Object) => boolean | Object'. await remoteCall.waitFor('isFileManagerLoaded', appId, true); -}; +} /** * Tests Files app opening without errors when there are no volumes at all and * then mounting Downloads volume which should appear and be able to display its * files. */ -// @ts-ignore: error TS4111: Property -// 'fileDisplayWithoutVolumesThenMountDownloads' comes from an index signature, -// so it must be accessed with ['fileDisplayWithoutVolumesThenMountDownloads']. -testcase.fileDisplayWithoutVolumesThenMountDownloads = async () => { +export async function fileDisplayWithoutVolumesThenMountDownloads() { // Ensure no volumes are mounted. chrome.test.assertEq('0', await sendTestMessage({name: 'getVolumesCount'})); @@ -617,8 +544,6 @@ chrome.test.assertTrue(!!appId, 'failed to open new window'); // Wait for Files app to finish loading. - // @ts-ignore: error TS2345: Argument of type 'boolean' is not assignable to - // parameter of type '(arg0: Object) => boolean | Object'. await remoteCall.waitFor('isFileManagerLoaded', appId, true); // Mount Downloads. @@ -634,23 +559,15 @@ [['Downloads', '--', 'Folder'], ['Linux files', '--', 'Folder']]; await remoteCall.waitForFiles( appId, expectedRows, - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); -}; +} /** * Tests Files app opening without errors when there are no volumes at all and * then mounting Drive volume which should appear and be able to display its * files. */ -// @ts-ignore: error TS4111: Property 'fileDisplayWithoutVolumesThenMountDrive' -// comes from an index signature, so it must be accessed with -// ['fileDisplayWithoutVolumesThenMountDrive']. -testcase.fileDisplayWithoutVolumesThenMountDrive = async () => { +export async function fileDisplayWithoutVolumesThenMountDrive() { // Ensure no volumes are mounted. chrome.test.assertEq('0', await sendTestMessage({name: 'getVolumesCount'})); @@ -659,8 +576,6 @@ chrome.test.assertTrue(!!appId, 'failed to open new window'); // Wait for Files app to finish loading. - // @ts-ignore: error TS2345: Argument of type 'boolean' is not assignable to - // parameter of type '(arg0: Object) => boolean | Object'. await remoteCall.waitFor('isFileManagerLoaded', appId, true); // Navigate to the Drive FakeItem. @@ -678,22 +593,16 @@ await remoteCall.waitFor('getVolumesCount', null, (count) => count === 1, []); // Add an entry to Drive. - // @ts-ignore: error TS4111: Property 'newlyAdded' comes from an index - // signature, so it must be accessed with ['newlyAdded']. await addEntries(['drive'], [ENTRIES.newlyAdded]); // Wait for "My Drive" files to display in the file list. - // @ts-ignore: error TS4111: Property 'newlyAdded' comes from an index - // signature, so it must be accessed with ['newlyAdded']. await remoteCall.waitForFiles(appId, [ENTRIES.newlyAdded.getExpectedRow()]); -}; +} /** * Tests Files app opening without Drive mounted. */ -// @ts-ignore: error TS4111: Property 'fileDisplayWithoutDrive' comes from an -// index signature, so it must be accessed with ['fileDisplayWithoutDrive']. -testcase.fileDisplayWithoutDrive = async () => { +export async function fileDisplayWithoutDrive() { // Ensure no volumes are mounted. chrome.test.assertEq('0', await sendTestMessage({name: 'getVolumesCount'})); @@ -705,8 +614,6 @@ // Open the files app. const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'newlyAdded' comes from an index - // signature, so it must be accessed with ['newlyAdded']. RootPath.DOWNLOADS, [ENTRIES.newlyAdded], []); // Wait for the loading indicator blink to finish. @@ -723,16 +630,13 @@ // Check: the fake Google Drive should be empty. await remoteCall.waitForFiles(appId, []); -}; +} /** * Tests Files app opening without Drive mounted and then disabling and * re-enabling Drive. */ -// @ts-ignore: error TS4111: Property 'fileDisplayWithoutDriveThenDisable' comes -// from an index signature, so it must be accessed with -// ['fileDisplayWithoutDriveThenDisable']. -testcase.fileDisplayWithoutDriveThenDisable = async () => { +export async function fileDisplayWithoutDriveThenDisable() { // Ensure no volumes are mounted. chrome.test.assertEq('0', await sendTestMessage({name: 'getVolumesCount'})); @@ -740,8 +644,6 @@ await sendTestMessage({name: 'mountDownloads'}); // Add a file to Downloads. - // @ts-ignore: error TS4111: Property 'newlyAdded' comes from an index - // signature, so it must be accessed with ['newlyAdded']. await addEntries(['local'], [ENTRIES.newlyAdded]); // Wait until it mounts. @@ -752,8 +654,6 @@ chrome.test.assertTrue(!!appId, 'failed to open new window'); // Wait for Files app to finish loading. - // @ts-ignore: error TS2345: Argument of type 'boolean' is not assignable to - // parameter of type '(arg0: Object) => boolean | Object'. await remoteCall.waitFor('isFileManagerLoaded', appId, true); // We should navigate to MyFiles. @@ -762,10 +662,6 @@ ['Linux files', '--', 'Folder'], ]; await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, expectedRows, {ignoreLastModifiedTime: true}); // Navigate to Drive. @@ -785,10 +681,6 @@ // Ensure Downloads has loaded. await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, expectedRows, {ignoreLastModifiedTime: true}); // Re-enabled Drive. @@ -796,21 +688,16 @@ // Wait for the fake drive to reappear. await directoryTree.waitForItemByLabel('Google Drive'); -}; +} /** * Tests that mounting a hidden Volume does not mount the volume in file * manager. */ -// @ts-ignore: error TS4111: Property 'fileDisplayWithHiddenVolume' comes from -// an index signature, so it must be accessed with -// ['fileDisplayWithHiddenVolume']. -testcase.fileDisplayWithHiddenVolume = async () => { +export async function fileDisplayWithHiddenVolume() { const initialVolumeCount = await sendTestMessage({name: 'getVolumesCount'}); const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Get the directory tree elements. @@ -828,24 +715,17 @@ // The hidden volume should not be counted in the number of volumes. chrome.test.assertEq( initialVolumeCount, await sendTestMessage({name: 'getVolumesCount'})); -}; +} /** * Tests Files app resisting the urge to switch to Downloads when mounts change. */ -// @ts-ignore: error TS4111: Property 'fileDisplayMountWithFakeItemSelected' -// comes from an index signature, so it must be accessed with -// ['fileDisplayMountWithFakeItemSelected']. -testcase.fileDisplayMountWithFakeItemSelected = async () => { +export async function fileDisplayMountWithFakeItemSelected() { // Open Files app on Drive with the given test files. const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'newlyAdded' comes from an index - // signature, so it must be accessed with ['newlyAdded']. RootPath.DOWNLOADS, [ENTRIES.newlyAdded], []); // Ensure Downloads has loaded. - // @ts-ignore: error TS4111: Property 'newlyAdded' comes from an index - // signature, so it must be accessed with ['newlyAdded']. await remoteCall.waitForFiles(appId, [ENTRIES.newlyAdded.getExpectedRow()]); // Navigate to My files. @@ -863,17 +743,13 @@ chrome.test.assertEq( '/My files', await remoteCall.callRemoteTestUtil('getBreadcrumbPath', appId, [])); -}; +} /** * Tests Files app switching away from Drive virtual folders when Drive is * unmounted. */ -// @ts-ignore: error TS4111: Property -// 'fileDisplayUnmountDriveWithSharedWithMeSelected' comes from an index -// signature, so it must be accessed with -// ['fileDisplayUnmountDriveWithSharedWithMeSelected']. -testcase.fileDisplayUnmountDriveWithSharedWithMeSelected = async () => { +export async function fileDisplayUnmountDriveWithSharedWithMeSelected() { // Open Files app on Drive with the given test files. const appId = await setupAndWaitUntilReady( RootPath.DRIVE, [ENTRIES.newlyAdded], @@ -888,8 +764,6 @@ // Check that the file is visible. await remoteCall.waitForFiles( - // @ts-ignore: error TS4111: Property 'testSharedDocument' comes from an - // index signature, so it must be accessed with ['testSharedDocument']. appId, [ENTRIES.testSharedDocument.getExpectedRow()]); // Unmount drive. @@ -905,21 +779,17 @@ ['Linux files', '--', 'Folder'], ]; await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, expectedRows, {ignoreLastModifiedTime: true}); -}; +} /** * Navigates to a removable volume, then unmounts it. Check to see whether * Files App switches away to the default Downloads directory. * - * @param {string} removableDirectory The removable directory to be inside + * @param removableDirectory The removable directory to be inside * before unmounting the USB. */ -async function unmountRemovableVolume(removableDirectory) { +async function unmountRemovableVolume(removableDirectory: string) { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); @@ -950,10 +820,6 @@ await remoteCall.waitUntilCurrentDirectoryIsChanged( appId, `/Drive Label/${removableDirectory}`); await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: - // boolean | null | undefined; ignoreFileSize: boolean | null | - // undefined; ignoreLastModifiedTime: boolean | null | undefined; }'. appId, partitionFiles, {ignoreLastModifiedTime: true}); } @@ -970,10 +836,6 @@ ['Linux files', '--', 'Folder'], ]; await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, expectedRows, {ignoreLastModifiedTime: true}); } @@ -981,56 +843,40 @@ * Tests Files app switches away from a removable device root after the USB is * unmounted. */ -// @ts-ignore: error TS4111: Property 'fileDisplayUnmountRemovableRoot' comes -// from an index signature, so it must be accessed with -// ['fileDisplayUnmountRemovableRoot']. -testcase.fileDisplayUnmountRemovableRoot = () => { +export async function fileDisplayUnmountRemovableRoot() { return unmountRemovableVolume('Drive Label'); -}; +} /** * Tests Files app switches away from a partition inside the USB after the USB * is unmounted. */ -// @ts-ignore: error TS4111: Property 'fileDisplayUnmountFirstPartition' comes -// from an index signature, so it must be accessed with -// ['fileDisplayUnmountFirstPartition']. -testcase.fileDisplayUnmountFirstPartition = () => { +export async function fileDisplayUnmountFirstPartition() { return unmountRemovableVolume('partition-1'); -}; +} /** * Tests Files app switches away from a partition inside the USB after the USB * is unmounted. Partition-1 will be ejected first. */ -// @ts-ignore: error TS4111: Property 'fileDisplayUnmountLastPartition' comes -// from an index signature, so it must be accessed with -// ['fileDisplayUnmountLastPartition']. -testcase.fileDisplayUnmountLastPartition = () => { +export async function fileDisplayUnmountLastPartition() { return unmountRemovableVolume('partition-2'); -}; +} /** * Tests files display in Downloads while the default blocking file I/O task * runner is blocked. */ -// @ts-ignore: error TS4111: Property -// 'fileDisplayDownloadsWithBlockedFileTaskRunner' comes from an index -// signature, so it must be accessed with -// ['fileDisplayDownloadsWithBlockedFileTaskRunner']. -testcase.fileDisplayDownloadsWithBlockedFileTaskRunner = async () => { +export async function fileDisplayDownloadsWithBlockedFileTaskRunner() { await sendTestMessage({name: 'blockFileTaskRunner'}); await fileDisplay(RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET); await sendTestMessage({name: 'unblockFileTaskRunner'}); -}; +} /** * Tests to make sure check-select mode enables when selecting one item */ -// @ts-ignore: error TS4111: Property -// 'fileDisplayCheckSelectWithFakeItemSelected' comes from an index signature, -// so it must be accessed with ['fileDisplayCheckSelectWithFakeItemSelected']. -testcase.fileDisplayCheckSelectWithFakeItemSelected = async () => { +export async function fileDisplayCheckSelectWithFakeItemSelected() { // Open files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -1045,16 +891,13 @@ // Make sure check-select is enabled. await remoteCall.waitForElement(appId, 'body.check-select'); -}; +} /** * Tests to make sure read-only indicator is visible when the current directory * is read-only. */ -// @ts-ignore: error TS4111: Property -// 'fileDisplayCheckReadOnlyIconOnFakeDirectory' comes from an index signature, -// so it must be accessed with ['fileDisplayCheckReadOnlyIconOnFakeDirectory']. -testcase.fileDisplayCheckReadOnlyIconOnFakeDirectory = async () => { +export async function fileDisplayCheckReadOnlyIconOnFakeDirectory() { // Open Files app on Drive with the given test files. const appId = await setupAndWaitUntilReady( RootPath.DRIVE, [ENTRIES.newlyAdded], @@ -1069,32 +912,26 @@ // Make sure read-only indicator on toolbar is visible. await remoteCall.waitForElement(appId, '#read-only-indicator:not([hidden])'); -}; +} /** * Tests to make sure read-only indicator is NOT visible when the current * is writable. */ -// @ts-ignore: error TS4111: Property -// 'fileDisplayCheckNoReadOnlyIconOnDownloads' comes from an index signature, so -// it must be accessed with ['fileDisplayCheckNoReadOnlyIconOnDownloads']. -testcase.fileDisplayCheckNoReadOnlyIconOnDownloads = async () => { +export async function fileDisplayCheckNoReadOnlyIconOnDownloads() { // Open files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Make sure read-only indicator on toolbar is NOT visible. await remoteCall.waitForElement(appId, '#read-only-indicator[hidden]'); -}; +} /** * Tests to make sure read-only indicator is NOT visible when the current * directory is the "Linux files" fake root. */ -// @ts-ignore: error TS4111: Property -// 'fileDisplayCheckNoReadOnlyIconOnLinuxFiles' comes from an index signature, -// so it must be accessed with ['fileDisplayCheckNoReadOnlyIconOnLinuxFiles']. -testcase.fileDisplayCheckNoReadOnlyIconOnLinuxFiles = async () => { +export async function fileDisplayCheckNoReadOnlyIconOnLinuxFiles() { // Block mounts from progressing. This should cause the file manager to always // show the loading bar for linux files. await sendTestMessage({name: 'blockMounts'}); @@ -1113,16 +950,13 @@ // Check: the toolbar read-only indicator should not be visible. await remoteCall.waitForElement(appId, '#read-only-indicator[hidden]'); -}; +} /** * Tests to make sure read-only indicator is NOT visible when the current * directory is a "GuestOs" fake root. */ -// @ts-ignore: error TS4111: Property 'fileDisplayCheckNoReadOnlyIconOnGuestOs' -// comes from an index signature, so it must be accessed with -// ['fileDisplayCheckNoReadOnlyIconOnGuestOs']. -testcase.fileDisplayCheckNoReadOnlyIconOnGuestOs = async () => { +export async function fileDisplayCheckNoReadOnlyIconOnGuestOs() { // Create a Bruschetta guest for this test. await sendTestMessage({ name: 'registerMountableGuest', @@ -1149,4 +983,4 @@ // Check: the toolbar read-only indicator should not be visible. await remoteCall.waitForElement(appId, '#read-only-indicator[hidden]'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/file_list.js b/ui/file_manager/integration_tests/file_manager/file_list.ts similarity index 80% rename from ui/file_manager/integration_tests/file_manager/file_list.js rename to ui/file_manager/integration_tests/file_manager/file_list.ts index e414624c..1c21d570 100644 --- a/ui/file_manager/integration_tests/file_manager/file_list.js +++ b/ui/file_manager/integration_tests/file_manager/file_list.ts
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import type {ElementObject} from '../prod/file_manager/shared_types.js'; import {ENTRIES, RootPath, sendTestMessage} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {remoteCall, setupAndWaitUntilReady} from './background.js'; import {BASIC_LOCAL_ENTRY_SET} from './test_data.js'; @@ -19,8 +19,7 @@ * updating the selected item which is async can be detected after an extra * Tab has been sent. */ -// @ts-ignore: error TS7006: Parameter 'appId' implicitly has an 'any' type. -async function tabUntilFileSelected(appId) { +async function tabUntilFileSelected(appId: string) { // Check: the file-list should have nothing selected. const selectedRows = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, ['#file-list li[selected]']); @@ -46,12 +45,8 @@ /** * Tests that file list column header have ARIA attributes. */ -// @ts-ignore: error TS4111: Property 'fileListAriaAttributes' comes from an -// index signature, so it must be accessed with ['fileListAriaAttributes']. -testcase.fileListAriaAttributes = async () => { +export async function fileListAriaAttributes() { const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Fetch column header. @@ -67,15 +62,13 @@ // role button is used so users know that it's clickable. chrome.test.assertEq('button', header.attributes['role']); } -}; +} /** * Tests using tab to focus the file list will select the first item, if * nothing is selected. */ -// @ts-ignore: error TS4111: Property 'fileListFocusFirstItem' comes from an -// index signature, so it must be accessed with ['fileListFocusFirstItem']. -testcase.fileListFocusFirstItem = async () => { +export async function fileListFocusFirstItem() { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -83,23 +76,19 @@ await tabUntilFileSelected(appId); // Check: The first file only is selected in the file entry rows. - const fileRows = await remoteCall.callRemoteTestUtil( + const fileRows: ElementObject[] = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, ['#file-list li']); chrome.test.assertEq(5, fileRows.length); - // @ts-ignore: error TS7006: Parameter 'item' implicitly has an 'any' type. const selectedRows = fileRows.filter(item => 'selected' in item.attributes); chrome.test.assertEq(1, selectedRows.length); - chrome.test.assertEq(0, fileRows.indexOf(selectedRows[0])); -}; + chrome.test.assertEq(0, fileRows.indexOf(selectedRows[0]!)); +} /** * Tests that after a multiple selection, canceling the selection and using * Tab to focus the files list it selects the item that was last focused. */ -// @ts-ignore: error TS4111: Property 'fileListSelectLastFocusedItem' comes from -// an index signature, so it must be accessed with -// ['fileListSelectLastFocusedItem']. -testcase.fileListSelectLastFocusedItem = async () => { +export async function fileListSelectLastFocusedItem() { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -137,8 +126,6 @@ chrome.test.assertEq(2, selectedRows.length); // Cancel the selection. - // @ts-ignore: error TS6133: 'button' is declared but its value is never read. - const button = ['#cancel-selection-button']; await remoteCall.waitAndClickElement(appId, '#cancel-selection-button'); // Wait until selection is removed. @@ -148,22 +135,19 @@ await tabUntilFileSelected(appId); // Check: The 3rd item only is selected. - const fileRows = await remoteCall.callRemoteTestUtil( + const fileRows: ElementObject[] = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, ['#file-list li']); chrome.test.assertEq(5, fileRows.length); - // @ts-ignore: error TS7006: Parameter 'item' implicitly has an 'any' type. selectedRows = fileRows.filter(item => 'selected' in item.attributes); chrome.test.assertEq(1, selectedRows.length); chrome.test.assertEq(2, fileRows.indexOf(selectedRows[0])); -}; +} /** * Tests that after a multiple selection, canceling the selection and using * Tab to focus the files list it selects the item that was last focused. */ -// @ts-ignore: error TS4111: Property 'fileListSortWithKeyboard' comes from an -// index signature, so it must be accessed with ['fileListSortWithKeyboard']. -testcase.fileListSortWithKeyboard = async () => { +export async function fileListSortWithKeyboard() { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -207,19 +191,17 @@ chrome.test.assertTrue( focusedElement['attributes']['aria-label'] === 'Click to sort the column in ascending order.'); -}; +} /** * Verifies the total number of a11y messages and asserts the latest message * is the expected one. * - * @param {string} appId - * @param {number} expectedCount - * @param {?string=} expectedMessage - * @return {!Promise<string>} Latest a11y message. + * @return Latest a11y message. */ async function countAndCheckLatestA11yMessage( - appId, expectedCount, expectedMessage) { + appId: string, expectedCount: number, + expectedMessage?: null|string): Promise<string> { const a11yMessages = await remoteCall.callRemoteTestUtil('getA11yAnnounces', appId, []); if (expectedMessage === null || expectedMessage === undefined) { @@ -240,9 +222,9 @@ * messages. * * NOTE: Test shared with grid_view.js. - * @param {boolean=} isGridView if the test is testing the grid view. + * @param isGridView if the test is testing the grid view. */ -export async function fileListKeyboardSelectionA11yImpl(isGridView) { +export async function fileListKeyboardSelectionA11yImpl(isGridView?: boolean) { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -257,16 +239,14 @@ } // Keys used for keyboard navigation in the file list. - const homeKey = [viewSelector, 'Home', false, false, false]; - const ctrlDownKey = [viewSelector, 'ArrowDown', true, false, false]; - const ctrlSpaceKey = [viewSelector, ' ', true, false, false]; - const shiftEndKey = [viewSelector, 'End', false, true, false]; - const ctrlAKey = [viewSelector + ' li', 'a', true, false, false]; - const escKey = [viewSelector, 'Escape', false, false, false]; + const homeKey = [viewSelector, 'Home', false, false, false] as const; + const ctrlDownKey = [viewSelector, 'ArrowDown', true, false, false] as const; + const ctrlSpaceKey = [viewSelector, ' ', true, false, false] as const; + const shiftEndKey = [viewSelector, 'End', false, true, false] as const; + const ctrlAKey = [viewSelector + ' li', 'a', true, false, false] as const; + const escKey = [viewSelector, 'Escape', false, false, false] as const; // Select first item with Home key. - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. await remoteCall.fakeKeyDown(appId, ...homeKey); // Navigating with Home key doesn't use aria-live message, it only uses the @@ -274,11 +254,7 @@ await countAndCheckLatestA11yMessage(appId, a11yMsgCount); // Ctrl+Down & Ctrl+Space to select second item: Beautiful Song.ogg - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. await remoteCall.fakeKeyDown(appId, ...ctrlDownKey); - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. await remoteCall.fakeKeyDown(appId, ...ctrlSpaceKey); // Check: Announced "Beautiful Song.add" added to selection. @@ -286,8 +262,6 @@ appId, ++a11yMsgCount, 'Added Beautiful Song.ogg to selection.'); // Shift+End to select from 2nd item to the last item. - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. await remoteCall.fakeKeyDown(appId, ...shiftEndKey); // Check: Announced range selection from "Beautiful Song.add" to hello.txt. @@ -296,8 +270,6 @@ 'Selected a range of 4 entries from Beautiful Song.ogg to hello.txt.'); // Ctrl+Space to de-select currently focused item (last item). - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. await remoteCall.fakeKeyDown(appId, ...ctrlSpaceKey); // Check: Announced de-selecting hello.txt @@ -305,8 +277,6 @@ appId, ++a11yMsgCount, 'Removed hello.txt from selection.'); // Ctrl+A to select all items. - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. await remoteCall.fakeKeyDown(appId, ...ctrlAKey); // Check: Announced selecting all entries. @@ -314,8 +284,6 @@ appId, ++a11yMsgCount, 'Selected all entries.'); // Esc key to deselect all. - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. await remoteCall.fakeKeyDown(appId, ...escKey); // Check: Announced deselecting all entries. @@ -323,20 +291,17 @@ appId, ++a11yMsgCount, 'Removed all entries from selection.'); } -// @ts-ignore: error TS4111: Property 'fileListKeyboardSelectionA11y' comes from -// an index signature, so it must be accessed with -// ['fileListKeyboardSelectionA11y']. -testcase.fileListKeyboardSelectionA11y = async () => { +export async function fileListKeyboardSelectionA11y() { return fileListKeyboardSelectionA11yImpl(/*isGridView*/ false); -}; +} /** * Tests that selecting/de-selecting files with mouse produces a11y messages. * * NOTE: Test shared with grid_view.js. - * @param {boolean=} isGridView if the test is testing the grid view. + * @param isGridView if the test is testing the grid view. */ -export async function fileListMouseSelectionA11yImpl(isGridView) { +export async function fileListMouseSelectionA11yImpl(isGridView?: boolean) { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -390,22 +355,16 @@ appId, ++a11yMsgCount, 'Removed all entries from selection.'); } -// @ts-ignore: error ts4111: property 'filelistmouseselectiona11y ' comes from -// an index signature, so it must be accessed with -// ['filelistmouseselectiona11y ']. -testcase.fileListMouseSelectionA11y = async () => { +export async function fileListMouseSelectionA11y() { return fileListMouseSelectionA11yImpl(/*isGridView*/ false); -}; +} /** * Tests the deletion of one or multiple items. After deletion, one of the * remaining items should have the lead, but shouldn't be in check-select * mode. */ -// @ts-ignore: error TS4111: Property 'fileListDeleteMultipleFiles' comes from -// an index signature, so it must be accessed with -// ['fileListDeleteMultipleFiles']. -testcase.fileListDeleteMultipleFiles = async () => { +export async function fileListDeleteMultipleFiles() { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -453,7 +412,7 @@ // Check: selected state of first item. chrome.test.assertTrue('selected' in item.attributes); -}; +} /** * Tests that in selection mode, the rename operation is applied to the @@ -461,9 +420,7 @@ * The lead and the selected item(s) are different when we deselect a file * list item in selection mode. crbug.com/1094260 */ -// @ts-ignore: error TS4111: Property 'fileListRenameSelectedItem' comes from an -// index signature, so it must be accessed with ['fileListRenameSelectedItem']. -testcase.fileListRenameSelectedItem = async () => { +export async function fileListRenameSelectedItem() { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -508,19 +465,14 @@ appId, '#file-list [file-name="world.ogv"]'); await remoteCall.waitForElement( appId, '#file-list li[selected][file-name="New File Name.txt"]'); -}; +} /** * Tests that user can rename a file/folder after using "select all" without * having selected any file previously. */ -// @ts-ignore: error TS4111: Property 'fileListRenameFromSelectAll' comes from -// an index signature, so it must be accessed with -// ['fileListRenameFromSelectAll']. -testcase.fileListRenameFromSelectAll = async () => { +export async function fileListRenameFromSelectAll() { const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Select all the files. @@ -541,4 +493,4 @@ // Check: the renaming text input should be shown in the file list. const textInput = '#file-list .table-row[renaming] input.rename'; await remoteCall.waitForElement(appId, textInput); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/format_dialog.js b/ui/file_manager/integration_tests/file_manager/format_dialog.ts similarity index 83% rename from ui/file_manager/integration_tests/file_manager/format_dialog.js rename to ui/file_manager/integration_tests/file_manager/format_dialog.ts index d7592795..bbef6fd 100644 --- a/ui/file_manager/integration_tests/file_manager/format_dialog.js +++ b/ui/file_manager/integration_tests/file_manager/format_dialog.ts
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {ENTRIES, RootPath, sendTestMessage} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {isSinglePartitionFormat, remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -11,9 +10,9 @@ /** * Lanuches file manager and stubs out the formatVolume private api. * - * @return {!Promise<string>} Files app window ID. + * @return Files app window ID. */ -async function setupFormatDialogTest() { +async function setupFormatDialogTest(): Promise<string> { const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); await remoteCall.callRemoteTestUtil('overrideFormat', appId, []); return appId; @@ -22,10 +21,10 @@ /** * Opens a format dialog for the USB with label |usbLabel|. * - * @param {string} appId Files app window ID. - * @param {string} usbLabel Label of usb to format. + * @param appId Files app window ID. + * @param usbLabel Label of usb to format. */ -async function openFormatDialog(appId, usbLabel) { +async function openFormatDialog(appId: string, usbLabel: string) { if (await isSinglePartitionFormat(appId)) { await openFormatDialogWithSinglePartitionFormat(appId, usbLabel, 'FAKEUSB'); return; @@ -52,12 +51,12 @@ * Opens a format dialog for the USB with label |usbLabel| and device with * label |deviceLabel|. * - * @param {string} appId Files app window ID. - * @param {string} usbLabel Label of usb to format. - * @param {string} deviceLabel Label of the parent device of usb. + * @param appId Files app window ID. + * @param usbLabel Label of usb to format. + * @param deviceLabel Label of the parent device of usb. */ async function openFormatDialogWithSinglePartitionFormat( - appId, usbLabel, deviceLabel) { + appId: string, usbLabel: string, deviceLabel: string) { // Focus the directory tree. const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall); await directoryTree.focusTree(); @@ -81,9 +80,7 @@ /** * Tests the format dialog for a sample USB with files on it. */ -// @ts-ignore: error TS4111: Property 'formatDialog' comes from an index -// signature, so it must be accessed with ['formatDialog']. -testcase.formatDialog = async () => { +export async function formatDialog() { await sendTestMessage({name: 'mountFakeUsb'}); const appId = await setupFormatDialogTest(); @@ -105,14 +102,12 @@ // Check the dialog is closed. await remoteCall.waitForElement( appId, ['files-format-dialog', 'cr-dialog:not([open])']); -}; +} /** * Tests the format dialog is a modal dialog. */ -// @ts-ignore: error TS4111: Property 'formatDialogIsModal' comes from an index -// signature, so it must be accessed with ['formatDialogIsModal']. -testcase.formatDialogIsModal = async () => { +export async function formatDialogIsModal() { await sendTestMessage({name: 'mountFakeUsb'}); const appId = await setupFormatDialogTest(); @@ -131,14 +126,12 @@ const selectedRows = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, ['#file-list li[selected]']); chrome.test.assertEq(0, selectedRows.length); -}; +} /** * Tests the format dialog for an empty USB. */ -// @ts-ignore: error TS4111: Property 'formatDialogEmpty' comes from an index -// signature, so it must be accessed with ['formatDialogEmpty']. -testcase.formatDialogEmpty = async () => { +export async function formatDialogEmpty() { await sendTestMessage({name: 'mountFakeUsbEmpty'}); const appId = await setupFormatDialogTest(); @@ -157,14 +150,12 @@ // Check the dialog is closed. await remoteCall.waitForElement( appId, ['files-format-dialog', 'cr-dialog:not([open])']); -}; +} /** * Tests cancelling out of the format dialog. */ -// @ts-ignore: error TS4111: Property 'formatDialogCancel' comes from an index -// signature, so it must be accessed with ['formatDialogCancel']. -testcase.formatDialogCancel = async () => { +export async function formatDialogCancel() { await sendTestMessage({name: 'mountFakeUsb'}); const appId = await setupFormatDialogTest(); @@ -178,18 +169,19 @@ // Check the dialog is closed. await remoteCall.waitForElement( appId, ['files-format-dialog', 'cr-dialog:not([open])']); -}; +} /** * Checks that formatting gives error |errorMessage| when given |label| and * |format|. * - * @param {string} appId Files app window ID. - * @param {string} label New label of usb drive. - * @param {string} format New filesystem of drive. - * @param {string} errorMessage Expected error message to be displayed. + * @param appId Files app window ID. + * @param label New label of usb drive. + * @param format New filesystem of drive. + * @param errorMessage Expected error message to be displayed. */ -async function checkError(appId, label, format, errorMessage) { +async function checkError( + appId: string, label: string, format: string, errorMessage: string) { // Enter in a label. const driveNameQuery = ['files-format-dialog', 'cr-input#label']; await remoteCall.inputText(appId, driveNameQuery, label); @@ -219,11 +211,11 @@ /** * Checks that formatting succeeds when given |label| and |format|. * - * @param {string} appId Files app window ID. - * @param {string} label New label of usb drive. - * @param {string} format New filesystem of drive. + * @param appId Files app window ID. + * @param label New label of usb drive. + * @param format New filesystem of drive. */ -async function checkSuccess(appId, label, format) { +async function checkSuccess(appId: string, label: string, format: string) { // Enter in a label. const driveNameQuery = ['files-format-dialog', 'cr-input#label']; await remoteCall.inputText(appId, driveNameQuery, label); @@ -250,9 +242,7 @@ /** * Tests validations for drive name length. */ -// @ts-ignore: error TS4111: Property 'formatDialogNameLength' comes from an -// index signature, so it must be accessed with ['formatDialogNameLength']. -testcase.formatDialogNameLength = async () => { +export async function formatDialogNameLength() { await sendTestMessage({name: 'mountFakeUsb'}); const appId = await setupFormatDialogTest(); @@ -293,14 +283,12 @@ // Check that a 32 character name succeeds on ntfs. await checkSuccess(appId, 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF', 'ntfs'); -}; +} /** * Test validations for invalid characters. */ -// @ts-ignore: error TS4111: Property 'formatDialogNameInvalid' comes from an -// index signature, so it must be accessed with ['formatDialogNameInvalid']. -testcase.formatDialogNameInvalid = async () => { +export async function formatDialogNameInvalid() { await sendTestMessage({name: 'mountFakeUsb'}); const appId = await setupFormatDialogTest(); @@ -312,14 +300,12 @@ // Check that a name without invalid characters succeeds. await checkSuccess(appId, 'Nice name', 'vfat'); -}; +} /** * Tests opening the format dialog from the gear menu. */ -// @ts-ignore: error TS4111: Property 'formatDialogGearMenu' comes from an index -// signature, so it must be accessed with ['formatDialogGearMenu']. -testcase.formatDialogGearMenu = async () => { +export async function formatDialogGearMenu() { await sendTestMessage({name: 'mountFakeUsb'}); const appId = await setupFormatDialogTest(); @@ -390,4 +376,4 @@ // Ensure the format menu item has disappeared. await remoteCall.waitForElement(appId, '#gear-menu-format[disabled][hidden]'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/grid_view.js b/ui/file_manager/integration_tests/file_manager/grid_view.ts similarity index 60% rename from ui/file_manager/integration_tests/file_manager/grid_view.js rename to ui/file_manager/integration_tests/file_manager/grid_view.ts index e435554..f8870b3 100644 --- a/ui/file_manager/integration_tests/file_manager/grid_view.js +++ b/ui/file_manager/integration_tests/file_manager/grid_view.ts
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import type {ElementObject} from '../prod/file_manager/shared_types.js'; import {addEntries, ENTRIES, getCaller, pending, repeatUntil, RootPath, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {openNewWindow, remoteCall, setupAndWaitUntilReady} from './background.js'; import {fileListKeyboardSelectionA11yImpl, fileListMouseSelectionA11yImpl} from './file_list.js'; @@ -13,16 +13,16 @@ /** * Shows the grid view and checks the label texts of entries. * - * @param {string} rootPath Root path to be used as a default current directory - * during initialization. Can be null, for no default path. - * @param {Array<TestEntryInfo>} expectedSet Set of entries that are expected - * to appear in the grid view. - * @return {Promise<void>} Promise to be fulfilled or rejected depending on the - * test result. + * @param rootPath Root path to be used as a default current directory during + * initialization. Can be null, for no default path. + * @param expectedSet Set of entries that are expected to appear in the grid + * view. + * @return Promise to be fulfilled or rejected depending on the test result. */ -async function showGridView(rootPath, expectedSet) { +async function showGridView( + rootPath: string, expectedSet: TestEntryInfo[]): Promise<string> { const caller = getCaller(); - const expectedLabels = + const expectedLabels: string[] = expectedSet.map((entryInfo) => entryInfo.nameText).sort(); // Open Files app on |rootPath|. @@ -35,133 +35,97 @@ // Compare the grid labels of the entries. await repeatUntil(async () => { - const labels = await remoteCall.callRemoteTestUtil( + const labels: ElementObject[] = await remoteCall.callRemoteTestUtil( 'queryAllElements', appId, ['grid:not([hidden]) .thumbnail-item .entry-name']); - // @ts-ignore: error TS7006: Parameter 'label' implicitly has an 'any' type. - const actualLabels = labels.map((label) => label.text).sort(); + const actualLabels = labels.map<string>((label) => label.text!).sort(); - // @ts-ignore: error TS2339: Property 'checkDeepEq' does not exist on type - // 'typeof test'. - if (chrome.test.checkDeepEq(expectedLabels, actualLabels)) { + if (chrome.test.checkDeepEq<string[]>(expectedLabels, actualLabels)) { return true; } return pending( caller, 'Failed to compare the grid lables, expected: %j, actual %j.', expectedLabels, actualLabels); }); - // @ts-ignore: error TS2322: Type 'string' is not assignable to type 'void'. return appId; } /** * Tests to show grid view on a local directory. */ -// @ts-ignore: error TS4111: Property 'showGridViewDownloads' comes from an -// index signature, so it must be accessed with ['showGridViewDownloads']. -testcase.showGridViewDownloads = () => { +export async function showGridViewDownloads() { return showGridView(RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET); -}; +} /** * Tests to show grid view on a drive directory. */ -// @ts-ignore: error TS4111: Property 'showGridViewDrive' comes from an index -// signature, so it must be accessed with ['showGridViewDrive']. -testcase.showGridViewDrive = () => { +export async function showGridViewDrive() { return showGridView(RootPath.DRIVE, BASIC_DRIVE_ENTRY_SET); -}; +} /** * Tests to view-button switches to thumbnail (grid) view and clicking again * switches back to detail (file list) view. */ -// @ts-ignore: error TS4111: Property 'showGridViewButtonSwitches' comes from an -// index signature, so it must be accessed with ['showGridViewButtonSwitches']. -testcase.showGridViewButtonSwitches = async () => { +export async function showGridViewButtonSwitches() { const appId = await showGridView(RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET); // Check that a11y message for switching to grid view. let a11yMessages = - // @ts-ignore: error TS2345: Argument of type 'void' is not assignable to - // parameter of type 'string | null'. await remoteCall.callRemoteTestUtil('getA11yAnnounces', appId, []); chrome.test.assertEq(1, a11yMessages.length, 'Missing a11y message'); chrome.test.assertEq( 'File list has changed to thumbnail view.', a11yMessages[0]); // Click view-button again to switch to detail view. - // @ts-ignore: error TS2345: Argument of type 'void' is not assignable to - // parameter of type 'string'. await remoteCall.waitAndClickElement(appId, '#view-button'); // Wait for detail-view to be visible and grid to be hidden. - // @ts-ignore: error TS2345: Argument of type 'void' is not assignable to - // parameter of type 'string'. await remoteCall.waitForElement(appId, '#detail-table:not([hidden])'); - // @ts-ignore: error TS2345: Argument of type 'void' is not assignable to - // parameter of type 'string'. await remoteCall.waitForElement(appId, 'grid[hidden]'); // Check that a11y message for switching to list view. a11yMessages = - // @ts-ignore: error TS2345: Argument of type 'void' is not assignable to - // parameter of type 'string | null'. await remoteCall.callRemoteTestUtil('getA11yAnnounces', appId, []); chrome.test.assertEq(2, a11yMessages.length, 'Missing a11y message'); chrome.test.assertEq('File list has changed to list view.', a11yMessages[1]); -}; +} /** * Tests that selecting/de-selecting files with keyboard produces a11y messages. */ -// @ts-ignore: error TS4111: Property 'showGridViewKeyboardSelectionA11y' comes -// from an index signature, so it must be accessed with -// ['showGridViewKeyboardSelectionA11y']. -testcase.showGridViewKeyboardSelectionA11y = async () => { +export async function showGridViewKeyboardSelectionA11y() { const isGridView = true; return fileListKeyboardSelectionA11yImpl(isGridView); -}; +} /** * Tests that selecting/de-selecting files with mouse produces a11y messages. */ -// @ts-ignore: error TS4111: Property 'showGridViewMouseSelectionA11y' comes -// from an index signature, so it must be accessed with -// ['showGridViewMouseSelectionA11y']. -testcase.showGridViewMouseSelectionA11y = async () => { +export async function showGridViewMouseSelectionA11y() { const isGridView = true; return fileListMouseSelectionA11yImpl(isGridView); -}; +} /** * Tests that Grid View shows "Folders" and "Files" titles before folders and * files respectively. */ -// @ts-ignore: error TS4111: Property 'showGridViewTitles' comes from an index -// signature, so it must be accessed with ['showGridViewTitles']. -testcase.showGridViewTitles = async () => { +export async function showGridViewTitles() { const appId = await showGridView(RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET); - const titles = await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS2345: Argument of type 'void' is not assignable to - // parameter of type 'string | null'. + const titles: ElementObject[] = await remoteCall.callRemoteTestUtil( 'queryAllElements', appId, ['.thumbnail-grid .grid-title']); chrome.test.assertEq(2, titles.length, 'Grid view should show 2 titles'); - // @ts-ignore: error TS7006: Parameter 'title' implicitly has an 'any' type. - const titleTexts = titles.map((title) => title.text).sort(); - // @ts-ignore: error TS2339: Property 'checkDeepEq' does not exist on type - // 'typeof test'. - chrome.test.checkDeepEq(['Files', 'Folders'], titleTexts); -}; + const titleTexts = titles.map<string>((title) => title.text!).sort(); + chrome.test.checkDeepEq<string[]>(['Files', 'Folders'], titleTexts); +} /** * Tests that Grid View shows DocumentsProvider thumbnails. */ -// @ts-ignore: error TS4111: Property 'showGridViewDocumentsProvider' comes from -// an index signature, so it must be accessed with -// ['showGridViewDocumentsProvider']. -testcase.showGridViewDocumentsProvider = async () => { +export async function showGridViewDocumentsProvider() { const caller = getCaller(); // Add files to the DocumentsProvider volume. @@ -200,8 +164,7 @@ const item = await remoteCall.waitForElement( appId, `#file-list [file-name="${fname}"]`); const thumbnailLoaded = - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - item.attributes['class'].split(/\s+/).includes('thumbnail-loaded'); + item.attributes!['class']?.split(/\s+/).includes('thumbnail-loaded'); if (thumbnailLoaded !== hasThumbnail) { return pending( caller, 'Unexpected thumbnail state for %j: %j', fname, @@ -210,17 +173,13 @@ } return true; }); -}; +} /** * Tests that an encrypted file will have a corresponding icon. */ -// @ts-ignore: error TS4111: Property 'showGridViewEncryptedFile' comes from an -// index signature, so it must be accessed with ['showGridViewEncryptedFile']. -testcase.showGridViewEncryptedFile = async () => { +export async function showGridViewEncryptedFile() { const appId = - // @ts-ignore: error TS4111: Property 'testCSEFile' comes from an index - // signature, so it must be accessed with ['testCSEFile']. await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.testCSEFile]); // Click the grid view button. @@ -230,8 +189,7 @@ const icon = await remoteCall.waitForElementStyles( appId, '.thumbnail-grid .no-thumbnail', ['-webkit-mask-image']); chrome.test.assertTrue( - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - icon.styles['-webkit-mask-image'].includes('encrypted.svg'), + icon.styles!['-webkit-mask-image']?.includes('encrypted.svg') ?? false, 'Icon does not seem to be the encrypted one'); // Move mouse out of the view change button, so we won't have its hover text. @@ -246,4 +204,4 @@ const label = await remoteCall.waitForElement( appId, ['files-tooltip[visible=true]', '#label']); chrome.test.assertEq('Encrypted file', label.text); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/guest_os.js b/ui/file_manager/integration_tests/file_manager/guest_os.ts similarity index 86% rename from ui/file_manager/integration_tests/file_manager/guest_os.js rename to ui/file_manager/integration_tests/file_manager/guest_os.ts index 561cd68..3150ffe 100644 --- a/ui/file_manager/integration_tests/file_manager/guest_os.js +++ b/ui/file_manager/integration_tests/file_manager/guest_os.ts
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {ENTRIES, RootPath, sendTestMessage} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -11,9 +10,7 @@ /** * Tests that Guest OS entries show up in the sidebar at files app launch. */ -// @ts-ignore: error TS4111: Property 'fakesListed' comes from an index -// signature, so it must be accessed with ['fakesListed']. -testcase.fakesListed = async () => { +export async function fakesListed() { // Prepopulate the list with a bunch of guests. const names = ['Electra', 'Etcetera', 'Jemima']; for (const name of names) { @@ -30,16 +27,13 @@ for (const name of names) { await directoryTree.waitForItemByLabel(name); } -}; +} /** * Tests that the list of guests is updated when new guests are added or * removed. */ -// @ts-ignore: error TS4111: Property 'listUpdatedWhenGuestsChanged' comes from -// an index signature, so it must be accessed with -// ['listUpdatedWhenGuestsChanged']. -testcase.listUpdatedWhenGuestsChanged = async () => { +export async function listUpdatedWhenGuestsChanged() { // Open the files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -77,16 +71,14 @@ } await directoryTree.waitForPlaceholderItemsCountByType( 'android_files', names.length); -}; +} /** * Tests that clicking on a Guest OS entry in the sidebar mounts the * corresponding volume, and that the UI is updated appropriately (volume in * sidebar and not fake, contents show up once done loading, etc). */ -// @ts-ignore: error TS4111: Property 'mountGuestSuccess' comes from an index -// signature, so it must be accessed with ['mountGuestSuccess']. -testcase.mountGuestSuccess = async () => { +export async function mountGuestSuccess() { const guestName = 'JennyAnyDots'; // Start off with one guest. const guestId = await sendTestMessage({ @@ -132,16 +124,14 @@ // And no more volume. await directoryTree.waitForItemLostByType('bruschetta'); -}; +} /** * Tests that clicking on a Guest OS Android entry in the sidebar mounts the * corresponding volume, and that the UI is update appropriately (volume in * sidebar and not fake, contents show up once done loading, etc). */ -// @ts-ignore: error TS4111: Property 'mountAndroidVolumeSuccess' comes from an -// index signature, so it must be accessed with ['mountAndroidVolumeSuccess']. -testcase.mountAndroidVolumeSuccess = async () => { +export async function mountAndroidVolumeSuccess() { await sendTestMessage({name: 'unmountPlayFiles'}); const guestName = 'Play files'; // Start off with one guest. @@ -188,4 +178,4 @@ // And no more volume. await directoryTree.waitForItemLostByType('android_files'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/keyboard_operations.js b/ui/file_manager/integration_tests/file_manager/keyboard_operations.ts similarity index 72% rename from ui/file_manager/integration_tests/file_manager/keyboard_operations.js rename to ui/file_manager/integration_tests/file_manager/keyboard_operations.ts index 93069a7..20395a2 100644 --- a/ui/file_manager/integration_tests/file_manager/keyboard_operations.js +++ b/ui/file_manager/integration_tests/file_manager/keyboard_operations.ts
@@ -3,20 +3,18 @@ // found in the LICENSE file. import {ENTRIES, getCaller, pending, repeatUntil, RootPath, sendTestMessage, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {IGNORE_APP_ERRORS, remoteCall, setupAndWaitUntilReady} from './background.js'; -import {TREEITEM_DOWNLOADS, TREEITEM_DRIVE} from './create_new_folder.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; /** * Waits until a dialog with an OK button is shown, and accepts it by clicking * on the dialog's OK button. * - * @param {string} appId The Files app windowId. - * @return {Promise<void>} Promise to be fulfilled after clicking the OK button. + * @param appId The Files app windowId. + * @return Promise to be fulfilled after clicking the OK button. */ -export async function waitAndAcceptDialog(appId) { +async function waitAndAcceptDialog(appId: string): Promise<void> { const okButton = '.cr-dialog-ok'; // Wait until the dialog is shown. @@ -32,12 +30,10 @@ /** * Tests copying a file to the same file list. * - * @param {string} path The path to be tested, Downloads or Drive. + * @param path The path to be tested, Downloads or Drive. */ -async function keyboardCopy(path) { +async function keyboardCopy(path: string) { const appId = - // @ts-ignore: error TS4111: Property 'world' comes from an index - // signature, so it must be accessed with ['world']. await setupAndWaitUntilReady(path, [ENTRIES.world], [ENTRIES.world]); // Copy the file into the same file list. @@ -45,15 +41,9 @@ await remoteCall.callRemoteTestUtil('copyFile', appId, ['world.ogv']), 'copyFile failed'); // Check: the copied file should appear in the file list. - // @ts-ignore: error TS4111: Property 'world' comes from an index signature, - // so it must be accessed with ['world']. const expectedEntryRows = [ENTRIES.world.getExpectedRow()].concat( [['world (1).ogv', '56 KB', 'OGG video']]); await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, expectedEntryRows, {ignoreLastModifiedTime: true}); const files = await remoteCall.callRemoteTestUtil('getFileList', appId, []); if (path === RootPath.DRIVE) { @@ -68,11 +58,11 @@ /** * Tests deleting a file from the file list. * - * @param {string} path The path to be tested, Downloads or Drive. - * @param {boolean=} confirmDeletion If the file system doesn't support trash, - * need to confirm the deletion. + * @param path The path to be tested, Downloads or Drive. + * @param confirmDeletion If the file system doesn't support trash, need to + * confirm the deletion. */ -async function keyboardDelete(path, confirmDeletion = false) { +async function keyboardDelete(path: string, confirmDeletion: boolean = false) { const appId = await setupAndWaitUntilReady(path, [ENTRIES.hello], [ENTRIES.hello]); @@ -93,13 +83,13 @@ * Tests deleting a folder from the file list. The folder is also shown in the * Files app directory tree, and should not be shown there when deleted. * - * @param {string} path The path to be tested, Downloads or Drive. - * @param {string} parentLabel The directory tree item label. - * @param {boolean=} confirmDeletion If the file system doesn't support trash, - * need to confirm the deletion. + * @param path The path to be tested, Downloads or Drive. + * @param parentLabel The directory tree item label. + * @param confirmDeletion If the file system doesn't support trash, need to + * confirm the deletion. */ async function keyboardDeleteFolder( - path, parentLabel, confirmDeletion = false) { + path: string, parentLabel: string, confirmDeletion: boolean = false) { const appId = await setupAndWaitUntilReady(path, [ENTRIES.photos], [ENTRIES.photos]); @@ -129,12 +119,13 @@ /** * Renames a file. * - * @param {string} appId The Files app windowId. - * @param {string} oldName Old name of a file. - * @param {string} newName New name of a file. - * @return {Promise<void>} Promise to be fulfilled on success. + * @param appId The Files app windowId. + * @param oldName Old name of a file. + * @param newName New name of a file. + * @return Promise to be fulfilled on success. */ -async function renameFile(appId, oldName, newName) { +async function renameFile( + appId: string, oldName: string, newName: string): Promise<void> { const textInput = '#file-list .table-row[renaming] input.rename'; // Select the file. @@ -161,11 +152,12 @@ * Tests renaming a folder. An extra enter key is sent to the file list during * renaming to check the folder cannot be entered while it is being renamed. * - * @param {string} path Initial path (Downloads or Drive). - * @param {string} parentLabel The directory tree item label. - * @return {Promise<void>} Promise to be fulfilled on success. + * @param path Initial path (Downloads or Drive). + * @param parentLabel The directory tree item label. + * @return Promise to be fulfilled on success. */ -async function testRenameFolder(path, parentLabel) { +async function testRenameFolder( + path: string, parentLabel: string): Promise<void> { const textInput = '#file-list .table-row[renaming] input.rename'; const appId = await setupAndWaitUntilReady(path, [ENTRIES.photos], [ENTRIES.photos]); @@ -225,10 +217,10 @@ /** * Tests renaming a file. * - * @param {string} path Initial path (Downloads or Drive). - * @return {Promise<void>} Promise to be fulfilled on success. + * @param path Initial path (Downloads or Drive). + * @return Promise to be fulfilled on success. */ -async function testRenameFile(path) { +async function testRenameFile(path: string): Promise<void> { const newFile = [['New File Name.txt', '51 bytes', 'Plain text', '']]; const appId = @@ -253,79 +245,53 @@ await remoteCall.waitForFiles(appId, newFile, {ignoreLastModifiedTime: true}); } -// @ts-ignore: error TS4111: Property 'keyboardCopyDownloads' comes from an -// index signature, so it must be accessed with ['keyboardCopyDownloads']. -testcase.keyboardCopyDownloads = () => { +export function keyboardCopyDownloads() { return keyboardCopy(RootPath.DOWNLOADS); -}; +} -// @ts-ignore: error TS4111: Property 'keyboardCopyDrive' comes from an index -// signature, so it must be accessed with ['keyboardCopyDrive']. -testcase.keyboardCopyDrive = () => { +export function keyboardCopyDrive() { return keyboardCopy(RootPath.DRIVE); -}; +} -// @ts-ignore: error TS4111: Property 'keyboardDeleteDownloads' comes from an -// index signature, so it must be accessed with ['keyboardDeleteDownloads']. -testcase.keyboardDeleteDownloads = () => { +export function keyboardDeleteDownloads() { return keyboardDelete(RootPath.DOWNLOADS); -}; +} -// @ts-ignore: error TS4111: Property 'keyboardDeleteDrive' comes from an index -// signature, so it must be accessed with ['keyboardDeleteDrive']. -testcase.keyboardDeleteDrive = () => { +export function keyboardDeleteDrive() { return keyboardDelete(RootPath.DRIVE, /*confirmDeletion=*/ true); -}; +} -// @ts-ignore: error TS4111: Property 'keyboardDeleteFolderDownloads' comes from -// an index signature, so it must be accessed with -// ['keyboardDeleteFolderDownloads']. -testcase.keyboardDeleteFolderDownloads = () => { - return keyboardDeleteFolder(RootPath.DOWNLOADS, TREEITEM_DOWNLOADS); -}; +export function keyboardDeleteFolderDownloads() { + return keyboardDeleteFolder(RootPath.DOWNLOADS, 'Downloads'); +} -// @ts-ignore: error TS4111: Property 'keyboardDeleteFolderDrive' comes from an -// index signature, so it must be accessed with ['keyboardDeleteFolderDrive']. -testcase.keyboardDeleteFolderDrive = () => { +export function keyboardDeleteFolderDrive() { return keyboardDeleteFolder( - RootPath.DRIVE, TREEITEM_DRIVE, /*confirmDeletion=*/ true); -}; + RootPath.DRIVE, 'My Drive', /*confirmDeletion=*/ true); +} -// @ts-ignore: error TS4111: Property 'renameFileDownloads' comes from an index -// signature, so it must be accessed with ['renameFileDownloads']. -testcase.renameFileDownloads = () => { +export function renameFileDownloads() { return testRenameFile(RootPath.DOWNLOADS); -}; +} -// @ts-ignore: error TS4111: Property 'renameFileDrive' comes from an index -// signature, so it must be accessed with ['renameFileDrive']. -testcase.renameFileDrive = () => { +export function renameFileDrive() { return testRenameFile(RootPath.DRIVE); -}; +} -// @ts-ignore: error TS4111: Property 'renameNewFolderDownloads' comes from an -// index signature, so it must be accessed with ['renameNewFolderDownloads']. -testcase.renameNewFolderDownloads = () => { - return testRenameFolder(RootPath.DOWNLOADS, TREEITEM_DOWNLOADS); -}; +export function renameNewFolderDownloads() { + return testRenameFolder(RootPath.DOWNLOADS, 'Downloads'); +} -// @ts-ignore: error TS4111: Property 'renameNewFolderDrive' comes from an index -// signature, so it must be accessed with ['renameNewFolderDrive']. -testcase.renameNewFolderDrive = () => { - return testRenameFolder(RootPath.DRIVE, TREEITEM_DRIVE); -}; +export function renameNewFolderDrive() { + return testRenameFolder(RootPath.DRIVE, 'My Drive'); +} /** * Tests renaming partitions with the keyboard on the file list. */ -// @ts-ignore: error TS4111: Property 'renameRemovableWithKeyboardOnFileList' -// comes from an index signature, so it must be accessed with -// ['renameRemovableWithKeyboardOnFileList']. -testcase.renameRemovableWithKeyboardOnFileList = async () => { +export async function renameRemovableWithKeyboardOnFileList() { // Open Files app on local downloads. const appId = - // @ts-ignore: error TS4111: Property 'world' comes from an index - // signature, so it must be accessed with ['world']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.world]); // Mount removable device with partitions. @@ -375,29 +341,21 @@ await remoteCall.waitForElementLost(appId, textInput); // verify the partition was successfully renamed. - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - expectedRows[2][0] = smallerPartitionName; + expectedRows[2]![0] = smallerPartitionName; await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, expectedRows, {ignoreLastModifiedTime: true}); // Even though the Files app rename flow worked, the background.js page // console errors about not being able to 'mount' the older volume name // due to a disk_mount_manager.cc error: user/fake-usb not found. return IGNORE_APP_ERRORS; -}; +} /** * Tests that the root html element .focus-outline-visible class appears for * keyboard interaction and is removed on mouse interaction. */ -// @ts-ignore: error TS4111: Property 'keyboardFocusOutlineVisible' comes from -// an index signature, so it must be accessed with -// ['keyboardFocusOutlineVisible']. -testcase.keyboardFocusOutlineVisible = async () => { +export async function keyboardFocusOutlineVisible() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -412,16 +370,13 @@ // Check: the html element should not have focus-outline-visible class. await remoteCall.waitForElementLost(appId, htmlFocusOutlineVisible); -}; +} /** * Tests that the root html element .pointer-active class is added and removed * for mouse interaction. */ -// @ts-ignore: error TS4111: Property 'keyboardFocusOutlineVisibleMouse' comes -// from an index signature, so it must be accessed with -// ['keyboardFocusOutlineVisibleMouse']. -testcase.keyboardFocusOutlineVisibleMouse = async () => { +export async function keyboardFocusOutlineVisibleMouse() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -443,16 +398,13 @@ // Check: the html element should not have pointer-active class. await remoteCall.waitForElementLost(appId, htmlPointerActive); -}; +} /** * Tests that the root html element .pointer-active class will be removed with * pointerup event triggered by touch. */ -// @ts-ignore: error TS4111: Property 'pointerActiveRemovedByTouch' comes from -// an index signature, so it must be accessed with -// ['pointerActiveRemovedByTouch']. -testcase.pointerActiveRemovedByTouch = async () => { +export async function pointerActiveRemovedByTouch() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -472,15 +424,13 @@ // Check: the html element should not have pointer-active class. await remoteCall.waitForElementLost(appId, htmlPointerActive); -}; +} /** * Tests that the root html element .pointer-active class should not be added if * the PointerDown event is triggered by touch. */ -// @ts-ignore: error TS4111: Property 'noPointerActiveOnTouch' comes from an -// index signature, so it must be accessed with ['noPointerActiveOnTouch']. -testcase.noPointerActiveOnTouch = async () => { +export async function noPointerActiveOnTouch() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -493,16 +443,13 @@ // Check: the html element should not have pointer-active class. const htmlPointerActive = ['html.pointer-active']; await remoteCall.waitForElementLost(appId, htmlPointerActive); -}; +} /** * Test that selecting "Google Drive" in the directory tree with the keyboard * expands it and selects "My Drive". */ -// @ts-ignore: error TS4111: Property 'keyboardSelectDriveDirectoryTree' comes -// from an index signature, so it must be accessed with -// ['keyboardSelectDriveDirectoryTree']. -testcase.keyboardSelectDriveDirectoryTree = async () => { +export async function keyboardSelectDriveDirectoryTree() { // Open Files app. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, [ENTRIES.world], [ENTRIES.hello]); @@ -539,16 +486,13 @@ // My Drive should be selected. await directoryTree.waitForSelectedItemByLabel('My Drive'); -}; +} /** * Tests that while the delete dialog is displayed, it is not possible to press * CONTROL-C to copy a file. */ -// @ts-ignore: error TS4111: Property 'keyboardDisableCopyWhenDialogDisplayed' -// comes from an index signature, so it must be accessed with -// ['keyboardDisableCopyWhenDialogDisplayed']. -testcase.keyboardDisableCopyWhenDialogDisplayed = async () => { +export async function keyboardDisableCopyWhenDialogDisplayed() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); @@ -588,14 +532,12 @@ // Check: no files should be pasted. const files = TestEntryInfo.getExpectedRows([ENTRIES.hello]); await remoteCall.waitForFiles(appId, files); -}; +} /** * Tests Ctrl+N opens a new windows crbug.com/933302. */ -// @ts-ignore: error TS4111: Property 'keyboardOpenNewWindow' comes from an -// index signature, so it must be accessed with ['keyboardOpenNewWindow']. -testcase.keyboardOpenNewWindow = async () => { +export async function keyboardOpenNewWindow() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -622,4 +564,4 @@ 'Waiting for new window to open, current windows: ' + currentWindowsIds); }); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/metadata.js b/ui/file_manager/integration_tests/file_manager/metadata.ts similarity index 78% rename from ui/file_manager/integration_tests/file_manager/metadata.js rename to ui/file_manager/integration_tests/file_manager/metadata.ts index bbfb9d7..195ed4f 100644 --- a/ui/file_manager/integration_tests/file_manager/metadata.js +++ b/ui/file_manager/integration_tests/file_manager/metadata.ts
@@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {MetadataStats} from '../prod/file_manager/shared_types.js'; +import type {MetadataStats} from '../prod/file_manager/shared_types.js'; import {addEntries, createTestFile, ENTRIES, EntryType, RootPath, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {openNewWindow, remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -12,11 +11,10 @@ /** * Check if |value| equals the |desiredValue| within 1% margin of tolerance. - * @param {number} value The variable value. - * @param {number} desiredValue The desired value. - * @return {boolean} + * @param value The variable value. + * @param desiredValue The desired value. */ -function equal1PercentMargin(value, desiredValue) { +function equal1PercentMargin(value: number, desiredValue: number): boolean { // floor and ceil to account to at least +/-1 unit. const minValue = Math.floor(desiredValue * 0.99); const maxValue = Math.ceil(desiredValue * 1.01); @@ -35,10 +33,9 @@ /** * Creates a test file, which can be inside another folder, however parent * folders have to be created by the caller. - * @param {string} path Folder path to be created, - * @return {TestEntryInfo} + * @param path Folder path to be created, */ -function createTestFolder(path) { +function createTestFolder(path: string): TestEntryInfo { const name = path.split('/').pop(); return new TestEntryInfo({ targetPath: path, @@ -52,17 +49,13 @@ /** * Creates a Shared Drive. - * @param {string} name Shared Drive name. - * @return {TestEntryInfo} + * @param name Shared Drive name. */ -function createTestTeamDrive(name) { +function createTestTeamDrive(name: string): TestEntryInfo { return new TestEntryInfo({ teamDriveName: name, type: EntryType.SHARED_DRIVE, - // @ts-ignore: error TS2561: Object literal may only specify known - // properties, but 'capabilites' does not exist in type - // 'TestEntryInfoOptions'. Did you mean to write 'capabilities'? - capabilites: { + capabilities: { canCopy: true, canDelete: true, canRename: true, @@ -74,7 +67,6 @@ /** * Entries used by Drive and Downloads tests. - * @type {!Array<TestEntryInfo>} */ const testEntries = [ createTestFile('file1.txt'), @@ -100,9 +92,7 @@ * - Opening Files app in My Drive with 8 files and 3 folders. * - Navigate to My Drive > photos1 > folder2, which is empty. */ -// @ts-ignore: error TS4111: Property 'metadataDrive' comes from an index -// signature, so it must be accessed with ['metadataDrive']. -testcase.metadataDrive = async () => { +export async function metadataDrive() { // Open Files app on Drive. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, testEntries, testEntries); @@ -113,8 +103,8 @@ await directoryTree.navigateToPath('/My Drive/photos1/folder1'); // Fetch the metadata stats. - const metadataStats = /** @type {!MetadataStats} */ - (await remoteCall.callRemoteTestUtil('getMetadataStats', appId, [])); + const metadataStats = + await remoteCall.callRemoteTestUtil('getMetadataStats', appId, []); // Verify the number of metadata operations generated by the whole // navigation above. @@ -134,16 +124,14 @@ chrome.test.assertEq(11, metadataStats.clearCacheCount); chrome.test.assertEq(0, metadataStats.clearAllCount); chrome.test.assertEq(0, metadataStats.invalidateCount); -}; +} /** * Measures the number of metadata operations generated for: * - Opening Files app in Downloads with 8 files and 3 folders. * - Navigate to Downloads > photos1 > folder1 which is empty. */ -// @ts-ignore: error TS4111: Property 'metadataDownloads' comes from an index -// signature, so it must be accessed with ['metadataDownloads']. -testcase.metadataDownloads = async () => { +export async function metadataDownloads() { // Open Files app on Downloads. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, testEntries, testEntries); @@ -179,7 +167,7 @@ chrome.test.assertEq(11, metadataStats.clearCacheCount); chrome.test.assertEq(0, metadataStats.clearAllCount); chrome.test.assertEq(0, metadataStats.invalidateCount); -}; +} /** * Measures the number of metadata operations generated for: @@ -189,9 +177,7 @@ * Using 50 files and 50 folders because in the Drive backend it has a * throttle for max of 20 concurrent operations. */ -// @ts-ignore: error TS4111: Property 'metadataLargeDrive' comes from an index -// signature, so it must be accessed with ['metadataLargeDrive']. -testcase.metadataLargeDrive = async () => { +export async function metadataLargeDrive() { const entries = [createTestFolder('folder1')]; const folder1ExpectedRows = []; @@ -222,41 +208,38 @@ // to wait until the metadata stats to have the expected count. // If the asserts below fail, check if your change has increased the number // of metadata operations, because they impact the overall app performance. - // @ts-ignore: error TS7006: Parameter 'metadataStats' implicitly has an 'any' - // type. - const checkMetadata = (metadataStats) => { - let result = true; + const checkMetadata = (metadataStats: MetadataStats) => { // Full fetch tally: // 51 files in My Drive. // + 50 files in My Drive>folder1. // + 1 My Drive root. // + 1 read again folder1 when naviated to it. // = 103 - // @ts-ignore: error TS2447: The '&=' operator is not allowed for boolean - // types. Consider using '&&' instead. - result &= equal1PercentMargin(metadataStats.fullFetch, 103); + if (!equal1PercentMargin(metadataStats.fullFetch, 103)) { + return false; + } // 50 team drives cached, reading from file list when navigating to // /team_drives, then read cached when expanding directory tree. - // @ts-ignore: error TS2447: The '&=' operator is not allowed for boolean - // types. Consider using '&&' instead. - result &= metadataStats.fromCache < 70; + if (metadataStats.fromCache >= 70) { + return false; + } // Cleared 51 folders when navigated out of My Drive and clearing file // list. - // @ts-ignore: error TS2447: The '&=' operator is not allowed for boolean - // types. Consider using '&&' instead. - result &= equal1PercentMargin(metadataStats.clearCacheCount, 51); - // @ts-ignore: error TS2447: The '&=' operator is not allowed for boolean - // types. Consider using '&&' instead. - result &= metadataStats.clearAllCount === 0; - // @ts-ignore: error TS2447: The '&=' operator is not allowed for boolean - // types. Consider using '&&' instead. - result &= metadataStats.invalidateCount === 0; - return result; + if (!equal1PercentMargin(metadataStats.clearCacheCount, 51)) { + return false; + } + if (metadataStats.clearAllCount !== 0) { + return false; + } + if (metadataStats.invalidateCount !== 0) { + return false; + } + return true; }; - await remoteCall.waitFor('getMetadataStats', appId, checkMetadata); -}; + await remoteCall.waitFor('getMetadataStats', appId, checkMetadata as any); +} /** * Measures the number of metadata operations generated for: @@ -264,9 +247,7 @@ * - Navigate to Shared Drives, with 50 team drives. * - Expand Shared Drives to display the 50 team drives.. */ -// @ts-ignore: error TS4111: Property 'metadataTeamDrives' comes from an index -// signature, so it must be accessed with ['metadataTeamDrives']. -testcase.metadataTeamDrives = async () => { +export async function metadataTeamDrives() { const entries = []; const driveEntries = []; @@ -334,14 +315,12 @@ chrome.test.assertEq(100, metadataStats.clearCacheCount); chrome.test.assertEq(0, metadataStats.clearAllCount); chrome.test.assertEq(0, metadataStats.invalidateCount); -}; +} /** * Tests that fetching content metadata from a DocumentsProvider completes. */ -// @ts-ignore: error TS4111: Property 'metadataDocumentsProvider' comes from an -// index signature, so it must be accessed with ['metadataDocumentsProvider']. -testcase.metadataDocumentsProvider = async () => { +export async function metadataDocumentsProvider() { // Add files to the DocumentsProvider volume. await addEntries(['documents_provider'], BASIC_LOCAL_ENTRY_SET); @@ -365,7 +344,5 @@ 'getContentMetadata', appId, [['mediaMimeType']]); // Check nothing in the result was returned. - // @ts-ignore: error TS2339: Property 'checkDeepEq' does not exist on type - // 'typeof test'. - chrome.test.checkDeepEq([], result); -}; + chrome.test.checkDeepEq<string[]>([], result); +}
diff --git a/ui/file_manager/integration_tests/file_manager/my_files.js b/ui/file_manager/integration_tests/file_manager/my_files.ts similarity index 67% rename from ui/file_manager/integration_tests/file_manager/my_files.js rename to ui/file_manager/integration_tests/file_manager/my_files.ts index 45e98ad..c328518e 100644 --- a/ui/file_manager/integration_tests/file_manager/my_files.js +++ b/ui/file_manager/integration_tests/file_manager/my_files.ts
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {addEntries, ENTRIES, EntryType, RootPath, sendTestMessage, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {mountCrostini, remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -11,9 +10,9 @@ /** * Select My files in directory tree and wait for load. * - * @param {string} appId ID of the app window. + * @param appId ID of the app window. */ -async function selectMyFiles(appId) { +async function selectMyFiles(appId: string) { // Select My Files folder. const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall); await directoryTree.selectItemByLabel('My files'); @@ -24,20 +23,13 @@ const crostiniRow = ['Linux files', '--', 'Folder']; await remoteCall.waitForFiles( appId, [downloadsRow, playFilesRow, crostiniRow], - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); } /** * Tests if MyFiles is displayed when flag is true. */ -// @ts-ignore: error TS4111: Property 'showMyFiles' comes from an index -// signature, so it must be accessed with ['showMyFiles']. -testcase.showMyFiles = async () => { +export async function showMyFiles() { const expectedElementLabels = [ 'Recent', 'My files', @@ -53,8 +45,6 @@ // Open Files app on local Downloads. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall); @@ -68,7 +58,7 @@ // Check that My Files is displayed on breadcrumbs. const expectedBreadcrumbs = '/My files/Downloads'; remoteCall.waitUntilCurrentDirectoryIsChanged(appId, expectedBreadcrumbs); -}; +} /** * Tests directory tree refresh doesn't hide Downloads folder. @@ -78,13 +68,9 @@ * DirectoryTree expects NavigationModelItem to be the same instance through * updates. */ -// @ts-ignore: error TS4111: Property 'directoryTreeRefresh' comes from an index -// signature, so it must be accessed with ['directoryTreeRefresh']. -testcase.directoryTreeRefresh = async () => { +export async function directoryTreeRefresh() { // Open Files app on local Downloads. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Mount a USB volume. @@ -96,20 +82,15 @@ // Select Downloads folder. await directoryTree.selectItemByLabel('Downloads'); -}; +} /** * Tests My Files displaying Downloads on file list (RHS) and opening Downloads * from file list. */ -// @ts-ignore: error TS4111: Property 'myFilesDisplaysAndOpensEntries' comes -// from an index signature, so it must be accessed with -// ['myFilesDisplaysAndOpensEntries']. -testcase.myFilesDisplaysAndOpensEntries = async () => { +export async function myFilesDisplaysAndOpensEntries() { // Open Files app on local Downloads. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Select My files in directory tree. @@ -122,20 +103,13 @@ // Wait for file list to Downloads' content. await remoteCall.waitForFiles( - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. appId, [ENTRIES.beautiful.getExpectedRow()], - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); // Get the selected navigation tree item. const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall); await directoryTree.waitForSelectedItemByLabel('Downloads'); -}; +} /** * Tests My files updating its children recursively. @@ -143,9 +117,7 @@ * If it doesn't update its children recursively it can cause directory tree to * not show or hide sub-folders crbug.com/864453. */ -// @ts-ignore: error TS4111: Property 'myFilesUpdatesChildren' comes from an -// index signature, so it must be accessed with ['myFilesUpdatesChildren']. -testcase.myFilesUpdatesChildren = async () => { +export async function myFilesUpdatesChildren() { const hiddenFolder = new TestEntryInfo({ type: EntryType.DIRECTORY, targetPath: '.hidden-folder', @@ -162,8 +134,6 @@ // Open Files app on local Downloads. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Select Downloads folder. @@ -194,14 +164,7 @@ // Check the hidden folder to be displayed in RHS. await remoteCall.waitForFiles( - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. appId, TestEntryInfo.getExpectedRows([hiddenFolder, ENTRIES.beautiful]), - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); // Wait for Downloads folder to have the expand icon because of hidden folder. @@ -214,15 +177,13 @@ // Check the hidden folder to be displayed in LHS. // Children of Downloads and named ".hidden-folder". await directoryTree.waitForChildItemByLabel('Downloads', '.hidden-folder'); -}; +} /** * Check naming a folder after navigating inside MyFiles using file list (RHS). * crbug.com/889636. */ -// @ts-ignore: error TS4111: Property 'myFilesFolderRename' comes from an index -// signature, so it must be accessed with ['myFilesFolderRename']. -testcase.myFilesFolderRename = async () => { +export async function myFilesFolderRename() { const textInput = '#file-list .table-row[renaming] input.rename'; // Open Files app on local Downloads. @@ -271,24 +232,15 @@ const expectedRows2 = [['new name', '--', 'Folder', '']]; await remoteCall.waitForFiles( appId, expectedRows2, - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); -}; +} /** * Tests that MyFiles only auto expands once. */ -// @ts-ignore: error TS4111: Property 'myFilesAutoExpandOnce' comes from an -// index signature, so it must be accessed with ['myFilesAutoExpandOnce']. -testcase.myFilesAutoExpandOnce = async () => { +export async function myFilesAutoExpandOnce() { // Open Files app on local Downloads. const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. RootPath.DOWNLOADS, [ENTRIES.photos], [ENTRIES.beautiful]); const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall); @@ -304,28 +256,18 @@ // Wait for My Drive to selected. await remoteCall.waitForFiles( - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. appId, [ENTRIES.beautiful.getExpectedRow()], - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); // Check that MyFiles is still collapsed. await directoryTree.waitForItemToCollapseByLabel('My files'); -}; +} /** * Tests that My files refreshes its contents when PlayFiles is mounted. * crbug.com/946972. */ -// @ts-ignore: error TS4111: Property 'myFilesUpdatesWhenAndroidVolumeMounts' -// comes from an index signature, so it must be accessed with -// ['myFilesUpdatesWhenAndroidVolumeMounts']. -testcase.myFilesUpdatesWhenAndroidVolumeMounts = async () => { +export async function myFilesUpdatesWhenAndroidVolumeMounts() { // Mount Downloads. await sendTestMessage({name: 'mountDownloads'}); @@ -334,8 +276,6 @@ // Open Files app on local Downloads. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall); @@ -346,11 +286,6 @@ await directoryTree.selectItemByLabel('My files'); await remoteCall.waitForFiles( appId, [downloadsRow, crostiniRow], - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); // Mount Play files volume. @@ -363,11 +298,6 @@ await directoryTree.waitForItemByLabel('Play files'); await remoteCall.waitForFiles( appId, [downloadsRow, playFilesRow, crostiniRow], - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); // Un-mount Play files volume. @@ -379,27 +309,18 @@ // Check: Play files should disappear from file list. await remoteCall.waitForFiles( appId, [downloadsRow, crostiniRow], - // @ts-ignore: error TS2345: Argument of type '{ ignoreFileSize: true; - // ignoreLastModifiedTime: true; }' is not assignable to parameter of type - // '{ orderCheck: boolean | null | undefined; ignoreFileSize: boolean | - // null | undefined; ignoreLastModifiedTime: boolean | null | undefined; - // }'. {ignoreFileSize: true, ignoreLastModifiedTime: true}); // Check: Play files should disappear from directory tree. await directoryTree.waitForItemLostByLabel('Play files'); -}; +} /** * Tests that toolbar delete is not shown for Downloads, or Linux files. */ -// @ts-ignore: error TS4111: Property 'myFilesToolbarDelete' comes from an index -// signature, so it must be accessed with ['myFilesToolbarDelete']. -testcase.myFilesToolbarDelete = async () => { +export async function myFilesToolbarDelete() { // Open Files app on local Downloads. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Select My files in directory tree. @@ -429,4 +350,4 @@ // Test that the delete button isn't visible. await remoteCall.waitForElement(appId, hiddenDeleteButton); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/office.js b/ui/file_manager/integration_tests/file_manager/office.ts similarity index 65% rename from ui/file_manager/integration_tests/file_manager/office.js rename to ui/file_manager/integration_tests/file_manager/office.ts index 659c51a9a..8ff756e 100644 --- a/ui/file_manager/integration_tests/file_manager/office.js +++ b/ui/file_manager/integration_tests/file_manager/office.ts
@@ -3,17 +3,14 @@ // found in the LICENSE file. import {ENTRIES, getCaller, pending, repeatUntil, RootPath, sendTestMessage} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {remoteCall, setupAndWaitUntilReady} from './background.js'; import {FILE_MANAGER_SWA_APP_ID, FILE_SWA_BASE_URL} from './test_data.js'; /** * Returns 'Open in Google Docs' task descriptor. - * - * @return {!FileTaskDescriptor} */ -function openDocWithDriveDescriptor() { +function openDocWithDriveDescriptor(): FileTaskDescriptor { const filesAppId = FILE_MANAGER_SWA_APP_ID; const filesTaskType = 'web'; const actionId = `${FILE_SWA_BASE_URL}?open-web-drive-office-word`; @@ -23,10 +20,8 @@ /** * Returns 'Open with Excel' task descriptor. - * - * @return {!FileTaskDescriptor} */ -function openExcelWithDriveDescriptor() { +function openExcelWithDriveDescriptor(): FileTaskDescriptor { const filesAppId = FILE_MANAGER_SWA_APP_ID; const filesTaskType = 'web'; const actionId = `${FILE_SWA_BASE_URL}?open-web-drive-office-excel`; @@ -36,10 +31,8 @@ /** * Returns 'Open in PowerPoint' task descriptor. - * - * @return {!FileTaskDescriptor} */ -function openPowerPointWithDriveDescriptor() { +function openPowerPointWithDriveDescriptor(): FileTaskDescriptor { const filesAppId = FILE_MANAGER_SWA_APP_ID; const filesTaskType = 'web'; const actionId = `${FILE_SWA_BASE_URL}?open-web-drive-office-powerpoint`; @@ -52,11 +45,10 @@ * Waits for the expected number of tasks executions, and returns the descriptor * of the last executed task. * - * @param {string} appId Window ID. - * @param {number} expectedCount - * @return {!Promise<!FileTaskDescriptor>} + * @param appId Window ID. */ -async function getExecutedTask(appId, expectedCount = 1) { +async function getExecutedTask( + appId: string, expectedCount: number = 1): Promise<FileTaskDescriptor> { const caller = getCaller(); // Wait until a task has been executed. @@ -79,20 +71,14 @@ return executeTaskArgs[0]; } -// @ts-ignore: error TS4111: Property 'openOfficeWordFile' comes from an index -// signature, so it must be accessed with ['openOfficeWordFile']. -testcase.openOfficeWordFile = async () => { +export async function openOfficeWordFile() { await sendTestMessage({ name: 'expectFileTask', - // @ts-ignore: error TS4111: Property 'smallDocxHosted' comes from an index - // signature, so it must be accessed with ['smallDocxHosted']. fileNames: [ENTRIES.smallDocxHosted.targetPath], openType: 'launch', }); const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'smallDocxHosted' comes from an - // index signature, so it must be accessed with ['smallDocxHosted']. RootPath.DRIVE, [], [ENTRIES.smallDocxHosted]); // Disable office setup flow so the dialog doesn't open when the file is @@ -101,8 +87,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallDocxHosted' comes from an - // index signature, so it must be accessed with ['smallDocxHosted']. 'openFile', appId, [ENTRIES.smallDocxHosted.nameText])); // Check that the Word file's alternate URL has been opened in a browser @@ -110,17 +94,11 @@ // opened from drive have this query parameter added // (https://crrev.com/c/3867338). await remoteCall.waitForLastOpenedBrowserTabUrl( - // @ts-ignore: error TS4111: Property 'smallDocxHosted' comes from an - // index signature, so it must be accessed with ['smallDocxHosted']. ENTRIES.smallDocxHosted.alternateUrl.concat('&cros_files=true')); -}; +} -// @ts-ignore: error TS4111: Property 'openOfficeWordFromMyFiles' comes from an -// index signature, so it must be accessed with ['openOfficeWordFromMyFiles']. -testcase.openOfficeWordFromMyFiles = async () => { +export async function openOfficeWordFromMyFiles() { const appId = - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.smallDocx]); // Fake chrome.fileManagerPrivate.executeTask to return @@ -132,8 +110,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. 'openFile', appId, [ENTRIES.smallDocx.nameText])); // The available Office task should be "Upload to Drive". @@ -145,18 +121,12 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} // Tests that "Upload to Drive" cannot be enabled if the "Upload Office To // Cloud" flag is disabled (test setup similar to `openOfficeWordFromMyFiles`). -// @ts-ignore: error TS4111: Property -// 'uploadToDriveRequiresUploadOfficeToCloudEnabled' comes from an index -// signature, so it must be accessed with -// ['uploadToDriveRequiresUploadOfficeToCloudEnabled']. -testcase.uploadToDriveRequiresUploadOfficeToCloudEnabled = async () => { +export async function uploadToDriveRequiresUploadOfficeToCloudEnabled() { const appId = - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.smallDocx]); // Fake chrome.fileManagerPrivate.executeTask to return // chrome.fileManagerPrivate.TaskResult.EMPTY. @@ -167,8 +137,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. 'openFile', appId, [ENTRIES.smallDocx.nameText])); // Since the Upload Office To Cloud flag isn't enabled, the Upload to Drive @@ -184,14 +152,10 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} -// @ts-ignore: error TS4111: Property 'openOfficeWordFromDrive' comes from an -// index signature, so it must be accessed with ['openOfficeWordFromDrive']. -testcase.openOfficeWordFromDrive = async () => { +export async function openOfficeWordFromDrive() { const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'smallDocxHosted' comes from an - // index signature, so it must be accessed with ['smallDocxHosted']. RootPath.DRIVE, [], [ENTRIES.smallDocxHosted]); // Fake chrome.fileManagerPrivate.executeTask to return @@ -203,8 +167,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallDocxHosted' comes from an - // index signature, so it must be accessed with ['smallDocxHosted']. 'openFile', appId, [ENTRIES.smallDocxHosted.nameText])); // The Drive/Docs task should be available and executed. @@ -215,14 +177,10 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} -// @ts-ignore: error TS4111: Property 'openOfficeExcelFromDrive' comes from an -// index signature, so it must be accessed with ['openOfficeExcelFromDrive']. -testcase.openOfficeExcelFromDrive = async () => { +export async function openOfficeExcelFromDrive() { const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'smallXlsxPinned' comes from an - // index signature, so it must be accessed with ['smallXlsxPinned']. RootPath.DRIVE, [], [ENTRIES.smallXlsxPinned]); // Fake chrome.fileManagerPrivate.executeTask to return @@ -234,8 +192,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallXlsxPinned' comes from an - // index signature, so it must be accessed with ['smallXlsxPinned']. 'openFile', appId, [ENTRIES.smallXlsxPinned.nameText])); // The Web Drive Office Excel task should be available and executed. @@ -246,15 +202,10 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} -// @ts-ignore: error TS4111: Property 'openOfficePowerPointFromDrive' comes from -// an index signature, so it must be accessed with -// ['openOfficePowerPointFromDrive']. -testcase.openOfficePowerPointFromDrive = async () => { +export async function openOfficePowerPointFromDrive() { const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'smallPptxPinned' comes from an - // index signature, so it must be accessed with ['smallPptxPinned']. RootPath.DRIVE, [], [ENTRIES.smallPptxPinned]); // Fake chrome.fileManagerPrivate.executeTask to return @@ -266,8 +217,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallPptxPinned' comes from an - // index signature, so it must be accessed with ['smallPptxPinned']. 'openFile', appId, [ENTRIES.smallPptxPinned.nameText])); // The Web Drive Office PowerPoint task should be available and executed. @@ -278,19 +227,14 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} -// @ts-ignore: error TS4111: Property 'openMultipleOfficeWordFromDrive' comes -// from an index signature, so it must be accessed with -// ['openMultipleOfficeWordFromDrive']. -testcase.openMultipleOfficeWordFromDrive = async () => { +export async function openMultipleOfficeWordFromDrive() { const appId = await setupAndWaitUntilReady( RootPath.DRIVE, [], - // @ts-ignore: error TS4111: Property 'smallDocxHosted' comes from an - // index signature, so it must be accessed with ['smallDocxHosted']. [ENTRIES.smallDocx, ENTRIES.smallDocxPinned, ENTRIES.smallDocxHosted]); - const enterKey = ['#file-list', 'Enter', false, false, false]; + const enterKey = ['#file-list', 'Enter', false, false, false] as const; // Fake chrome.fileManagerPrivate.executeTask to return // chrome.fileManagerPrivate.TaskResult.OPENED. @@ -300,28 +244,23 @@ await remoteCall.callRemoteTestUtil('foregroundFake', appId, [fakeData]); // Select all the files. - const ctrlA = ['#file-list', 'a', true, false, false]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. + const ctrlA = ['#file-list', 'a', true, false, false] as const; await remoteCall.fakeKeyDown(appId, ...ctrlA); // Check: the file-list should show 3 selected files. const caller = getCaller(); - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const element = await remoteCall.waitForElement( appId, '.check-select #files-selected-label'); - if (element.text !== '3 files selected') { - return pending( - caller, `Waiting for files to be selected, got: ${element.text}`); + if (element.text === '3 files selected') { + return; } + return pending( + caller, `Waiting for files to be selected, got: ${element.text}`); }); let taskDescriptor; let expectedExecuteTaskCount = 0; - // @ts-ignore: error TS6133: 'histogramCount' is declared but its value is - // never read. - let histogramCount; // Wait for the tasks calculation to complete, updating the "Open" button. await remoteCall.waitForElement(appId, '#tasks[get-tasks-completed]'); @@ -334,8 +273,6 @@ // "docs.google.com" alternate URL. // Press Enter to execute the task. - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. remoteCall.fakeKeyDown(appId, ...enterKey); // Check that it's the Docs task. @@ -346,20 +283,14 @@ // Unselect the file that doesn't have an alternate URL. await remoteCall.waitAndClickElement( - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. appId, `#file-list [file-name="${ENTRIES.smallDocx.nameText}"]`, {ctrl: true}); // Wait for the file to be unselected. await remoteCall.waitForElement( - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. appId, `[file-name="${ENTRIES.smallDocx.nameText}"]:not([selected])`); // Press Enter. - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. remoteCall.fakeKeyDown(appId, ...enterKey); // The Drive/Docs task should be available and executed. @@ -371,15 +302,10 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} -// @ts-ignore: error TS4111: Property 'openOfficeWordFromDriveNotSynced' comes -// from an index signature, so it must be accessed with -// ['openOfficeWordFromDriveNotSynced']. -testcase.openOfficeWordFromDriveNotSynced = async () => { +export async function openOfficeWordFromDriveNotSynced() { const appId = - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.smallDocx]); // Fake chrome.fileManagerPrivate.executeTask to return @@ -391,8 +317,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. 'openFile', appId, [ENTRIES.smallDocx.nameText])); // The Drive/Docs task should be available and executed. @@ -404,15 +328,10 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} -// @ts-ignore: error TS4111: Property 'openOfficeWordFromMyFilesOffline' comes -// from an index signature, so it must be accessed with -// ['openOfficeWordFromMyFilesOffline']. -testcase.openOfficeWordFromMyFilesOffline = async () => { +export async function openOfficeWordFromMyFilesOffline() { const appId = - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.smallDocx]); // Fake chrome.fileManagerPrivate.executeTask to return @@ -424,8 +343,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallDocx' comes from an index - // signature, so it must be accessed with ['smallDocx']. 'openFile', appId, [ENTRIES.smallDocx.nameText])); // The Drive/Docs task should be executed, but it will fall back to @@ -438,15 +355,10 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} -// @ts-ignore: error TS4111: Property 'openOfficeWordFromDriveOffline' comes -// from an index signature, so it must be accessed with -// ['openOfficeWordFromDriveOffline']. -testcase.openOfficeWordFromDriveOffline = async () => { +export async function openOfficeWordFromDriveOffline() { const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'smallDocxPinned' comes from an - // index signature, so it must be accessed with ['smallDocxPinned']. RootPath.DRIVE, [], [ENTRIES.smallDocxPinned]); // Fake chrome.fileManagerPrivate.executeTask to return @@ -458,8 +370,6 @@ // Open file. chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - // @ts-ignore: error TS4111: Property 'smallDocxPinned' comes from an - // index signature, so it must be accessed with ['smallDocxPinned']. 'openFile', appId, [ENTRIES.smallDocxPinned.nameText])); // The Drive/Docs task should be executed, but it will fall back to @@ -472,12 +382,10 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} /** Tests that the educational nudge is displayed when the preference is set. */ -// @ts-ignore: error TS4111: Property 'officeShowNudgeGoogleDrive' comes from an -// index signature, so it must be accessed with ['officeShowNudgeGoogleDrive']. -testcase.officeShowNudgeGoogleDrive = async () => { +export async function officeShowNudgeGoogleDrive() { // Set the pref emulating that the user has moved a file. await sendTestMessage({ name: 'setPrefOfficeFileMovedToGoogleDrive', @@ -486,11 +394,9 @@ // Open the Files app. const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'smallDocxPinned' comes from an - // index signature, so it must be accessed with ['smallDocxPinned']. RootPath.DRIVE, [], [ENTRIES.smallDocxPinned]); // Check that the nudge and its text is visible. await remoteCall.waitNudge( appId, 'Recently opened Microsoft files have moved to Google Drive'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/providers.js b/ui/file_manager/integration_tests/file_manager/providers.ts similarity index 79% rename from ui/file_manager/integration_tests/file_manager/providers.js rename to ui/file_manager/integration_tests/file_manager/providers.ts index adf2fdb..0194aff 100644 --- a/ui/file_manager/integration_tests/file_manager/providers.js +++ b/ui/file_manager/integration_tests/file_manager/providers.ts
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {getHistogramCount, RootPath, sendTestMessage} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {IGNORE_APP_ERRORS, remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -11,10 +10,10 @@ /** * Returns provider name of the given testing provider manifest viz., the * the value of the name field in the |manifest| file. - * @param {string} manifest Testing provider manifest file name. - * @return {string} Testing provider name. + * @param manifest Testing provider manifest file name. + * @return Testing provider name. */ -function getProviderNameForTest(manifest) { +function getProviderNameForTest(manifest: string): string { if (manifest === 'manifest.json') { return 'Files Testing Provider test extension'; } @@ -33,10 +32,10 @@ /** * Initializes the provider extension. - * @param {string} manifest The manifest name of testing provider extension - * to launch for the test case. + * @param manifest The manifest name of testing provider extension to launch for + * the test case. */ -async function setUpProvider(manifest) { +async function setUpProvider(manifest: string) { await sendTestMessage({name: 'launchProviderExtension', manifest: manifest}); const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); return appId; @@ -45,8 +44,7 @@ /** * Clicks on the "Services" menu button. */ -// @ts-ignore: error TS7006: Parameter 'appId' implicitly has an 'any' type. -async function showProvidersMenu(appId) { +async function showProvidersMenu(appId: string) { const providersMenuItem = '#gear-menu-providers:not([hidden])'; // Open the gear menu by clicking the gear button. @@ -68,9 +66,7 @@ /** * Confirms that a provided volume is mounted. */ -// @ts-ignore: error TS7006: Parameter 'ejectExpected' implicitly has an 'any' -// type. -async function confirmVolume(appId, ejectExpected) { +async function confirmVolume(appId: string, ejectExpected: boolean) { const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall); await directoryTree.selectItemByType('provided'); @@ -86,12 +82,11 @@ * Tests that a provided extension with |manifest| is mountable via the menu * button. * - * @param {boolean} multipleMounts Whether multiple mounts are supported by - * the providing extension. - * @param {string} manifest Name of the manifest file for the providing + * @param multipleMounts Whether multiple mounts are supported by the providing * extension. + * @param manifest Name of the manifest file for the providing extension. */ -async function requestMountInternal(multipleMounts, manifest) { +async function requestMountInternal(multipleMounts: boolean, manifest: string) { const providerName = getProviderNameForTest(manifest); const appId = await setUpProvider(manifest); await showProvidersMenu(appId); @@ -139,10 +134,9 @@ * Tests that a provided extension with |manifest| is not available in the * providers menu, but it's mounted automatically. * - * @param {string} manifest Name of the manifest file for the providing - * extension. + * @param manifest Name of the manifest file for the providing extension. */ -async function requestMountNotInMenuInternal(manifest) { +async function requestMountNotInMenuInternal(manifest: string) { const appId = await setUpProvider(manifest); await confirmVolume(appId, true /* ejectExpected */); @@ -190,48 +184,38 @@ /** * Tests mounting a single mount point in the button menu. */ -// @ts-ignore: error TS4111: Property 'requestMount' comes from an index -// signature, so it must be accessed with ['requestMount']. -testcase.requestMount = () => { +export async function requestMount() { const multipleMounts = false; return requestMountInternal(multipleMounts, 'manifest.json'); -}; +} /** * Tests mounting multiple mount points in the button menu. */ -// @ts-ignore: error TS4111: Property 'requestMountMultipleMounts' comes from an -// index signature, so it must be accessed with ['requestMountMultipleMounts']. -testcase.requestMountMultipleMounts = () => { +export async function requestMountMultipleMounts() { const multipleMounts = true; return requestMountInternal(multipleMounts, 'manifest_multiple_mounts.json'); -}; +} /** * Tests mounting a device not present in the button menu. */ -// @ts-ignore: error TS4111: Property 'requestMountSourceDevice' comes from an -// index signature, so it must be accessed with ['requestMountSourceDevice']. -testcase.requestMountSourceDevice = () => { +export async function requestMountSourceDevice() { return requestMountNotInMenuInternal('manifest_source_device.json'); -}; +} /** * Tests mounting a file not present in the button menu. */ -// @ts-ignore: error TS4111: Property 'requestMountSourceFile' comes from an -// index signature, so it must be accessed with ['requestMountSourceFile']. -testcase.requestMountSourceFile = () => { +export async function requestMountSourceFile() { return requestMountNotInMenuInternal('manifest_source_file.json'); -}; +} /** * Tests that pressing the eject button on a FSP adds a message to screen * reader. */ -// @ts-ignore: error TS4111: Property 'providerEject' comes from an index -// signature, so it must be accessed with ['providerEject']. -testcase.providerEject = async () => { +export async function providerEject() { const manifest = 'manifest_source_file.json'; const appId = await setUpProvider(manifest); @@ -255,16 +239,13 @@ // JS errors due to volume related actions performed while volume is // ejected. return IGNORE_APP_ERRORS; -}; +} /** * Tests mounting a file system provider emits only a single UMA when running * from either the SWA or Chrome app. */ -// @ts-ignore: error TS4111: Property -// 'deduplicatedUmaMetricForFileSystemProviders' comes from an index signature, -// so it must be accessed with ['deduplicatedUmaMetricForFileSystemProviders']. -testcase.deduplicatedUmaMetricForFileSystemProviders = async () => { +export async function deduplicatedUmaMetricForFileSystemProviders() { const umaMetricName = 'FileBrowser.FileSystemProviderMounted'; const testProviderMetricEnumValue = 0; // UNKNOWN = 0. @@ -290,4 +271,4 @@ await getHistogramCount(umaMetricName, testProviderMetricEnumValue); chrome.test.assertEq( 1, mountedVolumeCount, 'Unexpected value in UMA metric for mounted FSPs'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.ts similarity index 69% rename from ui/file_manager/integration_tests/file_manager/quick_view.js rename to ui/file_manager/integration_tests/file_manager/quick_view.ts index f203b17..00b378b9 100644 --- a/ui/file_manager/integration_tests/file_manager/quick_view.js +++ b/ui/file_manager/integration_tests/file_manager/quick_view.ts
@@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {DialogType} from '../prod/file_manager/shared_types.js'; +import {DialogType, type ElementObject} from '../prod/file_manager/shared_types.js'; import {ExecuteScriptError} from '../remote_call.js'; -import {addEntries, ENTRIES, EntryType, getCaller, getHistogramCount, pending, repeatUntil, RootPath, sanitizeDate, sendTestMessage, TestEntryInfo, wait} from '../test_util.js'; -import {testcase} from '../testcase.js'; +import {ENTRIES, EntryType, RootPath, TestEntryInfo, addEntries, getCaller, getHistogramCount, pending, repeatUntil, sanitizeDate, sendTestMessage, wait} from '../test_util.js'; import {mountCrostini, mountGuestOs, openNewWindow, remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -41,9 +40,9 @@ /** * Checks if dark mode has been turned on or not. * - * @return {!Promise<boolean>} enabled or not. + * @return enabled or not. */ -async function isDarkModeEnabled() { +async function isDarkModeEnabled(): Promise<boolean> { const isDarkModeEnabled = await sendTestMessage({name: 'isDarkModeEnabled'}); return isDarkModeEnabled === 'true'; } @@ -51,16 +50,14 @@ /** * Waits for Quick View dialog to be open. * - * @param {string} appId Files app windowId. + * @param appId Files app windowId. */ -async function waitQuickViewOpen(appId) { +async function waitQuickViewOpen(appId: string) { const caller = getCaller(); - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkQuickViewElementsDisplayBlock(elements) { + function checkQuickViewElementsDisplayBlock(elements: ElementObject[]) { const haveElements = Array.isArray(elements) && elements.length !== 0; - if (!haveElements || elements[0].styles.display !== 'block') { + if (!haveElements || elements[0]!.styles!['display'] !== 'block') { return pending(caller, 'Waiting for Quick View to open.'); } return; @@ -77,18 +74,18 @@ /** * Waits for Quick View dialog to be closed. * - * @param {string} appId Files app windowId. + * @param appId Files app windowId. */ -async function waitQuickViewClose(appId) { +async function waitQuickViewClose(appId: string) { const caller = getCaller(); - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkQuickViewElementsDisplayNone(elements) { + function checkQuickViewElementsDisplayNone(elements: ElementObject[]) { chrome.test.assertTrue(Array.isArray(elements)); - if (elements.length === 0 || elements[0].styles.display !== 'none') { + if (elements.length === 0 || elements[0]!.styles!['display'] !== 'none') { return pending(caller, 'Waiting for Quick View to close.'); } + + return; } // Check: the Quick View dialog should not be shown. @@ -104,10 +101,10 @@ * Opens the Quick View dialog on a given file |name|. The file must be * present in the Files app file list. * - * @param {string} appId Files app windowId. - * @param {string} name File name. + * @param appId Files app windowId. + * @param name File name. */ -async function openQuickView(appId, name) { +async function openQuickViewEx(appId: string, name: string) { // Select file |name| in the file list. await remoteCall.waitUntilSelected(appId, name); @@ -125,10 +122,10 @@ * Opens the Quick View dialog by right clicking on the file |name| and * using the "Get Info" command from the context menu. * - * @param {string} appId Files app windowId. - * @param {string} name File name. + * @param appId Files app windowId. + * @param name File name. */ -async function openQuickViewViaContextMenu(appId, name) { +async function openQuickViewViaContextMenu(appId: string, name: string) { // Right-click the file in the file-list. const query = `#file-list [file-name="${name}"]`; await remoteCall.waitAndRightClick(appId, query); @@ -150,10 +147,10 @@ * Opens the Quick View dialog with given file |names|. The files must be * present and check-selected in the Files app file list. * - * @param {string} appId Files app windowId. - * @param {Array<string>} names File names. + * @param appId Files app windowId. + * @param names File names. */ -async function openQuickViewMultipleSelection(appId, names) { +async function openQuickViewMultipleSelection(appId: string, names: string[]) { // Get the file-list rows that are check-selected (multi-selected). const selectedRows = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, ['#file-list li[selected]']); @@ -176,9 +173,9 @@ /** * Mount and select USB. * - * @param {string} appId Files app windowId. + * @param appId Files app windowId. */ -async function mountAndSelectUsb(appId) { +async function mountAndSelectUsb(appId: string) { // Mount a USB volume. await sendTestMessage({name: 'mountFakeUsb'}); @@ -195,9 +192,9 @@ * Assuming that Quick View is currently open per openQuickView above, closes * the Quick View dialog. * - * @param {string} appId Files app windowId. + * @param appId Files app windowId. */ -async function closeQuickView(appId) { +async function closeQuickViewEx(appId: string) { // Click on Quick View to close it. const panelElements = ['#quick-view', '#contentPanel']; chrome.test.assertTrue( @@ -214,13 +211,14 @@ * the text shown in the QuickView Metadata Box field |name|. If the optional * |hidden| is 'hidden', the field |name| should not be visible. * - * @param {string} appId Files app windowId. - * @param {string} name QuickView Metadata Box field name. - * @param {string} hidden Whether the field name should be visible. + * @param appId Files app windowId. + * @param name QuickView Metadata Box field name. + * @param hidden Whether the field name should be visible. * - * @return {!Promise<string>} text Text value in the field name. + * @return text Text value in the field name. */ -async function getQuickViewMetadataBoxField(appId, name, hidden = '') { +async function getQuickViewMetadataBoxField( + appId: string, name: string, hidden: string = ''): Promise<string> { let filesMetadataBox = 'files-metadata-box'; /** @@ -280,14 +278,14 @@ * Executes a script in the context of a <preview-tag> element and returns its * output. Returns undefined when ExecuteScriptError is caught. * - * @param {string} appId App window Id. - * @param {!Array<string>} query Query to the <preview-tag> element (this is + * @param appId App window Id. + * @param query Query to the <preview-tag> element (this is * ignored for SWA). - * @param {string} statement Javascript statement to be executed within the + * @param statement Javascript statement to be executed within the * <preview-tag>. - * @return {!Promise<*>} */ -async function executeJsInPreviewTagAndCatchErrors(appId, query, statement) { +async function executeJsInPreviewTagAndCatchErrors( + appId: string, query: string[], statement: string): Promise<unknown> { try { return await remoteCall.executeJsInPreviewTag(appId, query, statement); } catch (e) { @@ -302,49 +300,40 @@ /** * Tests opening Quick View on a local downloads file. */ -// @ts-ignore: error TS4111: Property 'openQuickView' comes from an index -// signature, so it must be accessed with ['openQuickView']. -testcase.openQuickView = async () => { +export async function openQuickView() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Check the open button is shown. await remoteCall.waitForElement( appId, ['#quick-view', '#open-button:not([hidden])']); -}; +} /** * Tests opening Quick View on a local downloads file in an open file dialog. */ -// @ts-ignore: error TS4111: Property 'openQuickViewDialog' comes from an index -// signature, so it must be accessed with ['openQuickViewDialog']. -testcase.openQuickViewDialog = async () => { +export async function openQuickViewDialog() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, [ENTRIES.hello], [], - // @ts-ignore: error TS2345: Argument of type '{ type: string; }' is not - // assignable to parameter of type 'FilesAppState'. {type: DialogType.SELECT_OPEN_FILE}); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Check the open button is not shown as we're in an open file dialog. await remoteCall.waitForElement( appId, ['#quick-view', '#open-button[hidden]']); -}; +} /** * Tests that Quick View opens via the context menu with a single selection. */ -// @ts-ignore: error TS4111: Property -// 'openQuickViewViaContextMenuSingleSelection' comes from an index signature, -// so it must be accessed with ['openQuickViewViaContextMenuSingleSelection']. -testcase.openQuickViewViaContextMenuSingleSelection = async () => { +export async function openQuickViewViaContextMenuSingleSelection() { // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -354,59 +343,49 @@ // Check: clicking the context menu "Get Info" should open Quick View. await openQuickViewViaContextMenu(appId, ENTRIES.hello.nameText); -}; +} /** * Tests that Quick View opens via the context menu when multiple files * are selected (file-list check-select mode). */ -// @ts-ignore: error TS4111: Property -// 'openQuickViewViaContextMenuCheckSelections' comes from an index signature, -// so it must be accessed with ['openQuickViewViaContextMenuCheckSelections']. -testcase.openQuickViewViaContextMenuCheckSelections = async () => { +export async function openQuickViewViaContextMenuCheckSelections() { // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); // Ctrl+A to select all files in the file-list. - const ctrlA = ['#file-list', 'a', true, false, false]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. - await remoteCall.fakeKeyDown(appId, ...ctrlA); + await remoteCall.fakeKeyDown(appId, '#file-list', 'a', true, false, false); // Check: clicking the context menu "Get Info" should open Quick View. await openQuickViewViaContextMenu(appId, ENTRIES.hello.nameText); -}; +} /** * Tests opening then closing Quick View on a local downloads file. */ -// @ts-ignore: error TS4111: Property 'closeQuickView' comes from an index -// signature, so it must be accessed with ['closeQuickView']. -testcase.closeQuickView = async () => { +export async function closeQuickView() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Close Quick View. - await closeQuickView(appId); -}; + await closeQuickViewEx(appId); +} /** * Tests opening Quick View on a Drive file. */ -// @ts-ignore: error TS4111: Property 'openQuickViewDrive' comes from an index -// signature, so it must be accessed with ['openQuickViewDrive']. -testcase.openQuickViewDrive = async () => { +export async function openQuickViewDrive() { // Open Files app on Drive containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Check: the correct mimeType should be displayed (see crbug.com/1067499 // for details on mimeType differences between Drive and local filesystem). @@ -416,14 +395,12 @@ // Check: the correct file location should be displayed in Drive. const location = await getQuickViewMetadataBoxField(appId, 'File location'); chrome.test.assertEq('My Drive/hello.txt', location); -}; +} /** * Tests opening Quick View on a Smbfs file. */ -// @ts-ignore: error TS4111: Property 'openQuickViewSmbfs' comes from an index -// signature, so it must be accessed with ['openQuickViewSmbfs']. -testcase.openQuickViewSmbfs = async () => { +export async function openQuickViewSmbfs() { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); @@ -442,31 +419,26 @@ await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); -}; + await openQuickViewEx(appId, ENTRIES.hello.nameText); +} /** * Tests opening Quick View on a USB file. */ -// @ts-ignore: error TS4111: Property 'openQuickViewUsb' comes from an index -// signature, so it must be accessed with ['openQuickViewUsb']. -testcase.openQuickViewUsb = async () => { +export async function openQuickViewUsb() { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); // Open a USB file in Quick View. await mountAndSelectUsb(appId); - await openQuickView(appId, ENTRIES.hello.nameText); -}; + await openQuickViewEx(appId, ENTRIES.hello.nameText); +} /** * Tests opening Quick View on a removable partition. */ -// @ts-ignore: error TS4111: Property 'openQuickViewRemovablePartitions' comes -// from an index signature, so it must be accessed with -// ['openQuickViewRemovablePartitions']. -testcase.openQuickViewRemovablePartitions = async () => { +export async function openQuickViewRemovablePartitions() { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); @@ -488,23 +460,17 @@ // Check: the USB files should appear in the file list. const files = TestEntryInfo.getExpectedRows(BASIC_FAKE_ENTRY_SET); - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); -}; + await openQuickViewEx(appId, ENTRIES.hello.nameText); +} /** * Tests opening Quick View on an item that was Trashed shows original location * instead of the current file location. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTrash' comes from an index -// signature, so it must be accessed with ['openQuickViewTrash']. -testcase.openQuickViewTrash = async () => { +export async function openQuickViewTrash() { const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -524,22 +490,19 @@ appId, '#file-list [file-name="hello.txt"]'); // Open the file in Quick View. - await openQuickView(appId, 'hello.txt'); + await openQuickViewEx(appId, 'hello.txt'); // Check: the original location should be shown instead of the actual file // location. const location = await getQuickViewMetadataBoxField(appId, 'Original location'); chrome.test.assertEq('My files/Downloads/hello.txt', location); -}; +} /** * Tests seeing dashes for an empty last_modified for DocumentsProvider. */ -// @ts-ignore: error TS4111: Property 'openQuickViewLastModifiedMetaData' comes -// from an index signature, so it must be accessed with -// ['openQuickViewLastModifiedMetaData']. -testcase.openQuickViewLastModifiedMetaData = async () => { +export async function openQuickViewLastModifiedMetaData() { const documentsProviderVolumeType = 'documents_provider'; // Add files to the DocumentsProvider volume. @@ -557,38 +520,30 @@ // Check: the DocumentsProvider files should appear in the file list. const files = TestEntryInfo.getExpectedRows(MODIFIED_ENTRY_SET); - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Open a DocumentsProvider file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); const lastValidModifiedText = await getQuickViewMetadataBoxField(appId, 'Date modified'); chrome.test.assertEq(ENTRIES.hello.lastModifiedTime, lastValidModifiedText); - await closeQuickView(appId); + await closeQuickViewEx(appId); // Open a DocumentsProvider file in Quick View. - // @ts-ignore: error TS4111: Property 'invalidLastModifiedDate' comes from an - // index signature, so it must be accessed with ['invalidLastModifiedDate']. - await openQuickView(appId, ENTRIES.invalidLastModifiedDate.nameText); + await openQuickViewEx(appId, ENTRIES.invalidLastModifiedDate.nameText); // Modified time should be displayed as "--" when it's absent. const lastInvalidModifiedText = await getQuickViewMetadataBoxField(appId, 'Date modified'); chrome.test.assertEq('--', lastInvalidModifiedText); -}; +} /** * Tests opening Quick View on an MTP file. */ -// @ts-ignore: error TS4111: Property 'openQuickViewMtp' comes from an index -// signature, so it must be accessed with ['openQuickViewMtp']. -testcase.openQuickViewMtp = async () => { +export async function openQuickViewMtp() { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); @@ -602,58 +557,46 @@ // Check: the MTP files should appear in the file list. const files = TestEntryInfo.getExpectedRows(BASIC_FAKE_ENTRY_SET); - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Open an MTP file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); -}; + await openQuickViewEx(appId, ENTRIES.hello.nameText); +} /** * Tests opening Quick View on a Crostini file. */ -// @ts-ignore: error TS4111: Property 'openQuickViewCrostini' comes from an -// index signature, so it must be accessed with ['openQuickViewCrostini']. -testcase.openQuickViewCrostini = async () => { +export async function openQuickViewCrostini() { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); // Open a Crostini file in Quick View. await mountCrostini(appId); - await openQuickView(appId, ENTRIES.hello.nameText); -}; + await openQuickViewEx(appId, ENTRIES.hello.nameText); +} /** * Tests opening Quick View on a GuestOS file. */ -// @ts-ignore: error TS4111: Property 'openQuickViewGuestOs' comes from an index -// signature, so it must be accessed with ['openQuickViewGuestOs']. -testcase.openQuickViewGuestOs = async () => { +export async function openQuickViewGuestOs() { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); // Open a GuestOS file in Quick View. await mountGuestOs(appId, BASIC_LOCAL_ENTRY_SET); - await openQuickView(appId, ENTRIES.hello.nameText); -}; + await openQuickViewEx(appId, ENTRIES.hello.nameText); +} /** * Tests opening Quick View on an Android file. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAndroid' comes from an index -// signature, so it must be accessed with ['openQuickViewAndroid']. -testcase.openQuickViewAndroid = async () => { +export async function openQuickViewAndroid() { // Open Files app on Android files. const appId = await openNewWindow(RootPath.ANDROID_FILES); // Add files to the Android files volume. - // @ts-ignore: error TS4111: Property 'documentsText' comes from an index - // signature, so it must be accessed with ['documentsText']. const entrySet = BASIC_ANDROID_ENTRY_SET.concat([ENTRIES.documentsText]); await addEntries(['android_files'], entrySet); @@ -662,10 +605,6 @@ // Check: the basic Android file set should appear in the file list. let files = TestEntryInfo.getExpectedRows(BASIC_ANDROID_ENTRY_SET); - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Navigate to the Android files '/Documents' directory. @@ -673,35 +612,22 @@ await directoryTree.navigateToPath('/My files/Play files/Documents'); // Check: the 'android.txt' file should appear in the file list. - // @ts-ignore: error TS4111: Property 'documentsText' comes from an index - // signature, so it must be accessed with ['documentsText']. files = [ENTRIES.documentsText.getExpectedRow()]; - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Open the Android file in Quick View. - // @ts-ignore: error TS4111: Property 'documentsText' comes from an index - // signature, so it must be accessed with ['documentsText']. const documentsFileName = ENTRIES.documentsText.nameText; - await openQuickView(appId, documentsFileName); -}; + await openQuickViewEx(appId, documentsFileName); +} /** * Tests opening Quick View on an Android file on GuestOS. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAndroidGuestOs' comes from -// an index signature, so it must be accessed with -// ['openQuickViewAndroidGuestOs']. -testcase.openQuickViewAndroidGuestOs = async () => { +export async function openQuickViewAndroidGuestOs() { // Open Files app on Android files. const appId = await openNewWindow(RootPath.ANDROID_FILES); // Add files to the Android files volume. - // @ts-ignore: error TS4111: Property 'documentsText' comes from an index - // signature, so it must be accessed with ['documentsText']. const entrySet = BASIC_ANDROID_ENTRY_SET.concat([ENTRIES.documentsText]); await addEntries(['android_files'], entrySet); @@ -710,10 +636,6 @@ // Check: the basic Android file set should appear in the file list. let files = TestEntryInfo.getExpectedRows(BASIC_ANDROID_ENTRY_SET); - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Navigate to the Android files '/Documents' directory. @@ -721,29 +643,18 @@ await directoryTree.navigateToPath('/My files/Play files/Documents'); // Check: the 'android.txt' file should appear in the file list. - // @ts-ignore: error TS4111: Property 'documentsText' comes from an index - // signature, so it must be accessed with ['documentsText']. files = [ENTRIES.documentsText.getExpectedRow()]; - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: true; - // }' is not assignable to parameter of type '{ orderCheck: boolean | null | - // undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Open the Android file in Quick View. - // @ts-ignore: error TS4111: Property 'documentsText' comes from an index - // signature, so it must be accessed with ['documentsText']. const documentsFileName = ENTRIES.documentsText.nameText; - await openQuickView(appId, documentsFileName); -}; + await openQuickViewEx(appId, documentsFileName); +} /** * Tests opening Quick View on a DocumentsProvider root. */ -// @ts-ignore: error TS4111: Property 'openQuickViewDocumentsProvider' comes -// from an index signature, so it must be accessed with -// ['openQuickViewDocumentsProvider']. -testcase.openQuickViewDocumentsProvider = async () => { +export async function openQuickViewDocumentsProvider() { const DOCUMENTS_PROVIDER_VOLUME_TYPE = 'documents_provider'; // Add files to the DocumentsProvider volume. @@ -765,7 +676,7 @@ await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); // Open a DocumentsProvider file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); /** * The text preview resides in the #quick-view shadow DOM, as a child of @@ -775,14 +686,12 @@ // Wait for the Quick View preview to load and display its content. const caller = getCaller(); - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -793,15 +702,15 @@ }); // Wait until the preview displays the file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; // Check: the content of text file should be shown. if (!text || !text[0] || !text[0].includes('chocolate and chips')) { return pending(caller, `Waiting for ${previewTag} content.`); } + return; }); // Check: the correct size and date modified values should be displayed. @@ -810,15 +719,13 @@ const lastModifiedText = await getQuickViewMetadataBoxField(appId, 'Date modified'); chrome.test.assertEq(ENTRIES.hello.lastModifiedTime, lastModifiedText); -}; +} /** * Tests opening Quick View with a local text document identified as text from * file sniffing (the first word of the file is "From ", note trailing space). */ -// @ts-ignore: error TS4111: Property 'openQuickViewSniffedText' comes from an -// index signature, so it must be accessed with ['openQuickViewSniffedText']. -testcase.openQuickViewSniffedText = async () => { +export async function openQuickViewSniffedText() { const caller = getCaller(); /** @@ -829,24 +736,18 @@ // Open Files app on Downloads containing ENTRIES.plainText. const appId = - // @ts-ignore: error TS4111: Property 'plainText' comes from an index - // signature, so it must be accessed with ['plainText']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.plainText], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'plainText' comes from an index - // signature, so it must be accessed with ['plainText']. - await openQuickView(appId, ENTRIES.plainText.nameText); + await openQuickViewEx(appId, ENTRIES.plainText.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -859,16 +760,13 @@ // Check: the correct mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('text/plain', mimeType); -}; +} /** * Tests opening Quick View with a local text document whose MIME type cannot * be identified by MIME type sniffing. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTextFileWithUnknownMimeType' -// comes from an index signature, so it must be accessed with -// ['openQuickViewTextFileWithUnknownMimeType']. -testcase.openQuickViewTextFileWithUnknownMimeType = async () => { +export async function openQuickViewTextFileWithUnknownMimeType() { const caller = getCaller(); /** @@ -882,17 +780,15 @@ await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -904,15 +800,13 @@ // Check: the mimeType field should not be displayed. await getQuickViewMetadataBoxField(appId, 'Type', 'hidden'); -}; +} /** * Tests opening Quick View with a text file containing some UTF-8 encoded * characters: crbug.com/1064855 */ -// @ts-ignore: error TS4111: Property 'openQuickViewUtf8Text' comes from an -// index signature, so it must be accessed with ['openQuickViewUtf8Text']. -testcase.openQuickViewUtf8Text = async () => { +export async function openQuickViewUtf8Text() { const caller = getCaller(); /** @@ -926,17 +820,15 @@ await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.utf8Text], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.utf8Text.nameText); + await openQuickViewEx(appId, ENTRIES.utf8Text.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -947,30 +839,29 @@ }); // Wait until the preview displays the file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; // Check: the content of ENTRIES.utf8Text should be shown. if (!text || !text[0] || !text[0].includes('їсти मुझे |∊☀✌✂♁ 🙂\n')) { return pending(caller, 'Waiting for preview content.'); } + + return; }); // Check: the correct file size should be displayed. const size = await getQuickViewMetadataBoxField(appId, 'Size'); chrome.test.assertEq('191 bytes', size); -}; +} /** * Tests opening Quick View and scrolling its preview contents which contains a * tall text document. */ -// @ts-ignore: error TS4111: Property 'openQuickViewScrollText' comes from an -// index signature, so it must be accessed with ['openQuickViewScrollText']. -testcase.openQuickViewScrollText = async () => { +export async function openQuickViewScrollText() { const caller = getCaller(); /** @@ -979,40 +870,33 @@ */ const preview = ['#quick-view', `#dialog[open] ${previewTag}.text-content`]; - // @ts-ignore: error TS7006: Parameter 'y' implicitly has an 'any' type. - function scrollQuickViewTextBy(y) { + function scrollQuickViewTextBy(y: number) { const doScrollBy = `${contentWindowQuery}.scrollBy(0,${y})`; return remoteCall.executeJsInPreviewTag(appId, preview, doScrollBy); } - // @ts-ignore: error TS7006: Parameter 'scrollY' implicitly has an 'any' type. - async function checkQuickViewTextScrollY(scrollY) { + async function checkQuickViewTextScrollY(scrollY: {toString: () => string}) { if (!scrollY || Number(scrollY.toString()) <= 150) { await scrollQuickViewTextBy(100); return pending(caller, 'Waiting for Quick View to scroll.'); } + return; } // Open Files app on Downloads containing ENTRIES.tallText. const appId = - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.tallText], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. - await openQuickView(appId, ENTRIES.tallText.nameText); + await openQuickViewEx(appId, ENTRIES.tallText.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1026,13 +910,13 @@ const getScrollY = `${contentWindowQuery}.scrollY`; // The initial preview scrollY should be 0. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const scrollY = await executeJsInPreviewTagAndCatchErrors(appId, preview, getScrollY); if (String(scrollY) !== '0') { return pending(caller, 'Waiting for preview text to load.'); } + return; }); // Scroll the preview and verify that it scrolled. @@ -1041,14 +925,12 @@ await remoteCall.executeJsInPreviewTag(appId, preview, getScrollY); return checkQuickViewTextScrollY(scrollY); }); -}; +} /** * Tests opening Quick View containing a PDF document. */ -// @ts-ignore: error TS4111: Property 'openQuickViewPdf' comes from an index -// signature, so it must be accessed with ['openQuickViewPdf']. -testcase.openQuickViewPdf = async () => { +export async function openQuickViewPdf() { const caller = getCaller(); /** @@ -1059,24 +941,18 @@ // Open Files app on Downloads containing ENTRIES.tallPdf. const appId = - // @ts-ignore: error TS4111: Property 'tallPdf' comes from an index - // signature, so it must be accessed with ['tallPdf']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.tallPdf], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'tallPdf' comes from an index signature, - // so it must be accessed with ['tallPdf']. - await openQuickView(appId, ENTRIES.tallPdf.nameText); + await openQuickViewEx(appId, ENTRIES.tallPdf.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewPdfLoaded(elements) { + function checkPreviewPdfLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1087,19 +963,18 @@ }); // Get the preview embed type attribute. - // @ts-ignore: error TS7006: Parameter 'type' implicitly has an 'any' type. - function checkPdfEmbedType(type) { + function checkPdfEmbedType(type: ElementObject[]) { const haveElements = Array.isArray(type) && type.length === 1; - if (!haveElements || !type[0].toString().includes('pdf')) { + if (!haveElements || !type[0]!.toString().includes('pdf')) { return pending(caller, 'Waiting for plugin <embed> type.'); } - return type[0]; + return type[0]!; } const type = await repeatUntil(async () => { const getType = contentWindowQuery + '.document.querySelector("embed").type'; - const type = - await executeJsInPreviewTagAndCatchErrors(appId, preview, getType); + const type = await executeJsInPreviewTagAndCatchErrors( + appId, preview, getType) as ElementObject[]; return checkPdfEmbedType(type); }); @@ -1109,14 +984,12 @@ // Check: the correct mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('application/pdf', mimeType); -}; +} /** * Tests opening Quick View on a PDF document that opens a popup JS dialog. */ -// @ts-ignore: error TS4111: Property 'openQuickViewPdfPopup' comes from an -// index signature, so it must be accessed with ['openQuickViewPdfPopup']. -testcase.openQuickViewPdfPopup = async () => { +export async function openQuickViewPdfPopup() { const caller = getCaller(); /** @@ -1127,24 +1000,18 @@ // Open Files app on Downloads containing ENTRIES.popupPdf. const appId = - // @ts-ignore: error TS4111: Property 'popupPdf' comes from an index - // signature, so it must be accessed with ['popupPdf']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.popupPdf], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'popupPdf' comes from an index - // signature, so it must be accessed with ['popupPdf']. - await openQuickView(appId, ENTRIES.popupPdf.nameText); + await openQuickViewEx(appId, ENTRIES.popupPdf.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewPdfLoaded(elements) { + function checkPreviewPdfLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1155,8 +1022,7 @@ }); // Get the preview embed type attribute. - // @ts-ignore: error TS7006: Parameter 'type' implicitly has an 'any' type. - function checkPdfEmbedType(type) { + function checkPdfEmbedType(type: unknown) { const haveElements = Array.isArray(type) && type.length === 1; if (!haveElements || !type[0].toString().includes('pdf')) { return pending(caller, 'Waiting for plugin <embed> type.'); @@ -1177,16 +1043,13 @@ // Check: the correct mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('application/pdf', mimeType); -}; +} /** * Tests that Quick View does not display a PDF file preview when that is * disabled by system settings (preferences). */ -// @ts-ignore: error TS4111: Property 'openQuickViewPdfPreviewsDisabled' comes -// from an index signature, so it must be accessed with -// ['openQuickViewPdfPreviewsDisabled']. -testcase.openQuickViewPdfPreviewsDisabled = async () => { +export async function openQuickViewPdfPreviewsDisabled() { const caller = getCaller(); /** @@ -1200,25 +1063,19 @@ // Open Files app on Downloads containing ENTRIES.tallPdf. const appId = - // @ts-ignore: error TS4111: Property 'tallPdf' comes from an index - // signature, so it must be accessed with ['tallPdf']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.tallPdf], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'tallPdf' comes from an index signature, - // so it must be accessed with ['tallPdf']. - await openQuickView(appId, ENTRIES.tallPdf.nameText); + await openQuickViewEx(appId, ENTRIES.tallPdf.nameText); // Wait for the innerContentPanel to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkInnerContentPanel(elements) { + function checkInnerContentPanel(elements: ElementObject[]) { const haveElements = Array.isArray(elements) && elements.length === 1; - if (!haveElements || elements[0].styles.display !== 'flex') { + if (!haveElements || elements[0]!.styles!['display'] !== 'flex') { return pending(caller, 'Waiting for inner content panel to load.'); } // Check: the PDF preview should not be shown. - chrome.test.assertEq('No preview available', elements[0].text); + chrome.test.assertEq('No preview available', elements[0]!.text); return; } await repeatUntil(async () => { @@ -1229,14 +1086,12 @@ // Check: the correct file mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('application/pdf', mimeType); -}; +} /** * Tests opening Quick View with a '.mhtml' filename extension. */ -// @ts-ignore: error TS4111: Property 'openQuickViewMhtml' comes from an index -// signature, so it must be accessed with ['openQuickViewMhtml']. -testcase.openQuickViewMhtml = async () => { +export async function openQuickViewMhtml() { const caller = getCaller(); /** @@ -1247,24 +1102,18 @@ // Open Files app on Downloads containing ENTRIES.plainText. const appId = - // @ts-ignore: error TS4111: Property 'mHtml' comes from an index - // signature, so it must be accessed with ['mHtml']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.mHtml], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'mHtml' comes from an index signature, - // so it must be accessed with ['mHtml']. - await openQuickView(appId, ENTRIES.mHtml.nameText); + await openQuickViewEx(appId, ENTRIES.mHtml.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1281,15 +1130,13 @@ // Check: the correct file location should be displayed. const location = await getQuickViewMetadataBoxField(appId, 'File location'); chrome.test.assertEq('My files/Downloads/page.mhtml', location); -}; +} /** * Tests opening Quick View and scrolling its preview contents which contains a * tall html document. */ -// @ts-ignore: error TS4111: Property 'openQuickViewScrollHtml' comes from an -// index signature, so it must be accessed with ['openQuickViewScrollHtml']. -testcase.openQuickViewScrollHtml = async () => { +export async function openQuickViewScrollHtml() { const caller = getCaller(); /** @@ -1298,40 +1145,33 @@ */ const preview = ['#quick-view', 'files-safe-media[type="html"]', previewTag]; - // @ts-ignore: error TS7006: Parameter 'y' implicitly has an 'any' type. - function scrollQuickViewHtmlBy(y) { + function scrollQuickViewHtmlBy(y: number) { const doScrollBy = `window.scrollBy(0,${y})`; return remoteCall.executeJsInPreviewTag(appId, preview, doScrollBy); } - // @ts-ignore: error TS7006: Parameter 'scrollY' implicitly has an 'any' type. - async function checkQuickViewHtmlScrollY(scrollY) { + async function checkQuickViewHtmlScrollY(scrollY: {toString: () => any}) { if (!scrollY || Number(scrollY.toString()) <= 200) { await scrollQuickViewHtmlBy(100); return pending(caller, 'Waiting for Quick View to scroll.'); } + return; } // Open Files app on Downloads containing ENTRIES.tallHtml. const appId = - // @ts-ignore: error TS4111: Property 'tallHtml' comes from an index - // signature, so it must be accessed with ['tallHtml']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.tallHtml], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'tallHtml' comes from an index - // signature, so it must be accessed with ['tallHtml']. - await openQuickView(appId, ENTRIES.tallHtml.nameText); + await openQuickViewEx(appId, ENTRIES.tallHtml.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewHtmlLoaded(elements) { + function checkPreviewHtmlLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1345,13 +1185,13 @@ const getScrollY = 'window.scrollY'; // The initial preview scrollY should be 0. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const scrollY = await executeJsInPreviewTagAndCatchErrors(appId, preview, getScrollY); if (String(scrollY) !== '0') { return pending(caller, `Waiting for preview text to load.`); } + return; }); // Scroll the preview and verify that it scrolled. @@ -1363,17 +1203,14 @@ // Check: the mimeType field should not be displayed. await getQuickViewMetadataBoxField(appId, 'Type', 'hidden'); -}; +} /** * Tests opening Quick View on an html document to verify that the background * color of the <files-safe-media type="html"> that contains the preview is * solid white. */ -// @ts-ignore: error TS4111: Property 'openQuickViewBackgroundColorHtml' comes -// from an index signature, so it must be accessed with -// ['openQuickViewBackgroundColorHtml']. -testcase.openQuickViewBackgroundColorHtml = async () => { +export async function openQuickViewBackgroundColorHtml() { const caller = getCaller(); /** @@ -1385,24 +1222,18 @@ // Open Files app on Downloads containing ENTRIES.tallHtml. const appId = - // @ts-ignore: error TS4111: Property 'tallHtml' comes from an index - // signature, so it must be accessed with ['tallHtml']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.tallHtml], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'tallHtml' comes from an index - // signature, so it must be accessed with ['tallHtml']. - await openQuickView(appId, ENTRIES.tallHtml.nameText); + await openQuickViewEx(appId, ENTRIES.tallHtml.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewHtmlLoaded(elements) { + function checkPreviewHtmlLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1419,14 +1250,12 @@ appId, preview, getBackgroundStyle); chrome.test.assertEq('rgba(0, 0, 0, 0)', backgroundColor[0]); -}; +} /** * Tests opening Quick View containing an audio file without album preview. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAudio' comes from an index -// signature, so it must be accessed with ['openQuickViewAudio']. -testcase.openQuickViewAudio = async () => { +export async function openQuickViewAudio() { const caller = getCaller(); /** @@ -1443,24 +1272,18 @@ // Open Files app on Downloads containing ENTRIES.beautiful song. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. - await openQuickView(appId, ENTRIES.beautiful.nameText); + await openQuickViewEx(appId, ENTRIES.beautiful.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewAudioLoaded(elements) { + function checkPreviewAudioLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1495,14 +1318,12 @@ // Check: the correct mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('audio/ogg', mimeType); -}; +} /** * Tests opening Quick View containing an audio file on Drive. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAudioOnDrive' comes from an -// index signature, so it must be accessed with ['openQuickViewAudioOnDrive']. -testcase.openQuickViewAudioOnDrive = async () => { +export async function openQuickViewAudioOnDrive() { const caller = getCaller(); /** @@ -1513,24 +1334,18 @@ // Open Files app on Downloads containing ENTRIES.beautiful song. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.beautiful]); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. - await openQuickView(appId, ENTRIES.beautiful.nameText); + await openQuickViewEx(appId, ENTRIES.beautiful.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewAudioLoaded(elements) { + function checkPreviewAudioLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1553,16 +1368,13 @@ // Check: the preview body backgroundColor should be transparent black. chrome.test.assertEq('rgba(0, 0, 0, 0)', backgroundColor[0]); } -}; +} /** * Tests opening Quick View containing an audio file that has an album art * image in its metadata. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAudioWithImageMetadata' -// comes from an index signature, so it must be accessed with -// ['openQuickViewAudioWithImageMetadata']. -testcase.openQuickViewAudioWithImageMetadata = async () => { +export async function openQuickViewAudioWithImageMetadata() { const caller = getCaller(); // Define a test file containing audio file with metadata. @@ -1588,17 +1400,15 @@ await setupAndWaitUntilReady(RootPath.DOWNLOADS, [id3Audio], []); // Open the file in Quick View. - await openQuickView(appId, id3Audio.nameText); + await openQuickViewEx(appId, id3Audio.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1617,14 +1427,12 @@ // Check: the audio album metadata should also be displayed. const album = await getQuickViewMetadataBoxField(appId, 'Album'); chrome.test.assertEq(album, 'OK Computer'); -}; +} /** * Tests opening Quick View containing an image with extension 'jpg'. */ -// @ts-ignore: error TS4111: Property 'openQuickViewImageJpg' comes from an -// index signature, so it must be accessed with ['openQuickViewImageJpg']. -testcase.openQuickViewImageJpg = async () => { +export async function openQuickViewImageJpg() { const caller = getCaller(); /** @@ -1635,24 +1443,18 @@ // Open Files app on Downloads containing ENTRIES.smallJpeg. const appId = - // @ts-ignore: error TS4111: Property 'smallJpeg' comes from an index - // signature, so it must be accessed with ['smallJpeg']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.smallJpeg], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'smallJpeg' comes from an index - // signature, so it must be accessed with ['smallJpeg']. - await openQuickView(appId, ENTRIES.smallJpeg.nameText); + await openQuickViewEx(appId, ENTRIES.smallJpeg.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1679,14 +1481,12 @@ // Check: the correct mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('image/jpeg', mimeType); -}; +} /** * Tests opening Quick View containing an image with extension 'jpeg'. */ -// @ts-ignore: error TS4111: Property 'openQuickViewImageJpeg' comes from an -// index signature, so it must be accessed with ['openQuickViewImageJpeg']. -testcase.openQuickViewImageJpeg = async () => { +export async function openQuickViewImageJpeg() { const caller = getCaller(); /** @@ -1697,24 +1497,18 @@ // Open Files app on Downloads containing ENTRIES.sampleJpeg. const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'sampleJpeg' comes from an index - // signature, so it must be accessed with ['sampleJpeg']. RootPath.DOWNLOADS, [ENTRIES.sampleJpeg], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'sampleJpeg' comes from an index - // signature, so it must be accessed with ['sampleJpeg']. - await openQuickView(appId, ENTRIES.sampleJpeg.nameText); + await openQuickViewEx(appId, ENTRIES.sampleJpeg.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1741,15 +1535,13 @@ // Check: the correct mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('image/jpeg', mimeType); -}; +} /** * Tests that opening Quick View on a JPEG image with EXIF displays the EXIF * information in the QuickView Metadata Box. */ -// @ts-ignore: error TS4111: Property 'openQuickViewImageExif' comes from an -// index signature, so it must be accessed with ['openQuickViewImageExif']. -testcase.openQuickViewImageExif = async () => { +export async function openQuickViewImageExif() { const caller = getCaller(); /** @@ -1760,24 +1552,18 @@ // Open Files app on Downloads containing ENTRIES.exifImage. const appId = - // @ts-ignore: error TS4111: Property 'exifImage' comes from an index - // signature, so it must be accessed with ['exifImage']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.exifImage], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'exifImage' comes from an index - // signature, so it must be accessed with ['exifImage']. - await openQuickView(appId, ENTRIES.exifImage.nameText); + await openQuickViewEx(appId, ENTRIES.exifImage.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1802,15 +1588,13 @@ chrome.test.assertEq('FinePix S5000', model); const film = await getQuickViewMetadataBoxField(appId, 'Device settings'); chrome.test.assertEq('f/2.8 0.004 5.7mm ISO200', film); -}; +} /** * Tests opening Quick View on an RAW image. The RAW image has EXIF and that * information should be displayed in the QuickView metadata box. */ -// @ts-ignore: error TS4111: Property 'openQuickViewImageRaw' comes from an -// index signature, so it must be accessed with ['openQuickViewImageRaw']. -testcase.openQuickViewImageRaw = async () => { +export async function openQuickViewImageRaw() { const caller = getCaller(); /** @@ -1821,24 +1605,18 @@ // Open Files app on Downloads containing ENTRIES.rawImage. const appId = - // @ts-ignore: error TS4111: Property 'rawImage' comes from an index - // signature, so it must be accessed with ['rawImage']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.rawImage], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'rawImage' comes from an index - // signature, so it must be accessed with ['rawImage']. - await openQuickView(appId, ENTRIES.rawImage.nameText); + await openQuickViewEx(appId, ENTRIES.rawImage.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1859,16 +1637,13 @@ chrome.test.assertEq('E-M1', model); const film = await getQuickViewMetadataBoxField(appId, 'Device settings'); chrome.test.assertEq('f/8 0.002 12mm ISO200', film); -}; +} /** * Tests opening Quick View on an RAW .NEF image and that the dimensions * shown in the metadata box respect the image EXIF orientation. */ -// @ts-ignore: error TS4111: Property 'openQuickViewImageRawWithOrientation' -// comes from an index signature, so it must be accessed with -// ['openQuickViewImageRawWithOrientation']. -testcase.openQuickViewImageRawWithOrientation = async () => { +export async function openQuickViewImageRawWithOrientation() { const caller = getCaller(); /** @@ -1880,24 +1655,18 @@ // Open Files app on Downloads containing ENTRIES.rawNef. const appId = - // @ts-ignore: error TS4111: Property 'nefImage' comes from an index - // signature, so it must be accessed with ['nefImage']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.nefImage], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'nefImage' comes from an index - // signature, so it must be accessed with ['nefImage']. - await openQuickView(appId, ENTRIES.nefImage.nameText); + await openQuickViewEx(appId, ENTRIES.nefImage.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1919,37 +1688,30 @@ // Get the fileSafeMedia element preview thumbnail image size. const element = await remoteCall.waitForElement(appId, filesSafeMedia); const image = new Image(); + let imageSize = ''; image.onload = () => { - // @ts-ignore: error TS2339: Property 'imageSize' does not exist on type - // 'HTMLImageElement'. - image.imageSize = `${image.naturalWidth} x ${image.naturalHeight}`; + imageSize = `${image.naturalWidth} x ${image.naturalHeight}`; }; - const sourceContent = - // @ts-ignore: error TS4111: Property 'src' comes from an index signature, - // so it must be accessed with ['src']. - /** @type {FilePreviewContent} */ (JSON.parse(element.attributes.src)); + const sourceContent = JSON.parse(element.attributes['src']!); chrome.test.assertTrue(!!sourceContent.data); - image.src = sourceContent.data; + image.src = sourceContent.data as string; - // Check: the preview thumbnail should have an orientiated size. - // @ts-ignore: error TS7030: Not all code paths return a value. + // Check: the preview thumbnail should have an orientated size. await repeatUntil(async () => { - // @ts-ignore: error TS2339: Property 'imageSize' does not exist on type - // 'HTMLImageElement'. - if (!image.complete || image.imageSize !== '120 x 160') { + if (!image.complete || imageSize !== '120 x 160') { return pending(caller, 'Waiting for preview thumbnail size.'); } + + return; }); -}; +} /** * Tests opening Quick View with a VP8X format WEBP image. */ -// @ts-ignore: error TS4111: Property 'openQuickViewImageWebp' comes from an -// index signature, so it must be accessed with ['openQuickViewImageWebp']. -testcase.openQuickViewImageWebp = async () => { +export async function openQuickViewImageWebp() { const caller = getCaller(); /** @@ -1960,24 +1722,18 @@ // Open Files app on Downloads containing ENTRIES.rawImage. const appId = - // @ts-ignore: error TS4111: Property 'webpImage' comes from an index - // signature, so it must be accessed with ['webpImage']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.webpImage], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'webpImage' comes from an index - // signature, so it must be accessed with ['webpImage']. - await openQuickView(appId, ENTRIES.webpImage.nameText); + await openQuickViewEx(appId, ENTRIES.webpImage.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -1994,16 +1750,14 @@ // Check: the correct dimensions should be displayed. const size = await getQuickViewMetadataBoxField(appId, 'Dimensions'); chrome.test.assertEq('400 x 175', size); -}; +} /** * Tests that opening Quick View on an image and clicking the image does not * focus the image. Instead, the user should still be able to cycle through * file list items in Quick View: crbug.com/1038835. */ -// @ts-ignore: error TS4111: Property 'openQuickViewImageClick' comes from an -// index signature, so it must be accessed with ['openQuickViewImageClick']. -testcase.openQuickViewImageClick = async () => { +export async function openQuickViewImageClick() { const caller = getCaller(); /** @@ -2014,24 +1768,18 @@ // Open Files app on Downloads containing two images. const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'image3' comes from an index - // signature, so it must be accessed with ['image3']. RootPath.DOWNLOADS, [ENTRIES.desktop, ENTRIES.image3], []); // Open the first image in Quick View. - // @ts-ignore: error TS4111: Property 'desktop' comes from an index signature, - // so it must be accessed with ['desktop']. - await openQuickView(appId, ENTRIES.desktop.nameText); + await openQuickViewEx(appId, ENTRIES.desktop.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2064,16 +1812,14 @@ chrome.test.assertEq('image/jpeg', mimeType); // Check: Quick View should be able to close. - await closeQuickView(appId); -}; + await closeQuickViewEx(appId); +} /** * Tests that opening a broken image in Quick View displays the "no-preview * available" generic icon and has a [load-error] attribute. */ -// @ts-ignore: error TS4111: Property 'openQuickViewBrokenImage' comes from an -// index signature, so it must be accessed with ['openQuickViewBrokenImage']. -testcase.openQuickViewBrokenImage = async () => { +export async function openQuickViewBrokenImage() { const caller = getCaller(); /** @@ -2088,24 +1834,18 @@ // Open Files app on Downloads containing ENTRIES.brokenJpeg. const appId = await setupAndWaitUntilReady( - // @ts-ignore: error TS4111: Property 'brokenJpeg' comes from an index - // signature, so it must be accessed with ['brokenJpeg']. RootPath.DOWNLOADS, [ENTRIES.brokenJpeg], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'brokenJpeg' comes from an index - // signature, so it must be accessed with ['brokenJpeg']. - await openQuickView(appId, ENTRIES.brokenJpeg.nameText); + await openQuickViewEx(appId, ENTRIES.brokenJpeg.nameText); // Check: the quick view element should have a 'load-error' attribute. await remoteCall.waitForElement(appId, '#quick-view[load-error]'); // Wait for the generic thumbnail to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkForGenericThumbnail(elements) { + function checkForGenericThumbnail(elements: ElementObject[]) { const haveElements = Array.isArray(elements) && elements.length === 1; - if (!haveElements || elements[0].styles.display !== 'block') { + if (!haveElements || elements[0]!.styles!['display'] !== 'block') { return pending(caller, 'Waiting for generic thumbnail to load.'); } return; @@ -2116,14 +1856,12 @@ return checkForGenericThumbnail(await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, [genericThumbnail, ['display']])); }); -}; +} /** * Tests opening Quick View containing a video. */ -// @ts-ignore: error TS4111: Property 'openQuickViewVideo' comes from an index -// signature, so it must be accessed with ['openQuickViewVideo']. -testcase.openQuickViewVideo = async () => { +export async function openQuickViewVideo() { const caller = getCaller(); /** @@ -2134,24 +1872,18 @@ // Open Files app on Downloads containing ENTRIES.webm video. const appId = - // @ts-ignore: error TS4111: Property 'webm' comes from an index - // signature, so it must be accessed with ['webm']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.webm], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'webm' comes from an index signature, so - // it must be accessed with ['webm']. - await openQuickView(appId, ENTRIES.webm.nameText); + await openQuickViewEx(appId, ENTRIES.webm.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewVideoLoaded(elements) { + function checkPreviewVideoLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2180,19 +1912,17 @@ chrome.test.assertEq('video/webm', mimeType); // Close Quick View. - await closeQuickView(appId); + await closeQuickViewEx(appId); // Check: closing Quick View should remove the video <files-safe-media> // preview element, so it stops playing the video. crbug.com/970192 await remoteCall.waitForElementLost(appId, preview); -}; +} /** * Tests opening Quick View containing a video on Drive. */ -// @ts-ignore: error TS4111: Property 'openQuickViewVideoOnDrive' comes from an -// index signature, so it must be accessed with ['openQuickViewVideoOnDrive']. -testcase.openQuickViewVideoOnDrive = async () => { +export async function openQuickViewVideoOnDrive() { const caller = getCaller(); /** @@ -2203,24 +1933,18 @@ // Open Files app on Downloads containing ENTRIES.webm video. const appId = - // @ts-ignore: error TS4111: Property 'webm' comes from an index - // signature, so it must be accessed with ['webm']. await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.webm]); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'webm' comes from an index signature, so - // it must be accessed with ['webm']. - await openQuickView(appId, ENTRIES.webm.nameText); + await openQuickViewEx(appId, ENTRIES.webm.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewVideoLoaded(elements) { + function checkPreviewVideoLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2249,21 +1973,18 @@ chrome.test.assertEq('video/webm', mimeType); // Close Quick View. - await closeQuickView(appId); + await closeQuickViewEx(appId); // Check: closing Quick View should remove the video <files-safe-media> // preview element, so it stops playing the video. crbug.com/970192 await remoteCall.waitForElementLost(appId, preview); -}; +} /** * Tests opening Quick View with multiple files and using the up/down arrow * keys to select and view their content. */ -// @ts-ignore: error TS4111: Property 'openQuickViewKeyboardUpDownChangesView' -// comes from an index signature, so it must be accessed with -// ['openQuickViewKeyboardUpDownChangesView']. -testcase.openQuickViewKeyboardUpDownChangesView = async () => { +export async function openQuickViewKeyboardUpDownChangesView() { const caller = getCaller(); /** @@ -2273,27 +1994,19 @@ const preview = ['#quick-view', `#dialog[open] ${previewTag}.text-content`]; // Open Files app on Downloads containing two text files. - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. const files = [ENTRIES.hello, ENTRIES.tallText]; - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); // Open the last file in Quick View. - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. - await openQuickView(appId, ENTRIES.tallText.nameText); + await openQuickViewEx(appId, ENTRIES.tallText.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2309,14 +2022,14 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, downArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; if (!text || !text[0] || !text[0].includes('This is a sample file')) { return pending(caller, 'Waiting for preview content.'); } + return; }); // Press the up arrow key to select the previous file. @@ -2325,25 +2038,22 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, upArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; if (!text || !text[0] || !text[0].includes('42 tall text')) { return pending(caller, 'Waiting for preview content.'); } + return; }); -}; +} /** * Tests opening Quick View with multiple files and using the left/right arrow * keys to select and view their content. */ -// @ts-ignore: error TS4111: Property -// 'openQuickViewKeyboardLeftRightChangesView' comes from an index signature, so -// it must be accessed with ['openQuickViewKeyboardLeftRightChangesView']. -testcase.openQuickViewKeyboardLeftRightChangesView = async () => { +export async function openQuickViewKeyboardLeftRightChangesView() { const caller = getCaller(); /** @@ -2353,27 +2063,19 @@ const preview = ['#quick-view', `#dialog[open] ${previewTag}.text-content`]; // Open Files app on Downloads containing two text files. - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. const files = [ENTRIES.hello, ENTRIES.tallText]; - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); // Open the last file in Quick View. - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. - await openQuickView(appId, ENTRIES.tallText.nameText); + await openQuickViewEx(appId, ENTRIES.tallText.nameText); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2389,14 +2091,14 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, rightArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; if (!text || !text[0] || !text[0].includes('This is a sample file')) { return pending(caller, 'Waiting for preview content.'); } + return; }); // Press the left arrow key to select the previous file item. @@ -2405,31 +2107,28 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, leftArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; if (!text || !text[0] || !text[0].includes('42 tall text')) { return pending(caller, 'Waiting for preview content.'); } + return; }); -}; +} /** * Tests that the metadatabox can be toggled opened/closed by pressing the * Enter key on the Quick View toolbar info button. */ -// @ts-ignore: error TS4111: Property 'openQuickViewToggleInfoButtonKeyboard' -// comes from an index signature, so it must be accessed with -// ['openQuickViewToggleInfoButtonKeyboard']. -testcase.openQuickViewToggleInfoButtonKeyboard = async () => { +export async function openQuickViewToggleInfoButtonKeyboard() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Check: the metadatabox should be open. const metaShown = ['#quick-view', '#contentPanel[metadata-box-active]']; @@ -2454,22 +2153,19 @@ // Check: the metadatabox should open. await remoteCall.waitForElement(appId, metaShown); -}; +} /** * Tests that the metadatabox can be toggled opened/closed by clicking the * the Quick View toolbar info button. */ -// @ts-ignore: error TS4111: Property 'openQuickViewToggleInfoButtonClick' comes -// from an index signature, so it must be accessed with -// ['openQuickViewToggleInfoButtonClick']. -testcase.openQuickViewToggleInfoButtonClick = async () => { +export async function openQuickViewToggleInfoButtonClick() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Check: the metadatabox should be open. const metaShown = ['#quick-view', '#contentPanel[metadata-box-active]']; @@ -2493,15 +2189,12 @@ // Check: the metadatabox should open. await remoteCall.waitForElement(appId, metaShown); -}; +} /** * Tests that Quick View opens with multiple files selected. */ -// @ts-ignore: error TS4111: Property 'openQuickViewWithMultipleFiles' comes -// from an index signature, so it must be accessed with -// ['openQuickViewWithMultipleFiles']. -testcase.openQuickViewWithMultipleFiles = async () => { +export async function openQuickViewWithMultipleFiles() { const caller = getCaller(); /** @@ -2541,14 +2234,12 @@ await openQuickViewMultipleSelection(appId, ['Desktop', 'hello']); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2563,16 +2254,13 @@ // Check: the correct file mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('image/png', mimeType); -}; +} /** * Tests that Quick View displays text files when multiple files are * selected. */ -// @ts-ignore: error TS4111: Property 'openQuickViewWithMultipleFilesText' comes -// from an index signature, so it must be accessed with -// ['openQuickViewWithMultipleFilesText']. -testcase.openQuickViewWithMultipleFilesText = async () => { +export async function openQuickViewWithMultipleFilesText() { const caller = getCaller(); /** @@ -2581,11 +2269,7 @@ */ const preview = ['#quick-view', 'files-safe-media[type="image"]', previewTag]; - // @ts-ignore: error TS4111: Property 'smallJpeg' comes from an index - // signature, so it must be accessed with ['smallJpeg']. const files = [ENTRIES.tallText, ENTRIES.hello, ENTRIES.smallJpeg]; - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); // Add item 1 to the check-selection, ENTRIES.smallJpeg. @@ -2613,14 +2297,12 @@ await openQuickViewMultipleSelection(appId, ['small', 'hello']); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2644,14 +2326,12 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, downArrow)); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2666,16 +2346,13 @@ // Check: the open button should be displayed. await remoteCall.waitForElement( appId, ['#quick-view', '#open-button:not([hidden])']); -}; +} /** * Tests that Quick View displays pdf files when multiple files are * selected. */ -// @ts-ignore: error TS4111: Property 'openQuickViewWithMultipleFilesPdf' comes -// from an index signature, so it must be accessed with -// ['openQuickViewWithMultipleFilesPdf']. -testcase.openQuickViewWithMultipleFilesPdf = async () => { +export async function openQuickViewWithMultipleFilesPdf() { const caller = getCaller(); /** @@ -2684,11 +2361,7 @@ */ const preview = ['#quick-view', 'files-safe-media[type="image"]', previewTag]; - // @ts-ignore: error TS4111: Property 'smallJpeg' comes from an index - // signature, so it must be accessed with ['smallJpeg']. const files = [ENTRIES.tallPdf, ENTRIES.desktop, ENTRIES.smallJpeg]; - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); // Add item 1 to the check-selection, ENTRIES.smallJpeg. @@ -2716,14 +2389,12 @@ await openQuickViewMultipleSelection(appId, ['small', 'tall']); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2747,14 +2418,12 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, downArrow)); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewPdfLoaded(elements) { + function checkPreviewPdfLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2769,16 +2438,13 @@ // Check: the open button should be displayed. await remoteCall.waitForElement( appId, ['#quick-view', '#open-button:not([hidden])']); -}; +} /** * Tests that the content panel changes when using the up/down arrow keys * when multiple files are selected. */ -// @ts-ignore: error TS4111: Property -// 'openQuickViewWithMultipleFilesKeyboardUpDown' comes from an index signature, -// so it must be accessed with ['openQuickViewWithMultipleFilesKeyboardUpDown']. -testcase.openQuickViewWithMultipleFilesKeyboardUpDown = async () => { +export async function openQuickViewWithMultipleFilesKeyboardUpDown() { const caller = getCaller(); /** @@ -2788,11 +2454,7 @@ const preview = ['#quick-view', `#dialog[open] ${previewTag}.text-content`]; // Open Files app on Downloads containing three text files. - // @ts-ignore: error TS4111: Property 'plainText' comes from an index - // signature, so it must be accessed with ['plainText']. const files = [ENTRIES.hello, ENTRIES.tallText, ENTRIES.plainText]; - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); // Add item 1 to the check-selection, ENTRIES.tallText. @@ -2820,14 +2482,12 @@ await openQuickViewMultipleSelection(appId, ['tall', 'hello']); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2843,15 +2503,15 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, downArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; // Check: the content of ENTRIES.hello should be shown. if (!text || !text[0] || !text[0].includes('This is a sample file')) { return pending(caller, 'Waiting for preview content.'); } + return; }); // Press the up arrow key to select the previous file. @@ -2860,27 +2520,23 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, upArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; // Check: the content of ENTRIES.tallText should be shown. if (!text || !text[0] || !text[0].includes('42 tall text')) { return pending(caller, 'Waiting for preview content.'); } + return; }); -}; +} /** * Tests that the content panel changes when using the left/right arrow keys * when multiple files are selected. */ -// @ts-ignore: error TS4111: Property -// 'openQuickViewWithMultipleFilesKeyboardLeftRight' comes from an index -// signature, so it must be accessed with -// ['openQuickViewWithMultipleFilesKeyboardLeftRight']. -testcase.openQuickViewWithMultipleFilesKeyboardLeftRight = async () => { +export async function openQuickViewWithMultipleFilesKeyboardLeftRight() { const caller = getCaller(); /** @@ -2890,11 +2546,7 @@ const preview = ['#quick-view', `#dialog[open] ${previewTag}.text-content`]; // Open Files app on Downloads containing three text files. - // @ts-ignore: error TS4111: Property 'plainText' comes from an index - // signature, so it must be accessed with ['plainText']. const files = [ENTRIES.hello, ENTRIES.tallText, ENTRIES.plainText]; - // @ts-ignore: error TS2345: Argument of type '(TestEntryInfo | undefined)[]' - // is not assignable to parameter of type 'TestEntryInfo[]'. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, files, []); // Add item 1 to the check-selection, ENTRIES.tallText. @@ -2922,14 +2574,12 @@ await openQuickViewMultipleSelection(appId, ['tall', 'hello']); // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewTextLoaded(elements) { + function checkPreviewTextLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || !elements[0].attributes.src) { + if (!haveElements || !elements[0]!.attributes['src']) { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -2945,15 +2595,15 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, rightArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; // Check: the content of ENTRIES.hello should be shown. if (!text || !text[0] || !text[0].includes('This is a sample file')) { return pending(caller, 'Waiting for preview content.'); } + return; }); // Press the left arrow key to select the previous file item. @@ -2962,31 +2612,29 @@ await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, leftArrow)); // Wait until the preview displays that file's content. - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const getTextContent = contentWindowQuery + '.document.body.textContent'; const text = await executeJsInPreviewTagAndCatchErrors( - appId, preview, getTextContent); + appId, preview, getTextContent) as string[]; // Check: the content of ENTRIES.tallText should be shown. if (!text || !text[0] || !text[0].includes('42 tall text')) { return pending(caller, 'Waiting for preview content.'); } + return; }); -}; +} /** * Tests opening Quick View and closing with Escape key returns focus to file * list. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAndEscape' comes from an -// index signature, so it must be accessed with ['openQuickViewAndEscape']. -testcase.openQuickViewAndEscape = async () => { +export async function openQuickViewAndEscape() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Hit Escape key to close Quick View. const panelElements = ['#quick-view', '#contentPanel']; @@ -3002,16 +2650,13 @@ const element = await remoteCall.waitForElement(appId, '#file-list:focus'); chrome.test.assertEq( 'file-list', element.attributes['id'], '#file-list should be focused'); -}; +} /** * Test opening Quick View when Directory Tree is focused it should display if * there is only 1 file/folder selected in the file list. */ -// @ts-ignore: error TS4111: Property 'openQuickViewFromDirectoryTree' comes -// from an index signature, so it must be accessed with -// ['openQuickViewFromDirectoryTree']. -testcase.openQuickViewFromDirectoryTree = async () => { +export async function openQuickViewFromDirectoryTree() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -3021,9 +2666,7 @@ await directoryTree.focusTree(); // Ctrl+A to select the only file. - const ctrlA = [directoryTree.rootSelector, 'a', true, false, false]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. + const ctrlA = [directoryTree.rootSelector, 'a', true, false, false] as const; await remoteCall.fakeKeyDown(appId, ...ctrlA); // Use selection menu button to open Quick View. @@ -3046,20 +2689,18 @@ const elements = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, [query, ['display']]); const haveElements = Array.isArray(elements) && elements.length !== 0; - if (!haveElements || elements[0].styles.display !== 'block') { + if (!haveElements || elements[0]!.styles!['display'] !== 'block') { return pending(caller, 'Waiting for Quick View to open.'); } return true; }); -}; +} /** * Tests the tab-index focus order when sending tab keys when an image file is * shown in Quick View. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTabIndexImage' comes from an -// index signature, so it must be accessed with ['openQuickViewTabIndexImage']. -testcase.openQuickViewTabIndexImage = async () => { +export async function openQuickViewTabIndexImage() { // Prepare a list of tab-index focus queries. const tabQueries = [ {'query': ['#quick-view', `[aria-label="Back"]:focus`]}, @@ -3070,21 +2711,15 @@ // Open Files app on Downloads containing ENTRIES.smallJpeg. const appId = - // @ts-ignore: error TS4111: Property 'smallJpeg' comes from an index - // signature, so it must be accessed with ['smallJpeg']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.smallJpeg], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'smallJpeg' comes from an index - // signature, so it must be accessed with ['smallJpeg']. - await openQuickView(appId, ENTRIES.smallJpeg.nameText); + await openQuickViewEx(appId, ENTRIES.smallJpeg.nameText); for (const query of tabQueries) { // Make the browser dispatch a tab key event to FilesApp. - const result = await sendTestMessage( - // @ts-ignore: error TS2339: Property 'shift' does not exist on type '{ - // query: string[]; }'. - {name: 'dispatchTabKey', shift: query.shift || false}); + const result = + await sendTestMessage({name: 'dispatchTabKey', shift: false}); chrome.test.assertEq( 'tabKeyDispatched', result, 'Tab key dispatch failure'); @@ -3095,15 +2730,13 @@ // Check: the queried element should gain the focus. await remoteCall.waitForElement(appId, query.query); } -}; +} /** * Tests the tab-index focus order when sending tab keys when a text file is * shown in Quick View. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTabIndexText' comes from an -// index signature, so it must be accessed with ['openQuickViewTabIndexText']. -testcase.openQuickViewTabIndexText = async () => { +export async function openQuickViewTabIndexText() { // Prepare a list of tab-index focus queries. const tabQueries = [ {'query': ['#quick-view', `[aria-label="Back"]:focus`]}, @@ -3116,21 +2749,15 @@ // Open Files app on Downloads containing ENTRIES.tallText. const appId = - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.tallText], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'tallText' comes from an index - // signature, so it must be accessed with ['tallText']. - await openQuickView(appId, ENTRIES.tallText.nameText); + await openQuickViewEx(appId, ENTRIES.tallText.nameText); for (const query of tabQueries) { // Make the browser dispatch a tab key event to FilesApp. - const result = await sendTestMessage( - // @ts-ignore: error TS2339: Property 'shift' does not exist on type '{ - // query: string[]; }'. - {name: 'dispatchTabKey', shift: query.shift || false}); + const result = + await sendTestMessage({name: 'dispatchTabKey', shift: false}); chrome.test.assertEq( 'tabKeyDispatched', result, 'Tab key dispatch failure'); @@ -3141,15 +2768,13 @@ // Check: the queried element should gain the focus. await remoteCall.waitForElement(appId, query.query); } -}; +} /** * Tests the tab-index focus order when sending tab keys when an HTML file is * shown in Quick View. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTabIndexHtml' comes from an -// index signature, so it must be accessed with ['openQuickViewTabIndexHtml']. -testcase.openQuickViewTabIndexHtml = async () => { +export async function openQuickViewTabIndexHtml() { // Prepare a list of tab-index focus queries. const tabQueries = [ {'query': ['#quick-view', `[aria-label="Back"]:focus`]}, @@ -3160,21 +2785,15 @@ // Open Files app on Downloads containing ENTRIES.tallHtml. const appId = - // @ts-ignore: error TS4111: Property 'tallHtml' comes from an index - // signature, so it must be accessed with ['tallHtml']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.tallHtml], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'tallHtml' comes from an index - // signature, so it must be accessed with ['tallHtml']. - await openQuickView(appId, ENTRIES.tallHtml.nameText); + await openQuickViewEx(appId, ENTRIES.tallHtml.nameText); for (const query of tabQueries) { // Make the browser dispatch a tab key event to FilesApp. - const result = await sendTestMessage( - // @ts-ignore: error TS2339: Property 'shift' does not exist on type '{ - // query: string[]; }'. - {name: 'dispatchTabKey', shift: query.shift || false}); + const result = + await sendTestMessage({name: 'dispatchTabKey', shift: false}); chrome.test.assertEq( 'tabKeyDispatched', result, 'Tab key dispatch failure'); @@ -3185,25 +2804,19 @@ // Check: the queried element should gain the focus. await remoteCall.waitForElement(appId, query.query); } -}; +} /** * Tests the tab-index focus order when sending tab keys when an audio file * is shown in Quick View. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTabIndexAudio' comes from an -// index signature, so it must be accessed with ['openQuickViewTabIndexAudio']. -testcase.openQuickViewTabIndexAudio = async () => { +export async function openQuickViewTabIndexAudio() { // Open Files app on Downloads containing ENTRIES.beautiful song. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. - await openQuickView(appId, ENTRIES.beautiful.nameText); + await openQuickViewEx(appId, ENTRIES.beautiful.nameText); // Prepare a list of tab-index focus queries. const tabQueries = [ @@ -3215,10 +2828,8 @@ for (const query of tabQueries) { // Make the browser dispatch a tab key event to FilesApp. - const result = await sendTestMessage( - // @ts-ignore: error TS2339: Property 'shift' does not exist on type '{ - // query: string[]; }'. - {name: 'dispatchTabKey', shift: query.shift || false}); + const result = + await sendTestMessage({name: 'dispatchTabKey', shift: false}); chrome.test.assertEq( 'tabKeyDispatched', result, 'Tab key dispatch failure'); @@ -3249,25 +2860,19 @@ break; } } -}; +} /** * Tests the tab-index focus order when sending tab keys when a video file is * shown in Quick View. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTabIndexVideo' comes from an -// index signature, so it must be accessed with ['openQuickViewTabIndexVideo']. -testcase.openQuickViewTabIndexVideo = async () => { +export async function openQuickViewTabIndexVideo() { // Open Files app on Downloads containing ENTRIES.webm video. const appId = - // @ts-ignore: error TS4111: Property 'webm' comes from an index - // signature, so it must be accessed with ['webm']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.webm], []); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'webm' comes from an index signature, so - // it must be accessed with ['webm']. - await openQuickView(appId, ENTRIES.webm.nameText); + await openQuickViewEx(appId, ENTRIES.webm.nameText); // Prepare a list of tab-index focus queries. const tabQueries = [ @@ -3279,10 +2884,8 @@ for (const query of tabQueries) { // Make the browser dispatch a tab key event to FilesApp. - const result = await sendTestMessage( - // @ts-ignore: error TS2339: Property 'shift' does not exist on type '{ - // query: string[]; }'. - {name: 'dispatchTabKey', shift: query.shift || false}); + const result = + await sendTestMessage({name: 'dispatchTabKey', shift: false}); chrome.test.assertEq( 'tabKeyDispatched', result, 'Tab key dispatch failure'); @@ -3313,15 +2916,12 @@ break; } } -}; +} /** * Tests that the tab-index focus stays within the delete confirm dialog. */ -// @ts-ignore: error TS4111: Property 'openQuickViewTabIndexDeleteDialog' comes -// from an index signature, so it must be accessed with -// ['openQuickViewTabIndexDeleteDialog']. -testcase.openQuickViewTabIndexDeleteDialog = async () => { +export async function openQuickViewTabIndexDeleteDialog() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); @@ -3329,7 +2929,7 @@ // Open a USB file in Quick View. USB delete never uses trash and always // shows the delete dialog. await mountAndSelectUsb(appId); - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Open the Quick View delete confirm dialog. const deleteKey = ['#quick-view', 'Delete', false, false, false]; @@ -3350,10 +2950,8 @@ for (const query of tabQueries) { // Make the browser dispatch a tab key event to FilesApp. - const result = await sendTestMessage( - // @ts-ignore: error TS2339: Property 'shift' does not exist on type '{ - // query: string[]; }'. - {name: 'dispatchTabKey', shift: query.shift || false}); + const result = + await sendTestMessage({name: 'dispatchTabKey', shift: false}); chrome.test.assertEq( 'tabKeyDispatched', result, 'Tab key dispatch failure'); @@ -3364,22 +2962,19 @@ // Check: the queried element should gain the focus. await remoteCall.waitForElement(appId, query.query); } -}; +} /** * Tests deleting an item from Quick View when in single select mode, and * that Quick View closes when there are no more items to view. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAndDeleteSingleSelection' -// comes from an index signature, so it must be accessed with -// ['openQuickViewAndDeleteSingleSelection']. -testcase.openQuickViewAndDeleteSingleSelection = async () => { +export async function openQuickViewAndDeleteSingleSelection() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Press delete key. const deleteKey = ['#quick-view', 'Delete', false, false, false]; @@ -3393,7 +2988,7 @@ // Check: the Quick View dialog should close. await waitQuickViewClose(appId); -}; +} /** * Tests deleting an item from Quick View while in check-selection mode. @@ -3401,10 +2996,7 @@ * the item below the item deleted is shown in Quick View after the item's * deletion. */ -// @ts-ignore: error TS4111: Property 'openQuickViewAndDeleteCheckSelection' -// comes from an index signature, so it must be accessed with -// ['openQuickViewAndDeleteCheckSelection']. -testcase.openQuickViewAndDeleteCheckSelection = async () => { +export async function openQuickViewAndDeleteCheckSelection() { // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -3441,14 +3033,12 @@ // Check: Quick View should display the entry below |hello.txt|, // which is |world.ogv|. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewVideoLoaded(elements) { + function checkPreviewVideoLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -3464,15 +3054,12 @@ // Check: the mimeType of |world.ogv| should be 'video/ogg'. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('video/ogg', mimeType); -}; +} /** * Tests that deleting all items in a check-selection closes the Quick View. */ -// @ts-ignore: error TS4111: Property 'openQuickViewDeleteEntireCheckSelection' -// comes from an index signature, so it must be accessed with -// ['openQuickViewDeleteEntireCheckSelection']. -testcase.openQuickViewDeleteEntireCheckSelection = async () => { +export async function openQuickViewDeleteEntireCheckSelection() { const caller = getCaller(); // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. @@ -3513,14 +3100,12 @@ ['#quick-view', 'files-safe-media[type="audio"]', previewTag]; // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewAudioLoaded(elements) { + function checkPreviewAudioLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -3548,14 +3133,12 @@ ['#quick-view', 'files-safe-media[type="image"]', previewTag]; // Wait for the Quick View preview to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkPreviewImageLoaded(elements) { + function checkPreviewImageLoaded(elements: ElementObject[]) { let haveElements = Array.isArray(elements) && elements.length === 1; if (haveElements) { - haveElements = elements[0].styles.display.includes('block'); + haveElements = elements[0]!.styles!['display']!.includes('block'); } - if (!haveElements || elements[0].attributes.loaded !== '') { + if (!haveElements || elements[0]!.attributes['loaded'] !== '') { return pending(caller, `Waiting for ${previewTag} to load.`); } return; @@ -3576,21 +3159,18 @@ // Check: the Quick View dialog should close. await waitQuickViewClose(appId); -}; +} /** * Tests that an item can be deleted using the Quick View delete button. */ -// @ts-ignore: error TS4111: Property 'openQuickViewClickDeleteButton' comes -// from an index signature, so it must be accessed with -// ['openQuickViewClickDeleteButton']. -testcase.openQuickViewClickDeleteButton = async () => { +export async function openQuickViewClickDeleteButton() { // Open Files app on Downloads containing ENTRIES.hello. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); // Open the file in Quick View. - await openQuickView(appId, ENTRIES.hello.nameText); + await openQuickViewEx(appId, ENTRIES.hello.nameText); // Click the Quick View delete button. const quickViewDeleteButton = ['#quick-view', '#delete-button:not([hidden])']; @@ -3602,16 +3182,13 @@ // Check: the Quick View dialog should close. await waitQuickViewClose(appId); -}; +} /** * Tests that the delete button is not shown if the file displayed in Quick * View cannot be deleted. */ -// @ts-ignore: error TS4111: Property 'openQuickViewDeleteButtonNotShown' comes -// from an index signature, so it must be accessed with -// ['openQuickViewDeleteButtonNotShown']. -testcase.openQuickViewDeleteButtonNotShown = async () => { +export async function openQuickViewDeleteButtonNotShown() { // Open Files app on My Files const appId = await openNewWindow(''); @@ -3625,28 +3202,21 @@ ['Linux files', '--', 'Folder'], ]; await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, expectedRows, {ignoreLastModifiedTime: true}); // Open Play files in Quick View, which cannot be deleted. - await openQuickView(appId, 'Play files'); + await openQuickViewEx(appId, 'Play files'); // Check: the delete button should not be shown. const quickViewDeleteButton = ['#quick-view', '#delete-button[hidden]']; await remoteCall.waitForElement(appId, quickViewDeleteButton); -}; +} /** * Tests that the correct WayToOpen UMA histogram is recorded when opening * a single file via Quick View using "Get Info" from the context menu. */ -// @ts-ignore: error TS4111: Property 'openQuickViewUmaViaContextMenu' comes -// from an index signature, so it must be accessed with -// ['openQuickViewUmaViaContextMenu']. -testcase.openQuickViewUmaViaContextMenu = async () => { +export async function openQuickViewUmaViaContextMenu() { // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -3676,17 +3246,14 @@ contextMenuUMAValueAfterOpening, contextMenuUMAValueBeforeOpening + 1); chrome.test.assertEq( selectionMenuUMAValueAfterOpening, selectionMenuUMAValueBeforeOpening); -}; +} /** * Tests that the correct WayToOpen UMA histogram is recorded when using * Quick View in check-select mode using "Get Info" from the context * menu. */ -// @ts-ignore: error TS4111: Property -// 'openQuickViewUmaForCheckSelectViaContextMenu' comes from an index signature, -// so it must be accessed with ['openQuickViewUmaForCheckSelectViaContextMenu']. -testcase.openQuickViewUmaForCheckSelectViaContextMenu = async () => { +export async function openQuickViewUmaForCheckSelectViaContextMenu() { // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); @@ -3701,9 +3268,7 @@ QuickViewUmaWayToOpenHistogramValues.SELECTION_MENU); // Ctrl+A to select all files in the file-list. - const ctrlA = ['#file-list', 'a', true, false, false]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. + const ctrlA = ['#file-list', 'a', true, false, false] as const; await remoteCall.fakeKeyDown(appId, ...ctrlA); // Open Quick View using the context menu. @@ -3722,37 +3287,31 @@ contextMenuUMAValueAfterOpening, contextMenuUMAValueBeforeOpening + 1); chrome.test.assertEq( selectionMenuUMAValueAfterOpening, selectionMenuUMAValueBeforeOpening); -}; +} /** * Tests that the correct WayToOpen UMA histogram is recorded when using * Quick View in check-select mode using "Get Info" from the Selection * menu. */ -// @ts-ignore: error TS4111: Property 'openQuickViewUmaViaSelectionMenu' comes -// from an index signature, so it must be accessed with -// ['openQuickViewUmaViaSelectionMenu']. -testcase.openQuickViewUmaViaSelectionMenu = async () => { +export async function openQuickViewUmaViaSelectionMenu() { // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. const appId = await setupAndWaitUntilReady( RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); // Ctrl+A to select all files in the file-list. - const ctrlA = ['#file-list', 'a', true, false, false]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. + const ctrlA = ['#file-list', 'a', true, false, false] as const; await remoteCall.fakeKeyDown(appId, ...ctrlA); const caller = getCaller(); // Wait until the selection menu is visible. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkElementsDisplayVisible(elements) { + function checkElementsDisplayVisible(elements: ElementObject[]) { chrome.test.assertTrue(Array.isArray(elements)); - if (elements.length === 0 || elements[0].styles.display === 'none') { + if (elements.length === 0 || elements[0]!.styles!['display'] === 'none') { return pending(caller, 'Waiting for Selection Menu to be visible.'); } + return; } await repeatUntil(async () => { @@ -3791,7 +3350,7 @@ const elements = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, [query, ['display']]); const haveElements = Array.isArray(elements) && elements.length !== 0; - if (!haveElements || elements[0].styles.display !== 'block') { + if (!haveElements || elements[0]!.styles!['display'] !== 'block') { return pending(caller, 'Waiting for Quick View to open.'); } return true; @@ -3811,17 +3370,14 @@ chrome.test.assertEq( selectionMenuUMAValueAfterOpening, selectionMenuUMAValueBeforeOpening + 1); -}; +} /** * Tests that the correct WayToOpen UMA histogram is recorded when using * Quick View in check-select mode using "Get Info" from the context * menu opened via keyboard tabbing (not mouse). */ -// @ts-ignore: error TS4111: Property 'openQuickViewUmaViaSelectionMenuKeyboard' -// comes from an index signature, so it must be accessed with -// ['openQuickViewUmaViaSelectionMenuKeyboard']. -testcase.openQuickViewUmaViaSelectionMenuKeyboard = async () => { +export async function openQuickViewUmaViaSelectionMenuKeyboard() { const caller = getCaller(); // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET. @@ -3829,19 +3385,16 @@ RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []); // Ctrl+A to select all files in the file-list. - const ctrlA = ['#file-list', 'a', true, false, false]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. + const ctrlA = ['#file-list', 'a', true, false, false] as const; await remoteCall.fakeKeyDown(appId, ...ctrlA); // Wait until the selection menu is visible. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkElementsDisplayVisible(elements) { + function checkElementsDisplayVisible(elements: ElementObject[]) { chrome.test.assertTrue(Array.isArray(elements)); - if (elements.length === 0 || elements[0].styles.display === 'none') { + if (elements.length === 0 || elements[0]!.styles!['display'] === 'none') { return pending(caller, 'Waiting for Selection Menu to be visible.'); } + return; } await repeatUntil(async () => { @@ -3902,7 +3455,7 @@ const elements = await remoteCall.callRemoteTestUtil( 'deepQueryAllElements', appId, [query, ['display']]); const haveElements = Array.isArray(elements) && elements.length !== 0; - if (!haveElements || elements[0].styles.display !== 'block') { + if (!haveElements || elements[0]!.styles!['display'] !== 'block') { return pending(caller, 'Waiting for Quick View to open.'); } return true; @@ -3922,14 +3475,12 @@ chrome.test.assertEq( selectionMenuUMAValueAfterOpening, selectionMenuUMAValueBeforeOpening + 1); -}; +} /** * Tests that Quick View does not display a CSE file preview. */ -// @ts-ignore: error TS4111: Property 'openQuickViewEncryptedFile' comes from an -// index signature, so it must be accessed with ['openQuickViewEncryptedFile']. -testcase.openQuickViewEncryptedFile = async () => { +export async function openQuickViewEncryptedFile() { const caller = getCaller(); /** @@ -3939,25 +3490,19 @@ const contentPanel = ['#quick-view', '#dialog[open] #innerContentPanel']; const appId = - // @ts-ignore: error TS4111: Property 'testCSEFile' comes from an index - // signature, so it must be accessed with ['testCSEFile']. await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.testCSEFile]); // Open the file in Quick View. - // @ts-ignore: error TS4111: Property 'testCSEFile' comes from an index - // signature, so it must be accessed with ['testCSEFile']. - await openQuickView(appId, ENTRIES.testCSEFile.nameText); + await openQuickViewEx(appId, ENTRIES.testCSEFile.nameText); // Wait for the innerContentPanel to load and display its content. - // @ts-ignore: error TS7006: Parameter 'elements' implicitly has an 'any' - // type. - function checkInnerContentPanel(elements) { + function checkInnerContentPanel(elements: ElementObject[]) { const haveElements = Array.isArray(elements) && elements.length === 1; - if (!haveElements || elements[0].styles.display !== 'flex') { + if (!haveElements || elements[0]!.styles!['display'] !== 'flex') { return pending(caller, 'Waiting for inner content panel to load.'); } // Check: the preview should not be shown. - chrome.test.assertEq('No preview available', elements[0].innerText); + chrome.test.assertEq('No preview available', elements[0]!.innerText); return; } await repeatUntil(async () => { @@ -3968,4 +3513,4 @@ // Check: the correct file mimeType should be displayed. const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('Encrypted text/plain', mimeType); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/sort_columns.js b/ui/file_manager/integration_tests/file_manager/sort_columns.ts similarity index 72% rename from ui/file_manager/integration_tests/file_manager/sort_columns.js rename to ui/file_manager/integration_tests/file_manager/sort_columns.ts index d2bfd0cd..f4a4a81 100644 --- a/ui/file_manager/integration_tests/file_manager/sort_columns.js +++ b/ui/file_manager/integration_tests/file_manager/sort_columns.ts
@@ -3,16 +3,13 @@ // found in the LICENSE file. import {ENTRIES, RootPath, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {remoteCall, setupAndWaitUntilReady} from './background.js'; /** * Tests the order is sorted correctly for each of the columns. */ -// @ts-ignore: error TS4111: Property 'sortColumns' comes from an index -// signature, so it must be accessed with ['sortColumns']. -testcase.sortColumns = async () => { +export async function sortColumns() { const NAME_ASC = TestEntryInfo.getExpectedRows([ ENTRIES.photos, ENTRIES.beautiful, @@ -90,10 +87,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(1)']); await remoteCall.waitForElement(appId, iconSortedAsc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, NAME_ASC, {orderCheck: true}); // Fetch A11y messages. @@ -110,10 +103,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(1)']); await remoteCall.waitForElement(appId, iconSortedDesc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, NAME_DESC, {orderCheck: true}); // Fetch A11y messages. @@ -125,10 +114,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(2)']); await remoteCall.waitForElement(appId, iconSortedDesc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, SIZE_DESC, {orderCheck: true}); // Fetch A11y messages. @@ -145,10 +130,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(2)']); await remoteCall.waitForElement(appId, iconSortedAsc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, SIZE_ASC, {orderCheck: true}); // Fetch A11y messages. @@ -166,10 +147,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(3)']); await remoteCall.waitForElement(appId, iconSortedAsc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, TYPE_ASC, {orderCheck: true}); // Fetch A11y messages. @@ -181,10 +158,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(3)']); await remoteCall.waitForElement(appId, iconSortedDesc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, TYPE_DESC, {orderCheck: true}); // Fetch A11y messages. @@ -202,10 +175,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(4)']); await remoteCall.waitForElement(appId, iconSortedDesc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, DATE_DESC, {orderCheck: true}); // Fetch A11y messages. @@ -217,10 +186,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(4)']); await remoteCall.waitForElement(appId, iconSortedAsc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, DATE_ASC, {orderCheck: true}); // Fetch A11y messages. @@ -237,10 +202,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['#sort-menu-sort-by-name']); await remoteCall.waitForElement(appId, iconSortedAsc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, NAME_ASC, {orderCheck: true}); // Fetch A11y messages. @@ -252,10 +213,6 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['.table-header-cell:nth-of-type(1)']); await remoteCall.waitForElement(appId, iconSortedDesc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, NAME_DESC, {orderCheck: true}); // Fetch A11y messages. @@ -268,14 +225,10 @@ await remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['#sort-menu-sort-by-name']); await remoteCall.waitForElement(appId, iconSortedAsc); - // @ts-ignore: error TS2345: Argument of type '{ orderCheck: true; }' is not - // assignable to parameter of type '{ orderCheck: boolean | null | undefined; - // ignoreFileSize: boolean | null | undefined; ignoreLastModifiedTime: boolean - // | null | undefined; }'. await remoteCall.waitForFiles(appId, NAME_ASC, {orderCheck: true}); // Fetch A11y messages. a11yMessages = await remoteCall.callRemoteTestUtil('getA11yAnnounces', appId, []); chrome.test.assertEq(11, a11yMessages.length, 'Missing a11y message'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/tasks.js b/ui/file_manager/integration_tests/file_manager/tasks.ts similarity index 71% rename from ui/file_manager/integration_tests/file_manager/tasks.js rename to ui/file_manager/integration_tests/file_manager/tasks.ts index 403a2ae..8fb4aed 100644 --- a/ui/file_manager/integration_tests/file_manager/tasks.js +++ b/ui/file_manager/integration_tests/file_manager/tasks.ts
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import type {ElementObject} from '../prod/file_manager/shared_types.js'; import {getCaller, pending, repeatUntil, RootPath} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -11,9 +11,6 @@ /** * Fake tasks for a local volume opening in browser. - * - * @type {Array<FakeTask>} - * @const */ const DOWNLOADS_FAKE_TEXT = [ new FakeTask(true, { @@ -25,9 +22,6 @@ /** * Fake tasks for a PDF file opening in browser. - * - * @type {Array<FakeTask>} - * @const */ const DOWNLOADS_FAKE_PDF = [ new FakeTask(true, { @@ -39,9 +33,6 @@ /** * Fake tasks for a drive volume. - * - * @type {Array<FakeTask>} - * @const */ const DRIVE_FAKE_TASKS = [ new FakeTask( @@ -55,10 +46,10 @@ /** * Sets up task tests. * - * @param {string} rootPath Root path. - * @param {Array<FakeTask>} fakeTasks Fake tasks. + * @param rootPath Root path. + * @param fakeTasks Fake tasks. */ -async function setupTaskTest(rootPath, fakeTasks) { +async function setupTaskTest(rootPath: string, fakeTasks: FakeTask[]) { const appId = await setupAndWaitUntilReady(rootPath); await remoteCall.callRemoteTestUtil('overrideTasks', appId, [fakeTasks]); return appId; @@ -67,11 +58,11 @@ /** * Tests executing the default task when there is only one task. * - * @param {string} appId Window ID. - * @param {!FileTaskDescriptor} descriptor Task - * descriptor. + * @param appId Window ID. + * @param descriptor Task descriptor. */ -async function executeDefaultTask(appId, descriptor) { +async function executeDefaultTask( + appId: string, descriptor: FileTaskDescriptor) { // Select file. await remoteCall.waitUntilSelected(appId, 'hello.txt'); @@ -87,13 +78,13 @@ /** * Tests to specify default task via the default task dialog. * - * @param {string} appId Window ID. - * @param {!FileTaskDescriptor} descriptor Task - * descriptor of the task expected to be newly specified as default. - * @return {Promise<void>} Promise to be fulfilled/rejected depends on the test - * result. + * @param appId Window ID. + * @param descriptor Task descriptor of the task expected to be newly specified + * as default. + * @return Promise to be fulfilled/rejected depends on the test result. */ -async function defaultTaskDialog(appId, descriptor) { +async function defaultTaskDialog( + appId: string, descriptor: FileTaskDescriptor): Promise<void> { // Prepare expected labels. const expectedLabels = [ 'DummyTask1 (default)', @@ -115,15 +106,12 @@ // Wait for the list of menu item is added as expected. await repeatUntil(async () => { // Obtains menu items. - const items = await remoteCall.callRemoteTestUtil( + const items: ElementObject[] = await remoteCall.callRemoteTestUtil( 'queryAllElements', appId, ['#default-task-dialog #default-tasks-list li']); // Compare the contents of items. - // @ts-ignore: error TS7006: Parameter 'item' implicitly has an 'any' type. const actualLabels = items.map((item) => item.text); - // @ts-ignore: error TS2339: Property 'checkDeepEq' does not exist on type - // 'typeof test'. if (chrome.test.checkDeepEq(expectedLabels, actualLabels)) { return true; } @@ -169,63 +157,41 @@ await remoteCall.waitUntilTaskExecutes(appId, descriptor, ['hello.txt']); } -// @ts-ignore: error TS4111: Property 'executeDefaultTaskDrive' comes from an -// index signature, so it must be accessed with ['executeDefaultTaskDrive']. -testcase.executeDefaultTaskDrive = async () => { +export async function executeDefaultTaskDrive() { const appId = await setupTaskTest(RootPath.DRIVE, DRIVE_FAKE_TASKS); - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await executeDefaultTask(appId, DRIVE_FAKE_TASKS[0].descriptor); -}; + await executeDefaultTask(appId, DRIVE_FAKE_TASKS[0]!.descriptor); +} -// @ts-ignore: error TS4111: Property 'executeDefaultTaskDownloads' comes from -// an index signature, so it must be accessed with -// ['executeDefaultTaskDownloads']. -testcase.executeDefaultTaskDownloads = async () => { +export async function executeDefaultTaskDownloads() { const appId = await setupTaskTest(RootPath.DOWNLOADS, DOWNLOADS_FAKE_TASKS); - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await executeDefaultTask(appId, DOWNLOADS_FAKE_TASKS[0].descriptor); -}; + await executeDefaultTask(appId, DOWNLOADS_FAKE_TASKS[0]!.descriptor); +} -// @ts-ignore: error TS4111: Property 'defaultTaskForTextPlain' comes from an -// index signature, so it must be accessed with ['defaultTaskForTextPlain']. -testcase.defaultTaskForTextPlain = async () => { +export async function defaultTaskForTextPlain() { const appId = await setupTaskTest(RootPath.DOWNLOADS, DOWNLOADS_FAKE_TEXT); - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await executeDefaultTask(appId, DOWNLOADS_FAKE_TEXT[0].descriptor); -}; + await executeDefaultTask(appId, DOWNLOADS_FAKE_TEXT[0]!.descriptor); +} -// @ts-ignore: error TS4111: Property 'defaultTaskForPdf' comes from an index -// signature, so it must be accessed with ['defaultTaskForPdf']. -testcase.defaultTaskForPdf = async () => { +export async function defaultTaskForPdf() { const appId = await setupTaskTest(RootPath.DOWNLOADS, DOWNLOADS_FAKE_PDF); - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await executeDefaultTask(appId, DOWNLOADS_FAKE_PDF[0].descriptor); -}; + await executeDefaultTask(appId, DOWNLOADS_FAKE_PDF[0]!.descriptor); +} -// @ts-ignore: error TS4111: Property 'defaultTaskDialogDrive' comes from an -// index signature, so it must be accessed with ['defaultTaskDialogDrive']. -testcase.defaultTaskDialogDrive = async () => { +export async function defaultTaskDialogDrive() { const appId = await setupTaskTest(RootPath.DRIVE, DRIVE_FAKE_TASKS); - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await defaultTaskDialog(appId, DRIVE_FAKE_TASKS[1].descriptor); -}; + await defaultTaskDialog(appId, DRIVE_FAKE_TASKS[1]!.descriptor); +} -// @ts-ignore: error TS4111: Property 'defaultTaskDialogDownloads' comes from an -// index signature, so it must be accessed with ['defaultTaskDialogDownloads']. -testcase.defaultTaskDialogDownloads = async () => { +export async function defaultTaskDialogDownloads() { const appId = await setupTaskTest(RootPath.DOWNLOADS, DOWNLOADS_FAKE_TASKS); - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await defaultTaskDialog(appId, DOWNLOADS_FAKE_TASKS[1].descriptor); -}; + await defaultTaskDialog(appId, DOWNLOADS_FAKE_TASKS[1]!.descriptor); +} /** * Tests that the Change Default Task dialog has a scrollable list. */ -// @ts-ignore: error TS4111: Property 'changeDefaultDialogScrollList' comes from -// an index signature, so it must be accessed with -// ['changeDefaultDialogScrollList']. -testcase.changeDefaultDialogScrollList = async () => { +export async function changeDefaultDialogScrollList() { const tasks = [ new FakeTask( true, @@ -284,11 +250,9 @@ // Check: CSS class bottom-shadow should be removed. await remoteCall.waitForElementLost( appId, '#default-task-dialog.bottom-shadow'); -}; +} -// @ts-ignore: error TS4111: Property 'genericTaskIsNotExecuted' comes from an -// index signature, so it must be accessed with ['genericTaskIsNotExecuted']. -testcase.genericTaskIsNotExecuted = async () => { +export async function genericTaskIsNotExecuted() { const tasks = [new FakeTask( false, {appId: 'dummytaskid', taskType: 'fake-type', actionId: 'open-with'}, @@ -305,12 +269,9 @@ taskType: 'file', actionId: 'view-in-browser', }); -}; +} -// @ts-ignore: error TS4111: Property 'genericTaskAndNonGenericTask' comes from -// an index signature, so it must be accessed with -// ['genericTaskAndNonGenericTask']. -testcase.genericTaskAndNonGenericTask = async () => { +export async function genericTaskAndNonGenericTask() { const tasks = [ new FakeTask( false, @@ -327,14 +288,10 @@ ]; const appId = await setupTaskTest(RootPath.DOWNLOADS, tasks); - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await executeDefaultTask(appId, tasks[1].descriptor); -}; + await executeDefaultTask(appId, tasks[1]!.descriptor); +} -// @ts-ignore: error TS4111: Property 'noActionBarOpenForDirectories' comes from -// an index signature, so it must be accessed with -// ['noActionBarOpenForDirectories']. -testcase.noActionBarOpenForDirectories = async () => { +export async function noActionBarOpenForDirectories() { const fileTasks = [new FakeTask( true, {appId: 'dummytaskid', taskType: 'fake-type', actionId: 'open-with'}, @@ -379,11 +336,9 @@ chrome.test.assertEq('DirTask1 (default)', appOptions[0].text); chrome.test.assertEq('DirTask2', appOptions[1].text); chrome.test.assertEq('Change default…', appOptions[2].text); -}; +} -// @ts-ignore: error TS4111: Property 'executeViaDblClick' comes from an index -// signature, so it must be accessed with ['executeViaDblClick']. -testcase.executeViaDblClick = async () => { +export async function executeViaDblClick() { const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); await remoteCall.callRemoteTestUtil( 'overrideTasks', appId, [DOWNLOADS_FAKE_TASKS]); @@ -393,8 +348,7 @@ ['#file-list li[file-name="hello.txt"] .filename-label span'])); // Wait until the task is executed. - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - const descriptor = DOWNLOADS_FAKE_TASKS[0].descriptor; + const descriptor = DOWNLOADS_FAKE_TASKS[0]!.descriptor; await remoteCall.waitUntilTaskExecutes(appId, descriptor, ['hello.txt']); // Reset the overridden tasks. @@ -412,4 +366,4 @@ // Check the tasks again. await remoteCall.waitUntilTaskExecutes(appId, descriptor, ['world.ogv']); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/toolbar.js b/ui/file_manager/integration_tests/file_manager/toolbar.ts similarity index 72% rename from ui/file_manager/integration_tests/file_manager/toolbar.js rename to ui/file_manager/integration_tests/file_manager/toolbar.ts index f61cf8823..f63ba4c 100644 --- a/ui/file_manager/integration_tests/file_manager/toolbar.js +++ b/ui/file_manager/integration_tests/file_manager/toolbar.ts
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {addEntries, ENTRIES, getCaller, pending, repeatUntil, RootPath, sendTestMessage, TestEntryInfo} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {openNewWindow, remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -12,10 +11,7 @@ /** * Tests that the Delete menu item is disabled if no entry is selected. */ -// @ts-ignore: error TS4111: Property 'toolbarDeleteWithMenuItemNoEntrySelected' -// comes from an index signature, so it must be accessed with -// ['toolbarDeleteWithMenuItemNoEntrySelected']. -testcase.toolbarDeleteWithMenuItemNoEntrySelected = async () => { +export async function toolbarDeleteWithMenuItemNoEntrySelected() { const contextMenu = '#file-context-menu:not([hidden])'; const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -32,25 +28,18 @@ // Assert the menu delete command is disabled. const deleteDisabled = '[command="#delete"][disabled="disabled"]'; await remoteCall.waitForElement(appId, contextMenu + ' ' + deleteDisabled); -}; +} /** * Tests that the toolbar Delete button opens the delete confirm dialog and * that the dialog cancel button has the focus by default. */ -// @ts-ignore: error TS4111: Property -// 'toolbarDeleteButtonOpensDeleteConfirmDialog' comes from an index signature, -// so it must be accessed with ['toolbarDeleteButtonOpensDeleteConfirmDialog']. -testcase.toolbarDeleteButtonOpensDeleteConfirmDialog = async () => { +export async function toolbarDeleteButtonOpensDeleteConfirmDialog() { // Open Files app. const appId = - // @ts-ignore: error TS4111: Property 'desktop' comes from an index - // signature, so it must be accessed with ['desktop']. await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.desktop]); // Select My Desktop Background.png - // @ts-ignore: error TS4111: Property 'desktop' comes from an index signature, - // so it must be accessed with ['desktop']. await remoteCall.waitUntilSelected(appId, ENTRIES.desktop.nameText); // Click the toolbar Delete button. @@ -63,16 +52,13 @@ const defaultDialogButton = await remoteCall.waitForElement(appId, '.cr-dialog-cancel:focus'); chrome.test.assertEq('Cancel', defaultDialogButton.text); -}; +} /** * Tests that the toolbar Delete button keeps focus after the delete confirm * dialog is closed. */ -// @ts-ignore: error TS4111: Property 'toolbarDeleteButtonKeepFocus' comes from -// an index signature, so it must be accessed with -// ['toolbarDeleteButtonKeepFocus']. -testcase.toolbarDeleteButtonKeepFocus = async () => { +export async function toolbarDeleteButtonKeepFocus() { // Open Files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); @@ -112,14 +98,12 @@ // Check: the toolbar Delete button should be focused. await remoteCall.waitForElement(appId, '#delete-button:focus'); -}; +} /** * Tests deleting an entry using the toolbar. */ -// @ts-ignore: error TS4111: Property 'toolbarDeleteEntry' comes from an index -// signature, so it must be accessed with ['toolbarDeleteEntry']. -testcase.toolbarDeleteEntry = async () => { +export async function toolbarDeleteEntry() { const beforeDeletion = TestEntryInfo.getExpectedRows([ ENTRIES.photos, ENTRIES.hello, @@ -140,10 +124,6 @@ // Confirm entries in the directory before the deletion. await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, beforeDeletion, {ignoreLastModifiedTime: true}); // Select My Desktop Background.png @@ -155,12 +135,8 @@ // Confirm the file is removed. await remoteCall.waitForFiles( - // @ts-ignore: error TS2345: Argument of type '{ ignoreLastModifiedTime: - // true; }' is not assignable to parameter of type '{ orderCheck: boolean - // | null | undefined; ignoreFileSize: boolean | null | undefined; - // ignoreLastModifiedTime: boolean | null | undefined; }'. appId, afterDeletion, {ignoreLastModifiedTime: true}); -}; +} /** * Tests that refresh button hides in selection mode. @@ -170,10 +146,7 @@ * button should be hidden when entering the selection mode. * crbug.com/978383 */ -// @ts-ignore: error TS4111: Property 'toolbarRefreshButtonWithSelection' comes -// from an index signature, so it must be accessed with -// ['toolbarRefreshButtonWithSelection']. -testcase.toolbarRefreshButtonWithSelection = async () => { +export async function toolbarRefreshButtonWithSelection() { // Open files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -190,26 +163,19 @@ await remoteCall.waitForElement(appId, '#refresh-button:not([hidden])'); // Ctrl+A to enter selection mode. - const ctrlA = ['#file-list', 'a', true, false, false]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. + const ctrlA = ['#file-list', 'a', true, false, false] as const; await remoteCall.fakeKeyDown(appId, ...ctrlA); // Check that the button should be hidden. await remoteCall.waitForElement(appId, '#refresh-button[hidden]'); -}; +} /** * Tests that refresh button is not shown when the Recent view is selected. */ -// @ts-ignore: error TS4111: Property 'toolbarRefreshButtonHiddenInRecents' -// comes from an index signature, so it must be accessed with -// ['toolbarRefreshButtonHiddenInRecents']. -testcase.toolbarRefreshButtonHiddenInRecents = async () => { +export async function toolbarRefreshButtonHiddenInRecents() { // Open files app. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Navigate to Recent. @@ -219,16 +185,12 @@ // Check that the button should be hidden. await remoteCall.waitForElement(appId, '#refresh-button[hidden]'); -}; +} /** * Tests that refresh button is shown for non-watchable volumes. */ -// @ts-ignore: error TS4111: Property -// 'toolbarRefreshButtonShownForNonWatchableVolume' comes from an index -// signature, so it must be accessed with -// ['toolbarRefreshButtonShownForNonWatchableVolume']. -testcase.toolbarRefreshButtonShownForNonWatchableVolume = async () => { +export async function toolbarRefreshButtonShownForNonWatchableVolume() { // Open files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -243,19 +205,14 @@ // Check that refresh button is visible. await remoteCall.waitForElement(appId, '#refresh-button:not([hidden])'); -}; +} /** * Tests that refresh button is hidden for watchable volumes. */ -// @ts-ignore: error TS4111: Property -// 'toolbarRefreshButtonHiddenForWatchableVolume' comes from an index signature, -// so it must be accessed with ['toolbarRefreshButtonHiddenForWatchableVolume']. -testcase.toolbarRefreshButtonHiddenForWatchableVolume = async () => { +export async function toolbarRefreshButtonHiddenForWatchableVolume() { // Open Files app on local Downloads. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // It should start in Downloads. @@ -264,24 +221,18 @@ // Check that the button should be hidden. await remoteCall.waitForElement(appId, '#refresh-button[hidden]'); -}; +} /** * Tests that command Alt+A focus the toolbar. */ -// @ts-ignore: error TS4111: Property 'toolbarAltACommand' comes from an index -// signature, so it must be accessed with ['toolbarAltACommand']. -testcase.toolbarAltACommand = async () => { +export async function toolbarAltACommand() { // Open files app. const appId = - // @ts-ignore: error TS4111: Property 'beautiful' comes from an index - // signature, so it must be accessed with ['beautiful']. await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); // Press Alt+A in the File List. - const altA = ['#file-list', 'a', false, false, true]; - // @ts-ignore: error TS2556: A spread argument must either have a tuple type - // or be passed to a rest parameter. + const altA = ['#file-list', 'a', false, false, true] as const; await remoteCall.fakeKeyDown(appId, ...altA); // Check that a menu-button should be focused. @@ -289,16 +240,13 @@ await remoteCall.callRemoteTestUtil('getActiveElement', appId, []); const cssClasses = focusedElement.attributes['class'] || ''; chrome.test.assertTrue(cssClasses.includes('menu-button')); -}; +} /** * Tests that the menu drop down follows the button if the button moves. This * happens when the search box is expanded and then collapsed. */ -// @ts-ignore: error TS4111: Property 'toolbarMultiMenuFollowsButton' comes from -// an index signature, so it must be accessed with -// ['toolbarMultiMenuFollowsButton']. -testcase.toolbarMultiMenuFollowsButton = async () => { +export async function toolbarMultiMenuFollowsButton() { const entry = ENTRIES.hello; // Open Files app on Downloads. @@ -325,29 +273,27 @@ // Check that the dropdown menu and "Open" button are aligned. const caller = getCaller(); - // @ts-ignore: error TS7030: Not all code paths return a value. await repeatUntil(async () => { const openButton = await remoteCall.waitForElementStyles(appId, '#tasks', ['width']); const menu = await remoteCall.waitForElementStyles(appId, '#tasks-menu', ['width']); - if (openButton.renderedLeft !== menu.renderedLeft) { - return pending( - caller, - `Waiting for the menu and button to be aligned: ` + - `${openButton.renderedLeft} !== ${menu.renderedLeft}`); + if (openButton.renderedLeft === menu.renderedLeft) { + return; } + + return pending( + caller, + `Waiting for the menu and button to be aligned: ` + + `${openButton.renderedLeft} !== ${menu.renderedLeft}`); }); -}; +} /** * Tests that the sharesheet button is enabled and executable. */ -// @ts-ignore: error TS4111: Property 'toolbarSharesheetButtonWithSelection' -// comes from an index signature, so it must be accessed with -// ['toolbarSharesheetButtonWithSelection']. -testcase.toolbarSharesheetButtonWithSelection = async () => { +export async function toolbarSharesheetButtonWithSelection() { const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); // Fake chrome.fileManagerPrivate.sharesheetHasTargets to return true. @@ -358,18 +304,13 @@ // Fake chrome.fileManagerPrivate.invokeSharesheet. fakeData = { - // @ts-ignore: error TS2353: Object literal may only specify known - // properties, and ''chrome.fileManagerPrivate.invokeSharesheet'' does not - // exist in type '{ 'chrome.fileManagerPrivate.sharesheetHasTargets': - // (string | boolean[])[]; }'. 'chrome.fileManagerPrivate.invokeSharesheet': ['static_fake', []], - }; + } as any; await remoteCall.callRemoteTestUtil('foregroundFake', appId, [fakeData]); const entry = ENTRIES.hello; // Select an entry in the file list. - // @ts-ignore: error TS18048: 'entry' is possibly 'undefined'. await remoteCall.waitUntilSelected(appId, entry.nameText); await remoteCall.waitAndClickElement( @@ -385,15 +326,12 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(2, removedCount); -}; +} /** * Tests that the sharesheet command in context menu is enabled and executable. */ -// @ts-ignore: error TS4111: Property -// 'toolbarSharesheetContextMenuWithSelection' comes from an index signature, so -// it must be accessed with ['toolbarSharesheetContextMenuWithSelection']. -testcase.toolbarSharesheetContextMenuWithSelection = async () => { +export async function toolbarSharesheetContextMenuWithSelection() { const contextMenu = '#file-context-menu:not([hidden])'; const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -406,12 +344,8 @@ // Fake chrome.fileManagerPrivate.invokeSharesheet. fakeData = { - // @ts-ignore: error TS2353: Object literal may only specify known - // properties, and ''chrome.fileManagerPrivate.invokeSharesheet'' does not - // exist in type '{ 'chrome.fileManagerPrivate.sharesheetHasTargets': - // (string | boolean[])[]; }'. 'chrome.fileManagerPrivate.invokeSharesheet': ['static_fake', []], - }; + } as any; await remoteCall.callRemoteTestUtil('foregroundFake', appId, [fakeData]); const entry = ENTRIES.hello; @@ -442,15 +376,12 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(2, removedCount); -}; +} /** * Tests that the sharesheet item is hidden if no entry is selected. */ -// @ts-ignore: error TS4111: Property 'toolbarSharesheetNoEntrySelected' comes -// from an index signature, so it must be accessed with -// ['toolbarSharesheetNoEntrySelected']. -testcase.toolbarSharesheetNoEntrySelected = async () => { +export async function toolbarSharesheetNoEntrySelected() { const contextMenu = '#file-context-menu:not([hidden])'; const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS); @@ -463,8 +394,6 @@ // Right click the list without selecting an entry. chrome.test.assertTrue( - // @ts-ignore: error TS1345: An expression of type 'void' cannot be tested - // for truthiness. !!await remoteCall.waitAndRightClick(appId, 'list.list')); // Wait until the context menu is shown. @@ -482,48 +411,36 @@ const removedCount = await remoteCall.callRemoteTestUtil( 'removeAllForegroundFakes', appId, []); chrome.test.assertEq(1, removedCount); -}; +} /** * Tests that the cloud icon does not appear if bulk pinning is disabled. */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconShouldNotShowWhenBulkPinningDisabled' comes from an index -// signature, so it must be accessed with -// ['toolbarCloudIconShouldNotShowWhenBulkPinningDisabled']. -testcase.toolbarCloudIconShouldNotShowWhenBulkPinningDisabled = async () => { +export async function toolbarCloudIconShouldNotShowWhenBulkPinningDisabled() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); -}; +} /** * Tests that the cloud icon does not appear if the bulk pinning preference is * disabled and the supplied Stage does not have a UI state in the progress * panel. */ -testcase - // @ts-ignore: error TS4111: Property - // 'toolbarCloudIconShouldNotShowIfPreferenceDisabledAndNoUIStateAvailable' - // comes from an index signature, so it must be accessed with - // ['toolbarCloudIconShouldNotShowIfPreferenceDisabledAndNoUIStateAvailable']. - .toolbarCloudIconShouldNotShowIfPreferenceDisabledAndNoUIStateAvailable = - async () => { +export async function +toolbarCloudIconShouldNotShowIfPreferenceDisabledAndNoUIStateAvailable() { await sendTestMessage({name: 'setBulkPinningEnabledPref', enabled: false}); const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); -}; +} /** * Tests that the cloud icon should only show when the bulk pinning is in * progress. */ -// @ts-ignore: error TS4111: Property 'toolbarCloudIconShouldShowForInProgress' -// comes from an index signature, so it must be accessed with -// ['toolbarCloudIconShouldShowForInProgress']. -testcase.toolbarCloudIconShouldShowForInProgress = async () => { +export async function toolbarCloudIconShouldShowForInProgress() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); @@ -539,17 +456,13 @@ await remoteCall.waitForElementLost(appId, '#cloud-button[hidden]'); await remoteCall.waitForElement( appId, '#cloud-button > xf-icon[type="cloud_sync"]'); -}; +} /** * Tests that the cloud icon should show when there is not enough disk space * available to pin. */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconShowsWhenNotEnoughDiskSpaceIsReturned' comes from an index -// signature, so it must be accessed with -// ['toolbarCloudIconShowsWhenNotEnoughDiskSpaceIsReturned']. -testcase.toolbarCloudIconShowsWhenNotEnoughDiskSpaceIsReturned = async () => { +export async function toolbarCloudIconShowsWhenNotEnoughDiskSpaceIsReturned() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); @@ -564,18 +477,14 @@ await remoteCall.waitForElementLost(appId, '#cloud-button[hidden]'); await remoteCall.waitForElement( appId, '#cloud-button > xf-icon[type="cloud_error"]'); -}; +} /** * Tests that the cloud icon should not show if an error state has been * returned (in this case `CannotGetFreeSpace`). */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconShouldNotShowWhenCannotGetFreeSpace' comes from an index -// signature, so it must be accessed with -// ['toolbarCloudIconShouldNotShowWhenCannotGetFreeSpace']. -testcase.toolbarCloudIconShouldNotShowWhenCannotGetFreeSpace = async () => { +export async function toolbarCloudIconShouldNotShowWhenCannotGetFreeSpace() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); @@ -595,17 +504,13 @@ // currently is done on a 60s poll). await sendTestMessage({name: 'forcePinningManagerSpaceCheck'}); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); -}; +} /** * Tests that when the cloud icon is pressed the xf-cloud-panel moves into space * and resizes correctly. */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconWhenPressedShouldOpenCloudPanel' comes from an index -// signature, so it must be accessed with -// ['toolbarCloudIconWhenPressedShouldOpenCloudPanel']. -testcase.toolbarCloudIconWhenPressedShouldOpenCloudPanel = async () => { +export async function toolbarCloudIconWhenPressedShouldOpenCloudPanel() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); @@ -629,17 +534,13 @@ // Click the cloud icon and wait for the dialog to move into space. await remoteCall.waitAndClickElement(appId, '#cloud-button:not([hidden])'); await remoteCall.waitForCloudPanelVisible(appId); -}; +} /** * Tests that the cloud icon should not show if bulk pinning is paused (which * represents an offline state) and the user preference is disabled. */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconShouldNotShowWhenPrefDisabled' comes from an index -// signature, so it must be accessed with -// ['toolbarCloudIconShouldNotShowWhenPrefDisabled']. -testcase.toolbarCloudIconShouldNotShowWhenPrefDisabled = async () => { +export async function toolbarCloudIconShouldNotShowWhenPrefDisabled() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], BASIC_DRIVE_ENTRY_SET); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); @@ -664,16 +565,13 @@ // Assert the stage is `PAUSED` and the cloud button is still hidden. await remoteCall.waitForBulkPinningStage('PausedOffline'); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); -}; +} /** * Tests that the cloud icon should show if bulk pinning is paused (which * represents an offline state) and the user preference is enabled. */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconShouldShowWhenPausedState' comes from an index signature, so -// it must be accessed with ['toolbarCloudIconShouldShowWhenPausedState']. -testcase.toolbarCloudIconShouldShowWhenPausedState = async () => { +export async function toolbarCloudIconShouldShowWhenPausedState() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], BASIC_DRIVE_ENTRY_SET); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); @@ -693,18 +591,14 @@ await remoteCall.waitForElement(appId, '#cloud-button:not([hidden])'); await remoteCall.waitForElement( appId, '#cloud-button > xf-icon[type="bulk_pinning_offline"]'); -}; +} /** * Tests that the cloud icon should show when a Files app window has started. * This mainly tests that on startup the bulk pin progress is fetched and * doesn't require an async event to show. */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconShouldShowOnStartupEvenIfSyncing' comes from an index -// signature, so it must be accessed with -// ['toolbarCloudIconShouldShowOnStartupEvenIfSyncing']. -testcase.toolbarCloudIconShouldShowOnStartupEvenIfSyncing = async () => { +export async function toolbarCloudIconShouldShowOnStartupEvenIfSyncing() { await addEntries(['drive'], [ENTRIES.hello]); // Mock the free space returned by spaced to be 4 GB. @@ -733,8 +627,6 @@ // Open a new window to the Drive root and ensure the cloud button is not // hidden. The cloud button will show on startup as it relies on the bulk // pinning preference to be set. - // @ts-ignore: error TS2345: Argument of type '{}' is not assignable to - // parameter of type 'FilesAppState'. const appId = await openNewWindow(RootPath.DRIVE, /*appState=*/ {}); await remoteCall.waitForElement(appId, '#detail-table'); await remoteCall.waitForElement(appId, '#cloud-button:not([hidden])'); @@ -746,17 +638,13 @@ // to ensure its done prior to the 60s free disk space check. await remoteCall.waitForCloudPanelState( appId, /*items=*/ 1, /*percentage=*/ 100); -}; +} /** * Tests that the cloud icon should show if bulk pinning is paused due to being * on a metered network. */ -// @ts-ignore: error TS4111: Property -// 'toolbarCloudIconShouldShowWhenOnMeteredNetwork' comes from an index -// signature, so it must be accessed with -// ['toolbarCloudIconShouldShowWhenOnMeteredNetwork']. -testcase.toolbarCloudIconShouldShowWhenOnMeteredNetwork = async () => { +export async function toolbarCloudIconShouldShowWhenOnMeteredNetwork() { const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.hello]); await remoteCall.waitForElement(appId, '#cloud-button[hidden]'); @@ -774,4 +662,4 @@ await remoteCall.waitForElement(appId, '#cloud-button:not([hidden])'); await remoteCall.waitForElement( appId, '#cloud-button > xf-icon[type="cloud_paused"]'); -}; +}
diff --git a/ui/file_manager/integration_tests/file_manager/zip_files.js b/ui/file_manager/integration_tests/file_manager/zip_files.ts similarity index 85% rename from ui/file_manager/integration_tests/file_manager/zip_files.js rename to ui/file_manager/integration_tests/file_manager/zip_files.ts index 2deb18b..c35a137 100644 --- a/ui/file_manager/integration_tests/file_manager/zip_files.js +++ b/ui/file_manager/integration_tests/file_manager/zip_files.ts
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {addEntries, ENTRIES, expectHistogramTotalCount, getCaller, pending, repeatUntil, RootPath, sendTestMessage} from '../test_util.js'; -import {testcase} from '../testcase.js'; import {remoteCall, setupAndWaitUntilReady} from './background.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; @@ -39,9 +38,7 @@ /** * Tests ZIP mounting from Downloads. */ -// @ts-ignore: error TS4111: Property 'zipFileOpenDownloads' comes from an index -// signature, so it must be accessed with ['zipFileOpenDownloads']. -testcase.zipFileOpenDownloads = async () => { +export async function zipFileOpenDownloads() { await sendTestMessage({ name: 'expectFileTask', fileNames: [ENTRIES.zipArchive.targetPath], @@ -64,14 +61,12 @@ // Check: the zip file content should be shown (unzip). const files = getUnzippedFileListRowEntries(); await remoteCall.waitForFiles(appId, files, {'ignoreLastModifiedTime': true}); -}; +} /** * Tests that Files app's ZIP mounting notifies FileTasks when mounted. */ -// @ts-ignore: error TS4111: Property 'zipNotifyFileTasks' comes from an index -// signature, so it must be accessed with ['zipNotifyFileTasks']. -testcase.zipNotifyFileTasks = async () => { +export async function zipNotifyFileTasks() { await sendTestMessage({ name: 'expectFileTask', fileNames: [ENTRIES.zipArchive.targetPath], @@ -89,14 +84,12 @@ // Wait for the zip archive to mount. await remoteCall.waitForElement(appId, `[scan-completed="archive.zip"]`); -}; +} /** * Tests ZIP mounting from Google Drive. */ -// @ts-ignore: error TS4111: Property 'zipFileOpenDrive' comes from an index -// signature, so it must be accessed with ['zipFileOpenDrive']. -testcase.zipFileOpenDrive = async () => { +export async function zipFileOpenDrive() { await sendTestMessage({ name: 'expectFileTask', fileNames: [ENTRIES.zipArchive.targetPath], @@ -119,14 +112,12 @@ // Check: the zip file content should be shown (unzip). const files = getUnzippedFileListRowEntries(); await remoteCall.waitForFiles(appId, files, {'ignoreLastModifiedTime': true}); -}; +} /** * Tests ZIP mounting from a removable USB volume. */ -// @ts-ignore: error TS4111: Property 'zipFileOpenUsb' comes from an index -// signature, so it must be accessed with ['zipFileOpenUsb']. -testcase.zipFileOpenUsb = async () => { +export async function zipFileOpenUsb() { await sendTestMessage({ name: 'expectFileTask', fileNames: [ENTRIES.zipArchive.targetPath], @@ -163,7 +154,7 @@ // Check: the zip file content should be shown (unzip). const files = getUnzippedFileListRowEntries(); await remoteCall.waitForFiles(appId, files, {'ignoreLastModifiedTime': true}); -}; +} /** * Returns the expected file list rows after invoking the 'Zip selection' menu @@ -179,9 +170,7 @@ /** * Tests creating a ZIP file on Downloads. */ -// @ts-ignore: error TS4111: Property 'zipCreateFileDownloads' comes from an -// index signature, so it must be accessed with ['zipCreateFileDownloads']. -testcase.zipCreateFileDownloads = async () => { +export async function zipCreateFileDownloads() { // Open Files app on Downloads containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); @@ -210,14 +199,12 @@ // Check: a zip time histogram value should have been recorded. await expectHistogramTotalCount(ZipCreationTimeHistogramName, 1); -}; +} /** * Tests creating a ZIP file on Drive. */ -// @ts-ignore: error TS4111: Property 'zipCreateFileDrive' comes from an index -// signature, so it must be accessed with ['zipCreateFileDrive']. -testcase.zipCreateFileDrive = async () => { +export async function zipCreateFileDrive() { // Open Files app on Drive containing ENTRIES.photos. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.photos]); @@ -246,14 +233,12 @@ // Check: a zip time histogram value should have been recorded. await expectHistogramTotalCount(ZipCreationTimeHistogramName, 1); -}; +} /** * Tests creating a ZIP file containing an Office file on Drive. */ -// @ts-ignore: error TS4111: Property 'zipCreateFileDriveOffice' comes from an -// index signature, so it must be accessed with ['zipCreateFileDriveOffice']. -testcase.zipCreateFileDriveOffice = async () => { +export async function zipCreateFileDriveOffice() { // Open Files app on Drive containing ENTRIES.photos and ENTRIES.docxFile. const appId = await setupAndWaitUntilReady( RootPath.DRIVE, [], [ENTRIES.photos, ENTRIES.docxFile]); @@ -286,15 +271,12 @@ // Check: a zip time histogram value should have been recorded. await expectHistogramTotalCount(ZipCreationTimeHistogramName, 1); -}; +} /** * Tests that creating a ZIP file containing an encrypted file is disabled. */ -// @ts-ignore: error TS4111: Property 'zipDoesntCreateFileEncrypted' comes from -// an index signature, so it must be accessed with -// ['zipDoesntCreateFileEncrypted']. -testcase.zipDoesntCreateFileEncrypted = async () => { +export async function zipDoesntCreateFileEncrypted() { // Open Files app on Drive containing a test CSE file. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.testCSEFile]); @@ -316,17 +298,13 @@ const element = await remoteCall.waitForElement(appId, '[command="#zip-selection"]'); - // @ts-ignore: error TS4111: Property 'disabled' comes from an index - // signature, so it must be accessed with ['disabled']. - chrome.test.assertEq('disabled', element.attributes.disabled); -}; + chrome.test.assertEq('disabled', element.attributes['disabled']); +} /** * Tests creating a ZIP file on a removable USB volume. */ -// @ts-ignore: error TS4111: Property 'zipCreateFileUsb' comes from an index -// signature, so it must be accessed with ['zipCreateFileUsb']. -testcase.zipCreateFileUsb = async () => { +export async function zipCreateFileUsb() { // Open Files app on Drive. const appId = await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.beautiful]); @@ -369,14 +347,12 @@ // Check: a zip time histogram value should have been recorded. await expectHistogramTotalCount(ZipCreationTimeHistogramName, 1); -}; +} /** * Tests that extraction of a ZIP archive produces a feedback panel. */ -// @ts-ignore: error TS4111: Property 'zipExtractShowPanel' comes from an index -// signature, so it must be accessed with ['zipExtractShowPanel']. -testcase.zipExtractShowPanel = async () => { +export async function zipExtractShowPanel() { const entry = ENTRIES.zipArchive; const targetDirectoryName = entry.nameText.split('.')[0]; @@ -391,7 +367,6 @@ const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [entry], []); // Select the file. - // @ts-ignore: error TS18048: 'entry' is possibly 'undefined'. await remoteCall.waitUntilSelected(appId, entry.nameText); // Right-click the selected file. @@ -414,14 +389,11 @@ 'fakeMouseClick failed'); // Check that the error appears in the feedback panel. - let element = {}; const caller = getCaller(); await repeatUntil(async () => { - element = await remoteCall.waitForElement( + const element = await remoteCall.waitForElement( appId, ['#progress-panel', 'xf-panel-item']); const expectedMsg = `Extracting ${entry.nameText} to Downloads`; - // @ts-ignore: error TS2339: Property 'attributes' does not exist on type - // '{}'. const actualMsg = element.attributes['primary-text']; if (actualMsg === expectedMsg) { @@ -435,29 +407,25 @@ // Check: a extract archive status histogram value should have been recorded. await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); -}; +} /** * Tests that extraction of a multiple ZIP archives produces the correct * feedback panel string. */ -// @ts-ignore: error TS4111: Property 'zipExtractShowMultiPanel' comes from an -// index signature, so it must be accessed with ['zipExtractShowMultiPanel']. -testcase.zipExtractShowMultiPanel = async () => { +export async function zipExtractShowMultiPanel() { const entries = COMPLEX_ZIP_ENTRY_SET; // Make sure the test extension handles the new window creation(s) properly. - let entry = entries[2]; // ENTRIES.zipArchive. - // @ts-ignore: error TS18048: 'entry' is possibly 'undefined'. - let targetDirectoryName = entry.nameText.split('.')[0]; + let entry = entries[2]!; // ENTRIES.zipArchive. + let targetDirectoryName = entry.nameText.split('.')[0]!; await sendTestMessage({ name: 'expectFileTask', fileNames: [targetDirectoryName], openType: 'launch', }); - entry = entries[3]; // ENTRIES.zipSJISArchive. - // @ts-ignore: error TS18048: 'entry' is possibly 'undefined'. - targetDirectoryName = entry.nameText.split('.')[0]; + entry = entries[3]!; // ENTRIES.zipSJISArchive. + targetDirectoryName = entry.nameText.split('.')[0]!; await sendTestMessage({ name: 'expectFileTask', fileNames: [targetDirectoryName], @@ -493,14 +461,11 @@ 'fakeMouseClick failed'); // Check that the error appears in the feedback panel. - let element = {}; const caller = getCaller(); await repeatUntil(async () => { - element = await remoteCall.waitForElement( + const element = await remoteCall.waitForElement( appId, ['#progress-panel', 'xf-panel-item']); const expectedMsg = `Extracting 2 items…`; - // @ts-ignore: error TS2339: Property 'attributes' does not exist on type - // '{}'. const actualMsg = element.attributes['primary-text']; if (actualMsg === expectedMsg) { @@ -514,22 +479,19 @@ // Check: a extract archive status histogram value should have been recorded. await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); -}; +} /** * Tests that various selections enable/hide the correct menu items. */ -// @ts-ignore: error TS4111: Property 'zipExtractSelectionMenus' comes from an -// index signature, so it must be accessed with ['zipExtractSelectionMenus']. -testcase.zipExtractSelectionMenus = async () => { +export async function zipExtractSelectionMenus() { const entries = BASIC_ZIP_ENTRY_SET; // Open files app. const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, entries, []); // Select the first file (ENTRIES.hello). - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await remoteCall.waitUntilSelected(appId, entries[0].nameText); + await remoteCall.waitUntilSelected(appId, entries[0]!.nameText); // Right-click the selected file. chrome.test.assertTrue( @@ -554,8 +516,7 @@ 'fakeMouseClick failed'); // Select the third file (ENTRIES.zipArchive). - // @ts-ignore: error TS2532: Object is possibly 'undefined'. - await remoteCall.waitUntilSelected(appId, entries[2].nameText); + await remoteCall.waitUntilSelected(appId, entries[2]!.nameText); // Right-click the selected file. chrome.test.assertTrue( @@ -629,14 +590,12 @@ // Check: the Zip selection menu item should be visible. await remoteCall.waitForElement( appId, '[command="#zip-selection"]:not([hidden])'); -}; +} /** * Tests that extraction of a ZIP archive generates correct output files. */ -// @ts-ignore: error TS4111: Property 'zipExtractCheckContent' comes from an -// index signature, so it must be accessed with ['zipExtractCheckContent']. -testcase.zipExtractCheckContent = async () => { +export async function zipExtractCheckContent() { const entry = ENTRIES.zipArchive; const targetDirectoryName = entry.nameText.split('.')[0]; @@ -685,14 +644,12 @@ // Check: a extract archive status histogram value should have been recorded. await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); -}; +} /** * Tests that repeated extraction of a ZIP archive generates extra directories. */ -// @ts-ignore: error TS4111: Property 'zipExtractCheckDuplicates' comes from an -// index signature, so it must be accessed with ['zipExtractCheckDuplicates']. -testcase.zipExtractCheckDuplicates = async () => { +export async function zipExtractCheckDuplicates() { const entry = ENTRIES.zipArchive; const directory = entry.nameText.split('.')[0]; @@ -760,14 +717,12 @@ // Check: 2 extract archive status histogram value should have been recorded. await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 2); -}; +} /** * Tests extraction of a ZIP archive can detect and unpack filename encodings. */ -// @ts-ignore: error TS4111: Property 'zipExtractCheckEncodings' comes from an -// index signature, so it must be accessed with ['zipExtractCheckEncodings']. -testcase.zipExtractCheckEncodings = async () => { +export async function zipExtractCheckEncodings() { const entry = ENTRIES.zipSJISArchive; const targetDirectoryName = entry.nameText.split('.')[0]; @@ -815,14 +770,12 @@ // Check: a extract archive status histogram value should have been recorded. await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); -}; +} /** * Tests extract option menu item has proper a11y labels. */ -// @ts-ignore: error TS4111: Property 'zipExtractA11y' comes from an index -// signature, so it must be accessed with ['zipExtractA11y']. -testcase.zipExtractA11y = async () => { +export async function zipExtractA11y() { const entry = ENTRIES.zipArchive; // Open files app. @@ -844,14 +797,12 @@ // NB: It's sufficient to check the ARIA role attribute is set correctly. await remoteCall.waitForElement( appId, '[command="#extract-all"][role="menuitem"]'); -}; +} /** * Tests extraction of a ZIP archive fails if there's not enough disk space. */ -// @ts-ignore: error TS4111: Property 'zipExtractNotEnoughSpace' comes from an -// index signature, so it must be accessed with ['zipExtractNotEnoughSpace']. -testcase.zipExtractNotEnoughSpace = async () => { +export async function zipExtractNotEnoughSpace() { const entry = ENTRIES.zipExtArchive; // 120TB fake archive. // Open files app. @@ -876,14 +827,11 @@ 'fakeMouseClick failed'); // Check: Error panel appears. - let element = {}; const caller = getCaller(); await repeatUntil(async () => { - element = await remoteCall.waitForElement( + const element = await remoteCall.waitForElement( appId, ['#progress-panel', 'xf-panel-item']); const expectedMsg = 'Extract operation failed. There is not enough space.'; - // @ts-ignore: error TS2339: Property 'attributes' does not exist on type - // '{}'. const actualMsg = element.attributes['primary-text']; if (actualMsg === expectedMsg) { @@ -897,14 +845,12 @@ // Check: a extract archive status histogram value should have been recorded. await expectHistogramTotalCount(ExtractArchiveStatusHistogramName, 1); -}; +} /** * Tests that extraction of a ZIP archive from a read only volume succeeds. */ -// @ts-ignore: error TS4111: Property 'zipExtractFromReadOnly' comes from an -// index signature, so it must be accessed with ['zipExtractFromReadOnly']. -testcase.zipExtractFromReadOnly = async () => { +export async function zipExtractFromReadOnly() { const entry = ENTRIES.readOnlyZipFile; const targetDirectoryName = entry.nameText.split('.')[0]; @@ -966,4 +912,4 @@ await remoteCall.waitForElement(appId, '#file-list [file-name="folder"]'); await remoteCall.waitForElement(appId, '#file-list [file-name="text.txt"]'); await remoteCall.waitForElement(appId, '#file-list [file-name="image.png"]'); -}; +}
diff --git a/ui/file_manager/integration_tests/remote_call.js b/ui/file_manager/integration_tests/remote_call.js index 3cd222a8..1d4bfacd 100644 --- a/ui/file_manager/integration_tests/remote_call.js +++ b/ui/file_manager/integration_tests/remote_call.js
@@ -268,8 +268,8 @@ * * @param {string} funcName Name of remote test function to be executed. * @param {?string} appId App window Id. - * @param {function(Object):boolean|boolean|Object} expectedResult An value to - * be checked against the return value of |funcName| or a callback that + * @param {(function(Object):boolean)|boolean|Object} expectedResult An value + * to be checked against the return value of |funcName| or a callback that * receives the return value of |funcName| and returns true if the result * is the expected value. * @param {?Array<*>=} args Arguments to be provided to |funcName| when
diff --git a/ui/file_manager/integration_tests/testcase.ts b/ui/file_manager/integration_tests/testcase.ts index a41e92e..351c4f1f 100644 --- a/ui/file_manager/integration_tests/testcase.ts +++ b/ui/file_manager/integration_tests/testcase.ts
@@ -4,9 +4,9 @@ import * as androidPhotosTests from './file_manager/android_photos.js'; // clang-format off -// import * as breadcrumbsTests from './file_manager/breadcrumbs.js'; +import * as breadcrumbsTests from './file_manager/breadcrumbs.js'; // import * as contextMenuTests from './file_manager/context_menu.js'; -// import * as copyBetweenWindowsTests from './file_manager/copy_between_windows.js'; +import * as copyBetweenWindowsTests from './file_manager/copy_between_windows.js'; // import * as createNewFolderTests from './file_manager/create_new_folder.js'; // import * as crostiniTests from './file_manager/crostini.js'; import * as directoryTreeTests from './file_manager/directory_tree.js'; @@ -15,43 +15,43 @@ // import * as dlpEnterpriseConnectorsTests from './file_manager/dlp_enterprise_connectors.js'; // import * as driveSpecificTests from './file_manager/drive_specific.js'; // import * as fileDialogTests from './file_manager/file_dialog.js'; -// import * as fileDisplayTests from './file_manager/file_display.js'; -// import * as fileListTests from './file_manager/file_list.js'; +import * as fileDisplayTests from './file_manager/file_display.js'; +import * as fileListTests from './file_manager/file_list.js'; // import * as fileTransferConnectorTests from './file_manager/file_transfer_connector.js'; import * as filesTooltipTests from './file_manager/files_tooltip.js'; // import * as folderShortcutsTests from './file_manager/folder_shortcuts.js'; -// import * as formatDialogTests from './file_manager/format_dialog.js'; +import * as formatDialogTests from './file_manager/format_dialog.js'; // import * as gearMenuTests from './file_manager/gear_menu.js'; -// import * as gridViewTests from './file_manager/grid_view.js'; -// import * as guestOsTests from './file_manager/guest_os.js'; +import * as gridViewTests from './file_manager/grid_view.js'; +import * as guestOsTests from './file_manager/guest_os.js'; // import * as holdingSpaceTests from './file_manager/holding_space.js'; // import * as installLinuxPackageDialogTests from './file_manager/install_linux_package_dialog.js'; -// import * as keyboardOperationsTests from './file_manager/keyboard_operations.js'; +import * as keyboardOperationsTests from './file_manager/keyboard_operations.js'; import * as manageDialogTests from './file_manager/manage_dialog.js'; -// import * as metadataTests from './file_manager/metadata.js'; +import * as metadataTests from './file_manager/metadata.js'; // import * as metricsTests from './file_manager/metrics.js'; -// import * as myFilesTests from './file_manager/my_files.js'; +import * as myFilesTests from './file_manager/my_files.js'; import * as navigationTests from './file_manager/navigation.js'; -// import * as officeTests from './file_manager/office.js'; +import * as officeTests from './file_manager/office.js'; import * as openAudioMediaAppTests from './file_manager/open_audio_media_app.js'; import * as openFilesInWebDriveTests from './file_manager/open_files_in_web_drive.js'; import * as openImageMediaAppTests from './file_manager/open_image_media_app.js'; import * as openSniffedFilesTests from './file_manager/open_sniffed_files.js'; import * as openVideoMediaAppTests from './file_manager/open_video_media_app.js'; -// import * as providersTests from './file_manager/providers.js'; -// import * as quickViewTests from './file_manager/quick_view.js'; +import * as providersTests from './file_manager/providers.js'; +import * as quickViewTests from './file_manager/quick_view.js'; // import * as recentsTests from './file_manager/recents.js'; // import * as restorePrefsTests from './file_manager/restore_prefs.js'; // import * as searchTests from './file_manager/search.js'; import * as shareTests from './file_manager/share.js'; -// import * as sortColumnsTests from './file_manager/sort_columns.js'; +import * as sortColumnsTests from './file_manager/sort_columns.js'; // import * as tabIndexTests from './file_manager/tab_index.js'; -// import * as tasksTests from './file_manager/tasks.js'; -// import * as toolbarTests from './file_manager/toolbar.js'; +import * as tasksTests from './file_manager/tasks.js'; +import * as toolbarTests from './file_manager/toolbar.js'; // import * as transferTests from './file_manager/transfer.js'; import * as trashTests from './file_manager/trash.js'; import * as traverseTests from './file_manager/traverse.js'; -// import * as zipFilesTests from './file_manager/zip_files.js'; +import * as zipFilesTests from './file_manager/zip_files.js'; // clang-format on export type TestFunctionName = string; @@ -62,9 +62,9 @@ */ export const testcase: Record<TestFunctionName, TestFunction> = { ...androidPhotosTests, - // ...breadcrumbsTests, + ...breadcrumbsTests, // ...contextMenuTests, - // ...copyBetweenWindowsTests, + ...copyBetweenWindowsTests, // ...createNewFolderTests, // ...crostiniTests, ...directoryTreeTests, @@ -73,41 +73,41 @@ // ...dlpEnterpriseConnectorsTests, // ...driveSpecificTests, // ...fileDialogTests, - // ...fileDisplayTests, - // ...fileListTests, + ...fileDisplayTests, + ...fileListTests, // ...fileTransferConnectorTests, ...filesTooltipTests, // ...folderShortcutsTests, - // ...formatDialogTests, + ...formatDialogTests, // ...gearMenuTests, - // ...gridViewTests, - // ...guestOsTests, + ...gridViewTests, + ...guestOsTests, // ...holdingSpaceTests, // ...installLinuxPackageDialogTests, - // ...keyboardOperationsTests, + ...keyboardOperationsTests, ...manageDialogTests, - // ...metadataTests, + ...metadataTests, // ...metricsTests, - // ...myFilesTests, + ...myFilesTests, ...navigationTests, - // ...officeTests, + ...officeTests, ...openAudioMediaAppTests, ...openFilesInWebDriveTests, ...openImageMediaAppTests, ...openSniffedFilesTests, ...openVideoMediaAppTests, - // ...providersTests, - // ...quickViewTests, + ...providersTests, + ...quickViewTests, // ...recentsTests, // ...restorePrefsTests, // ...searchTests, ...shareTests, - // ...sortColumnsTests, + ...sortColumnsTests, // ...tabIndexTests, - // ...tasksTests, - // ...toolbarTests, + ...tasksTests, + ...toolbarTests, // ...transferTests, ...trashTests, ...traverseTests, - // ...zipFilesTests, + ...zipFilesTests, };
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 358af34..9ea053f 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -1174,6 +1174,10 @@ ] } + if (is_chromeos_lacros) { + deps += [ "//chromeos/startup" ] + } + if (use_aura) { sources += [ "corewm/tooltip_controller_test_helper.cc",
diff --git a/ui/views/test/DEPS b/ui/views/test/DEPS index 220fb85d..38a40c7 100644 --- a/ui/views/test/DEPS +++ b/ui/views/test/DEPS
@@ -4,6 +4,7 @@ specific_include_rules = { "views_test_base\.cc": [ + "+chromeos/startup", "+mojo/core/embedder", "+ui/gl", ],
diff --git a/ui/views/test/views_test_base.cc b/ui/views/test/views_test_base.cc index c08f18d..6c93ddc2 100644 --- a/ui/views/test/views_test_base.cc +++ b/ui/views/test/views_test_base.cc
@@ -30,6 +30,10 @@ #include "ui/views/widget/native_widget_mac.h" #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/startup/browser_params_proxy.h" +#endif + namespace views { namespace { @@ -42,7 +46,16 @@ ViewsTestBase::ViewsTestBase( std::unique_ptr<base::test::TaskEnvironment> task_environment) - : task_environment_(std::move(task_environment)) {} + : task_environment_(std::move(task_environment)) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // ViewsTestBase is also used by a number of Lacros interactive_ui_tests. + // Lacros interactive_ui_tests are expected to process the + // --lacros-mojo-socket-for-testing command line switch in order to set up + // crosapi. However, ViewsTestBase doesn't implement that as it's also used by + // other tests and doesn't need crosapi. Hence disable crosapi explicitly. + chromeos::BrowserParamsProxy::DisableCrosapiForTesting(); +#endif +} ViewsTestBase::~ViewsTestBase() { CHECK(setup_called_)
diff --git a/v8 b/v8 index fb8803a8..ee50bc8 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit fb8803a8ccd3ccbca07e40deb509505b665af175 +Subproject commit ee50bc8415cbf6756bfa4cb078155e498c89a4f7