diff --git a/DEPS b/DEPS index 76c0908..523b4d8 100644 --- a/DEPS +++ b/DEPS
@@ -306,15 +306,15 @@ # 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': 'c0441ac66681bb025fe45ca06acbd21a72b8f39e', + 'src_internal_revision': '7dad41b491ac6ef10b238af85d0cfe5a91124393', # 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': '9b103a4148e291537909a1c0765b43a5125676d2', + 'skia_revision': 'fe4aa8a3ea5380f02ba16568299b2d11a2c0a41e', # 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': '93c5bbc582e38f3a543ae0e5a28e593f2e7cc6dd', + 'v8_revision': '4892aa3e774cdd84597e696d57b4468a6ae3d77f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -337,7 +337,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:18.20240127.1.1', + 'fuchsia_version': 'version:18.20240207.3.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -381,11 +381,11 @@ # 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': '27e029f52955bf8ac9e35a1dacf4f56bb39d3eb8', + 'catapult_revision': 'ca502d307f30e7ac2de76211d8d590ff31e5080f', # 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. - 'chromium_variations_revision': '94fec55cb64a630ad0790e1833dd195181ce6688', + 'chromium_variations_revision': '8460157bc5ad13094b0e93276c7387b47932195d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # 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': '9c463fdd34e5975521f6211c5609d1f3945f3c15', + 'quiche_revision': 'bccc7cc648236d93d8cd4f07c82d7a15a6218bf6', # 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. @@ -481,7 +481,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. - 'libunwind_revision': 'fc505746f02c927d792bdeb328307e0e87500342', + 'libunwind_revision': '8bad7bd6ec30f94bce82f7cb5b58ecbd6ce02996', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -501,7 +501,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '9d119c1f4a097b7d27210874f4eba3fc91a83a4e', + 'libcxx_revision': 'c51c9efb6c5a83e0e25c1e30864449d2beadd7a8', # GN CIPD package version. 'gn_version': 'git_revision:a2e2717ea670249a34b0de4b3e54f268d320bdfa', @@ -825,12 +825,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - 'cbd13ba3774974cb20cd7dbaf2acc4860fe6d0f4', + 'ab0b95197af40620e76f2054c376e0068d43a968', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'ac769493150a27e6a4dc32da747c9613496a9e87', + 'url': Var('chromium_git') + '/website.git' + '@' + '7854b9d90b9fb1e57c50e6f039bc44fa587a9eca', }, 'src/ios/third_party/earl_grey2/src': { @@ -1197,7 +1197,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '784db7a5f04f5093941b6c2228e40b9a10d553b2', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '74a6ca92bba677fc87328637bf573deb5944ac91', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1652,7 +1652,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '09a4f3ec842a8932341b195c5b01e141c8a16eb7', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '739dc8a257547a54c71ecf73bba66bef0726825a', + Var('chromium_git') + '/openscreen' + '@' + '03c85f7fe80efa241092f258e33452f47b2ace4e', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '95fe35ffb383710a6e0567e958ead9a3b66e930c', @@ -1663,7 +1663,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '74cdba3b28c2a48bb3c5b5cae32812eb6c76a8da', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '6821c955bdf682556ec4828a174a9cd916d0a02a', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '8ef97ff3b7332e38e61b347a2fbed425a4617151', @@ -1845,10 +1845,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'f4bf599a8b575df685c31d9c4729a70a04e377ed', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e082b08475761a2ba6a3349dfea72f704c8b68d4', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '6493b876ade082dc4e4d883691e8900d5b42f01c', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'aaa123debbd106669fc849425b92607edbd5d26f', + Var('webrtc_git') + '/src.git' + '@' + 'fe6178ef7d7f4f25ce93253bdda0b7daae0769a6', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index d5f49ab4..c7980532f 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -974,13 +974,15 @@ [_THIRD_PARTY_EXCEPT_BLINK], # Not an error in third_party folders. ), BanRule( - r'/(\babsl::Span\b|#include <span>)', + r'/(\babsl::Span\b|#include <span>|\bstd::span\b)', ( - 'absl::Span is banned and <span> is not allowed yet ', + 'absl::Span and std::span are not allowed ', '(https://crbug.com/1414652). Use base::span instead.', ), True, [ + # Included for conversions between base and std. + r'base/containers/span.h', # Test base::span<> compatibility against std::span<>. r'base/containers/span_unittest.cc', # Needed to use QUICHE API.
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index aa891392..8e9a73c5 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2726,6 +2726,8 @@ "wm/snap_group/snap_group_controller.h", "wm/splitview/auto_snap_controller.cc", "wm/splitview/auto_snap_controller.h", + "wm/splitview/faster_split_view.cc", + "wm/splitview/faster_split_view.h", "wm/splitview/layout_divider_controller.h", "wm/splitview/split_view_constants.h", "wm/splitview/split_view_controller.cc",
diff --git a/ash/DEPS b/ash/DEPS index a4ffe37..cea2d13 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -16,6 +16,7 @@ "+components/live_caption", "+components/media_message_center", "+components/metrics/structured/structured_events.h", + "+components/metrics/structured/structured_metrics_client.h", "+components/pref_registry", "+components/prefs", "+components/quirks",
diff --git a/ash/app_list/views/app_list_bubble_apps_page.cc b/ash/app_list/views/app_list_bubble_apps_page.cc index c317cea..b47d3df2 100644 --- a/ash/app_list/views/app_list_bubble_apps_page.cc +++ b/ash/app_list/views/app_list_bubble_apps_page.cc
@@ -187,8 +187,8 @@ // Set up scroll bars. scroll_view_->SetHorizontalScrollBarMode( views::ScrollView::ScrollBarMode::kDisabled); - auto vertical_scroll = - std::make_unique<RoundedScrollBar>(/*horizontal=*/false); + auto vertical_scroll = std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical); vertical_scroll->SetInsets(kVerticalScrollInsets); vertical_scroll->SetSnapBackOnDragOutside(false); scroll_bar_ = vertical_scroll.get();
diff --git a/ash/app_list/views/app_list_folder_view.cc b/ash/app_list/views/app_list_folder_view.cc index 209018b6..916eeeb0 100644 --- a/ash/app_list/views/app_list_folder_view.cc +++ b/ash/app_list/views/app_list_folder_view.cc
@@ -728,8 +728,8 @@ // Set up scroll bars. scroll_view_->SetHorizontalScrollBarMode( views::ScrollView::ScrollBarMode::kDisabled); - auto vertical_scroll = - std::make_unique<RoundedScrollBar>(/*horizontal=*/false); + auto vertical_scroll = std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical); vertical_scroll->SetInsets(kVerticalScrollInsets); scroll_view_->SetVerticalScrollBar(std::move(vertical_scroll));
diff --git a/ash/app_list/views/app_list_search_view.cc b/ash/app_list/views/app_list_search_view.cc index 2f28813b..cfb40db 100644 --- a/ash/app_list/views/app_list_search_view.cc +++ b/ash/app_list/views/app_list_search_view.cc
@@ -89,8 +89,8 @@ // Set up scroll bars. scroll_view_->SetHorizontalScrollBarMode( views::ScrollView::ScrollBarMode::kDisabled); - auto vertical_scroll = - std::make_unique<RoundedScrollBar>(/*horizontal=*/false); + auto vertical_scroll = std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical); vertical_scroll->SetInsets(kVerticalScrollInsets); scroll_view_->SetVerticalScrollBar(std::move(vertical_scroll));
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index c54e69fd..f996f305 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -2469,6 +2469,9 @@ <message name="IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_SKIP" desc="The text for the Faster Splitscreen toast skip button."> Dismiss </message> + <message name="IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_DISMISS_WINDOW_SUGGESTIONS" desc="The a11y text for the Faster Splitscreen toast to dismiss window suggestions."> + Dismiss window suggestions + </message> <message name="IDS_ASH_OVERVIEW_WINDOW_CLOSING_A11Y_ALERT" desc="The accessibility alert read by screen readers to alert the user that a window in overview mode is closing."> Window <ph name="WINDOW_TITILE">$1<ex>1</ex></ph> closed. </message> @@ -6945,6 +6948,15 @@ <message name="IDS_PICKER_GIFS_CATEGORY_LABEL" translateable="false" desc="Label of the Picker list item which can be clicked to show gif results."> Gifs </message> + <message name="IDS_PICKER_OPEN_TABS_CATEGORY_LABEL" translateable="false" desc="Label of the Picker list item which can be clicked to show open tab results."> + Open tabs + </message> + <message name="IDS_PICKER_BROWSING_HISTORY_CATEGORY_LABEL" translateable="false" desc="Label of the Picker list item which can be clicked to show browsing history results."> + Browsing history + </message> + <message name="IDS_PICKER_BOOKMARKS_CATEGORY_LABEL" translateable="false" desc="Label of the Picker list item which can be clicked to show bookmark results."> + Bookmarks + </message> <message name="IDS_PICKER_ZERO_STATE_SEARCH_FIELD_PLACEHOLDER_TEXT" translateable="false" desc="Placeholder text for the search field shown in the Picker UI."> Search to insert </message> @@ -6960,9 +6972,21 @@ <message name="IDS_PICKER_GIFS_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT" translateable="false" desc="Placeholder text for the search field shown in the Picker UI when the gifs category is selected."> Search Gifs </message> + <message name="IDS_PICKER_OPEN_TABS_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT" translateable="false" desc="Placeholder text for the search field shown in the Picker UI when the open tabs category is selected."> + Search Open Tabs + </message> + <message name="IDS_PICKER_BROWSING_HISTORY_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT" translateable="false" desc="Placeholder text for the search field shown in the Picker UI when the browsing history category is selected."> + Search Browsing History + </message> + <message name="IDS_PICKER_BOOKMARKS_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT" translateable="false" desc="Placeholder text for the search field shown in the Picker UI when the bookmarks category is selected."> + Search Bookmarks + </message> <message name="IDS_PICKER_EXPRESSIONS_CATEGORY_TYPE_SECTION_TITLE" translateable="false" desc="Title of the Picker section which contains expression categories, i.e. emojis, symbols, emoticons and gifs."> Expressions </message> + <message name="IDS_PICKER_LINKS_CATEGORY_TYPE_SECTION_TITLE" translateable="false" desc="Title of the Picker section which contains link categories, e.g. browsing history, open tabs, bookmarks."> + Links + </message> <!-- WM --> <message name="IDS_ENTER_PIP_A11Y_NOTIFICATION" is_accessibility_with_no_ui="true" desc="Accessibility text read by chromevox when a window starts picture-in-picture mode.">
diff --git a/ash/ash_strings_grd/IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_DISMISS_WINDOW_SUGGESTIONS.png.sha1 b/ash/ash_strings_grd/IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_DISMISS_WINDOW_SUGGESTIONS.png.sha1 new file mode 100644 index 0000000..3380a16 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_DISMISS_WINDOW_SUGGESTIONS.png.sha1
@@ -0,0 +1 @@ +f3be8dadf2d9794d73f8a4f1c329f4dcae04ad9a \ No newline at end of file
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index a22f211..fb86d7e 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -1143,12 +1143,6 @@ "FilesTrashDrive", base::FEATURE_DISABLED_BY_DEFAULT); -// If enabled, the jelly colors will be used in the firmware update app. -// Requires jelly-colors flag to also be enabled. -BASE_FEATURE(kFirmwareUpdateJelly, - "FirmwareUpdateJelly", - base::FEATURE_ENABLED_BY_DEFAULT); - // Enables the v2 version of the Firmware Updates app. BASE_FEATURE(kFirmwareUpdateUIV2, "FirmwareUpdateUIV2", @@ -2248,12 +2242,6 @@ "PreferConstantFrameRate", base::FEATURE_DISABLED_BY_DEFAULT); -// If enabled, the jelly colors will be used in the print management app. -// Requires jelly-colors flag to also be enabled. -BASE_FEATURE(kPrintManagementJelly, - "PrintManagementJelly", - base::FEATURE_ENABLED_BY_DEFAULT); - // If enabled, ChromeOS print preview app is available. Enabling does not // replace the existing Chrome print preview UI, and will require an additional // flag and pref configured to facilitate. See b/323421684 for more information. @@ -2406,11 +2394,6 @@ "ReleaseNotesNotificationAllChannels", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables or disables Release Notes suggestion chip on ChromeOS. -BASE_FEATURE(kReleaseNotesSuggestionChip, - "ReleaseNotesSuggestionChip", - base::FEATURE_ENABLED_BY_DEFAULT); - // Enables rendering ARC notifications using ChromeOS notification framework BASE_FEATURE(kRenderArcNotificationsByChrome, "RenderArcNotificationsByChrome", @@ -3696,21 +3679,11 @@ base::FeatureList::IsEnabled(kDiagnosticsAppJelly); } -bool IsJellyEnabledForFirmwareUpdate() { - return chromeos::features::IsJellyEnabled() && - base::FeatureList::IsEnabled(kFirmwareUpdateJelly); -} - bool IsJellyEnabledForOsFeedback() { return chromeos::features::IsJellyEnabled() && base::FeatureList::IsEnabled(kOsFeedbackJelly); } -bool IsJellyEnabledForPrintManagement() { - return chromeos::features::IsJellyEnabled() && - base::FeatureList::IsEnabled(kPrintManagementJelly); -} - bool IsJellyEnabledForScanningApp() { return chromeos::features::IsJellyEnabled() && base::FeatureList::IsEnabled(kScanningAppJelly);
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 08e7066..3d09e166 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -352,8 +352,6 @@ BASE_DECLARE_FEATURE(kFilesSinglePartitionFormat); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFilesTrashDrive); COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kFirmwareUpdateJelly); -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFirmwareUpdateUIV2); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFSPsInRecents); COMPONENT_EXPORT(ASH_CONSTANTS) @@ -696,7 +694,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPrinterSettingsPrinterStatus); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPrinterSettingsRevamp); -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPrintManagementJelly); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPrintPreviewCrosApp); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPrintPreviewDiscoveredPrinters); @@ -738,8 +735,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kReleaseNotesNotificationAllChannels); COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kReleaseNotesSuggestionChip); -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kRenderArcNotificationsByChrome); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kRemoveStalePolicyPinnedAppsFromShelf); @@ -1084,9 +1079,7 @@ bool IsInternalServerSideSpeechRecognitionControlEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsIppClientInfoEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyEnabledForDiagnosticsApp(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyEnabledForFirmwareUpdate(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyEnabledForOsFeedback(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyEnabledForPrintManagement(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyEnabledForScanningApp(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsJellyEnabledForShortcutCustomization(); COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/controls/rounded_scroll_bar.cc b/ash/controls/rounded_scroll_bar.cc index 5ba0858..aaab627 100644 --- a/ash/controls/rounded_scroll_bar.cc +++ b/ash/controls/rounded_scroll_bar.cc
@@ -148,8 +148,8 @@ views::Button::ButtonState current_state_ = views::Button::STATE_NORMAL; }; -RoundedScrollBar::RoundedScrollBar(bool horizontal) - : ScrollBar(horizontal), +RoundedScrollBar::RoundedScrollBar(Orientation orientation) + : ScrollBar(orientation), thumb_(new Thumb(this)), // Owned by views hierarchy. hide_scrollbar_timer_( FROM_HERE, @@ -192,8 +192,9 @@ int RoundedScrollBar::GetThickness() const { // Extend the thickness by the insets on the sides of the bar. - const int sides = IsHorizontal() ? insets_.top() + insets_.bottom() - : insets_.left() + insets_.right(); + const int sides = GetOrientation() == Orientation::kHorizontal + ? insets_.top() + insets_.bottom() + : insets_.left() + insets_.right(); return thumb_->GetThumbThickness() + sides; }
diff --git a/ash/controls/rounded_scroll_bar.h b/ash/controls/rounded_scroll_bar.h index 76cf97c..61855389 100644 --- a/ash/controls/rounded_scroll_bar.h +++ b/ash/controls/rounded_scroll_bar.h
@@ -27,7 +27,7 @@ METADATA_HEADER(RoundedScrollBar, views::ScrollBar) public: - explicit RoundedScrollBar(bool horizontal); + explicit RoundedScrollBar(Orientation orientation); RoundedScrollBar(const RoundedScrollBar&) = delete; RoundedScrollBar& operator=(const RoundedScrollBar&) = delete; ~RoundedScrollBar() override;
diff --git a/ash/controls/rounded_scroll_bar_unittest.cc b/ash/controls/rounded_scroll_bar_unittest.cc index 9fe8833..99baa35 100644 --- a/ash/controls/rounded_scroll_bar_unittest.cc +++ b/ash/controls/rounded_scroll_bar_unittest.cc
@@ -77,8 +77,8 @@ // Add a vertical scrollbar along the right edge. auto* contents = widget_->SetContentsView(std::make_unique<views::View>()); - scroll_bar_ = contents->AddChildView( - std::make_unique<RoundedScrollBar>(/*horizontal=*/false)); + scroll_bar_ = contents->AddChildView(std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical)); scroll_bar_->set_controller(&controller_); scroll_bar_->SetBounds(90, 0, kScrollBarWidth, kViewportHeight); scroll_bar_->Update(kViewportHeight, kContentHeight,
diff --git a/ash/display/display_prefs.cc b/ash/display/display_prefs.cc index fbb4399..5fd4e92 100644 --- a/ash/display/display_prefs.cc +++ b/ash/display/display_prefs.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include <string> +#include <utility> #include "ash/constants/ash_pref_names.h" #include "ash/constants/ash_switches.h" @@ -21,6 +22,7 @@ #include "base/system/sys_info.h" #include "base/values.h" #include "components/metrics/structured/structured_events.h" +#include "components/metrics/structured/structured_metrics_client.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" @@ -813,18 +815,19 @@ int product_id; base::StringToInt(display.product_id(), &product_id); - metrics::structured::events::v2::popular_displays::MonitorInfo() - .SetDisplayName(display.name()) - .SetManufacturerId(display.manufacturer_id()) - .SetProductId(product_id) - .SetNativeModeSize(native_mode->size().ToString()) - .SetNativeModeRefreshRate(native_mode->refresh_rate()) - .SetPhysicalSize(display.physical_size().ToString()) - .SetConnectionType( - display::DisplayConnectionTypeString(display.connection_type())) - .SetIsVrrCapable(display.variable_refresh_rate_state() < - display::VariableRefreshRateState::kVrrNotCapable) - .Record(); + metrics::structured::StructuredMetricsClient::Record(std::move( + metrics::structured::events::v2::popular_displays::MonitorInfo() + .SetDisplayName(display.name()) + .SetManufacturerId(display.manufacturer_id()) + .SetProductId(product_id) + .SetNativeModeSize(native_mode->size().ToString()) + .SetNativeModeRefreshRate(native_mode->refresh_rate()) + .SetPhysicalSize(display.physical_size().ToString()) + .SetConnectionType( + display::DisplayConnectionTypeString(display.connection_type())) + .SetIsVrrCapable( + display.variable_refresh_rate_state() < + display::VariableRefreshRateState::kVrrNotCapable))); cached_list.Append(display_id); }
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc index 8e01f3a..d9da359d 100644 --- a/ash/login/ui/lock_debug_view.cc +++ b/ash/login/ui/lock_debug_view.cc
@@ -944,10 +944,10 @@ scroll->SetPreferredSize(gfx::Size(600, height)); scroll->SetContents(base::WrapUnique(content)); scroll->SetBackgroundColor(std::nullopt); - scroll->SetVerticalScrollBar( - std::make_unique<views::OverlayScrollBar>(false)); - scroll->SetHorizontalScrollBar( - std::make_unique<views::OverlayScrollBar>(true)); + scroll->SetVerticalScrollBar(std::make_unique<views::OverlayScrollBar>( + views::ScrollBar::Orientation::kVertical)); + scroll->SetHorizontalScrollBar(std::make_unique<views::OverlayScrollBar>( + views::ScrollBar::Orientation::kHorizontal)); return scroll; }; container_->AddChildView(make_scroll(global_action_view_container_, 110));
diff --git a/ash/login/ui/scrollable_users_list_view.cc b/ash/login/ui/scrollable_users_list_view.cc index 42097eff..34f081f 100644 --- a/ash/login/ui/scrollable_users_list_view.cc +++ b/ash/login/ui/scrollable_users_list_view.cc
@@ -223,10 +223,12 @@ SetBackgroundColor(std::nullopt); SetDrawOverflowIndicator(false); - auto vertical_scroll = std::make_unique<RoundedScrollBar>(false); + auto vertical_scroll = std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical); vertical_scroll->SetInsets(kVerticalScrollInsets); SetVerticalScrollBar(std::move(vertical_scroll)); - SetHorizontalScrollBar(std::make_unique<RoundedScrollBar>(true)); + SetHorizontalScrollBar(std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kHorizontal)); observation_.Observe(Shell::Get()->wallpaper_controller()); }
diff --git a/ash/picker/model/picker_category.h b/ash/picker/model/picker_category.h index a83017ba..60fcfc1 100644 --- a/ash/picker/model/picker_category.h +++ b/ash/picker/model/picker_category.h
@@ -15,6 +15,9 @@ kSymbols, kEmoticons, kGifs, + kOpenTabs, + kBrowsingHistory, + kBookmarks, }; } // namespace ash
diff --git a/ash/picker/model/picker_model.cc b/ash/picker/model/picker_model.cc index 3c2b03ae..0d753b77 100644 --- a/ash/picker/model/picker_model.cc +++ b/ash/picker/model/picker_model.cc
@@ -10,10 +10,10 @@ std::vector<PickerCategory> PickerModel::GetAvailableCategories() const { return std::vector<PickerCategory>{ - PickerCategory::kEmojis, - PickerCategory::kSymbols, - PickerCategory::kEmoticons, - PickerCategory::kGifs, + PickerCategory::kEmojis, PickerCategory::kSymbols, + PickerCategory::kEmoticons, PickerCategory::kGifs, + PickerCategory::kOpenTabs, PickerCategory::kBrowsingHistory, + PickerCategory::kBookmarks, }; }
diff --git a/ash/picker/model/picker_model_unittest.cc b/ash/picker/model/picker_model_unittest.cc index 36d476f..8a8b45a 100644 --- a/ash/picker/model/picker_model_unittest.cc +++ b/ash/picker/model/picker_model_unittest.cc
@@ -15,9 +15,12 @@ TEST(PickerModel, AvailableCategories) { PickerModel model; - EXPECT_THAT(model.GetAvailableCategories(), - ElementsAre(PickerCategory::kEmojis, PickerCategory::kSymbols, - PickerCategory::kEmoticons, PickerCategory::kGifs)); + EXPECT_THAT( + model.GetAvailableCategories(), + ElementsAre(PickerCategory::kEmojis, PickerCategory::kSymbols, + PickerCategory::kEmoticons, PickerCategory::kGifs, + PickerCategory::kOpenTabs, PickerCategory::kBrowsingHistory, + PickerCategory::kBookmarks)); } } // namespace
diff --git a/ash/picker/views/picker_category_type.cc b/ash/picker/views/picker_category_type.cc index a080a85..3357f48 100644 --- a/ash/picker/views/picker_category_type.cc +++ b/ash/picker/views/picker_category_type.cc
@@ -15,6 +15,10 @@ case PickerCategory::kEmoticons: case PickerCategory::kGifs: return PickerCategoryType::kExpressions; + case PickerCategory::kOpenTabs: + case PickerCategory::kBrowsingHistory: + case PickerCategory::kBookmarks: + return PickerCategoryType::kLinks; } }
diff --git a/ash/picker/views/picker_category_type.h b/ash/picker/views/picker_category_type.h index b69e848d..b08fc1a 100644 --- a/ash/picker/views/picker_category_type.h +++ b/ash/picker/views/picker_category_type.h
@@ -13,6 +13,7 @@ // Used to group related categories together. enum class ASH_EXPORT PickerCategoryType { kExpressions, + kLinks, }; ASH_EXPORT PickerCategoryType GetPickerCategoryType(PickerCategory category);
diff --git a/ash/picker/views/picker_contents_view.cc b/ash/picker/views/picker_contents_view.cc index 29bb3e0..fedf580 100644 --- a/ash/picker/views/picker_contents_view.cc +++ b/ash/picker/views/picker_contents_view.cc
@@ -80,8 +80,8 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); auto* scroll_view = AddChildView(std::make_unique<PickerScrollView>()); - auto vertical_scroll_bar = - std::make_unique<RoundedScrollBar>(/*horizontal=*/false); + auto vertical_scroll_bar = std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical); vertical_scroll_bar->SetInsets(GetPickerScrollBarInsets(layout_type)); scroll_view->SetVerticalScrollBar(std::move(vertical_scroll_bar));
diff --git a/ash/picker/views/picker_icons.cc b/ash/picker/views/picker_icons.cc index aaa2d95..0e3f09f6 100644 --- a/ash/picker/views/picker_icons.cc +++ b/ash/picker/views/picker_icons.cc
@@ -22,6 +22,12 @@ return kPickerEmoticonIcon; case PickerCategory::kGifs: return kPickerGifIcon; + case PickerCategory::kOpenTabs: + return kPickerOpenTabIcon; + case PickerCategory::kBrowsingHistory: + return kPickerBrowsingHistoryIcon; + case PickerCategory::kBookmarks: + return kPickerBookmarkIcon; } }
diff --git a/ash/picker/views/picker_search_field_view.cc b/ash/picker/views/picker_search_field_view.cc index 03a5ec6..165b70c 100644 --- a/ash/picker/views/picker_search_field_view.cc +++ b/ash/picker/views/picker_search_field_view.cc
@@ -34,22 +34,22 @@ PickerSessionMetrics* session_metrics) : search_callback_(std::move(search_callback)), session_metrics_(session_metrics) { - SetLayoutManager(std::make_unique<views::FillLayout>()); - - textfield_ = AddChildView( - views::Builder<views::Textfield>() - .SetController(this) - .SetBorder(views::CreateEmptyBorder(kSearchFieldBorderInsets)) - .SetBackgroundColor(SK_ColorTRANSPARENT) - .SetFontList(TypographyProvider::Get()->ResolveTypographyToken( - TypographyToken::kCrosBody2)) - .SetPlaceholderText(l10n_util::GetStringUTF16( - IDS_PICKER_ZERO_STATE_SEARCH_FIELD_PLACEHOLDER_TEXT)) - // TODO(b/309706053): Replace this once the strings are finalized. - .SetAccessibleName(u"placeholder") - .Build()); - - SetProperty(views::kMarginsKey, kSearchFieldVerticalPadding); + views::Builder<PickerSearchFieldView>(this) + .SetUseDefaultFillLayout(true) + .SetProperty(views::kMarginsKey, kSearchFieldVerticalPadding) + .AddChild( + views::Builder<views::Textfield>() + .CopyAddressTo(&textfield_) + .SetController(this) + .SetBorder(views::CreateEmptyBorder(kSearchFieldBorderInsets)) + .SetBackgroundColor(SK_ColorTRANSPARENT) + .SetFontList(TypographyProvider::Get()->ResolveTypographyToken( + TypographyToken::kCrosBody2)) + .SetPlaceholderText(l10n_util::GetStringUTF16( + IDS_PICKER_ZERO_STATE_SEARCH_FIELD_PLACEHOLDER_TEXT)) + // TODO(b/309706053): Replace this once the strings are finalized. + .SetAccessibleName(u"placeholder")) + .BuildChildren(); } PickerSearchFieldView::~PickerSearchFieldView() = default;
diff --git a/ash/picker/views/picker_search_field_view.h b/ash/picker/views/picker_search_field_view.h index e4e4c9d..f4a6e66 100644 --- a/ash/picker/views/picker_search_field_view.h +++ b/ash/picker/views/picker_search_field_view.h
@@ -12,6 +12,7 @@ #include "base/functional/callback_forward.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/focus/focus_manager.h" +#include "ui/views/metadata/view_factory.h" #include "ui/views/view.h" namespace views { @@ -64,6 +65,11 @@ raw_ptr<views::Textfield> textfield_ = nullptr; }; +BEGIN_VIEW_BUILDER(ASH_EXPORT, PickerSearchFieldView, views::View) +END_VIEW_BUILDER + } // namespace ash +DEFINE_VIEW_BUILDER(ASH_EXPORT, ash::PickerSearchFieldView) + #endif // ASH_PICKER_VIEWS_PICKER_SEARCH_FIELD_VIEW_H_
diff --git a/ash/picker/views/picker_strings.cc b/ash/picker/views/picker_strings.cc index 125dec03..42c19b1 100644 --- a/ash/picker/views/picker_strings.cc +++ b/ash/picker/views/picker_strings.cc
@@ -21,6 +21,13 @@ return l10n_util::GetStringUTF16(IDS_PICKER_EMOTICONS_CATEGORY_LABEL); case PickerCategory::kGifs: return l10n_util::GetStringUTF16(IDS_PICKER_GIFS_CATEGORY_LABEL); + case PickerCategory::kOpenTabs: + return l10n_util::GetStringUTF16(IDS_PICKER_OPEN_TABS_CATEGORY_LABEL); + case PickerCategory::kBrowsingHistory: + return l10n_util::GetStringUTF16( + IDS_PICKER_BROWSING_HISTORY_CATEGORY_LABEL); + case PickerCategory::kBookmarks: + return l10n_util::GetStringUTF16(IDS_PICKER_BOOKMARKS_CATEGORY_LABEL); } } @@ -39,6 +46,15 @@ case PickerCategory::kGifs: return l10n_util::GetStringUTF16( IDS_PICKER_GIFS_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT); + case PickerCategory::kOpenTabs: + return l10n_util::GetStringUTF16( + IDS_PICKER_OPEN_TABS_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT); + case PickerCategory::kBrowsingHistory: + return l10n_util::GetStringUTF16( + IDS_PICKER_BROWSING_HISTORY_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT); + case PickerCategory::kBookmarks: + return l10n_util::GetStringUTF16( + IDS_PICKER_BOOKMARKS_CATEGORY_SEARCH_FIELD_PLACEHOLDER_TEXT); } } @@ -48,6 +64,9 @@ case PickerCategoryType::kExpressions: return l10n_util::GetStringUTF16( IDS_PICKER_EXPRESSIONS_CATEGORY_TYPE_SECTION_TITLE); + case PickerCategoryType::kLinks: + return l10n_util::GetStringUTF16( + IDS_PICKER_LINKS_CATEGORY_TYPE_SECTION_TITLE); } }
diff --git a/ash/picker/views/picker_view.h b/ash/picker/views/picker_view.h index d7dd66d..98c5660 100644 --- a/ash/picker/views/picker_view.h +++ b/ash/picker/views/picker_view.h
@@ -84,6 +84,7 @@ PickerSearchFieldView& search_field_view_for_testing() { return *search_field_view_; } + PickerContentsView& contents_view_for_testing() { return *contents_view_; } PickerSearchResultsView& search_results_view_for_testing() { return *search_results_view_; }
diff --git a/ash/picker/views/picker_view_unittest.cc b/ash/picker/views/picker_view_unittest.cc index 84556376..8f2bf49 100644 --- a/ash/picker/views/picker_view_unittest.cc +++ b/ash/picker/views/picker_view_unittest.cc
@@ -11,6 +11,7 @@ #include "ash/picker/model/picker_search_results.h" #include "ash/picker/views/picker_category_type.h" #include "ash/picker/views/picker_category_view.h" +#include "ash/picker/views/picker_contents_view.h" #include "ash/picker/views/picker_search_field_view.h" #include "ash/picker/views/picker_search_results_view.h" #include "ash/picker/views/picker_section_view.h" @@ -555,7 +556,7 @@ widget->Show(); PickerView* view = GetPickerViewFromWidget(*widget); - EXPECT_GE(view->zero_state_view_for_testing().GetBoundsInScreen().y(), + EXPECT_GE(view->contents_view_for_testing().GetBoundsInScreen().y(), view->search_field_view_for_testing().GetBoundsInScreen().bottom()); } @@ -571,7 +572,7 @@ widget->Show(); PickerView* view = GetPickerViewFromWidget(*widget); - EXPECT_LE(view->zero_state_view_for_testing().GetBoundsInScreen().bottom(), + EXPECT_LE(view->contents_view_for_testing().GetBoundsInScreen().bottom(), view->search_field_view_for_testing().GetBoundsInScreen().y()); }
diff --git a/ash/picker/views/picker_zero_state_view_unittest.cc b/ash/picker/views/picker_zero_state_view_unittest.cc index 714b781..0a4d5b6 100644 --- a/ash/picker/views/picker_zero_state_view_unittest.cc +++ b/ash/picker/views/picker_zero_state_view_unittest.cc
@@ -22,6 +22,7 @@ namespace { using ::testing::Contains; +using ::testing::ElementsAre; using ::testing::IsEmpty; using ::testing::Key; using ::testing::Not; @@ -30,11 +31,12 @@ using PickerZeroStateViewTest = AshTestBase; -TEST_F(PickerZeroStateViewTest, CreatesExpressionsSection) { +TEST_F(PickerZeroStateViewTest, CreatesCategorySections) { PickerZeroStateView view(kPickerWidth, base::DoNothing()); EXPECT_THAT(view.section_views_for_testing(), - Contains(Key(PickerCategoryType::kExpressions))); + ElementsAre(Key(PickerCategoryType::kExpressions), + Key(PickerCategoryType::kLinks))); } TEST_F(PickerZeroStateViewTest, LeftClickSelectsCategory) {
diff --git a/ash/public/cpp/picker/picker_client.cc b/ash/public/cpp/picker/picker_client.cc index 6b0f18f9a..ee933a07 100644 --- a/ash/public/cpp/picker/picker_client.cc +++ b/ash/public/cpp/picker/picker_client.cc
@@ -16,6 +16,10 @@ return std::nullopt; } +ValidGifUrl ValidGifUrl::CreateForTesting(const GURL& url) { + return ValidGifUrl(url); +} + ValidGifUrl::~ValidGifUrl() = default; GURL ValidGifUrl::ToGURL() const {
diff --git a/ash/public/cpp/picker/picker_client.h b/ash/public/cpp/picker/picker_client.h index 0a4edd3..00f1b16 100644 --- a/ash/public/cpp/picker/picker_client.h +++ b/ash/public/cpp/picker/picker_client.h
@@ -23,6 +23,9 @@ public: static std::optional<ValidGifUrl> Create(const GURL& url); + // Creates an instance bypassing the validation checks. + static ValidGifUrl CreateForTesting(const GURL& url); + ~ValidGifUrl(); GURL ToGURL() const;
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index 6be78e9..ea6b623 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -315,9 +315,12 @@ "phone_hub_mobile_no_sim.icon", "phone_hub_phone.icon", "phone_hub_silence_phone.icon", + "picker_bookmark.icon", + "picker_browsing_history.icon", "picker_emoji.icon", "picker_emoticon.icon", "picker_gif.icon", + "picker_open_tab.icon", "picker_symbol.icon", "pin_request_lock.icon", "pinned.icon",
diff --git a/ash/resources/vector_icons/picker_bookmark.icon b/ash/resources/vector_icons/picker_bookmark.icon new file mode 100644 index 0000000..059defc --- /dev/null +++ b/ash/resources/vector_icons/picker_bookmark.icon
@@ -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. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 7.43f, 13.68f, +LINE_TO, 10, 12.16f, +R_LINE_TO, 2.59f, 1.52f, +R_LINE_TO, -0.69f, -2.89f, +R_LINE_TO, 2.23f, -1.91f, +R_LINE_TO, -2.95f, -0.26f, +LINE_TO, 10, 5.87f, +LINE_TO, 8.82f, 8.62f, +R_LINE_TO, -2.95f, 0.25f, +R_LINE_TO, 2.25f, 1.91f, +R_LINE_TO, -0.69f, 2.89f, +CLOSE, +R_MOVE_TO, -2.62f, 3.58f, +R_LINE_TO, 1.38f, -5.82f, +LINE_TO, 1.6f, 7.52f, +LINE_TO, 7.64f, 7, +LINE_TO, 10, 1.5f, +R_LINE_TO, 2.36f, 5.52f, +R_LINE_TO, 6.04f, 0.5f, +R_LINE_TO, -4.6f, 3.93f, +R_LINE_TO, 1.38f, 5.82f, +R_LINE_TO, -5.19f, -3.09f, +R_LINE_TO, -5.19f, 3.09f, +CLOSE
diff --git a/ash/resources/vector_icons/picker_browsing_history.icon b/ash/resources/vector_icons/picker_browsing_history.icon new file mode 100644 index 0000000..e940aaa --- /dev/null +++ b/ash/resources/vector_icons/picker_browsing_history.icon
@@ -0,0 +1,43 @@ +// 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. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 10, 17.17f, +R_CUBIC_TO, -2, 0, -3.7f, -0.69f, -5.1f, -2.08f, +CUBIC_TO, 3.51f, 13.69f, 2.82f, 12, 2.83f, 10, +R_H_LINE_TO, 1.71f, +R_CUBIC_TO, 0.01f, 1.5f, 0.55f, 2.79f, 1.6f, 3.85f, +CUBIC_TO, 7.22f, 14.91f, 8.5f, 15.44f, 10, 15.44f, +R_CUBIC_TO, 1.49f, 0, 2.76f, -0.53f, 3.83f, -1.58f, +R_CUBIC_TO, 1.07f, -1.07f, 1.6f, -2.35f, 1.6f, -3.85f, +R_CUBIC_TO, 0, -1.5f, -0.53f, -2.78f, -1.6f, -3.83f, +R_CUBIC_TO, -1.07f, -1.07f, -2.35f, -1.6f, -3.83f, -1.6f, +R_CUBIC_TO, -0.83f, 0, -1.6f, 0.17f, -2.31f, 0.5f, +R_ARC_TO, 4.99f, 4.99f, 0, 0, 0, -1.77f, 1.35f, +H_LINE_TO, 8, +V_LINE_TO, 8, +H_LINE_TO, 2.88f, +V_LINE_TO, 2.88f, +R_H_LINE_TO, 1.56f, +V_LINE_TO, 5.5f, +R_ARC_TO, 7.28f, 7.28f, 0, 0, 1, 2.42f, -1.94f, +R_CUBIC_TO, 0.96f, -0.49f, 2.01f, -0.73f, 3.15f, -0.73f, +R_CUBIC_TO, 0.99f, 0, 1.91f, 0.19f, 2.77f, 0.56f, +R_ARC_TO, 7, 7, 0, 0, 1, 2.27f, 1.54f, +R_ARC_TO, 7, 7, 0, 0, 1, 1.54f, 2.27f, +ARC_TO, 6.78f, 6.78f, 0, 0, 1, 17.17f, 10, +R_CUBIC_TO, 0, 0.99f, -0.19f, 1.92f, -0.58f, 2.79f, +R_ARC_TO, 7.24f, 7.24f, 0, 0, 1, -1.54f, 2.29f, +R_ARC_TO, 7.17f, 7.17f, 0, 0, 1, -2.27f, 1.52f, +R_ARC_TO, 6.86f, 6.86f, 0, 0, 1, -2.77f, 0.56f, +CLOSE, +R_MOVE_TO, 2.04f, -4.29f, +R_LINE_TO, -2.83f, -2.83f, +V_LINE_TO, 6, +R_H_LINE_TO, 1.58f, +R_V_LINE_TO, 3.38f, +R_LINE_TO, 2.38f, 2.38f, +R_LINE_TO, -1.12f, 1.13f, +CLOSE, +NEW_PATH
diff --git a/ash/resources/vector_icons/picker_open_tab.icon b/ash/resources/vector_icons/picker_open_tab.icon new file mode 100644 index 0000000..de435c7f --- /dev/null +++ b/ash/resources/vector_icons/picker_open_tab.icon
@@ -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. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 3.56f, 14.44f, +R_H_LINE_TO, 12.87f, +V_LINE_TO, 9, +H_LINE_TO, 11, +V_LINE_TO, 5.56f, +H_LINE_TO, 3.56f, +R_V_LINE_TO, 8.88f, +CLOSE, +R_MOVE_TO, 0, 1.73f, +R_CUBIC_TO, -0.49f, 0, -0.9f, -0.17f, -1.23f, -0.5f, +R_ARC_TO, 1.67f, 1.67f, 0, 0, 1, -0.5f, -1.23f, +V_LINE_TO, 5.56f, +R_CUBIC_TO, 0, -0.49f, 0.17f, -0.9f, 0.5f, -1.23f, +R_ARC_TO, 1.67f, 1.67f, 0, 0, 1, 1.23f, -0.5f, +R_H_LINE_TO, 12.87f, +R_CUBIC_TO, 0.49f, 0, 0.9f, 0.17f, 1.23f, 0.5f, +R_CUBIC_TO, 0.33f, 0.33f, 0.5f, 0.74f, 0.5f, 1.23f, +R_V_LINE_TO, 8.88f, +R_CUBIC_TO, 0, 0.49f, -0.17f, 0.9f, -0.5f, 1.23f, +R_CUBIC_TO, -0.33f, 0.33f, -0.74f, 0.5f, -1.23f, 0.5f, +H_LINE_TO, 3.56f, +CLOSE, +R_MOVE_TO, 0, -1.73f, +V_LINE_TO, 5.56f, +R_V_LINE_TO, 8.88f, +CLOSE, +NEW_PATH
diff --git a/ash/system/notification_center/views/message_center_scroll_bar.cc b/ash/system/notification_center/views/message_center_scroll_bar.cc index b7b5e6ec..b2a93b5 100644 --- a/ash/system/notification_center/views/message_center_scroll_bar.cc +++ b/ash/system/notification_center/views/message_center_scroll_bar.cc
@@ -46,7 +46,7 @@ END_METADATA MessageCenterScrollBar::MessageCenterScrollBar() - : RoundedScrollBar(/*horizontal=*/false) { + : RoundedScrollBar(views::ScrollBar::Orientation::kVertical) { GetThumb()->layer()->SetVisible(features::IsNotificationScrollBarEnabled()); GetThumb()->layer()->CompleteAllAnimations(); }
diff --git a/ash/system/notification_center/views/notifier_settings_view.cc b/ash/system/notification_center/views/notifier_settings_view.cc index cb5ddb6..31997d6 100644 --- a/ash/system/notification_center/views/notifier_settings_view.cc +++ b/ash/system/notification_center/views/notifier_settings_view.cc
@@ -661,7 +661,8 @@ auto scroller = std::make_unique<views::ScrollView>(); scroller->SetBackgroundColor(std::nullopt); scroll_bar_ = scroller->SetVerticalScrollBar( - std::make_unique<views::OverlayScrollBar>(/*horizontal=*/false)); + std::make_unique<views::OverlayScrollBar>( + views::ScrollBar::Orientation::kVertical)); scroller->SetDrawOverflowIndicator(false); scroller_ = AddChildView(std::move(scroller));
diff --git a/ash/system/phonehub/app_stream_launcher_view.cc b/ash/system/phonehub/app_stream_launcher_view.cc index 021091e..6b1f279 100644 --- a/ash/system/phonehub/app_stream_launcher_view.cc +++ b/ash/system/phonehub/app_stream_launcher_view.cc
@@ -153,8 +153,8 @@ // Set up scroll bars. scroll_view->SetHorizontalScrollBarMode( views::ScrollView::ScrollBarMode::kDisabled); - auto vertical_scroll = - std::make_unique<RoundedScrollBar>(/*horizontal=*/false); + auto vertical_scroll = std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical); vertical_scroll->SetInsets(kVerticalScrollInsets); vertical_scroll->SetSnapBackOnDragOutside(false); scroll_view->SetVerticalScrollBar(std::move(vertical_scroll));
diff --git a/ash/system/tray/tray_detailed_view.cc b/ash/system/tray/tray_detailed_view.cc index 2a83854..49e476e 100644 --- a/ash/system/tray/tray_detailed_view.cc +++ b/ash/system/tray/tray_detailed_view.cc
@@ -172,7 +172,7 @@ scroll_content_ = scroller_->SetContents(std::move(scroll_content)); auto vertical_scroll = std::make_unique<RoundedScrollBar>( - /*horizontal=*/false); + views::ScrollBar::Orientation::kVertical); vertical_scroll->SetInsets(kScrollBarInsets); scroller_->SetVerticalScrollBar(std::move(vertical_scroll)); scroller_->SetProperty(views::kMarginsKey, delegate_->GetScrollViewMargin());
diff --git a/ash/webui/firmware_update_ui/firmware_update_app_ui.cc b/ash/webui/firmware_update_ui/firmware_update_app_ui.cc index a3634be6..a6abe6d 100644 --- a/ash/webui/firmware_update_ui/firmware_update_app_ui.cc +++ b/ash/webui/firmware_update_ui/firmware_update_app_ui.cc
@@ -38,8 +38,6 @@ source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER_JS); source->AddResourcePath("test_loader_util.js", IDR_WEBUI_JS_TEST_LOADER_UTIL_JS); - source->AddBoolean("isJellyEnabledForFirmwareUpdate", - ash::features::IsJellyEnabledForFirmwareUpdate()); source->AddBoolean("isFirmwareUpdateUIV2Enabled", ash::features::IsFirmwareUpdateUIV2Enabled()); }
diff --git a/ash/webui/firmware_update_ui/resources/firmware_update_app.ts b/ash/webui/firmware_update_ui/resources/firmware_update_app.ts index 71ac3e4..435b735 100644 --- a/ash/webui/firmware_update_ui/resources/firmware_update_app.ts +++ b/ash/webui/firmware_update_ui/resources/firmware_update_app.ts
@@ -9,7 +9,6 @@ import './peripheral_updates_list.js'; import './strings.m.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; import {ColorChangeUpdater} from 'chrome://resources/cr_components/color_change_listener/colors_css_updater.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -35,22 +34,11 @@ override connectedCallback(): void { super.connectedCallback(); - if (loadTimeData.getBoolean('isJellyEnabledForFirmwareUpdate')) { - // TODO(b/276493795): After the Jelly experiment is launched, replace - // `cros_styles.css` with `theme/colors.css` directly in `index.html`. - // Also add `theme/typography.css` to `index.html`. - document.querySelector('link[href*=\'cros_styles.css\']') - ?.setAttribute('href', 'chrome://theme/colors.css?sets=legacy,sys'); - const typographyLink = document.createElement('link'); - typographyLink.href = 'chrome://theme/typography.css'; - typographyLink.rel = 'stylesheet'; - document.head.appendChild(typographyLink); - document.body.classList.add('jelly-enabled'); - /** @suppress {checkTypes} */ - (function() { - ColorChangeUpdater.forDocument().start(); - })(); - } + + /** @suppress {checkTypes} */ + (function() { + ColorChangeUpdater.forDocument().start(); + })(); } }
diff --git a/ash/webui/firmware_update_ui/resources/index.html b/ash/webui/firmware_update_ui/resources/index.html index c1ed4f2b..f508194 100644 --- a/ash/webui/firmware_update_ui/resources/index.html +++ b/ash/webui/firmware_update_ui/resources/index.html
@@ -9,7 +9,8 @@ <title></title> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> - <link rel="stylesheet" href="chrome://resources/chromeos/colors/cros_styles.css"> + <link rel="stylesheet" href="chrome://theme/colors.css?sets=legacy,sys"> + <link rel="stylesheet" href="chrome://theme/typography.css"> <style> body { background-color: var(--cros-bg-color); @@ -27,7 +28,7 @@ } </style> </head> -<body> +<body class="jelly-enabled"> <firmware-update-app></firmware-update-app> <script type="module" src="firmware_update_app.js"></script>
diff --git a/ash/webui/print_management/print_management_ui.cc b/ash/webui/print_management/print_management_ui.cc index 2ee5f57..9b18721 100644 --- a/ash/webui/print_management/print_management_ui.cc +++ b/ash/webui/print_management/print_management_ui.cc
@@ -42,8 +42,6 @@ source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER_JS); source->AddResourcePath("test_loader_util.js", IDR_WEBUI_JS_TEST_LOADER_UTIL_JS); - source->AddBoolean("isJellyEnabledForPrintManagement", - ash::features::IsJellyEnabledForPrintManagement()); source->AddBoolean("isSetupAssistanceEnabled", base::FeatureList::IsEnabled( ash::features::kPrintManagementSetupAssistance));
diff --git a/ash/webui/print_management/resources/index.html b/ash/webui/print_management/resources/index.html index 7916b02..b4703ce 100644 --- a/ash/webui/print_management/resources/index.html +++ b/ash/webui/print_management/resources/index.html
@@ -8,7 +8,9 @@ <meta name="color-scheme" content="light dark"> <title>$i18n{printJobTitle}</title> <link rel="stylesheet" - href="chrome://resources/chromeos/colors/cros_styles.css"> + href="chrome://theme/colors.css?sets=legacy,sys"> + <link rel="stylesheet" + href="chrome://theme/typography.css"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <style> @@ -27,7 +29,7 @@ } </style> </head> - <body> + <body class="jelly-enabled"> <print-management></print-management> <script type="module" src="print_management.js"></script> <script type="module" src="mojo_interface_provider.js"></script>
diff --git a/ash/webui/print_management/resources/print_management.ts b/ash/webui/print_management/resources/print_management.ts index c56c633a..01a6253 100644 --- a/ash/webui/print_management/resources/print_management.ts +++ b/ash/webui/print_management/resources/print_management.ts
@@ -185,19 +185,7 @@ this.startObservingPrintJobs(); this.fetchDeletePrintJobHistoryPolicy(); - if (loadTimeData.getBoolean('isJellyEnabledForPrintManagement')) { - // TODO(b/276493795): After the Jelly experiment is launched, replace - // `cros_styles.css` with `theme/colors.css` directly in `index.html`. - // Also add `theme/typography.css` to `index.html`. - document.querySelector('link[href*=\'cros_styles.css\']') - ?.setAttribute('href', 'chrome://theme/colors.css?sets=legacy,sys'); - const typographyLink = document.createElement('link'); - typographyLink.href = 'chrome://theme/typography.css'; - typographyLink.rel = 'stylesheet'; - document.head.appendChild(typographyLink); - document.body.classList.add('jelly-enabled'); - ColorChangeUpdater.forDocument().start(); - } + ColorChangeUpdater.forDocument().start(); } override disconnectedCallback(): void {
diff --git a/ash/wm/desks/desk_bar_view_base.cc b/ash/wm/desks/desk_bar_view_base.cc index b74135a..24cd83ac 100644 --- a/ash/wm/desks/desk_bar_view_base.cc +++ b/ash/wm/desks/desk_bar_view_base.cc
@@ -538,7 +538,7 @@ new_desk_button_label_->SetPaintToLayer(); new_desk_button_label_->layer()->SetFillsBoundsOpaquely(false); - if (saved_desk_util::IsSavedDesksEnabled()) { + if (saved_desk_util::ShouldShowSavedDesksButtons()) { int button_text_id = IDS_ASH_DESKS_TEMPLATES_DESKS_BAR_BUTTON_LIBRARY; if (!saved_desk_util::AreDesksTemplatesEnabled()) { button_text_id = IDS_ASH_DESKS_TEMPLATES_DESKS_BAR_BUTTON_SAVED_FOR_LATER; @@ -882,7 +882,7 @@ } void DeskBarViewBase::UpdateButtonsForSavedDeskGrid() { - if (IsZeroState() || !saved_desk_util::IsSavedDesksEnabled()) { + if (IsZeroState() || !saved_desk_util::ShouldShowSavedDesksButtons()) { return; } @@ -906,7 +906,7 @@ } void DeskBarViewBase::UpdateLibraryButtonVisibility() { - if (!saved_desk_util::IsSavedDesksEnabled()) { + if (!saved_desk_util::ShouldShowSavedDesksButtons()) { return; } @@ -987,7 +987,7 @@ bool DeskBarViewBase::ShouldShowLibraryUi() { // Only update visibility when needed. This will save a lot of repeated work. if (library_ui_visibility_ == LibraryUiVisibility::kToBeChecked) { - if (!saved_desk_util::IsSavedDesksEnabled() || + if (!saved_desk_util::ShouldShowSavedDesksButtons() || display::Screen::GetScreen()->InTabletMode()) { library_ui_visibility_ = LibraryUiVisibility::kHidden; } else {
diff --git a/ash/wm/desks/desks_util.cc b/ash/wm/desks/desks_util.cc index 7370256..17a68f0 100644 --- a/ash/wm/desks/desks_util.cc +++ b/ash/wm/desks/desks_util.cc
@@ -184,8 +184,13 @@ } bool ShouldDesksBarBeCreated() { - return !display::Screen::GetScreen()->InTabletMode() || - DesksController::Get()->desks().size() > 1; + if (display::Screen::GetScreen()->InTabletMode()) { + return DesksController::Get()->desks().size() > 1; + } + + // If in clamshell mode, and overview was started by faster splitscreen setup, + // don't show the desk bar. + return !window_util::IsInFasterSplitScreenSetupSession(); } ui::Compositor* GetSelectedCompositorForPerformanceMetrics() {
diff --git a/ash/wm/desks/templates/saved_desk_library_view.cc b/ash/wm/desks/templates/saved_desk_library_view.cc index b1457a8..1bfbbf2 100644 --- a/ash/wm/desks/templates/saved_desk_library_view.cc +++ b/ash/wm/desks/templates/saved_desk_library_view.cc
@@ -262,8 +262,8 @@ scroll_view_->SetHorizontalScrollBarMode( views::ScrollView::ScrollBarMode::kDisabled); // Use ash style rounded scroll bar just like `AppListBubbleAppsPage`. - auto vertical_scroll = - std::make_unique<RoundedScrollBar>(/*horizontal=*/false); + auto vertical_scroll = std::make_unique<RoundedScrollBar>( + views::ScrollBar::Orientation::kVertical); vertical_scroll->SetInsets(kLibraryPageVerticalScrollInsets); vertical_scroll->SetSnapBackOnDragOutside(false); scroll_view_->SetVerticalScrollBar(std::move(vertical_scroll)); @@ -291,7 +291,7 @@ scroll_contents->AddChildView(std::move(group_contents)); } - if (saved_desk_util::IsSavedDesksEnabled()) { + if (saved_desk_util::ShouldShowSavedDesksButtons()) { auto group_contents = GetLabelAndGridGroupContents(); save_and_recall_grid_view_ = group_contents->AddChildView(std::make_unique<SavedDeskGridView>());
diff --git a/ash/wm/desks/templates/saved_desk_save_desk_button_container.cc b/ash/wm/desks/templates/saved_desk_save_desk_button_container.cc index 7158220f..b4bff89 100644 --- a/ash/wm/desks/templates/saved_desk_save_desk_button_container.cc +++ b/ash/wm/desks/templates/saved_desk_save_desk_button_container.cc
@@ -159,7 +159,7 @@ &kSaveDeskAsTemplateIcon)); } - if (saved_desk_util::IsSavedDesksEnabled()) { + if (saved_desk_util::ShouldShowSavedDesksButtons()) { save_desk_for_later_button_ = AddChildView(std::make_unique<SavedDeskSaveDeskButton>( save_for_later_callback,
diff --git a/ash/wm/desks/templates/saved_desk_util.cc b/ash/wm/desks/templates/saved_desk_util.cc index d8bc2b9..568e834 100644 --- a/ash/wm/desks/templates/saved_desk_util.cc +++ b/ash/wm/desks/templates/saved_desk_util.cc
@@ -13,6 +13,7 @@ #include "ash/wm/desks/templates/saved_desk_constants.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_session.h" +#include "ash/wm/window_util.h" #include "base/containers/adapters.h" #include "components/app_restore/full_restore_utils.h" #include "components/app_restore/window_properties.h" @@ -80,9 +81,10 @@ return features::AreDesksTemplatesEnabled(); } -bool IsSavedDesksEnabled() { - return !IsGuestSession(); +bool ShouldShowSavedDesksButtons() { + return !IsGuestSession() && !window_util::IsInFasterSplitScreenSetupSession(); } + SavedDeskDialogController* GetSavedDeskDialogController() { auto* overview_controller = Shell::Get()->overview_controller(); if (!overview_controller->InOverviewSession())
diff --git a/ash/wm/desks/templates/saved_desk_util.h b/ash/wm/desks/templates/saved_desk_util.h index cdb5c2a..7759699a 100644 --- a/ash/wm/desks/templates/saved_desk_util.h +++ b/ash/wm/desks/templates/saved_desk_util.h
@@ -28,7 +28,7 @@ ASH_EXPORT bool AreDesksTemplatesEnabled(); -ASH_EXPORT bool IsSavedDesksEnabled(); +ASH_EXPORT bool ShouldShowSavedDesksButtons(); // Will return null if overview mode is not active. ASH_EXPORT SavedDeskDialogController* GetSavedDeskDialogController();
diff --git a/ash/wm/overview/overview_focus_cycler.cc b/ash/wm/overview/overview_focus_cycler.cc index 03213c1e..9695f655 100644 --- a/ash/wm/overview/overview_focus_cycler.cc +++ b/ash/wm/overview/overview_focus_cycler.cc
@@ -8,6 +8,7 @@ #include "ash/accessibility/magnifier/magnifier_utils.h" #include "ash/accessibility/scoped_a11y_override_window_setter.h" #include "ash/shell.h" +#include "ash/style/icon_button.h" #include "ash/wm/desks/desk_icon_button.h" #include "ash/wm/desks/desk_mini_view.h" #include "ash/wm/desks/desk_name_view.h" @@ -25,6 +26,7 @@ #include "ash/wm/overview/overview_item_view.h" #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_utils.h" +#include "ash/wm/splitview/faster_split_view.h" #include "base/containers/contains.h" #include "base/ranges/algorithm.h" #include "chromeos/constants/chromeos_features.h" @@ -274,6 +276,10 @@ if (grid->IsSaveDeskForLaterButtonVisible()) { traversable_views.push_back(grid->GetSaveDeskForLaterButton()); } + if (auto* faster_split_view = grid->GetFasterSplitView()) { + traversable_views.push_back(faster_split_view->toast()); + traversable_views.push_back(faster_split_view->settings_button()); + } } return traversable_views; }
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index fbab0fb..eef661a 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -24,8 +24,6 @@ #include "ash/shell_delegate.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" -#include "ash/style/icon_button.h" -#include "ash/style/system_toast_style.h" #include "ash/system/toast/toast_manager_impl.h" #include "ash/wallpaper/wallpaper_controller_impl.h" #include "ash/wm/desks/default_desk_button.h" @@ -61,6 +59,7 @@ #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_window_drag_controller.h" #include "ash/wm/overview/scoped_overview_animation_settings.h" +#include "ash/wm/splitview/faster_split_view.h" #include "ash/wm/splitview/split_view_constants.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_divider.h" @@ -122,10 +121,6 @@ // splitscreen toast widget. constexpr int kFasterSplitScreenToastSpacingDp = 40; -// Distance from the right of the faster splitscreen toast to the left of the -// settings button. -constexpr int kSettingsButtonSpacingDp = 8; - // Windows are not allowed to get taller than this. constexpr int kMaxHeight = 512; @@ -815,6 +810,8 @@ } UpdateSaveDeskButtons(); + // Needed to include the toast when we init the grid. + UpdateFasterSplitViewWidget(); // This is a no-op if the feature ContinuousOverviewScrollAnimation is not // enabled. Once windows are placed at their final positions, clear transforms @@ -2098,8 +2095,9 @@ // overview grid changes, i.e. switches between active desks and/or the // saved desk grid. This will be needed when we make it so that switching // desks keeps us in overview mode. - if (!saved_desk_util::IsSavedDesksEnabled()) + if (!saved_desk_util::ShouldShowSavedDesksButtons()) { return; + } // If there is only one item and it is animating to close, hide the widget as // the closing window cannot be saved as part of a template. @@ -2306,6 +2304,13 @@ : nullptr; } +FasterSplitView* OverviewGrid::GetFasterSplitView() { + return faster_splitview_widget_ + ? views::AsViewClass<FasterSplitView>( + faster_splitview_widget_->GetContentsView()) + : nullptr; +} + void OverviewGrid::OnSplitViewStateChanged( SplitViewController::State previous_state, SplitViewController::State state) { @@ -2824,8 +2829,9 @@ void OverviewGrid::UpdateNumSavedDeskUnsupportedWindows( const std::vector<raw_ptr<aura::Window, VectorExperimental>>& windows, bool increment) { - if (!saved_desk_util::IsSavedDesksEnabled()) + if (!saved_desk_util::ShouldShowSavedDesksButtons()) { return; + } int addend = increment ? 1 : -1; @@ -2926,33 +2932,12 @@ params.init_properties_container.SetProperty(kOverviewUiKey, true); faster_splitview_widget_ = std::make_unique<views::Widget>(std::move(params)); - auto* box_layout_view = faster_splitview_widget_->SetContentsView( - std::make_unique<views::BoxLayoutView>()); - box_layout_view->SetOrientation(views::BoxLayout::Orientation::kHorizontal); - box_layout_view->SetBetweenChildSpacing(kSettingsButtonSpacingDp); - - box_layout_view->AddChildView(std::make_unique<SystemToastStyle>( + faster_splitview_widget_->GetLayer()->SetFillsBoundsOpaquely(false); + faster_splitview_widget_->SetContentsView(std::make_unique<FasterSplitView>( base::BindRepeating(&OverviewGrid::OnSkipButtonPressed, weak_ptr_factory_.GetWeakPtr()), - l10n_util::GetStringUTF16(IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST), - l10n_util::GetStringUTF16( - IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_SKIP))); - - auto* settings_button = - box_layout_view->AddChildView(std::make_unique<IconButton>( - base::BindRepeating(&OverviewGrid::OnSettingsButtonPressed, - weak_ptr_factory_.GetWeakPtr()), - IconButton::Type::kLarge, &kOverviewSettingsIcon, - IDS_ASH_OVERVIEW_SETTINGS_BUTTON_LABEL)); - - // TODO(b/323199185): Consider refactoring this from `SystemToastStyle`. - const int toast_height = settings_button->GetPreferredSize().height(); - const float toast_corner_radius = toast_height / 2.0f; - settings_button->SetBorder(std::make_unique<views::HighlightBorder>( - toast_corner_radius, - views::HighlightBorder::Type::kHighlightBorderOnShadow)); - settings_button->SetBackgroundColor(kColorAshShieldAndBase80); - + base::BindRepeating(&OverviewGrid::OnSettingsButtonPressed, + weak_ptr_factory_.GetWeakPtr()))); faster_splitview_widget_->Show(); } @@ -2977,7 +2962,7 @@ kFasterSplitScreenToastSpacingDp); faster_splitview_widget_->SetBounds(centered_bounds); - // TODO(b/323409897): Add a11y focus traversal and Chromevox support. + overview_session_->UpdateAccessibilityFocus(); } } // namespace ash
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index 2244721..8d965c7e 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -12,6 +12,7 @@ #include "ash/public/cpp/wallpaper/wallpaper_controller_observer.h" #include "ash/rotator/screen_rotation_animator_observer.h" +#include "ash/style/icon_button.h" #include "ash/style/rounded_label_widget.h" #include "ash/wm/desks/templates/saved_desk_save_desk_button_container.h" #include "ash/wm/overview/overview_item.h" @@ -41,6 +42,7 @@ namespace ash { +class FasterSplitView; class LegacyDeskBarView; class OverviewDropTarget; class OverviewGridEventHandler; @@ -399,6 +401,8 @@ SavedDeskSaveDeskButtonContainer* GetSaveDeskButtonContainer(); const SavedDeskSaveDeskButtonContainer* GetSaveDeskButtonContainer() const; + FasterSplitView* GetFasterSplitView(); + // SplitViewObserver: void OnSplitViewStateChanged(SplitViewController::State previous_state, SplitViewController::State state) override; @@ -428,6 +432,7 @@ // Returns the root window in which the grid displays the windows. aura::Window* root_window() { return root_window_; } + const aura::Window* root_window() const { return root_window_; } OverviewSession* overview_session() { return overview_session_; } @@ -466,6 +471,10 @@ return save_desk_button_container_widget_.get(); } + views::Widget* faster_splitview_widget() { + return faster_splitview_widget_.get(); + } + int num_incognito_windows() const { return num_incognito_windows_; } int num_unsupported_windows() const { return num_unsupported_windows_; } @@ -473,9 +482,6 @@ const gfx::Rect bounds_for_testing() const { return bounds_; } float scroll_offset_for_testing() const { return scroll_offset_; } views::Widget* pine_widget_for_testing() const { return pine_widget_.get(); } - views::Widget* faster_splitview_widget_for_testing() { - return faster_splitview_widget_.get(); - } private: friend class DesksTemplatesTest;
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc index 9dc7767..693222c 100644 --- a/ash/wm/overview/overview_session.cc +++ b/ash/wm/overview/overview_session.cc
@@ -175,7 +175,7 @@ Shell::Get()->AddShellObserver(this); - if (saved_desk_util::IsSavedDesksEnabled()) { + if (saved_desk_util::ShouldShowSavedDesksButtons()) { hide_windows_for_saved_desks_grid_ = std::make_unique< ScopedOverviewHideWindows>( /*windows=*/std::vector<raw_ptr<aura::Window, VectorExperimental>>{}, @@ -192,7 +192,8 @@ } // Create this before the desks bar widget. - if (saved_desk_util::IsSavedDesksEnabled() && !saved_desk_presenter_) { + if (saved_desk_util::ShouldShowSavedDesksButtons() && + !saved_desk_presenter_) { saved_desk_presenter_ = std::make_unique<SavedDeskPresenter>(this); saved_desk_dialog_controller_ = std::make_unique<SavedDeskDialogController>(); @@ -938,8 +939,9 @@ } bool OverviewSession::IsSavedDeskUiLosingActivation(aura::Window* lost_active) { - if (!saved_desk_util::IsSavedDesksEnabled() || !lost_active) + if (!saved_desk_util::ShouldShowSavedDesksButtons() || !lost_active) { return false; + } for (auto& grid : grid_list_) { auto* desk_library_view = grid->GetSavedDeskLibraryView(); @@ -1025,7 +1027,10 @@ } void OverviewSession::OnRootWindowClosing(aura::Window* root) { - auto iter = base::ranges::find(grid_list_, root, &OverviewGrid::root_window); + auto iter = base::ranges::find_if( + grid_list_, [root](const std::unique_ptr<OverviewGrid>& grid) { + return grid->root_window() == root; + }); DCHECK(iter != grid_list_.end()); (*iter)->Shutdown(OverviewEnterExitType::kImmediateExit); grid_list_.erase(iter); @@ -1215,15 +1220,21 @@ for (const auto& item : grid->window_list()) a11y_widgets.push_back(item->item_widget()); } - if (grid->desks_widget()) + if (grid->desks_widget()) { a11y_widgets.push_back(const_cast<views::Widget*>(grid->desks_widget())); + } - if (grid->IsSaveDeskButtonContainerVisible()) + if (grid->IsSaveDeskButtonContainerVisible()) { a11y_widgets.push_back(grid->save_desk_button_container_widget()); + } if (auto* no_windows_widget = grid->no_windows_widget()) { a11y_widgets.push_back(no_windows_widget); } + + if (auto* faster_splitview_widget = grid->faster_splitview_widget()) { + a11y_widgets.push_back(faster_splitview_widget); + } } if (a11y_widgets.empty()) @@ -1581,7 +1592,7 @@ } void OverviewSession::OnTabletModeChanged() { - DCHECK(saved_desk_util::IsSavedDesksEnabled()); + 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 a1c3492..05f4da03 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -3212,7 +3212,7 @@ // flip for Save & Recall has truly landed, remove the `NoSavedDesks` variant // of this test below and remove the Save & Recall feature check at the start // of this test. - if (GetParam() || !saved_desk_util::IsSavedDesksEnabled()) { + if (GetParam() || !saved_desk_util::ShouldShowSavedDesksButtons()) { return; } @@ -3265,7 +3265,7 @@ TEST_P(OverviewSessionTest, AccessibilityFocusAnnotatorNoSavedDesks) { // If saved desk is enabled, the a11y order changes. This is tested in // the saved desk test suite. - if (GetParam() || saved_desk_util::IsSavedDesksEnabled()) { + if (GetParam() || saved_desk_util::ShouldShowSavedDesksButtons()) { return; }
diff --git a/ash/wm/snap_group/snap_group_unittest.cc b/ash/wm/snap_group/snap_group_unittest.cc index 2a50999..e8438c8 100644 --- a/ash/wm/snap_group/snap_group_unittest.cc +++ b/ash/wm/snap_group/snap_group_unittest.cc
@@ -40,6 +40,7 @@ #include "ash/wm/overview/overview_window_drag_controller.h" #include "ash/wm/overview/scoped_overview_transform_window.h" #include "ash/wm/snap_group/snap_group_controller.h" +#include "ash/wm/splitview/faster_split_view.h" #include "ash/wm/splitview/split_view_constants.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_divider.h" @@ -178,8 +179,10 @@ if (!Shell::Get()->IsInTabletMode() && faster_split_screen_setup) { auto* overview_grid = GetOverviewGridForRoot(window->GetRootWindow()); - EXPECT_TRUE(overview_grid->faster_splitview_widget_for_testing()); + EXPECT_TRUE(overview_grid->faster_splitview_widget()); EXPECT_FALSE(overview_grid->no_windows_widget()); + EXPECT_FALSE(overview_grid->GetSaveDeskButtonContainer()); + EXPECT_FALSE(overview_grid->desks_bar_view()); } return split_view_overview_session; @@ -249,7 +252,7 @@ // Test fixture to verify faster split screen feature. -class FasterSplitScreenTest : public AshTestBase { +class FasterSplitScreenTest : public OverviewTestBase { public: FasterSplitScreenTest() : scoped_feature_list_(features::kFasterSplitScreenSetup) {} @@ -259,7 +262,7 @@ // AshTestBase: void SetUp() override { - AshTestBase::SetUp(); + OverviewTestBase::SetUp(); WindowCycleList::SetDisableInitialDelayForTesting(true); } @@ -336,7 +339,7 @@ ToggleOverview(); auto* overview_grid = GetOverviewGridForRoot(w1->GetRootWindow()); EXPECT_FALSE(overview_grid->no_windows_widget()); - EXPECT_FALSE(overview_grid->faster_splitview_widget_for_testing()); + EXPECT_FALSE(overview_grid->faster_splitview_widget()); } // Tests that faster split screen can only start with certain snap action @@ -636,8 +639,7 @@ auto* overview_grid = GetOverviewGridForRoot(w1->GetRootWindow()); ASSERT_TRUE(overview_grid); - auto* faster_splitview_widget = - overview_grid->faster_splitview_widget_for_testing(); + auto* faster_splitview_widget = overview_grid->faster_splitview_widget(); ASSERT_TRUE(faster_splitview_widget); auto* toast_view = views::AsViewClass<SystemToastStyle>( faster_splitview_widget->GetContentsView()->children()[0]); @@ -1041,6 +1043,68 @@ GetEventGenerator()->GestureTapAt(divider_center); } +TEST_F(FasterSplitScreenTest, BasicTabKeyNavigation) { + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + + const WindowSnapWMEvent snap_event(WM_EVENT_SNAP_PRIMARY, + WindowSnapActionSource::kTest); + WindowState::Get(window1.get())->OnWMEvent(&snap_event); + ASSERT_TRUE(OverviewController::Get()->InOverviewSession()); + + // Tab until we get to the first overview item. + SendKeyUntilOverviewItemIsFocused(ui::VKEY_TAB); + const std::vector<std::unique_ptr<OverviewItemBase>>& overview_windows = + GetOverviewItemsForRoot(0); + EXPECT_EQ(overview_windows[0]->GetWindow(), GetOverviewFocusedWindow()); + + OverviewFocusCycler* focus_cycler = GetOverviewSession()->focus_cycler(); + OverviewGrid* grid = GetOverviewSession()->grid_list()[0].get(); + + // Tab to the toast dismiss button. + PressAndReleaseKey(ui::VKEY_TAB); + EXPECT_EQ(grid->GetFasterSplitView()->toast()->dismiss_button(), + focus_cycler->focused_view()->GetView()); + + // Tab to the settings button. + PressAndReleaseKey(ui::VKEY_TAB); + EXPECT_EQ(grid->GetFasterSplitView()->settings_button(), + focus_cycler->focused_view()); +} + +TEST_F(FasterSplitScreenTest, AccessibilityFocusAnnotator) { + auto window1 = CreateTestWindow(gfx::Rect(100, 100)); + auto window0 = CreateTestWindow(gfx::Rect(100, 100)); + + // Snap `window0`, so it is excluded from the overview list. + SnapOneTestWindow(window0.get(), chromeos::WindowStateType::kPrimarySnapped, + chromeos::kDefaultSnapRatio, + WindowSnapActionSource::kDragWindowToEdgeToSnap); + + auto* focus_widget = views::Widget::GetWidgetForNativeWindow( + GetOverviewSession()->GetOverviewFocusWindow()); + ASSERT_TRUE(focus_widget); + OverviewGrid* grid = GetOverviewSession()->grid_list()[0].get(); + ASSERT_FALSE(grid->desks_widget()); + ASSERT_FALSE(grid->GetSaveDeskForLaterButton()); + auto* faster_splitview_widget = grid->faster_splitview_widget(); + ASSERT_TRUE(faster_splitview_widget); + + // Overview items are in MRU order, so the expected order in the grid list is + // the reverse creation order. + auto* item_widget1 = GetOverviewItemForWindow(window1.get())->item_widget(); + + // Order should be [focus_widget, item_widget1, faster_splitview_widget]. + CheckA11yOverrides("focus", focus_widget, + /*expected_previous=*/faster_splitview_widget, + /*expected_next=*/item_widget1); + CheckA11yOverrides("item1", item_widget1, /*expected_previous=*/focus_widget, + /*expected_next=*/faster_splitview_widget); + CheckA11yOverrides("splitview", faster_splitview_widget, + /*expected_previous=*/item_widget1, + /*expected_next=*/focus_widget); +} + // Tests the histograms for the split view overview session exit points are // recorded correctly in clamshell. TEST_F(FasterSplitScreenTest,
diff --git a/ash/wm/splitview/faster_split_view.cc b/ash/wm/splitview/faster_split_view.cc new file mode 100644 index 0000000..502e6d59 --- /dev/null +++ b/ash/wm/splitview/faster_split_view.cc
@@ -0,0 +1,115 @@ +// 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/splitview/faster_split_view.h" + +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/shell.h" +#include "ash/shell_delegate.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/style/ash_color_id.h" +#include "ash/style/system_toast_style.h" +#include "ash/wm/overview/overview_controller.h" +#include "ash/wm/overview/overview_utils.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/compositor/layer.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/highlight_border.h" +#include "ui/views/view_utils.h" + +namespace ash { + +namespace { + +// Distance from the right of the faster splitscreen toast to the left of the +// settings button. +constexpr int kSettingsButtonSpacingDp = 8; + +} // namespace + +FasterSplitViewToast::FasterSplitViewToast(base::RepeatingClosure skip_callback) + : SystemToastStyle( + std::move(skip_callback), + l10n_util::GetStringUTF16(IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST), + l10n_util::GetStringUTF16( + IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_SKIP)) { + dismiss_button()->SetTooltipText(l10n_util::GetStringUTF16( + IDS_ASH_OVERVIEW_FASTER_SPLITSCREEN_TOAST_DISMISS_WINDOW_SUGGESTIONS)); +} + +views::View* FasterSplitViewToast::GetView() { + return dismiss_button(); +} + +void FasterSplitViewToast::MaybeActivateFocusedView() { + // TODO(sophiewen): Copy `skip_callback` and run it. + // Destroys `this`. + OverviewController::Get()->EndOverview(OverviewEndAction::kKeyEscapeOrBack); +} + +void FasterSplitViewToast::MaybeCloseFocusedView(bool primary_action) {} + +void FasterSplitViewToast::MaybeSwapFocusedView(bool right) {} + +void FasterSplitViewToast::OnFocusableViewFocused() {} + +void FasterSplitViewToast::OnFocusableViewBlurred() {} + +BEGIN_METADATA(FasterSplitViewToast, SystemToastStyle) +END_METADATA + +FasterSplitViewSettingsButton::FasterSplitViewSettingsButton( + views::Button::PressedCallback settings_callback) + : IconButton(std::move(settings_callback), + IconButton::Type::kLarge, + &kOverviewSettingsIcon, + IDS_ASH_OVERVIEW_SETTINGS_BUTTON_LABEL) {} + +views::View* FasterSplitViewSettingsButton::GetView() { + return this; +} +void FasterSplitViewSettingsButton::MaybeActivateFocusedView() { + // TODO(sophiewen): Copy `settings_callback` and run it. + // Destroys `this`. + Shell::Get()->shell_delegate()->OpenMultitaskingSettings(); +} +void FasterSplitViewSettingsButton::MaybeCloseFocusedView(bool primary_action) { +} + +void FasterSplitViewSettingsButton::MaybeSwapFocusedView(bool right) {} + +void FasterSplitViewSettingsButton::OnFocusableViewFocused() {} + +void FasterSplitViewSettingsButton::OnFocusableViewBlurred() {} + +BEGIN_METADATA(FasterSplitViewSettingsButton, views::View) +END_METADATA + +FasterSplitView::FasterSplitView( + base::RepeatingClosure skip_callback, + views::Button::PressedCallback settings_callback) { + SetOrientation(views::BoxLayout::Orientation::kHorizontal); + SetBetweenChildSpacing(kSettingsButtonSpacingDp); + + toast_ = AddChildView( + std::make_unique<FasterSplitViewToast>(std::move(skip_callback))); + + settings_button_ = + AddChildView(std::make_unique<FasterSplitViewSettingsButton>( + std::move(settings_callback))); + + // TODO(b/323199185): Consider refactoring this from `SystemToastStyle`. + const int toast_height = settings_button_->GetPreferredSize().height(); + const float toast_corner_radius = toast_height / 2.0f; + settings_button_->SetBorder(std::make_unique<views::HighlightBorder>( + toast_corner_radius, + views::HighlightBorder::Type::kHighlightBorderOnShadow)); + settings_button_->SetBackgroundColor(kColorAshShieldAndBase80); +} + +BEGIN_METADATA(FasterSplitView, views::BoxLayoutView) +END_METADATA + +} // namespace ash
diff --git a/ash/wm/splitview/faster_split_view.h b/ash/wm/splitview/faster_split_view.h new file mode 100644 index 0000000..0727a41f --- /dev/null +++ b/ash/wm/splitview/faster_split_view.h
@@ -0,0 +1,83 @@ +// 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_SPLITVIEW_FASTER_SPLIT_VIEW_H_ +#define ASH_WM_SPLITVIEW_FASTER_SPLIT_VIEW_H_ + +#include "ash/style/icon_button.h" +#include "ash/style/system_toast_style.h" +#include "ash/wm/overview/overview_focusable_view.h" +#include "base/functional/callback.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/layout/box_layout_view.h" + +namespace ash { + +// A toast in faster splitscreen setup. Contains a dialog and skip button. +class FasterSplitViewToast : public SystemToastStyle, + public OverviewFocusableView { + public: + METADATA_HEADER(FasterSplitViewToast); + + explicit FasterSplitViewToast(base::RepeatingClosure skip_callback); + FasterSplitViewToast(const FasterSplitViewToast&) = delete; + FasterSplitViewToast& operator=(const FasterSplitViewToast&) = delete; + ~FasterSplitViewToast() override = default; + + // OverviewFocusableView: + views::View* GetView() override; + void MaybeActivateFocusedView() override; + void MaybeCloseFocusedView(bool primary_action) override; + void MaybeSwapFocusedView(bool right) override; + void OnFocusableViewFocused() override; + void OnFocusableViewBlurred() override; +}; + +// A settings button in faster splitscreen setup. +class FasterSplitViewSettingsButton : public IconButton, + public OverviewFocusableView { + public: + METADATA_HEADER(FasterSplitViewSettingsButton); + + explicit FasterSplitViewSettingsButton( + views::Button::PressedCallback settings_callback); + FasterSplitViewSettingsButton(const FasterSplitViewSettingsButton&) = delete; + FasterSplitViewSettingsButton& operator=( + const FasterSplitViewSettingsButton&) = delete; + ~FasterSplitViewSettingsButton() override = default; + + // OverviewFocusableView: + views::View* GetView() override; + void MaybeActivateFocusedView() override; + void MaybeCloseFocusedView(bool primary_action) override; + void MaybeSwapFocusedView(bool right) override; + void OnFocusableViewFocused() override; + void OnFocusableViewBlurred() override; +}; + +// A container for the contents view of the faster splitscreen setup widget. +// TODO(b/324347613): Find a better name for this class. +class FasterSplitView : public views::BoxLayoutView { + METADATA_HEADER(FasterSplitView, views::BoxLayoutView) + + public: + FasterSplitView(base::RepeatingClosure skip_callback, + views::Button::PressedCallback settings_callback); + FasterSplitView(const FasterSplitView&) = delete; + FasterSplitView& operator=(const FasterSplitView&) = delete; + ~FasterSplitView() override = default; + + // TODO(sophiewen): Store these as OverviewFocusableViews and private these + // from the header. + FasterSplitViewToast* toast() { return toast_; } + FasterSplitViewSettingsButton* settings_button() { return settings_button_; } + + private: + raw_ptr<FasterSplitViewToast> toast_ = nullptr; + raw_ptr<FasterSplitViewSettingsButton> settings_button_ = nullptr; +}; + +} // namespace ash + +#endif // ASH_WM_SPLITVIEW_FASTER_SPLIT_VIEW_H_
diff --git a/ash/wm/splitview/split_view_overview_session.cc b/ash/wm/splitview/split_view_overview_session.cc index b699a4ea..69ccb951 100644 --- a/ash/wm/splitview/split_view_overview_session.cc +++ b/ash/wm/splitview/split_view_overview_session.cc
@@ -64,10 +64,12 @@ return; } + // Set the type before we start overview, which will initialize the grid and + // check whether to create the desk bar and buttons based on `setup_type_`. + setup_type_ = SplitViewOverviewSetupType::kSnapThenAutomaticOverview; OverviewController::Get()->StartOverview( action.value_or(OverviewStartAction::kFasterSplitScreenSetup), type.value_or(OverviewEnterExitType::kNormal)); - setup_type_ = SplitViewOverviewSetupType::kSnapThenAutomaticOverview; } void SplitViewOverviewSession::RecordSplitViewOverviewSessionExitPointMetrics(
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc index 721a6fb..496fe8b 100644 --- a/ash/wm/window_util.cc +++ b/ash/wm/window_util.cc
@@ -734,7 +734,7 @@ SnapGroupController::Get()); } -bool IsInFasterSplitScreenSetupSession(aura::Window* window) { +bool IsInFasterSplitScreenSetupSession(const aura::Window* window) { SplitViewOverviewSession* split_view_overview_session = RootWindowController::ForWindow(window)->split_view_overview_session(); return !Shell::Get()->IsInTabletMode() && split_view_overview_session && @@ -742,4 +742,18 @@ SplitViewOverviewSetupType::kSnapThenAutomaticOverview; } +bool IsInFasterSplitScreenSetupSession() { + if (!IsInOverviewSession() || display::Screen::GetScreen()->InTabletMode()) { + return false; + } + auto* overview_session = GetOverviewSession(); + for (const auto& grid : overview_session->grid_list()) { + // Return true if any grid is in faster splitscreen setup. + if (IsInFasterSplitScreenSetupSession(grid->root_window())) { + return true; + } + } + return false; +} + } // namespace ash::window_util
diff --git a/ash/wm/window_util.h b/ash/wm/window_util.h index e10e109..67ea391 100644 --- a/ash/wm/window_util.h +++ b/ash/wm/window_util.h
@@ -219,7 +219,12 @@ // Returns true if `SplitViewOverviewSession` is created through faster split // screen setup, i.e. partial overview is started on the other side of the // screen when `window` is snapped. -bool IsInFasterSplitScreenSetupSession(aura::Window* window); +bool IsInFasterSplitScreenSetupSession(const aura::Window* window); + +// Returns true if overview is in session in clamshell mode and any overview +// grid is in faster splitview. This is a specific mode during which we don't +// show the desk bar or save desk buttons. +bool IsInFasterSplitScreenSetupSession(); } // namespace ash::window_util
diff --git a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc index 62449af4..537304f 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc +++ b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc
@@ -62,7 +62,7 @@ branch_size_in_bytes_ += usable_size; PA_DCHECK(branch_size_in_bytes_ <= capacity_in_bytes); - slots_.emplace_back(object, usable_size); + slots_.emplace_back(slot_start, usable_size); // Swap randomly so that the quarantine list remain shuffled. // This is not uniformly random, but sufficiently random. @@ -79,6 +79,17 @@ return true; } +bool LightweightQuarantineBranch::IsQuarantinedForTesting(void* object) { + ConditionalScopedGuard guard(lock_required_, lock_); + uintptr_t slot_start = root_.allocator_root_.ObjectToSlotStart(object); + for (const auto& slot : slots_) { + if (slot.slot_start == slot_start) { + return true; + } + } + return false; +} + void LightweightQuarantineBranch::PurgeInternal(size_t target_size_in_bytes) { size_t size_in_bytes = root_.size_in_bytes_.load(std::memory_order_acquire); int64_t freed_count = 0; @@ -91,14 +102,13 @@ const auto& to_free = slots_.back(); size_t to_free_size = to_free.usable_size; - auto* slot_span = SlotSpanMetadata::FromObject(to_free.object); - uintptr_t slot_start = - root_.allocator_root_.ObjectToSlotStart(to_free.object); - PA_DCHECK(slot_span == SlotSpanMetadata::FromSlotStart(slot_start)); + auto* slot_span = SlotSpanMetadata::FromSlotStart(to_free.slot_start); + void* object = root_.allocator_root_.SlotStartToObject(to_free.slot_start); + PA_DCHECK(slot_span == SlotSpanMetadata::FromObject(object)); - PA_DCHECK(to_free.object); - root_.allocator_root_.FreeNoHooksImmediate(to_free.object, slot_span, - slot_start); + PA_DCHECK(to_free.slot_start); + root_.allocator_root_.FreeNoHooksImmediate(object, slot_span, + to_free.slot_start); freed_count++; freed_size_in_bytes += to_free_size;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h index 5f763b23..aebff11 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h +++ b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h
@@ -127,15 +127,7 @@ } // Determines this list contains an object. - bool IsQuarantinedForTesting(void* object) { - ConditionalScopedGuard guard(lock_required_, lock_); - for (const auto& slot : slots_) { - if (slot.object == object) { - return true; - } - } - return false; - } + bool IsQuarantinedForTesting(void* object); Root& GetRoot() { return root_; } @@ -182,7 +174,7 @@ // `slots_` hold quarantined entries. struct QuarantineSlot { - void* object; + uintptr_t slot_start; size_t usable_size; }; std::vector<QuarantineSlot, InternalAllocator<QuarantineSlot>> slots_
diff --git a/base/containers/span.h b/base/containers/span.h index 8beadb6..a2686a8 100644 --- a/base/containers/span.h +++ b/base/containers/span.h
@@ -14,6 +14,7 @@ #include <iterator> #include <limits> #include <memory> +#include <span> #include <type_traits> #include <utility> @@ -429,6 +430,33 @@ std::copy(other.data(), other.data() + other.size(), data()); } + // Implicit conversion from std::span<T, N> to base::span<T, N>. + // + // We get other conversions for free from std::span's constructors, but it + // does not deduce N on its range constructor. + span(std::span<std::remove_const_t<T>, N> other) + : // SAFETY: std::span contains a valid data pointer and size such + // that pointer+size remains valid. + UNSAFE_BUFFERS( + span(std::ranges::data(other), std::ranges::size(other))) {} + span(std::span<T, N> other) + requires(std::is_const_v<T>) + : // SAFETY: std::span contains a valid data pointer and size such + // that pointer+size remains valid. + UNSAFE_BUFFERS( + span(std::ranges::data(other), std::ranges::size(other))) {} + + // Implicit conversion from base::span<T, N> to std::span<T, N>. + // + // We get other conversions for free from std::span's constructors, but it + // does not deduce N on its range constructor. + operator std::span<T, N>() const { return std::span<T, N>(*this); } + operator std::span<const T, N>() const + requires(!std::is_const_v<T>) + { + return std::span<const T, N>(*this); + } + private: // This field is not a raw_ptr<> because it was filtered by the rewriter // for: #constexpr-ctor-field-initializer, #global-scope, #union @@ -831,8 +859,8 @@ // * |std::size| should be preferred for plain arrays. // * In run-time contexts, functions such as |std::array::size| should be // preferred. -#define EXTENT(x) \ - ::base::internal::must_not_be_dynamic_extent<decltype( \ - ::base::make_span(x))::extent>() +#define EXTENT(x) \ + ::base::internal::must_not_be_dynamic_extent<decltype(::base::make_span( \ + x))::extent>() #endif // BASE_CONTAINERS_SPAN_H_
diff --git a/base/containers/span_nocompile.nc b/base/containers/span_nocompile.nc index 9c5a3ef1..41506d2a 100644 --- a/base/containers/span_nocompile.nc +++ b/base/containers/span_nocompile.nc
@@ -167,6 +167,18 @@ span s2(vector.data(), kSize2); // expected-error@*:* {{The source type is out of range for the destination type}} } +void BadConstConversionsWithStdSpan() { + int kData[] = {10, 11, 12}; + { + base::span<const int, 3u> fixed_base_span(kData); + std::span<int, 3u> s(fixed_base_span); // expected-error {{no matching constructor}} + } + { + std::span<const int, 3u> fixed_std_span(kData); + base::span<int, 3u> s(fixed_std_span); // expected-error {{no matching constructor}} + } +} + void FromVolatileArrayDisallowed() { static volatile int array[] = {1, 2, 3}; span<int> s(array); // expected-error {{no matching constructor for initialization of 'span<int>'}}
diff --git a/base/containers/span_unittest.cc b/base/containers/span_unittest.cc index f09e7c3..34f979d2 100644 --- a/base/containers/span_unittest.cc +++ b/base/containers/span_unittest.cc
@@ -1988,29 +1988,106 @@ // API decides to use it. The size() and data() convention should mean // that everyone's spans are compatible with each other. TEST(SpanTest, FromStdSpan) { - const int kData[] = {10, 11, 12}; - std::span std_span(kData); + int kData[] = {10, 11, 12}; + std::span<const int> std_span(kData); + std::span<int> mut_std_span(kData); + std::span<const int, 3u> fixed_std_span(kData); + std::span<int, 3u> mut_fixed_std_span(kData); - base::span base_span(std_span); - EXPECT_EQ(base_span.size(), 3u); - EXPECT_EQ(base_span.data(), kData); + // Tests *implicit* conversions through assignment construction. + { + base::span<const int> base_span = std_span; + EXPECT_EQ(base_span.size(), 3u); + EXPECT_EQ(base_span.data(), kData); + } + { + base::span<const int> base_span = mut_std_span; + EXPECT_EQ(base_span.size(), 3u); + EXPECT_EQ(base_span.data(), kData); + } + { + base::span<const int> base_span = fixed_std_span; + EXPECT_EQ(base_span.size(), 3u); + EXPECT_EQ(base_span.data(), kData); + } + { + base::span<const int> base_span = mut_fixed_std_span; + EXPECT_EQ(base_span.size(), 3u); + EXPECT_EQ(base_span.data(), kData); + } - auto base_made_span = base::make_span(std_span); - EXPECT_EQ(base_made_span.size(), 3u); - EXPECT_EQ(base_made_span.data(), kData); + { + base::span<const int, 3u> base_span = fixed_std_span; + EXPECT_EQ(base_span.size(), 3u); + EXPECT_EQ(base_span.data(), kData); + } + { + base::span<const int, 3u> base_span = mut_fixed_std_span; + EXPECT_EQ(base_span.size(), 3u); + EXPECT_EQ(base_span.data(), kData); + } + { + base::span<int, 3u> base_span = mut_fixed_std_span; + EXPECT_EQ(base_span.size(), 3u); + EXPECT_EQ(base_span.data(), kData); + } - auto base_byte_span = base::as_byte_span(std_span); - EXPECT_EQ(base_byte_span.size(), sizeof(int) * 3u); - EXPECT_EQ(base_byte_span.data(), reinterpret_cast<const uint8_t*>(kData)); + { + auto base_made_span = base::make_span(std_span); + EXPECT_EQ(base_made_span.size(), 3u); + EXPECT_EQ(base_made_span.data(), kData); + } + { + auto base_byte_span = base::as_byte_span(std_span); + EXPECT_EQ(base_byte_span.size(), sizeof(int) * 3u); + EXPECT_EQ(base_byte_span.data(), reinterpret_cast<const uint8_t*>(kData)); + } } TEST(SpanTest, ToStdSpan) { - const int kData[] = {10, 11, 12}; - base::span base_span(kData); + int kData[] = {10, 11, 12}; + base::span<const int> base_span(kData); + base::span<int> mut_base_span(kData); + base::span<const int, 3u> fixed_base_span(kData); + base::span<int, 3u> mut_fixed_base_span(kData); - std::span std_span(base_span); - EXPECT_EQ(std_span.size(), 3u); - EXPECT_EQ(std_span.data(), kData); + // Tests *implicit* conversions through assignment construction. + { + std::span<const int> std_span = base_span; + EXPECT_EQ(std_span.size(), 3u); + EXPECT_EQ(std_span.data(), kData); + } + { + std::span<const int> std_span = mut_base_span; + EXPECT_EQ(std_span.size(), 3u); + EXPECT_EQ(std_span.data(), kData); + } + { + std::span<const int> std_span = fixed_base_span; + EXPECT_EQ(std_span.size(), 3u); + EXPECT_EQ(std_span.data(), kData); + } + { + std::span<const int> std_span = mut_fixed_base_span; + EXPECT_EQ(std_span.size(), 3u); + EXPECT_EQ(std_span.data(), kData); + } + + { + std::span<const int, 3u> std_span = fixed_base_span; + EXPECT_EQ(std_span.size(), 3u); + EXPECT_EQ(std_span.data(), kData); + } + { + std::span<const int, 3u> std_span = mut_fixed_base_span; + EXPECT_EQ(std_span.size(), 3u); + EXPECT_EQ(std_span.data(), kData); + } + { + std::span<int, 3u> std_span = mut_fixed_base_span; + EXPECT_EQ(std_span.size(), 3u); + EXPECT_EQ(std_span.data(), kData); + } // no make_span() or as_byte_span() in std::span. }
diff --git a/base/task/thread_pool/thread_group.cc b/base/task/thread_pool/thread_group.cc index 00cc588..91d68d6 100644 --- a/base/task/thread_pool/thread_group.cc +++ b/base/task/thread_pool/thread_group.cc
@@ -189,8 +189,7 @@ max_tasks_ = max_tasks; DCHECK_GE(max_tasks_, 1U); - in_start().initial_max_tasks = max_tasks_; - DCHECK_LE(in_start().initial_max_tasks, kMaxNumberOfWorkers); + in_start().initial_max_tasks = std::min(max_tasks_, kMaxNumberOfWorkers); max_best_effort_tasks_ = max_best_effort_tasks; in_start().suggested_reclaim_time = suggested_reclaim_time; in_start().worker_environment = worker_environment;
diff --git a/base/task/thread_pool/thread_pool_instance.h b/base/task/thread_pool/thread_pool_instance.h index a4f78b3..1fd429d 100644 --- a/base/task/thread_pool/thread_pool_instance.h +++ b/base/task/thread_pool/thread_pool_instance.h
@@ -63,7 +63,9 @@ ~InitParams(); // Maximum number of unblocked tasks that can run concurrently in the - // foreground thread group. + // foreground thread group. This is capped at 256 (and should likely not be + // configured anywhere close to this in a browser, approaching that limit is + // most useful on compute farms running tests or compiles in parallel). size_t max_num_foreground_threads; // Maximum number of unblocked tasks that can run concurrently in the
diff --git a/build/config/siso/clang_code_coverage_wrapper.star b/build/config/siso/clang_code_coverage_wrapper.star index 70f18d4..9eb1c1c 100644 --- a/build/config/siso/clang_code_coverage_wrapper.star +++ b/build/config/siso/clang_code_coverage_wrapper.star
@@ -204,7 +204,9 @@ files_to_instrument = [] if instrument_file: files_to_instrument = str(ctx.fs.read(ctx.fs.canonpath(instrument_file))).splitlines() - files_to_instrument = [ctx.fs.canonpath(f) for f in files_to_instrument] + + # strip() is for removing '\r' on Windows. + files_to_instrument = [ctx.fs.canonpath(f).strip() for f in files_to_instrument] should_remove_flags = False if compile_source_file not in force_list: @@ -215,6 +217,7 @@ if should_remove_flags: return _remove_flags_from_command(compile_command) + print("Keeping code coverage flags for %s" % compile_source_file) return compile_command clang_code_coverage_wrapper = module(
diff --git a/build/config/siso/clang_linux.star b/build/config/siso/clang_linux.star index f74bbf2a..a4793525 100644 --- a/build/config/siso/clang_linux.star +++ b/build/config/siso/clang_linux.star
@@ -9,6 +9,8 @@ load("./android.star", "android") load("./clang_all.star", "clang_all") load("./clang_code_coverage_wrapper.star", "clang_code_coverage_wrapper") +load("./config.star", "config") +load("./cros.star", "cros") # TODO: b/323091468 - Propagate target android ABI and android SDK version # from GN, and remove remove hardcoded filegroups. @@ -52,6 +54,26 @@ "type": "glob", "includes": ["*"], }, + "third_party/llvm-build/Release+Asserts/lib/clang/18/lib:libs": { + "type": "glob", + "includes": ["*"], + }, + "third_party/llvm-build/Release+Asserts/lib/clang/18/share:share": { + "type": "glob", + "includes": ["*"], + }, + "build/linux/debian_bullseye_amd64-sysroot/lib/x86_64-linux-gnu:libso": { + "type": "glob", + "includes": ["*.so*"], + }, + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/x86_64-linux-gnu:libs": { + "type": "glob", + "includes": ["*.o", "*.so*", "lib*.a"], + }, + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/gcc/x86_64-linux-gnu:libgcc": { + "type": "glob", + "includes": ["*.o", "*.a", "*.so"], + }, } if android.enabled(ctx): for arch in android_archs: @@ -84,6 +106,23 @@ "build/linux/debian_bullseye_i386-sysroot/usr/include:include", "build/linux/debian_bullseye_i386-sysroot/usr/lib:headers", ], + "build/linux/debian_bullseye_amd64-sysroot:link": [ + "build/linux/debian_bullseye_amd64-sysroot/lib/x86_64-linux-gnu:libso", + "build/linux/debian_bullseye_amd64-sysroot/lib64/ld-linux-x86-64.so.2", + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/gcc/x86_64-linux-gnu:libgcc", + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/x86_64-linux-gnu:libs", + "third_party/llvm-build/Release+Asserts/bin/clang", + "third_party/llvm-build/Release+Asserts/bin/clang++", + "third_party/llvm-build/Release+Asserts/bin/ld.lld", + "third_party/llvm-build/Release+Asserts/bin/lld", + "third_party/llvm-build/Release+Asserts/bin/llvm-nm", + "third_party/llvm-build/Release+Asserts/bin/llvm-readelf", + "third_party/llvm-build/Release+Asserts/bin/llvm-readobj", + # The following inputs are used for sanitizer builds. + # It might be better to add them only for sanitizer builds if there is a performance issue. + "third_party/llvm-build/Release+Asserts/lib/clang/18/lib:libs", + "third_party/llvm-build/Release+Asserts/lib/clang/18/share:share", + ], "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot:headers": [ "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include:include", "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include:include", @@ -142,6 +181,52 @@ "timeout": "2m", }, ]) + + # TODO: b/316267242 - Enable remote links for Android and CrOS toolchain builds. + if not android.enabled(ctx) and not (cros.custom_toolchain(ctx) or cros.custom_sysroot(ctx)): + step_config["rules"].extend([ + { + "name": "clang/alink/llvm-ar", + "action": "(.*_)?alink", + "inputs": [ + # TODO: b/316267242 - Add inputs to GN config. + "third_party/llvm-build/Release+Asserts/bin/llvm-ar", + ], + "exclude_input_patterns": [ + "*.cc", + "*.h", + "*.js", + "*.pak", + "*.py", + "*.stamp", + ], + "remote": config.get(ctx, "remote-library-link"), + "platform_ref": "large", + "accumulate": True, + }, + { + "name": "clang/solink/gcc_solink_wrapper", + "action": "(.*_)?solink", + "command_prefix": "\"python3\" \"../../build/toolchain/gcc_solink_wrapper.py\"", + "inputs": [ + # TODO: b/316267242 - Add inputs to GN config. + "build/toolchain/gcc_solink_wrapper.py", + "build/toolchain/whole_archive.py", + "build/toolchain/wrapper_utils.py", + "build/linux/debian_bullseye_amd64-sysroot:link", + ], + "exclude_input_patterns": [ + "*.cc", + "*.h", + "*.js", + "*.pak", + "*.py", + "*.stamp", + ], + "remote": config.get(ctx, "remote-library-link"), + "platform_ref": "large", + }, + ]) return step_config clang = module(
diff --git a/build/config/siso/clang_mac.star b/build/config/siso/clang_mac.star index 415a932..1c21a1a 100644 --- a/build/config/siso/clang_mac.star +++ b/build/config/siso/clang_mac.star
@@ -75,8 +75,9 @@ "clang_large": largePlatform, }) step_config["input_deps"].update(clang_all.input_deps) + # TODO: https://issues.chromium.org/40120210 - remove this - # once we can use relative path in hmap. + # once we can use relative path in hmap. need_input_root_absolute_path_for_objc = False gn_args = gn.args(ctx) if gn_args.get("target_os") == "\"ios\"":
diff --git a/build/config/siso/config.star b/build/config/siso/config.star index 562cec7f..422345c 100644 --- a/build/config/siso/config.star +++ b/build/config/siso/config.star
@@ -12,6 +12,9 @@ # TODO: b/308405411 - Enable this config for all builders. "remote-devtools-frontend-typescript", + + # TODO: b/316267242 - Enable remote links after confirming performance. + "remote-library-link", ] def __check(ctx):
diff --git a/build/config/siso/cros.star b/build/config/siso/cros.star index 076eb86..6b95e04e 100644 --- a/build/config/siso/cros.star +++ b/build/config/siso/cros.star
@@ -122,6 +122,8 @@ cros = module( "cros", + custom_toolchain = __custom_toolchain, + custom_sysroot = __custom_sysroot, filegroups = __filegroups, handlers = __handlers, step_config = __step_config,
diff --git a/build/config/siso/linux.star b/build/config/siso/linux.star index 3067516..9969dac 100644 --- a/build/config/siso/linux.star +++ b/build/config/siso/linux.star
@@ -47,10 +47,13 @@ if android.enabled(ctx): step_config = android.step_config(ctx, step_config) + # nacl step config should be added before clang step config for link step + # rules. + step_config = nacl.step_config(ctx, step_config) + step_config = clang.step_config(ctx, step_config) step_config = cros.step_config(ctx, step_config) step_config = devtools_frontend.step_config(ctx, step_config) - step_config = nacl.step_config(ctx, step_config) step_config = nasm.step_config(ctx, step_config) step_config = proto.step_config(ctx, step_config) step_config = rust.step_config(ctx, step_config)
diff --git a/build/config/siso/nacl_linux.star b/build/config/siso/nacl_linux.star index e296d016..f6ee6e5 100644 --- a/build/config/siso/nacl_linux.star +++ b/build/config/siso/nacl_linux.star
@@ -51,6 +51,7 @@ def __step_config(ctx, step_config): step_config["rules"].extend([ + # pnacl { "name": "nacl/pnacl-clang++", "action": "newlib_pnacl.*_cxx", @@ -86,18 +87,34 @@ "input_root_absolute_path": True, }, { + "name": "nacl/pnacl-ar", + "action": "newlib_pnacl_alink", + "remote": False, + }, + # glibc + { "name": "nacl/glibc/x86_64-nacl-g++", "action": "glibc_x64_cxx", "inputs": [ "native_client/toolchain/linux_x86/nacl_x86_glibc/bin/x86_64-nacl-g++", ], # ELF-32 doesn't work on gVisor, - # so will local-fallback if gVisor is used. - # TODO(b/278485912): remote=True for trusted instance. "remote": False, - "input_root_absolute_path": True, }, { + "name": "nacl/glibc/x86_64-nacl-ar", + "action": "glibc_x64_alink", + # ELF-32 doesn't work on gVisor, + "remote": False, + }, + { + "name": "nacl/glibc/x86_64_solink/gcc_solink_wrapper", + "action": "glibc_x64_solink", + # ELF-32 doesn't work on gVisor, + "remote": False, + }, + # pnacl_newlib + { "name": "nacl/pnacl_newlib/x86_64-nacl-clang++", "action": "clang_newlib_x64_cxx", "inputs": [ @@ -120,6 +137,12 @@ "timeout": "2m", }, { + "name": "nacl/pnacl_newlib/x86_64-nacl-ar", + "action": "clang_newlib_x64_alink", + "remote": False, + }, + # saigo_newlib + { "name": "nacl/saigo_newlib/x86_64-nacl-clang++", "action": "irt_x64_cxx", "command_prefix": "../../native_client/toolchain/linux_x86/saigo_newlib/bin/x86_64-nacl-clang++", @@ -141,6 +164,11 @@ "input_root_absolute_path": True, "timeout": "2m", }, + { + "name": "nacl/saigo_newlib/x86_64-nacl-ar", + "action": "(.*_)?irt_x64_alink", + "remote": False, + }, ]) step_config["input_deps"].update({
diff --git a/build/config/siso/reproxy.star b/build/config/siso/reproxy.star index 7a78208a..8b264b6f 100644 --- a/build/config/siso/reproxy.star +++ b/build/config/siso/reproxy.star
@@ -283,11 +283,12 @@ new_rules.append(new_rule) continue - # clang will always have rewrapper config when use_remoteexec=true. + # clang cxx/cc will always have rewrapper config when use_remoteexec=true. # Remove the native siso handling and replace with custom rewrapper-specific handling. # All other rule values are not reused, instead use rewrapper config via handler. # (In particular, command_prefix should be avoided because it will be rewrapper.) - if rule["name"].startswith("clang/") or rule["name"].startswith("clang-cl/"): + if (rule["name"].startswith("clang/cxx") or rule["name"].startswith("clang/cc") or + rule["name"].startswith("clang-cl/cxx") or rule["name"].startswith("clang-cl/cc")): if not rule.get("action"): fail("clang rule %s found without action" % rule["name"])
diff --git a/build/fuchsia/test/flash_device.py b/build/fuchsia/test/flash_device.py index 41eaeff4..c4fd13b 100755 --- a/build/fuchsia/test/flash_device.py +++ b/build/fuchsia/test/flash_device.py
@@ -83,12 +83,16 @@ # This prevents multiple fastboot binaries from flashing concurrently, # which should increase the odds of flashing success. with lock(_FF_LOCK, timeout=_FF_LOCK_ACQ_TIMEOUT): + # The ffx.fastboot.inline_target has negative impact when ffx + # discovering devices in fastboot, so it's inlined here to limit its + # scope. See the discussion in https://fxbug.dev/issues/317228141. logging.info( 'Flash result %s', common.run_ffx_command(cmd=('target', 'flash', '-b', system_image_dir, '--no-bootloader-reboot'), target_id=target_id, + configs=['ffx.fastboot.inline_target=true'], capture_output=True).stdout)
diff --git a/build/fuchsia/test/isolate_daemon.py b/build/fuchsia/test/isolate_daemon.py index 30d6dd6..9e260b17 100755 --- a/build/fuchsia/test/isolate_daemon.py +++ b/build/fuchsia/test/isolate_daemon.py
@@ -47,7 +47,6 @@ ScopedFfxConfig('fastboot.flash.timeout_rate', '1'), ScopedFfxConfig('fastboot.reboot.reconnect_timeout', '120'), ScopedFfxConfig('fastboot.usb.disabled', 'true'), - ScopedFfxConfig('ffx.fastboot.inline_target', 'true'), ScopedFfxConfig('log.level', 'debug'), ScopedFfxConfig('repository.server.listen', '"[::]:0"'), ] + (extra_inits or [])
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 798353c7..88fcca8a 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision vars in //DEPS. - libcxx_revision = "9d119c1f4a097b7d27210874f4eba3fc91a83a4e" + libcxx_revision = "c51c9efb6c5a83e0e25c1e30864449d2beadd7a8" }
diff --git a/buildtools/reclient_cfgs/linux/chromium-browser-clang/rewrapper_linux.cfg b/buildtools/reclient_cfgs/linux/chromium-browser-clang/rewrapper_linux.cfg index 37fca98..b2ec06d 100644 --- a/buildtools/reclient_cfgs/linux/chromium-browser-clang/rewrapper_linux.cfg +++ b/buildtools/reclient_cfgs/linux/chromium-browser-clang/rewrapper_linux.cfg
@@ -1,7 +1,7 @@ platform=container-image=docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:26de99218a1a8b527d4840490bcbf1690ee0b55c84316300b60776e6b3a03fe1,label:action_default=1 server_address=unix:///tmp/reproxy.sock labels=type=compile,compiler=clang,lang=cpp -exec_strategy=remote_local_fallback +exec_strategy=racing dial_timeout=10m exec_timeout=2m reclient_timeout=2m
diff --git a/chrome/VERSION b/chrome/VERSION index 835953f..9dd77b2 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=123 MINOR=0 -BUILD=6288 +BUILD=6289 PATCH=0
diff --git a/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected index 70e7318..9dd7bc28 100644 --- a/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected +++ b/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected
@@ -372,6 +372,10 @@ getDistortionCoefficientsCount(); getLeftEyeFieldOfViewAngles(int); } +# Prevent native methods which are used from being obfuscated. +-keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class com.google.cardboard.sdk.** { + native <methods>; +} # File: ../../android_webview/support_library/boundary_interfaces/proguard.flags # Copyright 2018 The Chromium Authors
diff --git a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected index 17e22eee..354c3da6 100644 --- a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected +++ b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
@@ -372,6 +372,10 @@ getDistortionCoefficientsCount(); getLeftEyeFieldOfViewAngles(int); } +# Prevent native methods which are used from being obfuscated. +-keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class com.google.cardboard.sdk.** { + native <methods>; +} # File: ../../android_webview/support_library/boundary_interfaces/proguard.flags # Copyright 2018 The Chromium Authors
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java index 256c1020..93f8c95 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -68,7 +68,9 @@ import org.chromium.chrome.browser.toolbar.ToolbarFeatures; import org.chromium.chrome.browser.toolbar.ToolbarManager; import org.chromium.chrome.browser.toolbar.top.TabStripTransitionCoordinator.TabStripHeightObserver; +import org.chromium.chrome.browser.ui.system.StatusBarColorController; import org.chromium.components.browser_ui.styles.SemanticColorUtils; +import org.chromium.components.browser_ui.widget.scrim.ScrimProperties; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.base.PageTransition; @@ -162,6 +164,7 @@ private boolean mIsHidden; private boolean mIsTransitioning; private final ToolbarManager mToolbarManager; + private final StatusBarColorController mStatusBarColorController; private TabStripSceneLayer mTabStripTreeProvider; private TabStripEventHandler mTabStripEventHandler; private TabSwitcherLayoutObserver mTabSwitcherLayoutObserver; @@ -452,6 +455,7 @@ } mToolbarManager = toolbarManager; + mStatusBarColorController = mToolbarManager.getStatusBarColorController(); mNormalHelper = new StripLayoutHelper( @@ -545,6 +549,7 @@ /** Mark whether tab strip |isHidden|. */ public void setIsTabStripHidden(boolean isHidden) { mIsHidden = isHidden; + mStatusBarColorController.setTabStripHiddenOnTablet(mIsHidden); } @Override @@ -606,6 +611,8 @@ // The fade-out is implemented by adding a scrim layer on top of the tab strip, with the // same bg as the toolbar background color. scrimOpacity = calculateScrimOpacityDuringTransition(visibleHeight); + mStatusBarColorController.setTabStripColorOverlay( + getStripTransitionScrimColor(), scrimOpacity); yOffset = 0; } else if (mIsHidden) { @@ -627,7 +634,7 @@ } private int getStripTransitionScrimColor() { - if (!ToolbarFeatures.USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM.getValue()) { + if (!ToolbarFeatures.shouldUseToolbarBgColorForStripTransitionScrim()) { return getBackgroundColor(); } return mToolbarManager.getPrimaryColor(); @@ -676,11 +683,26 @@ public void onHeightChanged(int newHeight) { mIsTransitioning = true; mIsHidden = newHeight == 0; + // Update the strip visibility state in StatusBarController just after the margins are + // updated during a hide->show transition so that the status bar assumes the base tab strip + // color for the remaining duration of the transition while a scrim is applied. + if (!mIsHidden) { + mStatusBarColorController.setTabStripHiddenOnTablet(false); + } + // Set the status bar color and scrim overlay at the start of the transition. + mStatusBarColorController.setTabStripColorOverlay( + getStripTransitionScrimColor(), mIsHidden ? 0f : 1f); } @Override public void onTransitionFinished() { mIsTransitioning = false; + // Update the strip visibility state in StatusBarColorController only after a show->hide + // transition, so that the status bar assumes the toolbar color when the strip is hidden. + if (mIsHidden) { + mStatusBarColorController.setTabStripHiddenOnTablet(true); + } + mStatusBarColorController.setTabStripColorOverlay(ScrimProperties.INVALID_COLOR, 0f); } private boolean duringTabStripTransition() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java index 7e1c59e..17f158e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -109,6 +109,7 @@ import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.chrome.browser.tasks.tab_management.UndoGroupSnackbarController; import org.chromium.chrome.browser.toolbar.ToolbarButtonInProductHelpController; +import org.chromium.chrome.browser.toolbar.ToolbarFeatures; import org.chromium.chrome.browser.toolbar.ToolbarIntentMetadata; import org.chromium.chrome.browser.ui.RootUiCoordinator; import org.chromium.chrome.browser.ui.appmenu.AppMenuBlocker; @@ -395,6 +396,8 @@ }; mMultiInstanceManager = multiInstanceManager; mHubManagerSupplier = hubManagerSupplier; + mStatusBarColorController.setAllowToolbarColorOnTablets( + ToolbarFeatures.shouldUseToolbarBgColorForStripTransitionScrim()); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index b5ed2fa..e345fe8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -2117,6 +2117,13 @@ } /** + * @return The {@link StatusBarColorController} instance maintained by this class. + */ + public StatusBarColorController getStatusBarColorController() { + return mStatusBarColorController; + } + + /** * Updates the primary color used by the model to the given color. * @param color The primary color for the current tab. * @param shouldAnimate Whether the change of color should be animated.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java index 73aaac8..7e946287 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
@@ -117,6 +117,12 @@ private StartSurface.StateObserver mStartSurfaceStateObserver; private @StartSurfaceState int mStartSurfaceState = StartSurfaceState.NOT_SHOWN; + // Tab strip transition states. + private boolean mTabStripHiddenOnTablet; + private @ColorInt int mTabStripTransitionOverlayColor = ScrimProperties.INVALID_COLOR; + private float mTabStripTransitionOverlayAlpha; + private boolean mAllowToolbarColorOnTablets; + private final LayoutStateObserver mLayoutStateObserver = new LayoutStateObserver() { @Override @@ -171,6 +177,7 @@ mStatusBarColorProvider = statusBarColorProvider; mStartSurfaceSupplier = startSurfaceSupplier; mIsSurfacePolishEnabled = ChromeFeatureList.sSurfacePolish.isEnabled(); + mAllowToolbarColorOnTablets = false; mStandardPrimaryBgColor = ChromeColors.getPrimaryBackgroundColor(context, false); mIncognitoPrimaryBgColor = ChromeColors.getPrimaryBackgroundColor(context, true); @@ -372,12 +379,13 @@ // TopToolbarCoordinator.ToolbarColorObserver implementation. @Override public void onToolbarColorChanged(@ColorInt int color) { - if (!OmniboxFeatures.shouldMatchToolbarAndStatusBarColor()) { - return; - } - - // Status bar on tablets should not change at all times. - if (mIsTablet) { + boolean shouldUseToolbarColorOnPhone = + !mIsTablet && OmniboxFeatures.shouldMatchToolbarAndStatusBarColor(); + // Status bar color on tablets could change when the DYNAMIC_TOP_CHROME feature is enabled, + // where it might be required for the status bar color to match the toolbar color when the + // tab strip is hidden. + boolean shouldUseToolbarColorOnTablet = mIsTablet && mAllowToolbarColorOnTablets; + if (!shouldUseToolbarColorOnPhone && !shouldUseToolbarColorOnTablet) { return; } @@ -438,6 +446,20 @@ } /** + * Add the tab strip transition scrim overlay on the status bar during a tab strip transition. + * + * @param overlayColor The overlay color. + * @param overlayAlpha The alpha that |overlayColor| should have on the status bar color. + */ + public void setTabStripColorOverlay(@ColorInt int overlayColor, float overlayAlpha) { + assert mIsTablet; + if (!mAllowToolbarColorOnTablets) return; + mTabStripTransitionOverlayColor = overlayColor; + mTabStripTransitionOverlayAlpha = overlayAlpha; + updateStatusBarColor(); + } + + /** * @param tabModelSelector The {@link TabModelSelector} to check whether incognito model is * selected. */ @@ -456,11 +478,24 @@ mStatusBarColorWithoutStatusIndicator = calculateBaseStatusBarColor(); @ColorInt int statusBarColor = applyStatusBarIndicatorColor(mStatusBarColorWithoutStatusIndicator); + statusBarColor = applyTabStripOverlay(statusBarColor); statusBarColor = applyCurrentScrimToColor(statusBarColor); setStatusBarColor(mWindow, statusBarColor); } /** + * Set whether the tab strip is hidden or visible on a tablet. This state will be used to + * determine the base status bar color on a tablet. + * + * @param tabStripHiddenOnTablet Whether the tab strip is hidden or visible on a tablet. + */ + public void setTabStripHiddenOnTablet(boolean tabStripHiddenOnTablet) { + assert mIsTablet; + if (!mAllowToolbarColorOnTablets) return; + mTabStripHiddenOnTablet = tabStripHiddenOnTablet; + } + + /** * @return The status bar color without the status indicator's color taken into consideration. * However, scrimming isn't included since it's managed completely by this class. */ @@ -480,7 +515,9 @@ } if (mIsTablet) { - return TabUiThemeUtil.getTabStripBackgroundColor(mWindow.getContext(), mIsIncognito); + return mTabStripHiddenOnTablet + ? mToolbarColor + : TabUiThemeUtil.getTabStripBackgroundColor(mWindow.getContext(), mIsIncognito); } // When Omnibox gains focus, we want to clear the status bar theme color. @@ -587,6 +624,31 @@ } /** + * Apply and get the tab strip overlay applied color if the strip transition scrim is showing. + * + * @param color Base color to apply the overlay to. + */ + private @ColorInt int applyTabStripOverlay(@ColorInt int color) { + // If the tab strip is transitioning on a tablet, apply the strip overlay on the status bar. + if (mIsTablet && mTabStripTransitionOverlayAlpha > 0) { + return ColorUtils.getColorWithOverlay( + color, mTabStripTransitionOverlayColor, mTabStripTransitionOverlayAlpha); + } + return color; + } + + /** + * Determines whether the status bar color could use the toolbar color on tablets when certain + * conditions are met. This is currently supported on ChromeTabbedActivity's with the + * DYNAMIC_TOP_CHROME feature enabled. + * + * @param allowToolbarColorOnTablets Whether the status bar color could use the toolbar color. + */ + public void setAllowToolbarColorOnTablets(boolean allowToolbarColorOnTablets) { + mAllowToolbarColorOnTablets = allowToolbarColorOnTablets; + } + + /** * @return Whether or not the current tab is a new tab page in standard mode. */ private boolean isStandardNtp() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java index 8321410..86f4e26e7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java
@@ -46,6 +46,7 @@ import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tasks.tab_management.TabUiThemeUtil; +import org.chromium.chrome.browser.toolbar.ToolbarFeatures; import org.chromium.chrome.browser.toolbar.top.ToolbarLayout; import org.chromium.chrome.browser.toolbar.top.ToolbarPhone; import org.chromium.chrome.features.start_surface.StartSurfaceTestUtils; @@ -57,6 +58,7 @@ import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.chrome.test.util.browser.ThemeTestUtils; import org.chromium.components.browser_ui.styles.ChromeColors; +import org.chromium.components.browser_ui.widget.scrim.ScrimProperties; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils; @@ -490,7 +492,7 @@ UiRestriction.RESTRICTION_TYPE_TABLET, DeviceRestriction.RESTRICTION_TYPE_NON_AUTO }) - public void testStatusBarColorForTabStripRedesignFolioTablet() throws Exception { + public void testStatusBarColorForTabStripRedesignFolioTablet() { final ChromeActivity activity = sActivityTestRule.getActivity(); final StatusBarColorController statusBarColorController = sActivityTestRule @@ -498,12 +500,6 @@ .getRootUiCoordinatorForTesting() .getStatusBarColorController(); - // Before enable tab strip redesign, status bar should be black. - assertEquals( - "Wrong initial value returned before enable Tab Strip Redesign Folio", - Color.BLACK, - activity.getWindow().getStatusBarColor()); - TestThreadUtils.runOnUiThreadBlocking( () -> statusBarColorController.updateStatusBarColor()); assertEquals( @@ -512,6 +508,70 @@ activity.getWindow().getStatusBarColor()); } + @Test + @LargeTest + @Feature({"StatusBar"}) + @Restriction({ + UiRestriction.RESTRICTION_TYPE_TABLET, + DeviceRestriction.RESTRICTION_TYPE_NON_AUTO + }) + public void testStatusBarColorOnTabletDuringTabStripTransition() { + final ChromeActivity activity = sActivityTestRule.getActivity(); + final StatusBarColorController statusBarColorController = + sActivityTestRule + .getActivity() + .getRootUiCoordinatorForTesting() + .getStatusBarColorController(); + statusBarColorController.setAllowToolbarColorOnTablets(true); + + var toolbarColor = sActivityTestRule.getActivity().getToolbarManager().getPrimaryColor(); + + // We will invoke #onToolbarColorChanged() on a tablet that in turn invokes + // #updateStatusBarColor() to assert that it sets |mToolbarColor| as expected. The status + // bar should use |mToolbarColor| when the tab strip is hidden, and the tab strip background + // color otherwise. + + // Assume that the tab strip is initially hidden. + statusBarColorController.setTabStripHiddenOnTablet(true); + TestThreadUtils.runOnUiThreadBlocking( + () -> statusBarColorController.onToolbarColorChanged(toolbarColor)); + assertEquals( + "Status bar color on tablet should match the toolbar background when the tab strip" + + " is hidden.", + toolbarColor, + activity.getWindow().getStatusBarColor()); + + // Simulate an in-progress hide->show transition, where a scrim will be added on the status + // bar. + // TabStripHeightObserver#onHeightChanged() is expected to update the final strip visibility + // state in StatusBarColorController for this transition once the control container margins + // are updated and before the transition runs to completion. + statusBarColorController.setTabStripHiddenOnTablet(false); + TestThreadUtils.runOnUiThreadBlocking( + () -> statusBarColorController.setTabStripColorOverlay(toolbarColor, 0.5f)); + assertEquals( + "Status bar color on tablet should use the tab strip transition scrim overlay" + + " during a strip transition.", + ColorUtils.getColorWithOverlay( + TabUiThemeUtil.getTabStripBackgroundColor(activity, false), + toolbarColor, + 0.5f), + activity.getWindow().getStatusBarColor()); + + // Simulate transition completion by resetting the transition overlay state in + // StatusBarColorController. + TestThreadUtils.runOnUiThreadBlocking( + () -> + statusBarColorController.setTabStripColorOverlay( + ScrimProperties.INVALID_COLOR, 0f)); + assertEquals( + "Status bar color on tablet should match the tab strip background when the tab" + + " strip is visible.", + TabUiThemeUtil.getTabStripBackgroundColor(activity, false), + activity.getWindow().getStatusBarColor()); + ToolbarFeatures.USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM.setForTesting(false); + } + /** Test status bar is always black in Automotive devices. */ @Test @SmallTest
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java index 394fd74..8095a52 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
@@ -14,6 +14,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -37,7 +38,9 @@ import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; @@ -72,8 +75,10 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.ToolbarFeatures; import org.chromium.chrome.browser.toolbar.ToolbarManager; +import org.chromium.chrome.browser.ui.system.StatusBarColorController; import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.styles.SemanticColorUtils; +import org.chromium.components.browser_ui.widget.scrim.ScrimProperties; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.dragdrop.DragAndDropDelegate; @@ -108,6 +113,7 @@ @Mock private BrowserControlsStateProvider mBrowserControlStateProvider; @Mock private WindowAndroid mWindowAndroid; @Mock private ToolbarManager mToolbarManager; + @Mock private StatusBarColorController mStatusBarColorController; private StripLayoutHelperManager mStripLayoutHelperManager; private Context mContext; @@ -130,6 +136,8 @@ ApplicationProvider.getApplicationContext(), R.style.Theme_BrowserUI_DayNight); when(mToolbarContainerView.getContext()).thenReturn(mContext); + when(mToolbarManager.getStatusBarColorController()).thenReturn(mStatusBarColorController); + TabStripSceneLayer.setTestFlag(true); ToolbarFeatures.USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM.setForTesting(true); @@ -608,6 +616,16 @@ anyInt(), eq(mToolbarPrimaryColor), /* scrimOpacity= */ eq(0f)); + + // Verify StatusBarColorController method invocations. + InOrder inOrder = Mockito.inOrder(mStatusBarColorController); + // Invocation during the transition. + inOrder.verify(mStatusBarColorController) + .setTabStripColorOverlay(mToolbarPrimaryColor, expectedOpacity); + // Invocation after the transition finished. + inOrder.verify(mStatusBarColorController).setTabStripHiddenOnTablet(true); + inOrder.verify(mStatusBarColorController) + .setTabStripColorOverlay(ScrimProperties.INVALID_COLOR, 0f); } @Test @@ -656,11 +674,14 @@ mStripLayoutHelperManager.setIsTabStripHidden(true); mStripLayoutHelperManager.getVirtualViews(views); assertTrue("Views are empty when tab strip hidden.", views.isEmpty()); + verify(mStatusBarColorController).setTabStripHiddenOnTablet(true); mStripLayoutHelperManager.setIsTabStripHidden(false); mStripLayoutHelperManager.onHeightChanged(40); mStripLayoutHelperManager.getVirtualViews(views); assertTrue("Views are empty during tab strip transition.", views.isEmpty()); + // Invoked once by #setIsTabStripHidden(), once by #onHeightChanged(). + verify(mStatusBarColorController, times(2)).setTabStripHiddenOnTablet(false); mStripLayoutHelperManager.onTransitionFinished(); mStripLayoutHelperManager.getVirtualViews(views); @@ -728,5 +749,19 @@ anyInt(), eq(scrimColor), /* scrimOpacity= */ eq(0f)); + + // Verify StatusBarColorController method invocations. + InOrder inOrder = Mockito.inOrder(mStatusBarColorController); + // Invocations before the transition started. + inOrder.verify(mStatusBarColorController).setTabStripHiddenOnTablet(true); + inOrder.verify(mStatusBarColorController) + .setTabStripColorOverlay(ScrimProperties.INVALID_COLOR, 0f); + // Invocations during the transition. + inOrder.verify(mStatusBarColorController).setTabStripHiddenOnTablet(false); + inOrder.verify(mStatusBarColorController) + .setTabStripColorOverlay(scrimColor, expectedOpacity); + // Invocation after the transition finished. + inOrder.verify(mStatusBarColorController) + .setTabStripColorOverlay(ScrimProperties.INVALID_COLOR, 0f); } }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 0337c31..e379d74a 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -7072,20 +7072,26 @@ Can't upload files while on a metered connection. </message> <message name="IDS_OFFICE_FALLBACK_INSTRUCTIONS_METERED" desc="Office Fallback dialog instructions for the choices (and buttons) the user has available to open the office file when the system is on a metered network (network where bandwidth usage incurs cost to the user)."> - Check your internet connection and choose "Try again", or choose "Open in offline editor" to use limited view and editing options. + Change your internet connection and choose "Try again", or choose "Open in offline editor" to use limited view and editing options. </message> <message name="IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE" desc="Title for a dialog that appears when an office file is unable to be opened due to Google Drive not being available."> - Can't open <ph name="FILE_NAMES">$1<ex>file.docx</ex></ph> when Drive is not available + Can't open <ph name="FILE_NAMES">$1<ex>file.docx</ex></ph> when Google Drive is not available </message> <message name="IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE" desc="Explanation for a dialog that appears when an office file is unable to be opened due to Google Drive not being available."> - The application <ph name="APPLICATION_NAME">$1<ex>Google Docs</ex></ph> requires Drive to be available. + The application <ph name="APPLICATION_NAME">$1<ex>Google Docs</ex></ph> requires Google Drive to be available. + </message> + <message name="IDS_OFFICE_FALLBACK_INSTRUCTIONS_DISABLE_DRIVE_PREFERENCE" desc="Office Fallback dialog instructions for the choices (buttons) the user has available when Google Drive is disabled in settings."> + Try enabling Google Drive in Settings and choose "Try again", or choose "Open in offline editor" to use limited view and editing options. + </message> + <message name="IDS_OFFICE_FALLBACK_REASON_DRIVE_DISABLED_FOR_ACCOUNT" desc="Explanation for a dialog that appears when Google Drive is not available for the account type."> + Google Drive is disabled for this account type. + </message> + <message name="IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_DISABLED_FOR_ACCOUNT" desc="Office Fallback dialog instructions for the choices (buttons) the user has available when Google Drive is not available for the account type."> + Choose "Open in offline editor" to use limited view and editing options. </message> <message name="IDS_OFFICE_FALLBACK_INSTRUCTIONS" desc="Office Fallback dialog instructions for the choices (buttons) the user has available to open the office file."> Choose "Try again", or choose "Open in offline editor" to use limited view and editing options. </message> - <message name="IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_UNAVAILABLE" desc="Office Fallback dialog instructions for when Google Drive is not available in Files app and the user should try to enable it." translateable="false"> - Try enabling Google Drive in Settings. - </message> <!-- Office file handler selection dialog --> <message name="IDS_OFFICE_FILE_HANDLER_TITLE" desc="Title for office file handler selection dialog, which allows the user to choose an app to open office files.">
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_DISABLE_DRIVE_PREFERENCE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_DISABLE_DRIVE_PREFERENCE.png.sha1 new file mode 100644 index 0000000..cb34f16 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_DISABLE_DRIVE_PREFERENCE.png.sha1
@@ -0,0 +1 @@ +a58b3567aaca00dece5d3212807e1b4c3f482c4a \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_DISABLED_FOR_ACCOUNT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_DISABLED_FOR_ACCOUNT.png.sha1 new file mode 100644 index 0000000..8bc62c7 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_DISABLED_FOR_ACCOUNT.png.sha1
@@ -0,0 +1 @@ +35ba6a1fde6a00f620752f91bc508c2cf3f1fbcc \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_METERED.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_METERED.png.sha1 index 32db01e..fa61c0fe 100644 --- a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_METERED.png.sha1 +++ b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_INSTRUCTIONS_METERED.png.sha1
@@ -1 +1 @@ -3bc34a3a5fd0a52711481b8c2cfa33f144a4d74d \ No newline at end of file +8878e19bbb684dab2ee4b26528c5b67a78e200df \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_REASON_DRIVE_DISABLED_FOR_ACCOUNT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_REASON_DRIVE_DISABLED_FOR_ACCOUNT.png.sha1 new file mode 100644 index 0000000..6d6109d --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_REASON_DRIVE_DISABLED_FOR_ACCOUNT.png.sha1
@@ -0,0 +1 @@ +52a364dc1133941cd03d1171c3cc6f3675167f80 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE.png.sha1 index 920b5bc2..7143eaff 100644 --- a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE.png.sha1 +++ b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE.png.sha1
@@ -1 +1 @@ -a83d60c4feaf2c589b5a889d7181f5b592bc9f2d \ No newline at end of file +199a0514431077ab8723a546d4c63dbd917ca611 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE.png.sha1 index 7634320..ef2d015d 100644 --- a/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE.png.sha1 +++ b/chrome/app/chromeos_strings_grdp/IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE.png.sha1
@@ -1 +1 @@ -020bf1d2cdbf68cf19bbfc4e504d66aec2fdfe91 \ No newline at end of file +1bf34ac666d2a8c43a5dcee1fc9c9597275861ca \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 61353e1..6169026 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4342,9 +4342,6 @@ {"disable-dns-proxy", flag_descriptions::kDisableDnsProxyName, flag_descriptions::kDisableDnsProxyDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kDisableDnsProxy)}, - {"firmware-update-jelly", flag_descriptions::kFirmwareUpdateJellyName, - flag_descriptions::kFirmwareUpdateJellyDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kFirmwareUpdateJelly)}, {"firmware-update-ui-v2", flag_descriptions::kFirmwareUpdateUIV2Name, flag_descriptions::kFirmwareUpdateUIV2Description, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kFirmwareUpdateUIV2)}, @@ -5828,6 +5825,11 @@ {"files-trash-drive", flag_descriptions::kFilesTrashDriveName, flag_descriptions::kFilesTrashDriveDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kFilesTrashDrive)}, + {"file-system-provider-cloud-file-system", + flag_descriptions::kFileSystemProviderCloudFileSystemName, + flag_descriptions::kFileSystemProviderCloudFileSystemDescription, kOsCrOS, + FEATURE_VALUE_TYPE( + chromeos::features::kFileSystemProviderCloudFileSystem)}, {"file-system-provider-content-cache", flag_descriptions::kFileSystemProviderContentCacheName, flag_descriptions::kFileSystemProviderContentCacheDescription, kOsCrOS, @@ -5901,9 +5903,6 @@ flag_descriptions::kPhoneHubOnboardingNotifierRevampName, flag_descriptions::kPhoneHubOnboardingNotifierRevampDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kPhoneHubOnboardingNotifierRevamp)}, - {"print-management-jelly", flag_descriptions::kPrintManagementJellyName, - flag_descriptions::kPrintManagementJellyDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kPrintManagementJelly)}, {"print-management-setup-assistance", flag_descriptions::kPrintManagementSetupAssistanceName, flag_descriptions::kPrintManagementSetupAssistanceDescription, kOsCrOS,
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index b06b3fa..0f07a311 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -1639,6 +1639,10 @@ "kerberos/kerberos_credentials_manager_factory.h", "kerberos/kerberos_ticket_expiry_notification.cc", "kerberos/kerberos_ticket_expiry_notification.h", + "language_packs/language_pack_font_service.cc", + "language_packs/language_pack_font_service.h", + "language_packs/language_pack_font_service_factory.cc", + "language_packs/language_pack_font_service_factory.h", "language_preferences.cc", "language_preferences.h", "locale_change_guard.cc",
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc index 5bd7417..74f72b89 100644 --- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -2334,7 +2334,7 @@ // TODO(crbug.com/1360638): Remove the conditional here when the Save & Recall // flag flip has landed since it will always be true. - if (saved_desk_util::IsSavedDesksEnabled()) { + if (saved_desk_util::ShouldShowSavedDesksButtons()) { sm_.Call([this]() { SendKeyPressWithShift(ui::VKEY_TAB); }); sm_.ExpectSpeechPattern("Save desk for later"); sm_.ExpectSpeech("Button");
diff --git a/chrome/browser/ash/app_list/search/app_discovery_metrics_manager.cc b/chrome/browser/ash/app_list/search/app_discovery_metrics_manager.cc index 233526c..83f1e9c8 100644 --- a/chrome/browser/ash/app_list/search/app_discovery_metrics_manager.cc +++ b/chrome/browser/ash/app_list/search/app_discovery_metrics_manager.cc
@@ -4,12 +4,15 @@ #include "chrome/browser/ash/app_list/search/app_discovery_metrics_manager.h" +#include <utility> + #include "ash/public/cpp/app_list/app_list_metrics.h" #include "chrome/browser/ash/app_list/search/common/types_util.h" #include "chrome/browser/sync/sync_service_factory.h" #include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h" #include "chromeos/ash/components/string_matching/tokenized_string.h" #include "components/metrics/structured/structured_events.h" +#include "components/metrics/structured/structured_metrics_client.h" #include "components/sync/base/model_type.h" #include "components/sync/service/sync_service.h" #include "components/sync/service/sync_service_utils.h" @@ -51,16 +54,17 @@ std::string app_id = IsAppSyncEnabled() ? result->id() : ""; std::u16string app_title = IsAppSyncEnabled() ? result->title() : u""; - cros_events::AppDiscovery_AppLauncherResultOpened() - .SetAppId(app_id) - .SetAppName(std::string(app_title.begin(), app_title.end())) - .SetFuzzyStringMatch(string_match_score) - .SetResultCategory(result->metrics_type()) - .Record(); + metrics::structured::StructuredMetricsClient::Record( + std::move(cros_events::AppDiscovery_AppLauncherResultOpened() + .SetAppId(app_id) + .SetAppName(std::string(app_title.begin(), app_title.end())) + .SetFuzzyStringMatch(string_match_score) + .SetResultCategory(result->metrics_type()))); } void AppDiscoveryMetricsManager::OnLauncherOpen() { - cros_events::AppDiscovery_LauncherOpen().Record(); + metrics::structured::StructuredMetricsClient::Record( + std::move(cros_events::AppDiscovery_LauncherOpen())); } bool AppDiscoveryMetricsManager::IsAppSyncEnabled() {
diff --git a/chrome/browser/ash/app_list/search/help_app_provider_unittest.cc b/chrome/browser/ash/app_list/search/help_app_provider_unittest.cc index d0f2b3bb..811f7f23 100644 --- a/chrome/browser/ash/app_list/search/help_app_provider_unittest.cc +++ b/chrome/browser/ash/app_list/search/help_app_provider_unittest.cc
@@ -6,13 +6,10 @@ #include <memory> -#include "ash/constants/ash_features.h" #include "ash/webui/help_app_ui/search/search_handler.h" #include "ash/webui/help_app_ui/search/search_tag_registry.h" #include "ash/webui/help_app_ui/url_constants.h" -#include "base/feature_list.h" #include "base/memory/raw_ptr.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/app_list/app_list_test_util.h" @@ -84,11 +81,7 @@ /*for_testing=*/true)), search_tag_registry_(local_search_service_proxy_.get()), mock_handler_(&search_tag_registry_, - local_search_service_proxy_.get()) { - scoped_feature_list_.InitWithFeatures( - /*enabled_features=*/{ash::features::kReleaseNotesSuggestionChip}, - /*disabled_features=*/{}); - } + local_search_service_proxy_.get()) {} ~HelpAppProviderTest() override = default; void SetUp() override { @@ -126,7 +119,6 @@ ash::help_app::SearchTagRegistry search_tag_registry_; raw_ptr<HelpAppProvider> provider_ = nullptr; raw_ptr<apps::AppServiceProxy> proxy_; - base::test::ScopedFeatureList scoped_feature_list_; MockSearchHandler mock_handler_; };
diff --git a/chrome/browser/ash/app_list/search/help_app_zero_state_provider_unittest.cc b/chrome/browser/ash/app_list/search/help_app_zero_state_provider_unittest.cc index f2a0ba6..0042f02c 100644 --- a/chrome/browser/ash/app_list/search/help_app_zero_state_provider_unittest.cc +++ b/chrome/browser/ash/app_list/search/help_app_zero_state_provider_unittest.cc
@@ -7,11 +7,8 @@ #include <memory> #include <string> -#include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/app_list_types.h" -#include "base/feature_list.h" #include "base/memory/raw_ptr.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/ash/app_list/app_list_notifier_impl.h" #include "chrome/browser/ash/app_list/app_list_test_util.h" #include "chrome/browser/ash/app_list/search/chrome_search_result.h" @@ -43,11 +40,7 @@ class HelpAppZeroStateProviderTest : public AppListTestBase { public: - HelpAppZeroStateProviderTest() { - scoped_feature_list_.InitWithFeatures( - /*enabled_features=*/{ash::features::kReleaseNotesSuggestionChip}, - /*disabled_features=*/{}); - } + HelpAppZeroStateProviderTest() = default; ~HelpAppZeroStateProviderTest() override = default; void SetUp() override { @@ -81,7 +74,6 @@ std::unique_ptr<ash::AppListNotifier> app_list_notifier_; TestSearchController search_controller_; raw_ptr<HelpAppZeroStateProvider> provider_ = nullptr; - base::test::ScopedFeatureList scoped_feature_list_; }; // Test for empty query.
diff --git a/chrome/browser/ash/app_list/search/search_metrics_manager.cc b/chrome/browser/ash/app_list/search/search_metrics_manager.cc index 7c0f5b7b..68f9908 100644 --- a/chrome/browser/ash/app_list/search/search_metrics_manager.cc +++ b/chrome/browser/ash/app_list/search/search_metrics_manager.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/profiles/profile.h" #include "components/drive/drive_pref_names.h" #include "components/metrics/structured/structured_events.h" +#include "components/metrics/structured/structured_metrics_client.h" #include "components/prefs/pref_service.h" namespace app_list { @@ -214,15 +215,15 @@ base::Time::Exploded now_exploded; now.LocalExplode(&now_exploded); - metrics::structured::events::v2::launcher_usage::LauncherUsage() - .SetTarget(NormalizeId(launch_data.id)) - .SetApp(last_launched_app_id_) - .SetSearchQuery(query) - .SetSearchQueryLength(query.size()) - .SetProviderType(static_cast<int>(launch_data.result_type)) - .SetHour(now_exploded.hour) - .SetScore(launch_data.score) - .Record(); + metrics::structured::StructuredMetricsClient::Record( + std::move(metrics::structured::events::v2::launcher_usage::LauncherUsage() + .SetTarget(NormalizeId(launch_data.id)) + .SetApp(last_launched_app_id_) + .SetSearchQuery(query) + .SetSearchQueryLength(query.size()) + .SetProviderType(static_cast<int>(launch_data.result_type)) + .SetHour(now_exploded.hour) + .SetScore(launch_data.score))); // Only record the last launched app if the hashed logging feature flag is // enabled, because it is only used by hashed logging.
diff --git a/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc b/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc index f8eda90..9e9bcbf 100644 --- a/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc +++ b/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
@@ -26,7 +26,6 @@ #include "chrome/browser/ash/arc/session/arc_provisioning_result.h" #include "chrome/browser/ash/arc/session/arc_session_manager.h" #include "chrome/browser/ash/arc/test/test_arc_session_manager.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/settings/stats_reporting_controller.h" #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h" #include "chrome/common/pref_names.h" @@ -40,9 +39,8 @@ #include "components/language/core/browser/pref_names.h" #include "components/live_caption/pref_names.h" #include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" #include "components/prefs/testing_pref_store.h" -#include "components/user_manager/scoped_user_manager.h" -#include "components/user_manager/user_manager.h" #include "testing/gmock/include/gmock/gmock.h" namespace arc { @@ -63,8 +61,7 @@ class ArcSettingsServiceTest : public BrowserWithTestWindowTest { public: - ArcSettingsServiceTest() - : fake_user_manager_(std::make_unique<ash::FakeChromeUserManager>()) {} + ArcSettingsServiceTest() = default; ArcSettingsServiceTest(const ArcSettingsServiceTest&) = delete; ArcSettingsServiceTest& operator=(const ArcSettingsServiceTest&) = delete; ~ArcSettingsServiceTest() override = default; @@ -101,11 +98,6 @@ base_name); })); - const AccountId account_id(AccountId::FromUserEmailGaiaId( - profile()->GetProfileUserName(), "1234567890")); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - arc_session_manager()->SetProfile(profile()); arc_session_manager()->Initialize(); @@ -177,8 +169,6 @@ std::unique_ptr<ash::network_config::CrosNetworkConfigTestHelper> network_config_helper_; TestingPrefServiceSimple local_state_; - user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> - fake_user_manager_; std::unique_ptr<FakeIntentHelperHost> intent_helper_host_; std::unique_ptr<ArcSessionManager> arc_session_manager_; std::unique_ptr<ArcServiceManager> arc_service_manager_;
diff --git a/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc b/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc index 0565d433..e1e9cac 100644 --- a/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc +++ b/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/ash/arc/session/arc_session_manager.h" #include "chrome/browser/ash/arc/test/test_arc_session_manager.h" #include "chrome/browser/ash/login/ui/fake_login_display_host.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" @@ -31,8 +30,6 @@ #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" #include "components/sync_preferences/testing_pref_service_syncable.h" -#include "components/user_manager/scoped_user_manager.h" -#include "components/user_manager/user_manager.h" #include "ui/message_center/public/cpp/notification.h" namespace arc { @@ -43,9 +40,7 @@ class ArcProvisionNotificationServiceTest : public BrowserWithTestWindowTest { protected: - ArcProvisionNotificationServiceTest() - : fake_user_manager_(std::make_unique<ash::FakeChromeUserManager>()) {} - + ArcProvisionNotificationServiceTest() = default; ArcProvisionNotificationServiceTest( const ArcProvisionNotificationServiceTest&) = delete; ArcProvisionNotificationServiceTest& operator=( @@ -84,11 +79,6 @@ arc::prefs::RegisterLocalStatePrefs(local_state_.registry()); arc::StabilityMetricsManager::Initialize(&local_state_); - - const AccountId account_id(AccountId::FromUserEmailGaiaId( - profile()->GetProfileUserName(), "1234567890")); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); } void TearDown() override { @@ -112,8 +102,6 @@ raw_ptr<session_manager::SessionManager> session_manager_; private: - user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> - fake_user_manager_; TestingPrefServiceSimple local_state_; };
diff --git a/chrome/browser/ash/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc b/chrome/browser/ash/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc index de9fe48..b8c0bb4 100644 --- a/chrome/browser/ash/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc +++ b/chrome/browser/ash/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/ash/arc/arc_support_host.h" #include "chrome/browser/ash/arc/extensions/fake_arc_support.h" #include "chrome/browser/ash/arc/optin/arc_optin_preference_handler.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h" #include "chrome/browser/ash/policy/core/device_policy_builder.h" #include "chrome/browser/ash/settings/device_settings_test_helper.h" @@ -44,7 +43,6 @@ #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/sync_preferences/testing_pref_service_syncable.h" -#include "components/user_manager/scoped_user_manager.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" @@ -164,7 +162,6 @@ fake_arc_support_.reset(); support_host_->SetErrorDelegate(nullptr); support_host_.reset(); - fake_user_manager_.Reset(); owner_key_util_->Clear(); test_metrics_service_.reset(); @@ -191,10 +188,6 @@ return test_metrics_service_client_.get(); } - ash::FakeChromeUserManager* user_manager() { - return fake_user_manager_.Get(); - } - consent_auditor::FakeConsentAuditor* consent_auditor() { return static_cast<consent_auditor::FakeConsentAuditor*>( ConsentAuditorFactory::GetForProfile(profile())); @@ -230,8 +223,6 @@ test_enabled_state_provider_; std::unique_ptr<metrics::MetricsService> test_metrics_service_; - user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> - fake_user_manager_{std::make_unique<ash::FakeChromeUserManager>()}; std::unique_ptr<ArcSupportHost> support_host_; std::unique_ptr<FakeArcSupport> fake_arc_support_; std::unique_ptr<ArcTermsOfServiceDefaultNegotiator> negotiator_; @@ -253,14 +244,6 @@ ArcTermsOfServiceDefaultNegotiatorTest::SetUp(); } - - // BrowserWithTestWindowTest: - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindow. - const AccountId account_id = AccountId::FromUserEmail(email); - user_manager()->AddUser(account_id); - user_manager()->LoginUser(account_id); - } }; namespace {
diff --git a/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc b/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc index 7b8dbcc..06390d5 100644 --- a/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc +++ b/chrome/browser/ash/arc/tracing/arc_app_performance_tracing_unittest.cc
@@ -144,17 +144,6 @@ BrowserWithTestWindowTest::TearDown(); } - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. - AccountId account_id = AccountId::FromUserEmail(email); - user_manager()->AddUser(account_id); - user_manager()->UserLoggedIn( - account_id, - user_manager::FakeUserManager::GetFakeUsernameHash(account_id), - /*browser_restart=*/false, - /*is_child=*/false); - } - TestingProfile* CreateProfile(const std::string& profile_name) override { auto* profile = BrowserWithTestWindowTest::CreateProfile(profile_name); auto* user = user_manager()->FindUserAndModify(
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn index 9ce62c1..21085f2 100644 --- a/chrome/browser/ash/crosapi/BUILD.gn +++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -401,6 +401,7 @@ "//components/session_manager/core", "//components/ukm:ukm", "//components/user_prefs:user_prefs", + "//components/variations/service", "//components/version_info:channel", "//content/public/common", "//extensions/browser/api",
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc index 017b894..9f87160 100644 --- a/chrome/browser/ash/crosapi/crosapi_util.cc +++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -169,6 +169,7 @@ #include "components/ukm/ukm_service.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" +#include "components/variations/service/limited_entropy_synthetic_trial.h" #include "components/version_info/version_info.h" #include "content/public/common/content_switches.h" #include "device/bluetooth/floss/floss_features.h" @@ -560,6 +561,15 @@ params->device_properties = GetDeviceProperties(); params->device_settings = GetDeviceSettings(); + + // Syncing the randomization seed ensures that the group membership of the + // limited entropy synthetic trial will be the same between Ash Chrome and + // Lacros. + // TODO(crbug.com/1508150): Remove after completing the trial. + params->limited_entropy_synthetic_trial_seed = + variations::LimitedEntropySyntheticTrial::GetRandomizationSeed( + local_state); + // |metrics_service| could be nullptr in tests. if (auto* metrics_service = g_browser_process->metrics_service()) { // Send metrics service client id to Lacros if it's present.
diff --git a/chrome/browser/ash/file_manager/office_file_tasks.cc b/chrome/browser/ash/file_manager/office_file_tasks.cc index fe393ab..dccbf8b 100644 --- a/chrome/browser/ash/file_manager/office_file_tasks.cc +++ b/chrome/browser/ash/file_manager/office_file_tasks.cc
@@ -76,60 +76,6 @@ return OfficeOpenExtensions::kOther; } -void LogOneDriveMetricsAfterFallback( - ash::office_fallback::FallbackReason fallback_reason, - ash::cloud_upload::OfficeTaskResult task_result, - std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> cloud_open_metrics) { - switch (fallback_reason) { - case ash::office_fallback::FallbackReason::kOffline: - cloud_open_metrics->LogOneDriveOpenError( - ash::cloud_upload::OfficeOneDriveOpenErrors::kOffline); - break; - case ash::office_fallback::FallbackReason::kDriveDisabled: - case ash::office_fallback::FallbackReason::kNoDriveService: - case ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady: - case ash::office_fallback::FallbackReason::kDriveFsInterfaceError: - case ash::office_fallback::FallbackReason::kMeteredConnection: - NOTREACHED(); - break; - } - cloud_open_metrics->LogTaskResult(task_result); -} - -void LogGoogleDriveMetricsAfterFallback( - ash::office_fallback::FallbackReason fallback_reason, - ash::cloud_upload::OfficeTaskResult task_result, - std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> cloud_open_metrics) { - switch (fallback_reason) { - case ash::office_fallback::FallbackReason::kOffline: - cloud_open_metrics->LogGoogleDriveOpenError( - ash::cloud_upload::OfficeDriveOpenErrors::kOffline); - break; - case ash::office_fallback::FallbackReason::kDriveDisabled: - cloud_open_metrics->LogGoogleDriveOpenError( - ash::cloud_upload::OfficeDriveOpenErrors::kDriveDisabled); - break; - case ash::office_fallback::FallbackReason::kNoDriveService: - cloud_open_metrics->LogGoogleDriveOpenError( - ash::cloud_upload::OfficeDriveOpenErrors::kNoDriveService); - break; - case ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady: - cloud_open_metrics->LogGoogleDriveOpenError( - ash::cloud_upload::OfficeDriveOpenErrors:: - kDriveAuthenticationNotReady); - break; - case ash::office_fallback::FallbackReason::kDriveFsInterfaceError: - cloud_open_metrics->LogGoogleDriveOpenError( - ash::cloud_upload::OfficeDriveOpenErrors::kDriveFsInterface); - break; - case ash::office_fallback::FallbackReason::kMeteredConnection: - cloud_open_metrics->LogGoogleDriveOpenError( - ash::cloud_upload::OfficeDriveOpenErrors::kMeteredConnection); - break; - } - cloud_open_metrics->LogTaskResult(task_result); -} - std::optional<ash::office_fallback::FallbackReason> DriveConnectionStatusToFallbackReason( drive::util::ConnectionStatus drive_connection_status) { @@ -269,6 +215,71 @@ return; } +void LogOneDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason fallback_reason, + ash::cloud_upload::OfficeTaskResult task_result, + std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> cloud_open_metrics) { + switch (fallback_reason) { + case ash::office_fallback::FallbackReason::kOffline: + cloud_open_metrics->LogOneDriveOpenError( + ash::cloud_upload::OfficeOneDriveOpenErrors::kOffline); + break; + case ash::office_fallback::FallbackReason::kDriveDisabled: + case ash::office_fallback::FallbackReason::kNoDriveService: + case ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady: + case ash::office_fallback::FallbackReason::kDriveFsInterfaceError: + case ash::office_fallback::FallbackReason::kMeteredConnection: + case ash::office_fallback::FallbackReason::kDisableDrivePreferenceSet: + case ash::office_fallback::FallbackReason::kDriveDisabledForAccountType: + NOTREACHED(); + break; + } + cloud_open_metrics->LogTaskResult(task_result); +} + +void LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason fallback_reason, + ash::cloud_upload::OfficeTaskResult task_result, + std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> cloud_open_metrics) { + switch (fallback_reason) { + case ash::office_fallback::FallbackReason::kOffline: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors::kOffline); + break; + case ash::office_fallback::FallbackReason::kDriveDisabled: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors::kDriveDisabled); + break; + case ash::office_fallback::FallbackReason::kNoDriveService: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors::kNoDriveService); + break; + case ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors:: + kDriveAuthenticationNotReady); + break; + case ash::office_fallback::FallbackReason::kDriveFsInterfaceError: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors::kDriveFsInterface); + break; + case ash::office_fallback::FallbackReason::kMeteredConnection: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors::kMeteredConnection); + break; + case ash::office_fallback::FallbackReason::kDisableDrivePreferenceSet: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors::kDisableDrivePreferenceSet); + break; + case ash::office_fallback::FallbackReason::kDriveDisabledForAccountType: + cloud_open_metrics->LogGoogleDriveOpenError( + ash::cloud_upload::OfficeDriveOpenErrors:: + kDriveDisabledForAccountType); + break; + } + cloud_open_metrics->LogTaskResult(task_result); +} + void OnDialogChoiceReceived( Profile* profile, const TaskDescriptor& task,
diff --git a/chrome/browser/ash/file_manager/office_file_tasks.h b/chrome/browser/ash/file_manager/office_file_tasks.h index b5f1db1..e3445c2 100644 --- a/chrome/browser/ash/file_manager/office_file_tasks.h +++ b/chrome/browser/ash/file_manager/office_file_tasks.h
@@ -11,6 +11,7 @@ #include "base/files/file_path.h" #include "base/time/time.h" +#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h" #include "chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h" class Profile; @@ -121,6 +122,16 @@ void LaunchQuickOffice(Profile* profile, const std::vector<storage::FileSystemURL>& file_urls); +void LogOneDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason fallback_reason, + ash::cloud_upload::OfficeTaskResult task_result, + std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> cloud_open_metrics); + +void LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason fallback_reason, + ash::cloud_upload::OfficeTaskResult task_result, + std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> cloud_open_metrics); + // Executes appropriate task to open the selected `file_urls`. // If user's `choice` is `kDialogChoiceQuickOffice`, launch QuickOffice. // If user's `choice` is `kDialogChoiceTryAgain`, execute the `task`.
diff --git a/chrome/browser/ash/file_manager/office_file_tasks_unittest.cc b/chrome/browser/ash/file_manager/office_file_tasks_unittest.cc index 0fbb91a0..5dd7af33 100644 --- a/chrome/browser/ash/file_manager/office_file_tasks_unittest.cc +++ b/chrome/browser/ash/file_manager/office_file_tasks_unittest.cc
@@ -7,10 +7,13 @@ #include <memory> #include <string> +#include "base/test/metrics/histogram_tester.h" #include "base/values.h" #include "chrome/browser/ash/file_manager/app_id.h" #include "chrome/browser/ash/file_manager/file_tasks.h" #include "chrome/browser/ash/file_manager/office_file_tasks.h" +#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.h" +#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -44,6 +47,19 @@ profile()->GetTestingPrefService()->ClearPref(prefs::kDefaultTasksBySuffix); } + protected: + std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> + cloud_open_metrics_for_drive_ = + std::make_unique<ash::cloud_upload::CloudOpenMetrics>( + ash::cloud_upload::CloudProvider::kGoogleDrive, + /*file_count=*/1); + std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> + cloud_open_metrics_for_one_drive_ = + std::make_unique<ash::cloud_upload::CloudOpenMetrics>( + ash::cloud_upload::CloudProvider::kOneDrive, + /*file_count=*/1); + base::HistogramTester histogram_; + private: content::BrowserTaskEnvironment task_environment_; std::unique_ptr<TestingProfile> profile_; @@ -269,4 +285,127 @@ *profile()->GetPrefs(), pptx_mime, ".pptx")); } +/** + * Check Log*MetricsAfterFallback() maps the FallbackReason to the correct + * OpenError and logs the TaskResult. + */ +TEST_F(FileManagerOfficeFileTasksTest, + LogOneDriveMetricsAfterFallback_kOffline) { + LogOneDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kOffline, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, + std::move(cloud_open_metrics_for_one_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kOneDriveErrorMetricName, + ash::cloud_upload::OfficeOneDriveOpenErrors::kOffline, 1); + histogram_.ExpectUniqueSample( + ash::cloud_upload::kOneDriveTaskResultMetricName, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kOffline) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kOffline, + ash::cloud_upload::OfficeTaskResult::kFallbackQuickOffice, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kOffline, 1); + histogram_.ExpectUniqueSample( + ash::cloud_upload::kGoogleDriveTaskResultMetricName, + ash::cloud_upload::OfficeTaskResult::kFallbackQuickOffice, 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kDriveDisabled) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kDriveDisabled, + ash::cloud_upload::OfficeTaskResult::kCancelledAtFallback, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kDriveDisabled, 1); + histogram_.ExpectUniqueSample( + ash::cloud_upload::kGoogleDriveTaskResultMetricName, + ash::cloud_upload::OfficeTaskResult::kCancelledAtFallback, 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kNoDriveService) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kNoDriveService, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kNoDriveService, 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kDriveAuthenticationNotReady) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kDriveAuthenticationNotReady, + 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kDriveFsInterfaceError) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kDriveFsInterfaceError, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kDriveFsInterface, 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kMeteredConnection) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kMeteredConnection, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kMeteredConnection, 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kDisableDrivePreferenceSet) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kDisableDrivePreferenceSet, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kDisableDrivePreferenceSet, 1); +} + +TEST_F(FileManagerOfficeFileTasksTest, + LogGoogleDriveMetricsAfterFallback_kDriveDisabledForAccountType) { + LogGoogleDriveMetricsAfterFallback( + ash::office_fallback::FallbackReason::kDriveDisabledForAccountType, + ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, + std::move(cloud_open_metrics_for_drive_)); + + histogram_.ExpectUniqueSample( + ash::cloud_upload::kDriveErrorMetricName, + ash::cloud_upload::OfficeDriveOpenErrors::kDriveDisabledForAccountType, + 1); +} + } // namespace file_manager::file_tasks
diff --git a/chrome/browser/ash/file_system_provider/cloud_file_system.cc b/chrome/browser/ash/file_system_provider/cloud_file_system.cc index 622fcf6..87d7a03 100644 --- a/chrome/browser/ash/file_system_provider/cloud_file_system.cc +++ b/chrome/browser/ash/file_system_provider/cloud_file_system.cc
@@ -77,6 +77,10 @@ } // namespace CloudFileSystem::CloudFileSystem( + std::unique_ptr<ProvidedFileSystemInterface> file_system) + : CloudFileSystem(std::move(file_system), nullptr) {} + +CloudFileSystem::CloudFileSystem( std::unique_ptr<ProvidedFileSystemInterface> file_system, ContentCache* content_cache) : file_system_(std::move(file_system)), content_cache_(content_cache) {}
diff --git a/chrome/browser/ash/file_system_provider/cloud_file_system.h b/chrome/browser/ash/file_system_provider/cloud_file_system.h index d280ce9..b09eb51d 100644 --- a/chrome/browser/ash/file_system_provider/cloud_file_system.h +++ b/chrome/browser/ash/file_system_provider/cloud_file_system.h
@@ -33,10 +33,13 @@ namespace ash::file_system_provider { // A simple wrapper over a `ProvidedFileSystem` that adds additional logging, -// currently this is hidden behind the `FileSystemProviderContentCache` feature -// flag. +// currently this is hidden behind the `FileSystemProviderCloudFileSystem` +// feature flag. class CloudFileSystem : public ProvidedFileSystemInterface { public: + explicit CloudFileSystem( + std::unique_ptr<ProvidedFileSystemInterface> file_system); + CloudFileSystem(std::unique_ptr<ProvidedFileSystemInterface> file_system, ContentCache* content_cache);
diff --git a/chrome/browser/ash/file_system_provider/content_cache/content_cache.h b/chrome/browser/ash/file_system_provider/content_cache/content_cache.h index f588e8d..e6b44cc 100644 --- a/chrome/browser/ash/file_system_provider/content_cache/content_cache.h +++ b/chrome/browser/ash/file_system_provider/content_cache/content_cache.h
@@ -9,8 +9,9 @@ // A singleton that is the hub for all FileSystemProvider extensions that are // enabled with a content cache. Currently this is just an experiment hidden -// behind the FileSystemProviderContentCache flag and only enabled on ODFS when -// the flag is toggled on. +// behind both the `FileSystemProviderCloudFileSystem` and +// `FileSystemProviderContentCache` flags and only enabled on ODFS when the +// flags are toggled on. class ContentCache { public: ContentCache();
diff --git a/chrome/browser/ash/file_system_provider/extension_provider.cc b/chrome/browser/ash/file_system_provider/extension_provider.cc index b228b53e..93ff8e3b 100644 --- a/chrome/browser/ash/file_system_provider/extension_provider.cc +++ b/chrome/browser/ash/file_system_provider/extension_provider.cc
@@ -99,16 +99,27 @@ const ProvidedFileSystemInfo& file_system_info, ContentCache* content_cache) { DCHECK(profile); - // Cache type is only set when `FileSystemProviderContentCache` feature flag - // is enabled and the provider is ODFS. + if (!chromeos::features::IsFileSystemProviderCloudFileSystemEnabled()) { + return std::make_unique<ThrottledFileSystem>( + std::make_unique<ProvidedFileSystem>(profile, file_system_info)); + } + // TODO(b/317137739): Check the file system has a CLOUD source before + // creating a CloudFileSystem. + // Cache type is only set when the + // `FileSystemProviderCloudFileSystemEnabled` and + // `FileSystemProviderContentCache` feature flags are enabled and the + // provider is ODFS. if (file_system_info.cache_type() != CacheType::NONE) { + // CloudFileSystem with cache. return std::make_unique<ThrottledFileSystem>( std::make_unique<CloudFileSystem>( std::make_unique<ProvidedFileSystem>(profile, file_system_info), content_cache)); } + // CloudFileSystem without cache. return std::make_unique<ThrottledFileSystem>( - std::make_unique<ProvidedFileSystem>(profile, file_system_info)); + std::make_unique<CloudFileSystem>( + std::make_unique<ProvidedFileSystem>(profile, file_system_info))); } const Capabilities& ExtensionProvider::GetCapabilities() const {
diff --git a/chrome/browser/ash/file_system_provider/service.cc b/chrome/browser/ash/file_system_provider/service.cc index 9b430a45..cf8a5f1 100644 --- a/chrome/browser/ash/file_system_provider/service.cc +++ b/chrome/browser/ash/file_system_provider/service.cc
@@ -124,8 +124,8 @@ util::GetMountPath(profile_, provider_id, options.file_system_id); const std::string mount_point_name = mount_path.BaseName().AsUTF8Unsafe(); - // The content cache is an experimentation on ODFS behind a feature flag, only - // pass it through if those conditions are met. + // The content cache is an experimentation on ODFS behind two feature flags, + // only pass it through if those conditions are met. // TODO(b/317137739): This logic should be moved to a capability in the // manifest.json. const bool is_content_cache_enabled_and_odfs =
diff --git a/chrome/browser/ash/fileapi/file_change_service_unittest.cc b/chrome/browser/ash/fileapi/file_change_service_unittest.cc index cd1d4c9..031fc24 100644 --- a/chrome/browser/ash/fileapi/file_change_service_unittest.cc +++ b/chrome/browser/ash/fileapi/file_change_service_unittest.cc
@@ -15,13 +15,11 @@ #include "chrome/browser/ash/fileapi/file_change_service_factory.h" #include "chrome/browser/ash/fileapi/file_change_service_observer.h" #include "chrome/browser/ash/fileapi/file_system_backend.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/file_system_access/chrome_file_system_access_permission_context.h" #include "chrome/browser/file_system_access/file_system_access_permission_context_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile_manager.h" -#include "components/user_manager/scoped_user_manager.h" #include "mojo/public/cpp/system/data_pipe.h" #include "mojo/public/cpp/system/data_pipe_producer.h" #include "mojo/public/cpp/system/string_data_source.h" @@ -233,9 +231,7 @@ class FileChangeServiceTest : public BrowserWithTestWindowTest { public: - FileChangeServiceTest() - : fake_user_manager_(new FakeChromeUserManager), - user_manager_enabler_(base::WrapUnique(fake_user_manager_.get())) {} + FileChangeServiceTest() = default; FileChangeServiceTest(const FileChangeServiceTest& other) = delete; FileChangeServiceTest& operator=(const FileChangeServiceTest& other) = delete; @@ -252,15 +248,6 @@ std::string GetDefaultProfileName() override { return "promary_profile@test"; } - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindowTest. - const AccountId account_id = AccountId::FromUserEmail(email); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - } - - raw_ptr<FakeChromeUserManager, DanglingUntriaged> fake_user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; }; } // namespace
diff --git a/chrome/browser/ash/hats/hats_notification_controller_unittest.cc b/chrome/browser/ash/hats/hats_notification_controller_unittest.cc index ee4e7cb8..97d4864 100644 --- a/chrome/browser/ash/hats/hats_notification_controller_unittest.cc +++ b/chrome/browser/ash/hats/hats_notification_controller_unittest.cc
@@ -99,9 +99,11 @@ std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs( factory.CreateSyncable(registry.get())); RegisterUserProfilePrefs(registry.get()); - return profile_manager()->CreateTestingProfile( + auto* profile = profile_manager()->CreateTestingProfile( profile_name, std::move(prefs), std::u16string(), 0, TestingProfile::TestingFactories()); + OnUserProfileCreated(profile_name, profile); + return profile; } void TearDown() override {
diff --git a/chrome/browser/ash/input_method/editor_metrics_enums.h b/chrome/browser/ash/input_method/editor_metrics_enums.h index 81c213b4..eb77650 100644 --- a/chrome/browser/ash/input_method/editor_metrics_enums.h +++ b/chrome/browser/ash/input_method/editor_metrics_enums.h
@@ -126,7 +126,11 @@ kPromoCardExplicitDismissal = 40, // Increase by 1 when the webui consent screen is shown. kConsentScreenImpression = 41, - kMaxValue = kConsentScreenImpression, + // Increase by 1 when a text insertion has been requested.. + kTextInsertionRequested = 42, + // Increase by 1 when text has been queued for insertion. + kTextQueuedForInsertion = 43, + kMaxValue = kTextQueuedForInsertion, }; } // namespace ash::input_method
diff --git a/chrome/browser/ash/input_method/editor_metrics_recorder_unittest.cc b/chrome/browser/ash/input_method/editor_metrics_recorder_unittest.cc index c241f1b..269ea1e 100644 --- a/chrome/browser/ash/input_method/editor_metrics_recorder_unittest.cc +++ b/chrome/browser/ash/input_method/editor_metrics_recorder_unittest.cc
@@ -79,7 +79,6 @@ {"NativeRequestFreeformRewrite", EditorOpportunityMode::kRewrite, EditorTone::kFreeformRewrite, EditorStates::kNativeRequest, /*histogram_name=*/"InputMethod.Manta.Orca.States.FreeformRewrite"}, - }), [](const testing::TestParamInfo<StateCase> info) { return info.param.test_name;
diff --git a/chrome/browser/ash/input_method/editor_system_actuator.cc b/chrome/browser/ash/input_method/editor_system_actuator.cc index 18c7d9c..bff0ce28 100644 --- a/chrome/browser/ash/input_method/editor_system_actuator.cc +++ b/chrome/browser/ash/input_method/editor_system_actuator.cc
@@ -42,10 +42,7 @@ void EditorSystemActuator::InsertText(const std::string& text) { EditorMetricsRecorder* logger = system_->GetMetricsRecorder(); - logger->LogEditorState(EditorStates::kInsert); - logger->LogNumberOfCharactersInserted(text.length()); - logger->LogNumberOfCharactersSelectedForInsert( - system_->GetSelectedTextLength()); + logger->LogEditorState(EditorStates::kTextInsertionRequested); // After making an announcement there needs to be a small delay to ensure any // other announcements triggered from a text insertion do not collide with the // original announcement. @@ -90,9 +87,22 @@ } void EditorSystemActuator::OnFocus(int context_id) { - if (queued_text_insertion_ && (queued_text_insertion_->HasTimedOut() || - queued_text_insertion_->Commit())) { + if (queued_text_insertion_ == nullptr) { + return; + } + if (queued_text_insertion_->HasTimedOut()) { queued_text_insertion_ = nullptr; + return; + } + if (queued_text_insertion_->Commit()) { + EditorMetricsRecorder* logger = system_->GetMetricsRecorder(); + logger->LogEditorState(EditorStates::kInsert); + logger->LogNumberOfCharactersInserted( + queued_text_insertion_->GetTextLength()); + logger->LogNumberOfCharactersSelectedForInsert( + system_->GetSelectedTextLength()); + queued_text_insertion_ = nullptr; + return; } } @@ -102,6 +112,8 @@ // return to the original text input. queued_text_insertion_ = std::make_unique<EditorTextInsertion>(std::move(pending_text)); + EditorMetricsRecorder* logger = system_->GetMetricsRecorder(); + logger->LogEditorState(EditorStates::kTextQueuedForInsertion); system_->CloseUI(); }
diff --git a/chrome/browser/ash/input_method/editor_text_insertion.cc b/chrome/browser/ash/input_method/editor_text_insertion.cc index be291fe..4e9c9e1 100644 --- a/chrome/browser/ash/input_method/editor_text_insertion.cc +++ b/chrome/browser/ash/input_method/editor_text_insertion.cc
@@ -46,6 +46,10 @@ return true; } +int EditorTextInsertion::GetTextLength() { + return pending_text_.size(); +} + void EditorTextInsertion::CancelTextInsertion() { state_ = State::kTimedOut; }
diff --git a/chrome/browser/ash/input_method/editor_text_insertion.h b/chrome/browser/ash/input_method/editor_text_insertion.h index b59940f..9e7b1f5 100644 --- a/chrome/browser/ash/input_method/editor_text_insertion.h +++ b/chrome/browser/ash/input_method/editor_text_insertion.h
@@ -16,7 +16,7 @@ class EditorTextInsertion { public: - EditorTextInsertion(const std::string& text); + explicit EditorTextInsertion(const std::string& text); ~EditorTextInsertion(); // To help ensure that we do not insert the pending text in text fields other @@ -28,6 +28,9 @@ // Attempts to commit the pending text into the currently focused text input. bool Commit(); + // Returns the length of the text to be inserted with this operation. + int GetTextLength(); + private: enum State { kPending,
diff --git a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc index 0a6c410..850abde 100644 --- a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc +++ b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc
@@ -31,6 +31,7 @@ #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/components/kiosk/kiosk_test_utils.h" #include "components/account_id/account_id.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -1530,19 +1531,16 @@ ImeIdFromEngineId(kNaclMozcJpId))); } -TEST_F(InputMethodManagerImplTest, EnableAllowedInputMethodsInKiosk) { - // Login as a kiosk app user. - const std::string user_id = "kiosk@account.user"; - const std::string user_email = user_id; - const AccountId account_id = - AccountId::FromUserEmailGaiaId(user_email, user_id); +class InputMethodManagerImplKioskTest : public InputMethodManagerImplTest { + public: + void LogIn(const std::string& email) override { + chromeos::SetUpFakeKioskSession(email); + ash_test_helper()->test_session_controller_client()->AddUserSession( + email, user_manager::UserType::kKioskApp); + } +}; - ash::FakeChromeUserManager* fake_user_manager = - static_cast<ash::FakeChromeUserManager*>( - user_manager::UserManager::Get()); - fake_user_manager->AddKioskAppUser(account_id); - fake_user_manager->LoginUser(account_id); - +TEST_F(InputMethodManagerImplKioskTest, EnableAllowedInputMethods) { // First, setup xkb:fr::fra input method std::string original_input_method(ImeIdFromEngineId("xkb:fr::fra")); ASSERT_TRUE( @@ -1567,8 +1565,6 @@ EXPECT_THAT(manager_->GetActiveIMEState()->GetAllowedInputMethodIds(), testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"), ImeIdFromEngineId("xkb:de::ger"))); - // Logout kiosk app user. - fake_user_manager->RemoveUserFromList(account_id); } TEST_F(InputMethodManagerImplTest, SetLoginDefaultWithAllowedInputMethods) {
diff --git a/chrome/browser/ash/language_packs/OWNERS b/chrome/browser/ash/language_packs/OWNERS new file mode 100644 index 0000000..1e4bc2b --- /dev/null +++ b/chrome/browser/ash/language_packs/OWNERS
@@ -0,0 +1 @@ +file://chromeos/ash/components/language_packs/OWNERS
diff --git a/chrome/browser/ash/language_packs/language_pack_font_service.cc b/chrome/browser/ash/language_packs/language_pack_font_service.cc new file mode 100644 index 0000000..974e33c2 --- /dev/null +++ b/chrome/browser/ash/language_packs/language_pack_font_service.cc
@@ -0,0 +1,14 @@ +// 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/language_packs/language_pack_font_service.h" + +class PrefService; + +namespace ash::language_packs { + +LanguagePackFontService::LanguagePackFontService(PrefService* prefs) + : prefs_(*prefs) {} + +} // namespace ash::language_packs
diff --git a/chrome/browser/ash/language_packs/language_pack_font_service.h b/chrome/browser/ash/language_packs/language_pack_font_service.h new file mode 100644 index 0000000..caeb9b3 --- /dev/null +++ b/chrome/browser/ash/language_packs/language_pack_font_service.h
@@ -0,0 +1,26 @@ +// 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_LANGUAGE_PACKS_LANGUAGE_PACK_FONT_SERVICE_H_ +#define CHROME_BROWSER_ASH_LANGUAGE_PACKS_LANGUAGE_PACK_FONT_SERVICE_H_ + +#include "base/memory/raw_ref.h" +#include "components/keyed_service/core/keyed_service.h" + +class PrefService; + +namespace ash::language_packs { + +class LanguagePackFontService : public KeyedService { + public: + explicit LanguagePackFontService(PrefService* prefs); + + private: + // Not owned by this class + const raw_ref<PrefService> prefs_; +}; + +} // namespace ash::language_packs + +#endif // CHROME_BROWSER_ASH_LANGUAGE_PACKS_LANGUAGE_PACK_FONT_SERVICE_H_
diff --git a/chrome/browser/ash/language_packs/language_pack_font_service_factory.cc b/chrome/browser/ash/language_packs/language_pack_font_service_factory.cc new file mode 100644 index 0000000..bcefc59 --- /dev/null +++ b/chrome/browser/ash/language_packs/language_pack_font_service_factory.cc
@@ -0,0 +1,52 @@ +// 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/language_packs/language_pack_font_service_factory.h" + +#include "ash/constants/ash_features.h" +#include "base/feature_list.h" +#include "base/no_destructor.h" +#include "chrome/browser/ash/language_packs/language_pack_font_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_selections.h" + +class KeyedService; + +namespace ash::language_packs { + +LanguagePackFontServiceFactory* LanguagePackFontServiceFactory::GetInstance() { + static base::NoDestructor<LanguagePackFontServiceFactory> instance; + return instance.get(); +} + +LanguagePackFontServiceFactory::LanguagePackFontServiceFactory() + : ProfileKeyedServiceFactory( + "FontManagerFactory", + ProfileSelections::Builder() + // OTR renderers in Ash will inherit fontconfig from the original. + .WithRegular(ProfileSelection::kRedirectedToOriginal) + // No DLC fonts if there is no user. + .WithGuest(ProfileSelection::kNone) + .WithSystem(ProfileSelection::kNone) + .WithAshInternals(ProfileSelection::kNone) + .Build()) {} + +LanguagePackFontServiceFactory::~LanguagePackFontServiceFactory() = default; + +std::unique_ptr<KeyedService> +LanguagePackFontServiceFactory::BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const { + if (!base::FeatureList::IsEnabled(features::kLanguagePacksFonts)) { + return nullptr; + } + return std::make_unique<LanguagePackFontService>( + Profile::FromBrowserContext(context)->GetPrefs()); +} + +bool LanguagePackFontServiceFactory::ServiceIsCreatedWithBrowserContext() + const { + return true; +} + +} // namespace ash::language_packs
diff --git a/chrome/browser/ash/language_packs/language_pack_font_service_factory.h b/chrome/browser/ash/language_packs/language_pack_font_service_factory.h new file mode 100644 index 0000000..30e96e3 --- /dev/null +++ b/chrome/browser/ash/language_packs/language_pack_font_service_factory.h
@@ -0,0 +1,46 @@ +// 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_LANGUAGE_PACKS_LANGUAGE_PACK_FONT_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_ASH_LANGUAGE_PACKS_LANGUAGE_PACK_FONT_SERVICE_FACTORY_H_ + +#include <memory> + +#include "chrome/browser/profiles/profile_keyed_service_factory.h" + +class KeyedService; + +namespace base { +template <typename T> +class NoDestructor; +} + +namespace content { +class BrowserContext; +} + +namespace ash::language_packs { + +// Factory for `LanguagePackFontService`. +// This service is "internal" - other code should not access it, so +// `GetForProfile()` is omitted on purpose. +class LanguagePackFontServiceFactory : public ProfileKeyedServiceFactory { + public: + static LanguagePackFontServiceFactory* GetInstance(); + + private: + friend class base::NoDestructor<LanguagePackFontServiceFactory>; + + LanguagePackFontServiceFactory(); + ~LanguagePackFontServiceFactory() override; + + // BrowserContextKeyedServiceFactory overrides + std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; +}; + +} // namespace ash::language_packs + +#endif // CHROME_BROWSER_ASH_LANGUAGE_PACKS_LANGUAGE_PACK_FONT_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc index 8bfd080..edf34c0 100644 --- a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc +++ b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
@@ -32,7 +32,6 @@ #include "chrome/browser/ash/lock_screen_apps/first_app_run_toast_manager.h" #include "chrome/browser/ash/lock_screen_apps/focus_cycler_delegate.h" #include "chrome/browser/ash/lock_screen_apps/state_observer.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/note_taking_helper.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/test_extension_system.h" @@ -45,7 +44,6 @@ #include "chromeos/ash/components/dbus/concierge/concierge_client.h" #include "chromeos/dbus/power/fake_power_manager_client.h" #include "chromeos/dbus/power_manager/suspend.pb.h" -#include "components/user_manager/scoped_user_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/browser_task_environment.h" @@ -379,13 +377,9 @@ class LockScreenAppStateTest : public BrowserWithTestWindowTest { public: - LockScreenAppStateTest() - : fake_user_manager_(new ash::FakeChromeUserManager), - user_manager_enabler_(base::WrapUnique(fake_user_manager_.get())) {} - + LockScreenAppStateTest() = default; LockScreenAppStateTest(const LockScreenAppStateTest&) = delete; LockScreenAppStateTest& operator=(const LockScreenAppStateTest&) = delete; - ~LockScreenAppStateTest() override = default; void SetUp() override { @@ -460,20 +454,6 @@ ash::ConciergeClient::Shutdown(); } - // BrowserWithTestWindow: - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindow. - const AccountId account_id = AccountId::FromUserEmail(email); - AddTestUser(account_id); - fake_user_manager()->LoginUser(account_id); - } - - // Adds test user for the primary profile - virtual so test fixture can - // override the test user type. - virtual void AddTestUser(const AccountId& account_id) { - fake_user_manager()->AddUser(account_id); - } - // Exposed so test fixtures can override default (empty) command line. virtual void SetUpCommandLine(base::CommandLine* command_line) {} @@ -629,8 +609,6 @@ lock_screen_profile_creator_->CreateProfile(); } - ash::FakeChromeUserManager* fake_user_manager() { return fake_user_manager_; } - Profile* LockScreenProfile() { return lock_screen_profile_creator_->lock_screen_profile(); } @@ -671,9 +649,6 @@ std::unique_ptr<base::test::ScopedCommandLine> command_line_; - raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> fake_user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; - // Run loop used to throttle test until async state controller initialization // is fully complete. The quit closure for this run loop will be passed to // |state_controller_| as the callback to be run when the state controller is @@ -717,8 +692,16 @@ ~LockScreenAppStateKioskUserTest() override {} - void AddTestUser(const AccountId& account_id) override { - fake_user_manager()->AddKioskAppUser(account_id); + // BrowserWithTestWindow: + void LogIn(const std::string& email) override { + const AccountId account_id = AccountId::FromUserEmail(email); + // Log in as a kiosk user. + user_manager()->AddKioskAppUser(account_id); + user_manager()->UserLoggedIn( + account_id, + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); } };
diff --git a/chrome/browser/ash/login/existing_user_controller.cc b/chrome/browser/ash/login/existing_user_controller.cc index f7e840eb..4755261 100644 --- a/chrome/browser/ash/login/existing_user_controller.cc +++ b/chrome/browser/ash/login/existing_user_controller.cc
@@ -61,6 +61,7 @@ #include "chrome/browser/ash/login/ui/user_adding_screen.h" #include "chrome/browser/ash/login/ui/webui_login_view.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" +#include "chrome/browser/ash/login/users/chrome_user_manager_util.h" #include "chrome/browser/ash/login/wizard_controller.h" #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/ash/policy/core/device_local_account.h" @@ -440,7 +441,7 @@ } if (LoginDisplayHostMojo::Get()) { - auto login_users = ExtractLoginUsers(users); + auto login_users = chrome_user_manager_util::FindLoginAllowedUsers(users); LoginDisplayHostMojo::Get()->SetUsers(login_users); } } @@ -1098,34 +1099,6 @@ return password_changed_; } -// static -user_manager::UserList ExistingUserController::ExtractLoginUsers( - const user_manager::UserList& users) { - bool show_users_on_signin; - CrosSettings::Get()->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, - &show_users_on_signin); - user_manager::UserList filtered_users; - for (user_manager::User* user : users) { - // Skip kiosk apps for login screen user list. Kiosk apps as pods (aka new - // kiosk UI) is currently disabled and it gets the apps directly from - // KioskChromeAppManager, ArcKioskAppManager and WebKioskAppManager. - if (user->IsKioskType()) { - continue; - } - const bool meets_allowlist_requirements = - !user->HasGaiaAccount() || - user_manager::UserManager::Get()->IsGaiaUserAllowed(*user); - // Public session accounts are always shown on login screen. - const bool meets_show_users_requirements = - show_users_on_signin || - user->GetType() == user_manager::UserType::kPublicAccount; - if (meets_allowlist_requirements && meets_show_users_requirements) { - filtered_users.push_back(user); - } - } - return filtered_users; -} - void ExistingUserController::LoginAuthenticated( std::unique_ptr<UserContext> user_context) { CHECK(login_performer_);
diff --git a/chrome/browser/ash/login/screens/user_selection_screen.cc b/chrome/browser/ash/login/screens/user_selection_screen.cc index f1da5bce..9fd6d40 100644 --- a/chrome/browser/ash/login/screens/user_selection_screen.cc +++ b/chrome/browser/ash/login/screens/user_selection_screen.cc
@@ -187,15 +187,17 @@ return true; } -void GetMultiUserSignInPolicy(const user_manager::User* user, - bool* out_is_allowed, - user_manager::MultiUserSignInPolicy* out_policy) { +// Returns a pair of 1) whether it is allowed to be part of the current +// multi user sign-in session, and 2) that policy for the user. +std::tuple<bool, user_manager::MultiUserSignInPolicy> GetMultiUserSignInPolicy( + const user_manager::User* user) { const std::string& user_id = user->GetAccountId().GetUserEmail(); - MultiProfileUserController* multi_profile_user_controller = + MultiProfileUserController* controller = ChromeUserManager::Get()->GetMultiProfileUserController(); - *out_is_allowed = - multi_profile_user_controller->IsUserAllowedInSession(user_id, nullptr); - *out_policy = multi_profile_user_controller->GetCachedValue(user_id); + return { + controller->IsUserAllowedInSession(user_id), + controller->GetCachedValue(user_id), + }; } // Determines if user auth status requires online sign in. @@ -845,8 +847,9 @@ if (!is_signin_to_add) { user_info.is_multi_user_sign_in_allowed = true; } else { - GetMultiUserSignInPolicy(user, &user_info.is_multi_user_sign_in_allowed, - &user_info.multi_user_sign_in_policy); + std::tie(user_info.is_multi_user_sign_in_allowed, + user_info.multi_user_sign_in_policy) = + GetMultiUserSignInPolicy(user); } // Fill public session data.
diff --git a/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc b/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc index 9046ed7..322459e6 100644 --- a/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc +++ b/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc
@@ -12,7 +12,6 @@ #include "base/memory/ptr_util.h" #include "build/build_config.h" #include "chrome/browser/ash/login/signin/signin_error_notifier_factory.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" @@ -25,7 +24,6 @@ #include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/supervised_user/core/browser/supervised_user_service.h" -#include "components/user_manager/scoped_user_manager.h" #include "google_apis/gaia/google_service_auth_error.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" @@ -54,8 +52,6 @@ // Required to initialize TokenHandleUtil. ash::UserDataAuthClient::InitializeFake(); - fake_user_manager_.Reset(std::make_unique<ash::FakeChromeUserManager>()); - SigninErrorNotifierFactory::GetForProfile(GetProfile()); display_service_ = std::make_unique<NotificationDisplayServiceTester>(profile()); @@ -90,8 +86,6 @@ protected: std::unique_ptr<NotificationDisplayServiceTester> display_service_; - user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> - fake_user_manager_; std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> identity_test_env_profile_adaptor_; };
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc index d04ff9d..a106431 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -42,7 +42,6 @@ #include "base/values.h" #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h" #include "chrome/browser/ash/login/enterprise_user_session_metrics.h" -#include "chrome/browser/ash/login/existing_user_controller.h" #include "chrome/browser/ash/login/session/user_session_manager.h" #include "chrome/browser/ash/login/signin/auth_error_observer.h" #include "chrome/browser/ash/login/signin/auth_error_observer_factory.h" @@ -462,29 +461,25 @@ return user_manager::UserList(); } - user_manager::UserList result; - const user_manager::UserList& users = GetUsers(); - for (user_manager::UserList::const_iterator it = users.begin(); - it != users.end(); ++it) { - if ((*it)->GetType() == user_manager::UserType::kRegular && - !(*it)->is_logged_in()) { - MultiProfileUserController::UserAllowedInSessionReason check; - multi_profile_user_controller_.IsUserAllowedInSession( - (*it)->GetAccountId().GetUserEmail(), &check); - if (check == - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS) { - return user_manager::UserList(); - } + // No user is allowed if the primary user policy forbids it. + if (multi_profile_user_controller_.GetPrimaryUserPolicy() == + MultiUserSignInPolicy::kNotAllowed) { + return {}; + } + user_manager::UserList result; + for (user_manager::User* user : GetUsers()) { + if (user->GetType() == user_manager::UserType::kRegular && + !user->is_logged_in()) { // Users with a policy that prevents them being added to a session will be // shown in login UI but will be grayed out. // Same applies to owner account (see http://crbug.com/385034). - result.push_back(*it); + result.push_back(user); } } // Extract out users that are allowed on login screen. - return ExistingUserController::ExtractLoginUsers(result); + return chrome_user_manager_util::FindLoginAllowedUsers(result); } user_manager::UserList ChromeUserManagerImpl::GetUnlockUsers() const {
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_util.cc b/chrome/browser/ash/login/users/chrome_user_manager_util.cc index eb7721c..55ff620 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_util.cc +++ b/chrome/browser/ash/login/users/chrome_user_manager_util.cc
@@ -78,4 +78,31 @@ user_manager->IsCurrentUserCryptohomeDataEphemeral(); } +user_manager::UserList FindLoginAllowedUsers( + const user_manager::UserList& users) { + bool show_users_on_signin; + CrosSettings::Get()->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, + &show_users_on_signin); + user_manager::UserList found_users; + for (user_manager::User* user : users) { + // Skip kiosk apps for login screen user list. Kiosk apps as pods (aka new + // kiosk UI) is currently disabled and it gets the apps directly from + // KioskChromeAppManager, ArcKioskAppManager and WebKioskAppManager. + if (user->IsKioskType()) { + continue; + } + const bool meets_allowlist_requirements = + !user->HasGaiaAccount() || + user_manager::UserManager::Get()->IsGaiaUserAllowed(*user); + // Public session accounts are always shown on login screen. + const bool meets_show_users_requirements = + show_users_on_signin || + user->GetType() == user_manager::UserType::kPublicAccount; + if (meets_allowlist_requirements && meets_show_users_requirements) { + found_users.push_back(user); + } + } + return found_users; +} + } // namespace ash::chrome_user_manager_util
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_util.h b/chrome/browser/ash/login/users/chrome_user_manager_util.h index 4d2e24f..67d7cc1a 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_util.h +++ b/chrome/browser/ash/login/users/chrome_user_manager_util.h
@@ -29,6 +29,10 @@ // user has logged in). bool IsManagedGuestSessionOrEphemeralLogin(); +// Returns users allowed on login screen. +user_manager::UserList FindLoginAllowedUsers( + const user_manager::UserList& users); + } // namespace ash::chrome_user_manager_util #endif // CHROME_BROWSER_ASH_LOGIN_USERS_CHROME_USER_MANAGER_UTIL_H_
diff --git a/chrome/browser/ash/login/users/multi_profile_user_controller.cc b/chrome/browser/ash/login/users/multi_profile_user_controller.cc index 849b91ed..2dfc95b 100644 --- a/chrome/browser/ash/login/users/multi_profile_user_controller.cc +++ b/chrome/browser/ash/login/users/multi_profile_user_controller.cc
@@ -30,19 +30,6 @@ using user_manager::MultiUserSignInPolicyToPrefValue; using user_manager::ParseMultiUserSignInPolicyPref; -namespace { - -bool SetUserAllowedReason( - MultiProfileUserController::UserAllowedInSessionReason* reason, - MultiProfileUserController::UserAllowedInSessionReason value) { - if (reason) { - *reason = value; - } - return value == MultiProfileUserController::ALLOWED; -} - -} // namespace - MultiProfileUserController::MultiProfileUserController( PrefService* local_state, user_manager::UserManager* user_manager) @@ -73,31 +60,24 @@ pref_watchers_.clear(); } -MultiProfileUserController::UserAllowedInSessionReason +std::optional<MultiUserSignInPolicy> MultiProfileUserController::GetPrimaryUserPolicy() const { const user_manager::User* user = user_manager_->GetPrimaryUser(); if (!user) { - return ALLOWED; + return std::nullopt; } auto* prefs = user->GetProfilePrefs(); if (!prefs) { - return ALLOWED; + return std::nullopt; } - // No user is allowed if the primary user policy forbids it. - auto value = ParseMultiUserSignInPolicyPref( + return ParseMultiUserSignInPolicyPref( prefs->GetString(prefs::kMultiProfileUserBehaviorPref)); - if (value == MultiUserSignInPolicy::kNotAllowed) { - return NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS; - } - - return ALLOWED; } bool MultiProfileUserController::IsUserAllowedInSession( - const std::string& user_email, - MultiProfileUserController::UserAllowedInSessionReason* reason) const { + const std::string& user_email) const { const user_manager::User* primary_user = user_manager_->GetPrimaryUser(); std::string primary_user_email; if (primary_user) { @@ -107,20 +87,17 @@ // Always allow if there is no primary user or user being checked is the // primary user. if (primary_user_email.empty() || primary_user_email == user_email) { - return SetUserAllowedReason(reason, ALLOWED); + return true; } - UserAllowedInSessionReason primary_user_policy = GetPrimaryUserPolicy(); - if (primary_user_policy != ALLOWED) { - return SetUserAllowedReason(reason, primary_user_policy); + auto primary_user_policy = GetPrimaryUserPolicy(); + if (primary_user_policy == MultiUserSignInPolicy::kNotAllowed) { + return false; } // The user must have 'unrestricted' policy to be a secondary user. const auto policy = GetCachedValue(user_email); - return SetUserAllowedReason(reason, - policy == MultiUserSignInPolicy::kUnrestricted - ? ALLOWED - : NOT_ALLOWED_POLICY_FORBIDS); + return policy == MultiUserSignInPolicy::kUnrestricted; } void MultiProfileUserController::StartObserving(user_manager::User* user) { @@ -171,7 +148,7 @@ void MultiProfileUserController::CheckSessionUsers() { for (const user_manager::User* user : user_manager_->GetLoggedInUsers()) { const std::string& user_email = user->GetAccountId().GetUserEmail(); - if (!IsUserAllowedInSession(user_email, /*reason=*/nullptr)) { + if (!IsUserAllowedInSession(user_email)) { user_manager_->NotifyUserNotAllowed(user_email); return; }
diff --git a/chrome/browser/ash/login/users/multi_profile_user_controller.h b/chrome/browser/ash/login/users/multi_profile_user_controller.h index 2783d33..44a2207 100644 --- a/chrome/browser/ash/login/users/multi_profile_user_controller.h +++ b/chrome/browser/ash/login/users/multi_profile_user_controller.h
@@ -34,20 +34,6 @@ // user login and checks if the meaning of the value is respected. class MultiProfileUserController { public: - // Second return value of IsUserAllowedInSession(). - enum UserAllowedInSessionReason { - // User is allowed in multi-profile session. - ALLOWED, - - // Not allowed since primary user policy forbids it to be part of - // multi-profiles session. - NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, - - // Not allowed since user policy forbids this user being part of - // multi-profiles session. Either 'primary-only' or 'not-allowed'. - NOT_ALLOWED_POLICY_FORBIDS - }; - MultiProfileUserController(PrefService* local_state, user_manager::UserManager* user_manager); @@ -67,15 +53,13 @@ user_manager::MultiUserSignInPolicy GetCachedValue( std::string_view user_email) const; - // Returns primary user policy (only ALLOW, - // NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, - // NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS) - UserAllowedInSessionReason GetPrimaryUserPolicy() const; + // Returns the primary user's policy. If there's no primary user, + // returns std::nullopt. + std::optional<user_manager::MultiUserSignInPolicy> GetPrimaryUserPolicy() + const; - // Returns true if user allowed to be in the current session. If `reason` not - // null stores UserAllowedInSessionReason enum that describes actual reason. - bool IsUserAllowedInSession(const std::string& user_email, - UserAllowedInSessionReason* reason) const; + // Returns true if user allowed to be in the current session. + bool IsUserAllowedInSession(const std::string& user_email) const; // Starts to observe the multiprofile user behavior pref of the given user. void StartObserving(user_manager::User* user);
diff --git a/chrome/browser/ash/login/users/multi_profile_user_controller_unittest.cc b/chrome/browser/ash/login/users/multi_profile_user_controller_unittest.cc index a10133d..d4cf485 100644 --- a/chrome/browser/ash/login/users/multi_profile_user_controller_unittest.cc +++ b/chrome/browser/ash/login/users/multi_profile_user_controller_unittest.cc
@@ -57,66 +57,54 @@ struct BehaviorTestCase { MultiUserSignInPolicy primary; MultiUserSignInPolicy secondary; - MultiProfileUserController::UserAllowedInSessionReason - expected_primary_policy; - MultiProfileUserController::UserAllowedInSessionReason - expected_secondary_allowed; + bool expected_secondary_allowed; }; constexpr BehaviorTestCase kBehaviorTestCases[] = { { MultiUserSignInPolicy::kUnrestricted, MultiUserSignInPolicy::kUnrestricted, - MultiProfileUserController::ALLOWED, - MultiProfileUserController::ALLOWED, + true, }, { MultiUserSignInPolicy::kUnrestricted, MultiUserSignInPolicy::kPrimaryOnly, - MultiProfileUserController::ALLOWED, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + false, }, { MultiUserSignInPolicy::kUnrestricted, MultiUserSignInPolicy::kNotAllowed, - MultiProfileUserController::ALLOWED, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + false, }, { MultiUserSignInPolicy::kPrimaryOnly, MultiUserSignInPolicy::kUnrestricted, - MultiProfileUserController::ALLOWED, - MultiProfileUserController::ALLOWED, + true, }, { MultiUserSignInPolicy::kPrimaryOnly, MultiUserSignInPolicy::kPrimaryOnly, - MultiProfileUserController::ALLOWED, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + false, }, { MultiUserSignInPolicy::kPrimaryOnly, MultiUserSignInPolicy::kNotAllowed, - MultiProfileUserController::ALLOWED, - MultiProfileUserController::NOT_ALLOWED_POLICY_FORBIDS, + false, }, { MultiUserSignInPolicy::kNotAllowed, MultiUserSignInPolicy::kUnrestricted, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + false, }, { MultiUserSignInPolicy::kNotAllowed, MultiUserSignInPolicy::kPrimaryOnly, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + false, }, { MultiUserSignInPolicy::kNotAllowed, MultiUserSignInPolicy::kNotAllowed, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, - MultiProfileUserController::NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, + false, }, }; @@ -238,15 +226,11 @@ MultiUserSignInPolicy::kNotAllowed, }; for (size_t i = 0; i < std::size(kTestCases); ++i) { + SCOPED_TRACE(i); SetCachedBehavior(0, kTestCases[i]); - MultiProfileUserController::UserAllowedInSessionReason reason; - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[0].GetUserEmail(), &reason)) - << "Case " << i; - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason) << "Case " << i; - EXPECT_EQ(MultiProfileUserController::ALLOWED, - controller()->GetPrimaryUserPolicy()) - << "Case " << i; + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[0].GetUserEmail())); + EXPECT_EQ(std::nullopt, controller()->GetPrimaryUserPolicy()); } } @@ -312,16 +296,14 @@ LoginUser(0); for (size_t i = 0; i < std::size(kBehaviorTestCases); ++i) { + SCOPED_TRACE(i); SetPrefBehavior(0, kBehaviorTestCases[i].primary); SetCachedBehavior(1, kBehaviorTestCases[i].secondary); - EXPECT_EQ(kBehaviorTestCases[i].expected_primary_policy, - controller()->GetPrimaryUserPolicy()) - << "Case " << i; - MultiProfileUserController::UserAllowedInSessionReason reason; - controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail(), - &reason); - EXPECT_EQ(kBehaviorTestCases[i].expected_secondary_allowed, reason) - << "Case " << i; + EXPECT_EQ(kBehaviorTestCases[i].primary, + controller()->GetPrimaryUserPolicy()); + EXPECT_EQ( + kBehaviorTestCases[i].expected_secondary_allowed, + controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail())); } } @@ -339,6 +321,7 @@ testing::Mock::VerifyAndClearExpectations(&mock_observer); for (size_t i = 0; i < std::size(kBehaviorTestCases); ++i) { + SCOPED_TRACE(i); EXPECT_CALL(mock_observer, OnUserNotAllowed(testing::_)) .Times(testing::AnyNumber()); SetPrefBehavior(0, MultiUserSignInPolicy::kUnrestricted); @@ -346,8 +329,7 @@ testing::Mock::VerifyAndClearExpectations(&mock_observer); EXPECT_CALL(mock_observer, OnUserNotAllowed(testing::_)) - .Times(kBehaviorTestCases[i].expected_secondary_allowed == - MultiProfileUserController::ALLOWED + .Times(kBehaviorTestCases[i].expected_secondary_allowed ? testing::Exactly(0) : testing::AtLeast(1)); SetPrefBehavior(0, kBehaviorTestCases[i].primary); @@ -366,15 +348,10 @@ policy::PolicyCertServiceFactory::GetForProfile(profile(0)) ->SetUsedPolicyCertificates(); - MultiProfileUserController::UserAllowedInSessionReason reason; - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[0].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[1].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); - EXPECT_EQ(MultiProfileUserController::ALLOWED, - controller()->GetPrimaryUserPolicy()); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[0].GetUserEmail())); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail())); } TEST_F(MultiProfileUserControllerTest, @@ -387,10 +364,8 @@ // changed back to enabled. SetPrefBehavior(1, MultiUserSignInPolicy::kUnrestricted); - MultiProfileUserController::UserAllowedInSessionReason reason; - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[0].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[0].GetUserEmail())); ASSERT_TRUE( policy::PolicyCertServiceFactory::GetInstance()->SetTestingFactoryAndUse( @@ -398,9 +373,8 @@ policy::PolicyCertServiceFactory::GetForProfile(profile(0)) ->SetUsedPolicyCertificates(); - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[0].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[0].GetUserEmail())); } TEST_F(MultiProfileUserControllerTest, @@ -414,12 +388,8 @@ ->SetUsedPolicyCertificates(); LoginUser(0); - MultiProfileUserController::UserAllowedInSessionReason reason; - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[1].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); - EXPECT_EQ(MultiProfileUserController::ALLOWED, - controller()->GetPrimaryUserPolicy()); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail())); ASSERT_TRUE( policy::PolicyCertServiceFactory::GetInstance()->SetTestingFactoryAndUse( @@ -427,11 +397,8 @@ policy::PolicyCertServiceFactory::GetForProfile(profile(1)) ->SetUsedPolicyCertificates(); - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[1].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); - EXPECT_EQ(MultiProfileUserController::ALLOWED, - controller()->GetPrimaryUserPolicy()); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail())); // Flush tasks posted to IO. base::RunLoop().RunUntilIdle(); @@ -455,23 +422,16 @@ ASSERT_TRUE(service); EXPECT_FALSE(service->has_policy_certificates()); - MultiProfileUserController::UserAllowedInSessionReason reason; - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[1].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); - EXPECT_EQ(MultiProfileUserController::ALLOWED, - controller()->GetPrimaryUserPolicy()); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail())); net::CertificateList certificates; certificates.push_back( net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem")); service->SetPolicyTrustAnchorsForTesting(/*trust_anchors=*/certificates); EXPECT_TRUE(service->has_policy_certificates()); - EXPECT_TRUE(controller()->IsUserAllowedInSession( - test_users_[1].GetUserEmail(), &reason)); - EXPECT_EQ(MultiProfileUserController::ALLOWED, reason); - EXPECT_EQ(MultiProfileUserController::ALLOWED, - controller()->GetPrimaryUserPolicy()); + EXPECT_TRUE( + controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail())); // Flush tasks posted to IO. base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ash/note_taking_helper_unittest.cc b/chrome/browser/ash/note_taking_helper_unittest.cc index 469e080..93835ad 100644 --- a/chrome/browser/ash/note_taking_helper_unittest.cc +++ b/chrome/browser/ash/note_taking_helper_unittest.cc
@@ -411,8 +411,7 @@ auto* profile = profile_manager()->CreateTestingProfile( profile_name, std::move(prefs), u"Test profile", 1 /*avatar_id*/, TestingProfile::TestingFactories()); - user_manager()->OnUserProfileCreated(AccountId::FromUserEmail(profile_name), - nullptr /*TODO*/); + OnUserProfileCreated(profile_name, profile); return profile; } @@ -425,8 +424,7 @@ TestingProfile* profile = profile_manager()->CreateTestingProfile( kSecondProfileName, std::move(prefs), u"second-profile-username", /*avatar_id=*/1, TestingProfile::TestingFactories()); - user_manager()->OnUserProfileCreated( - AccountId::FromUserEmail(kSecondProfileName), nullptr /*TODO*/); + OnUserProfileCreated(kSecondProfileName, profile); InitExtensionService(profile); InitWebAppProvider(profile);
diff --git a/chrome/browser/ash/notifications/low_disk_notification_unittest.cc b/chrome/browser/ash/notifications/low_disk_notification_unittest.cc index 3ff59c3..4657e5eb 100644 --- a/chrome/browser/ash/notifications/low_disk_notification_unittest.cc +++ b/chrome/browser/ash/notifications/low_disk_notification_unittest.cc
@@ -22,7 +22,6 @@ #include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/user_manager/fake_user_manager.h" -#include "components/user_manager/scoped_user_manager.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/message_center/public/cpp/notification.h" @@ -50,11 +49,6 @@ GetCrosSettingsHelper()->SetBoolean(kDeviceShowLowDiskSpaceNotification, true); - auto user_manager = std::make_unique<user_manager::FakeUserManager>(); - user_manager_ = user_manager.get(); - scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( - std::move(user_manager)); - TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper( std::make_unique<SystemNotificationHelper>()); tester_ = std::make_unique<NotificationDisplayServiceTester>( @@ -86,9 +80,6 @@ void OnNotificationAdded() { notification_count_++; } protected: - raw_ptr<user_manager::FakeUserManager, DanglingUntriaged> user_manager_ = - nullptr; - std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; std::unique_ptr<NotificationDisplayServiceTester> tester_; std::unique_ptr<LowDiskNotification> low_disk_notification_; int notification_count_; @@ -142,9 +133,9 @@ } TEST_F(LowDiskNotificationTest, ShowForMultipleUsersWhenEnrolled) { - user_manager_->AddUser( + user_manager()->AddUser( AccountId::FromUserEmailGaiaId("test_user1@example.com", "1234567891")); - user_manager_->AddUser( + user_manager()->AddUser( AccountId::FromUserEmailGaiaId("test_user2@example.com", "1234567892")); SetNotificationThrottlingInterval(-1); @@ -153,9 +144,9 @@ } TEST_F(LowDiskNotificationTest, SupressedForMultipleUsersWhenEnrolled) { - user_manager_->AddUser( + user_manager()->AddUser( AccountId::FromUserEmailGaiaId("test_user1@example.com", "1234567891")); - user_manager_->AddUser( + user_manager()->AddUser( AccountId::FromUserEmailGaiaId("test_user2@example.com", "1234567892")); GetCrosSettingsHelper()->SetBoolean(kDeviceShowLowDiskSpaceNotification,
diff --git a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc index cf1d744..d740e5ac 100644 --- a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc +++ b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
@@ -128,6 +128,16 @@ ash::ChunneldClient::Shutdown(); } + // BrowserWithTestWindowTest: + // Override to do nothing to inject this test's specific behavior. + // TODO(b/40286020): Consider migrating into BrowserWithTestWindowTest + // in better way. Current test implementation is different from + // what we're seeing in production. + void LogIn(const std::string& email) override {} + void OnUserProfileCreated(const std::string& email, + Profile* profile) override {} + void SwitchActiveUser(const std::string& email) override {} + void LogInUser(bool is_affiliated) { base::RunLoop run_loop; const AccountId account_id(AccountId::FromUserEmailGaiaId(
diff --git a/chrome/browser/ash/release_notes/release_notes_storage.cc b/chrome/browser/ash/release_notes/release_notes_storage.cc index 9a633f2..0e72e19 100644 --- a/chrome/browser/ash/release_notes/release_notes_storage.cc +++ b/chrome/browser/ash/release_notes/release_notes_storage.cc
@@ -117,10 +117,6 @@ } bool ReleaseNotesStorage::ShouldShowSuggestionChip() { - if (!base::FeatureList::IsEnabled(features::kReleaseNotesSuggestionChip)) { - return false; - } - const int times_left_to_show = profile_->GetPrefs()->GetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow); return times_left_to_show > 0;
diff --git a/chrome/browser/ash/release_notes/release_notes_storage_unittest.cc b/chrome/browser/ash/release_notes/release_notes_storage_unittest.cc index 1789fff..ee44aca 100644 --- a/chrome/browser/ash/release_notes/release_notes_storage_unittest.cc +++ b/chrome/browser/ash/release_notes/release_notes_storage_unittest.cc
@@ -75,10 +75,8 @@ } void SetUp() override { - scoped_feature_list_.InitWithFeatures( - /*enabled_features=*/{features::kReleaseNotesNotificationAllChannels, - features::kReleaseNotesSuggestionChip}, - /*disabled_features=*/{}); + scoped_feature_list_.InitAndEnableFeature( + features::kReleaseNotesNotificationAllChannels); } raw_ptr<FakeChromeUserManager, DanglingUntriaged> user_manager_;
diff --git a/chrome/browser/ash/sync/sync_error_notifier_unittest.cc b/chrome/browser/ash/sync/sync_error_notifier_unittest.cc index eed5f41..94f29bd 100644 --- a/chrome/browser/ash/sync/sync_error_notifier_unittest.cc +++ b/chrome/browser/ash/sync/sync_error_notifier_unittest.cc
@@ -9,13 +9,11 @@ #include "ash/constants/ash_features.h" #include "base/functional/bind.h" #include "base/test/scoped_feature_list.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "components/sync/test/test_sync_service.h" -#include "components/user_manager/scoped_user_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/message_center/public/cpp/notification.h" @@ -93,8 +91,6 @@ syncer::TestSyncService service_; FakeLoginUI login_ui_; std::unique_ptr<NotificationDisplayServiceTester> display_service_; - user_manager::ScopedUserManager scoped_user_manager_{ - std::make_unique<ash::FakeChromeUserManager>()}; }; TEST_F(SyncErrorNotifierTest, NoNotificationWhenNoPassphrase) {
diff --git a/chrome/browser/ash/system_web_apps/apps/help_app/help_app_notification_controller_unittest.cc b/chrome/browser/ash/system_web_apps/apps/help_app/help_app_notification_controller_unittest.cc index fd2e04a..e381df0d 100644 --- a/chrome/browser/ash/system_web_apps/apps/help_app/help_app_notification_controller_unittest.cc +++ b/chrome/browser/ash/system_web_apps/apps/help_app/help_app_notification_controller_unittest.cc
@@ -11,7 +11,6 @@ #include "base/memory/raw_ptr.h" #include "base/test/scoped_feature_list.h" #include "base/version.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/system_web_apps/apps/help_app/help_app_discover_tab_notification.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/notifications/notification_display_service_tester.h" @@ -26,10 +25,7 @@ #include "components/account_id/account_id.h" #include "components/language/core/browser/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" -#include "components/prefs/pref_service.h" -#include "components/prefs/pref_service_factory.h" #include "components/prefs/testing_pref_store.h" -#include "components/user_manager/scoped_user_manager.h" #include "components/version_info/version_info.h" namespace { @@ -42,43 +38,27 @@ class HelpAppNotificationControllerTest : public BrowserWithTestWindowTest { public: - HelpAppNotificationControllerTest() - : user_manager_(new FakeChromeUserManager()), - scoped_user_manager_( - std::unique_ptr<FakeChromeUserManager>(user_manager_)) {} + HelpAppNotificationControllerTest() = default; ~HelpAppNotificationControllerTest() override = default; - std::unique_ptr<TestingProfile> CreateRegularProfile() { - AccountId account_id_ = - AccountId::FromUserEmailGaiaId("user@gmail.com", "12345"); - user_manager_->AddUser(account_id_); - TestingProfile::Builder builder; - builder.SetProfileName("user@gmail.com"); - std::unique_ptr<TestingProfile> profile = builder.Build(); + TestingProfile* CreateRegularProfile() { + constexpr char kEmail[] = "user@gmail.com"; + LogIn(kEmail); + auto* profile = CreateProfile(kEmail); // Set profile creation version, otherwise it defaults to 1.0.0.0. ChromeVersionService::SetVersion( profile->GetPrefs(), std::string(version_info::GetVersionNumber())); return profile; } - std::unique_ptr<TestingProfile> CreateChildProfile() { - std::unique_ptr<TestingProfile> profile = CreateRegularProfile(); + TestingProfile* CreateChildProfile() { + TestingProfile* profile = CreateRegularProfile(); ChromeVersionService::SetVersion( profile->GetPrefs(), std::string(version_info::GetVersionNumber())); profile->SetIsSupervisedProfile(); return profile; } - // Creates a PrefService and registers Autofill prefs. - std::unique_ptr<PrefService> CreatePrefServiceAndRegisterPrefs() { - scoped_refptr<user_prefs::PrefRegistrySyncable> registry( - new user_prefs::PrefRegistrySyncable()); - HelpAppNotificationController::RegisterProfilePrefs(registry.get()); - PrefServiceFactory factory; - factory.set_user_prefs(base::MakeRefCounted<TestingPrefStore>()); - return factory.Create(registry); - } - void SetUp() override { BrowserWithTestWindowTest::SetUp(); help_app_notification_controller_ = @@ -95,7 +75,6 @@ {features::kHelpAppDiscoverTabNotificationAllChannels, features::kReleaseNotesNotificationAllChannels}, /*disabled_features=*/{}); - pref_service_ = CreatePrefServiceAndRegisterPrefs(); } void TearDown() override { @@ -131,24 +110,19 @@ .value(); } - PrefService* pref_service() { return pref_service_.get(); } - - raw_ptr<FakeChromeUserManager, DanglingUntriaged> user_manager_; - user_manager::ScopedUserManager scoped_user_manager_; int notification_count_ = 0; std::unique_ptr<HelpAppNotificationController> help_app_notification_controller_; std::unique_ptr<NotificationDisplayServiceTester> notification_tester_; base::test::ScopedFeatureList scoped_feature_list_; - std::unique_ptr<PrefService> pref_service_; }; // Tests for regular profiles. TEST_F(HelpAppNotificationControllerTest, DoesNotShowAnyNotificationIfNewRegularProfile) { - std::unique_ptr<Profile> profile = CreateRegularProfile(); + Profile* profile = CreateRegularProfile(); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); controller->MaybeShowReleaseNotesNotification(); @@ -163,11 +137,11 @@ TEST_F(HelpAppNotificationControllerTest, ShowsReleaseNotesNotificationIfShownInOlderMilestone) { - std::unique_ptr<Profile> profile = CreateRegularProfile(); + Profile* profile = CreateRegularProfile(); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, 20); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); controller->MaybeShowReleaseNotesNotification(); @@ -180,11 +154,11 @@ TEST_F(HelpAppNotificationControllerTest, DoesNotShowReleaseNotificationIfAlreadyShownInCurrentMilestone) { - std::unique_ptr<Profile> profile = CreateRegularProfile(); + Profile* profile = CreateRegularProfile(); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, CurrentMilestone()); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); controller->MaybeShowReleaseNotesNotification(); @@ -194,9 +168,9 @@ TEST_F(HelpAppNotificationControllerTest, DoesNotShowDiscoverNotificationIfNotChildProfile) { - std::unique_ptr<Profile> profile = CreateRegularProfile(); + Profile* profile = CreateRegularProfile(); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, 20); @@ -209,9 +183,9 @@ // Tests for Child profile. TEST_F(HelpAppNotificationControllerTest, DoesNotShowAnyNotificationIfNewChildProfile) { - std::unique_ptr<Profile> profile = CreateChildProfile(); + Profile* profile = CreateChildProfile(); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); controller->MaybeShowReleaseNotesNotification(); @@ -227,12 +201,12 @@ // TODO(b/187774783): Remove this when discover tab is supported in all locales. TEST_F(HelpAppNotificationControllerTest, DoesNotShowDiscoverNotificationIfSystemLanguageNotEnglish) { - std::unique_ptr<Profile> profile = CreateChildProfile(); + Profile* profile = CreateChildProfile(); g_browser_process->SetApplicationLocale("fr"); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, 20); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); controller->MaybeShowDiscoverNotification(); @@ -242,11 +216,11 @@ TEST_F(HelpAppNotificationControllerTest, ShowsDiscoverNotificationIfShownInPreviousMilestone) { - std::unique_ptr<Profile> profile = CreateChildProfile(); + Profile* profile = CreateChildProfile(); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, 91); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); controller->MaybeShowDiscoverNotification(); @@ -259,11 +233,11 @@ TEST_F(HelpAppNotificationControllerTest, DoesNotShowMoreThanOneNotificationPerMilestone) { - std::unique_ptr<Profile> profile = CreateChildProfile(); + Profile* profile = CreateChildProfile(); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, 91); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); controller->MaybeShowDiscoverNotification(); @@ -279,11 +253,11 @@ // Tests for suggestion chips. TEST_F(HelpAppNotificationControllerTest, UpdatesReleaseNotesChipPrefWhenReleaseNotesNotificationShown) { - std::unique_ptr<Profile> profile = CreateRegularProfile(); + Profile* profile = CreateRegularProfile(); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, 20); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); EXPECT_EQ(0, profile->GetPrefs()->GetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow)); @@ -296,11 +270,11 @@ TEST_F(HelpAppNotificationControllerTest, UpdatesDiscoverTabChipPrefWhenDiscoverTabNotificationShown) { - std::unique_ptr<Profile> profile = CreateChildProfile(); + Profile* profile = CreateChildProfile(); profile->GetPrefs()->SetInteger(prefs::kHelpAppNotificationLastShownMilestone, 20); std::unique_ptr<HelpAppNotificationController> controller = - std::make_unique<HelpAppNotificationController>(profile.get()); + std::make_unique<HelpAppNotificationController>(profile); EXPECT_EQ(0, profile->GetPrefs()->GetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow));
diff --git a/chrome/browser/ash/system_web_apps/apps/help_app/help_app_untrusted_ui_config.cc b/chrome/browser/ash/system_web_apps/apps/help_app/help_app_untrusted_ui_config.cc index eb937eed..212b68e 100644 --- a/chrome/browser/ash/system_web_apps/apps/help_app/help_app_untrusted_ui_config.cc +++ b/chrome/browser/ash/system_web_apps/apps/help_app/help_app_untrusted_ui_config.cc
@@ -110,6 +110,8 @@ source->AddBoolean("HelpAppAutoTriggerInstallDialog", base::FeatureList::IsEnabled( features::kHelpAppAutoTriggerInstallDialog)); + source->AddBoolean("AppInstallServiceUri", + chromeos::features::IsAppInstallServiceUriEnabled()); } Profile* profile = Profile::FromWebUI(web_ui);
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc b/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc index 40243db..84e3319 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/common/api_guard_delegate_unittest.cc
@@ -136,13 +136,6 @@ // Make sure device manufacturer is allowlisted. SetDeviceManufacturer(manufacturer()); -#if BUILDFLAG(IS_CHROMEOS_ASH) - auto user_manager = std::make_unique<ash::FakeChromeUserManager>(); - scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( - std::move(user_manager)); - AddUserAndLogIn(); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - #if BUILDFLAG(IS_CHROMEOS_LACROS) auto params = crosapi::mojom::BrowserInitParams::New(); params->is_current_user_device_owner = true; @@ -153,22 +146,10 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) } - void TearDown() override { #if BUILDFLAG(IS_CHROMEOS_ASH) - // Explicitly removing the user is required; otherwise ProfileHelper keeps a - // dangling pointer to the User. - // TODO(b/208629291): Consider removing all users from ProfileHelper in the - // destructor of ash::FakeChromeUserManager. - if (GetFakeUserManager().GetActiveUser()) { - GetFakeUserManager().RemoveUserFromList( - GetFakeUserManager().GetActiveUser()->GetAccountId()); - } - scoped_user_manager_.reset(); + std::string GetDefaultProfileName() override { return kUserEmail; } #endif // BUILDFLAG(IS_CHROMEOS_ASH) - BrowserWithTestWindowTest::TearDown(); - } - protected: extensions::ExtensionId extension_id() const { return GetParam().extension_id; @@ -183,25 +164,10 @@ const extensions::Extension* extension() { return extension_.get(); } #if BUILDFLAG(IS_CHROMEOS_ASH) - ash::FakeChromeUserManager& GetFakeUserManager() { - return CHECK_DEREF(static_cast<ash::FakeChromeUserManager*>( - user_manager::UserManager::Get())); - } - - virtual void AddUserAndLogIn() { - auto& user_manager = GetFakeUserManager(); - // Make sure the current user is affiliated. - const AccountId account_id = AccountId::FromUserEmail(kUserEmail); - user_manager.AddUser(account_id); - user_manager.LoginUser(account_id); - user_manager.SwitchActiveUser(account_id); - } - void SetUserAsOwner() { - auto& user_manager = GetFakeUserManager(); // Make sure the current user is affiliated. const AccountId account_id = AccountId::FromUserEmail(kUserEmail); - user_manager.SetOwnerId(account_id); + user_manager()->SetOwnerId(account_id); } #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -248,18 +214,13 @@ scoped_refptr<const extensions::Extension> extension_; std::unique_ptr<HardwareInfoDelegate::Factory> hardware_info_delegate_factory_; - -#if BUILDFLAG(IS_CHROMEOS_ASH) - std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; -#endif // BUILDFLAG(IS_CHROMEOS_ASH) }; TEST_P(ApiGuardDelegateTest, CurrentUserNotOwner) { #if BUILDFLAG(IS_CHROMEOS_ASH) - auto& user_manager = GetFakeUserManager(); // Make sure the current user is not the device owner. const AccountId regular_user = AccountId::FromUserEmail("regular@gmail.com"); - user_manager.SetOwnerId(regular_user); + user_manager()->SetOwnerId(regular_user); #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_LACROS) @@ -430,13 +391,15 @@ protected: #if BUILDFLAG(IS_CHROMEOS_ASH) - void AddUserAndLogIn() override { - auto& user_manager = GetFakeUserManager(); + void LogIn(const std::string& email) override { // Make sure the current user is affiliated. - const AccountId account_id = AccountId::FromUserEmail("user@example.com"); - user_manager.AddUserWithAffiliation(account_id, /*is_affiliated=*/true); - user_manager.LoginUser(account_id); - user_manager.SwitchActiveUser(account_id); + const AccountId account_id = AccountId::FromUserEmail(email); + user_manager()->AddUserWithAffiliation(account_id, /*is_affiliated=*/true); + user_manager()->UserLoggedIn( + account_id, + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); } #endif // BUILDFLAG(IS_CHROMEOS_ASH) }; @@ -643,10 +606,11 @@ return ash::kShimlessRmaAppBrowserContextBaseName; } - // ApiGuardDelegateTest overrides. - void AddUserAndLogIn() override { - // No user is logged in during Shimless RMA. - } + // Do nothing for special profile for shimless RMA App. + void LogIn(const std::string& email) override {} + void SwitchActiveUser(const std::string& email) override {} + void OnUserProfileCreated(const std::string& email, + Profile* profile) override {} private: base::test::ScopedFeatureList feature_list_;
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index 1637b74da..efc22ad 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -2340,7 +2340,8 @@ if (UseOopif()) { content::NavigateIframeToURL(web_contents, /*iframe_id=*/"test", subframe_url); - GetTestPdfViewerStreamManager()->WaitUntilPdfLoadedInFirstChild(); + ASSERT_TRUE( + GetTestPdfViewerStreamManager()->WaitUntilPdfLoadedInFirstChild()); content::RenderFrameHost* extension_host = pdf_extension_test_util::GetOnlyPdfExtensionHost(web_contents); @@ -2525,7 +2526,8 @@ if (UseOopif()) { content::NavigateIframeToURL(web_contents, /*iframe_id=*/"test", subframe_url); - GetTestPdfViewerStreamManager()->WaitUntilPdfLoadedInFirstChild(); + ASSERT_TRUE( + GetTestPdfViewerStreamManager()->WaitUntilPdfLoadedInFirstChild()); target_frame = pdf_extension_test_util::GetOnlyPdfPluginFrame(web_contents); ASSERT_TRUE(target_frame);
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc index 58c4507..e10427e 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -15,7 +15,6 @@ #include "base/strings/string_piece.h" #include "base/values.h" #include "chrome/browser/ash/attestation/mock_tpm_challenge_key.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/platform_keys/key_permissions/fake_user_private_token_kpm_service.h" #include "chrome/browser/ash/platform_keys/key_permissions/mock_key_permissions_manager.h" #include "chrome/browser/ash/platform_keys/key_permissions/user_private_token_kpm_service_factory.h" @@ -29,7 +28,6 @@ #include "chromeos/ash/components/dbus/constants/attestation_constants.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" -#include "components/user_manager/scoped_user_manager.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/extension_function_dispatcher.h" #include "extensions/common/extension_builder.h" @@ -61,10 +59,7 @@ class EPKChallengeKeyTestBase : public BrowserWithTestWindowTest { protected: - EPKChallengeKeyTestBase() - : extension_(ExtensionBuilder("Test").Build()), - fake_user_manager_(new ash::FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(fake_user_manager_.get())) { + EPKChallengeKeyTestBase() : extension_(ExtensionBuilder("Test").Build()) { stub_install_attributes_.SetCloudManaged("google.com", "device_id"); } @@ -114,9 +109,9 @@ void LogIn(const std::string& email) override { const AccountId account_id = AccountId::FromUserEmail(email); - fake_user_manager_->AddUserWithAffiliation(account_id, - /*is_affiliated=*/true); - fake_user_manager_->UserLoggedIn( + user_manager()->AddUserWithAffiliation(account_id, + /*is_affiliated=*/true); + user_manager()->UserLoggedIn( account_id, user_manager::FakeUserManager::GetFakeUsernameHash(account_id), /*browser_restart=*/false, @@ -178,10 +173,6 @@ scoped_refptr<const extensions::Extension> extension_; ash::StubInstallAttributes stub_install_attributes_; - // fake_user_manager_ is owned by user_manager_enabler_. - raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> fake_user_manager_ = - nullptr; - user_manager::ScopedUserManager user_manager_enabler_; ash::platform_keys::MockKeyPermissionsManager key_permissions_manager_; raw_ptr<PrefService, DanglingUntriaged> prefs_ = nullptr; raw_ptr<ash::attestation::MockTpmChallengeKey, DanglingUntriaged>
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc index 4d03cd64..88de4db 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -10,14 +10,12 @@ #include "base/memory/raw_ptr.h" #include "base/values.h" #include "chrome/browser/ash/attestation/mock_tpm_challenge_key.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" -#include "components/user_manager/scoped_user_manager.h" #include "extensions/browser/api_test_utils.h" #include "extensions/common/extension_builder.h" #include "testing/gmock/include/gmock/gmock.h" @@ -35,11 +33,7 @@ class EPKPChallengeKeyTestBase : public BrowserWithTestWindowTest { protected: - EPKPChallengeKeyTestBase() - : fake_user_manager_(new ash::FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(fake_user_manager_.get())) { - extension_ = ExtensionBuilder("Test").Build(); - } + EPKPChallengeKeyTestBase() : extension_(ExtensionBuilder("Test").Build()) {} void SetUp() override { BrowserWithTestWindowTest::SetUp(); @@ -58,9 +52,9 @@ // This will be called by BrowserWithTestWindowTest::SetUp(); void LogIn(const std::string& email) override { const AccountId account_id = AccountId::FromUserEmail(email); - fake_user_manager_->AddUserWithAffiliation(account_id, - /*is_affiliated=*/true); - fake_user_manager_->UserLoggedIn( + user_manager()->AddUserWithAffiliation(account_id, + /*is_affiliated=*/true); + user_manager()->UserLoggedIn( account_id, user_manager::FakeUserManager::GetFakeUsernameHash(account_id), /*browser_restart=*/false, @@ -77,11 +71,6 @@ } scoped_refptr<const Extension> extension_; - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindowTest. - // fake_user_manager_ is owned by user_manager_enabler_. - raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> fake_user_manager_ = - nullptr; - user_manager::ScopedUserManager user_manager_enabler_; raw_ptr<PrefService, DanglingUntriaged> prefs_ = nullptr; };
diff --git a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc index d70d0e1..be1c228b 100644 --- a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc +++ b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -32,7 +32,6 @@ #include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h" #include "chrome/browser/ash/login/smart_lock/smart_lock_service.h" #include "chrome/browser/ash/login/smart_lock/smart_lock_service_factory.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_api_unittest.h" @@ -54,7 +53,6 @@ #include "components/prefs/testing_pref_service.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "components/user_manager/known_user.h" -#include "components/user_manager/scoped_user_manager.h" #include "content/public/test/test_utils.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/extension_function_dispatcher.h" @@ -83,8 +81,6 @@ } constexpr char kTestUserEmail[] = "testuser@gmail.com"; -constexpr char kTestUserGaiaId[] = "9876543210"; -constexpr char kTestUserEmailHash[] = "testuser@gmail.com-hash"; constexpr char kInvalidToken[] = "invalid"; constexpr char kValidPassword[] = "valid"; constexpr char kInvalidPassword[] = "invalid"; @@ -185,7 +181,7 @@ const cryptohome::AccountIdentifier account_id = cryptohome::CreateAccountIdentifierFromAccountId( - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId)); + AccountId::FromUserEmail(kTestUserEmail)); ash::Key key{kValidPassword}; key.Transform(ash::Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, @@ -201,10 +197,6 @@ ash::SystemSaltGetter::Initialize(); - auto fake_user_manager = std::make_unique<ash::FakeChromeUserManager>(); - fake_user_manager_ = fake_user_manager.get(); - scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( - std::move(fake_user_manager)); auth_parts_ = ash::AuthPartsImpl::CreateTestInstance(); auth_parts_->SetAuthSessionStorage( std::make_unique<ash::AuthSessionStorageImpl>( @@ -231,13 +223,6 @@ std::string GetDefaultProfileName() override { return kTestUserEmail; } - void LogIn(const std::string& email) override { - auto test_account = AccountId::FromUserEmailGaiaId(email, kTestUserGaiaId); - fake_user_manager_->AddUser(test_account); - fake_user_manager_->UserLoggedIn(test_account, kTestUserEmailHash, false, - false); - } - TestingProfile* CreateProfile(const std::string& profile_name) override { auto pref_service = std::make_unique<sync_preferences::TestingPrefServiceSyncable>(); @@ -247,28 +232,26 @@ TestingProfile* profile = profile_manager()->CreateTestingProfile( profile_name, std::move(pref_service), u"Test profile", 1 /* avatar_id */, GetTestingFactories()); + OnUserProfileCreated(profile_name, profile); // Setup a primary user. - auto test_account = - AccountId::FromUserEmailGaiaId(profile_name, kTestUserGaiaId); - fake_user_manager_->SimulateUserProfileLoad(test_account); ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting( - fake_user_manager_->GetPrimaryUser(), profile); + user_manager()->GetPrimaryUser(), profile); // Generate an auth token. - auth_token_user_context_.SetAccountId(test_account); - auth_token_user_context_.SetUserIDHash(kTestUserEmailHash); + AccountId account_id = AccountId::FromUserEmail(profile_name); + auth_token_user_context_.SetAccountId(account_id); + auth_token_user_context_.SetUserIDHash( + user_manager::FakeUserManager::GetFakeUsernameHash(account_id)); auth_token_user_context_.SetSessionLifetime( base::Time::Now() + ash::quick_unlock::AuthToken::kTokenExpiration); if (std::get<0>(GetParam()) == TestType::kCryptohome) { auto* fake_userdataauth_client_testapi = ash::FakeUserDataAuthClient::TestApi::Get(); - const cryptohome::AccountIdentifier account_id = - cryptohome::CreateAccountIdentifierFromAccountId( - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId)); auto session_ids = fake_userdataauth_client_testapi->AddSession( - account_id, /*authenticated=*/true); + cryptohome::CreateAccountIdentifierFromAccountId(account_id), + /*authenticated=*/true); auth_token_user_context_.SetAuthSessionIds(session_ids.first, session_ids.second); // Technically configuration should contain password as factor, but @@ -290,8 +273,6 @@ ExtensionApiUnittest::TearDown(); - fake_user_manager_ = nullptr; - scoped_user_manager_.reset(); test_api_.reset(); ash::SystemSaltGetter::Shutdown(); @@ -523,8 +504,7 @@ // Returns if the pin is set in the backend. bool IsPinSetInBackend() { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); base::test::TestFuture<bool> is_pin_set_future; ash::quick_unlock::PinBackend::GetInstance()->IsSet( @@ -546,43 +526,37 @@ } int GetExposedPinLength() { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); return user_manager::KnownUser(g_browser_process->local_state()) .GetUserPinLength(account_id); } void ClearExposedPinLength() { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); user_manager::KnownUser(g_browser_process->local_state()) .SetUserPinLength(account_id, 0); } bool IsBackfillNeeded() { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); return user_manager::KnownUser(g_browser_process->local_state()) .PinAutosubmitIsBackfillNeeded(account_id); } void SetBackfillNotNeeded() { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); user_manager::KnownUser(g_browser_process->local_state()) .PinAutosubmitSetBackfillNotNeeded(account_id); } void SetBackfillNeededForTests() { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); user_manager::KnownUser(g_browser_process->local_state()) .PinAutosubmitSetBackfillNeededForTests(account_id); } void OnUpdateUserPods() { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); ash::quick_unlock::PinBackend::GetInstance()->GetExposedPinLength( account_id); } @@ -612,8 +586,7 @@ // Run an authentication attempt with the plain-text |password|. bool TryAuthenticate(const std::string& password) { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); auto user_context = std::make_unique<ash::UserContext>( user_manager::UserType::kRegular, account_id); user_context->SetIsUsingPin(true); @@ -629,8 +602,7 @@ } bool SetPinAutosubmitEnabled(const std::string& pin, const bool enabled) { - const AccountId account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + const AccountId account_id = AccountId::FromUserEmail(kTestUserEmail); base::test::TestFuture<bool> set_pin_future; ash::quick_unlock::PinBackend::GetInstance()->SetPinAutoSubmitEnabled( account_id, pin, enabled, set_pin_future.GetCallback()); @@ -685,8 +657,6 @@ } std::unique_ptr<ash::AuthPartsImpl> auth_parts_; - raw_ptr<ash::FakeChromeUserManager> fake_user_manager_ = nullptr; - std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; QuickUnlockPrivateSetModesFunction::ModesChangedEventHandler modes_changed_handler_; bool expect_modes_changed_ = false;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index c3c0971..48865a0 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -4320,6 +4320,11 @@ "expiry_milestone": 130 }, { + "name": "file-system-provider-cloud-file-system", + "owners": [ "benreich@chromium.org", "cassycc@chromium.org", "simmonsjosh@google.com" ], + "expiry_milestone": 130 + }, + { "name": "file-system-provider-content-cache", "owners": [ "benreich@chromium.org", "cassycc@chromium.org", "simmonsjosh@google.com" ], "expiry_milestone": 130 @@ -4380,14 +4385,6 @@ "expiry_milestone": 125 }, { - "name": "firmware-update-jelly", - "owners": [ - "//ash/webui/firmware_update_ui/OWNERS", - "cros-peripherals@google.com" - ], - "expiry_milestone": 130 - }, - { "name": "firmware-update-ui-v2", "owners": [ "//ash/webui/firmware_update_ui/OWNERS", @@ -6556,14 +6553,6 @@ "expiry_milestone": 122 }, { - "name": "print-management-jelly", - "owners": [ - "//ash/webui/print_management/OWNERS", - "cros-peripherals@google.com" - ], - "expiry_milestone": 130 - }, - { "name": "print-management-setup-assistance", "owners": [ "//ash/webui/print_management/OWNERS"
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 3c42d23..0bf2fefb 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -6534,17 +6534,17 @@ const char kFilesTrashDriveDescription[] = "Enable trash for Drive volume in Files App."; +const char kFileSystemProviderCloudFileSystemName[] = + "Enable CloudFileSystem for FileSystemProvider extensions."; +const char kFileSystemProviderCloudFileSystemDescription[] = + "Enable the ability for individual FileSystemProvider extensions to " + "be serviced by a CloudFileSystem."; + const char kFileSystemProviderContentCacheName[] = "Enable content caching for FileSystemProvider extensions."; const char kFileSystemProviderContentCacheDescription[] = - "Enable the ability for individual FileSystemProvider extensions to " - "leverage a content cache."; - -const char kFirmwareUpdateJellyName[] = - "Enable jelly colors for the Firmware Update App"; -const char kFirmwareUpdateJellyDescription[] = - "Enable jelly colors for the Firmware Update App. Requires " - "jelly-colors flag to be enabled."; + "Enable the ability for individual FileSystemProvider extensions being " + "serviced by CloudFileSystem to leverage a content cache."; const char kFirmwareUpdateUIV2Name[] = "Enables the v2 version of the Firmware Updates app"; @@ -7000,12 +7000,6 @@ "The channel from which PPD index " "is loaded when matching PPD files during printer setup."; -const char kPrintManagementJellyName[] = - "Enable jelly colors for the Print Management App"; -const char kPrintManagementJellyDescription[] = - "Enable jelly colors for the Print Management App. Requires " - "jelly-colors flag to be enabled."; - const char kPrintManagementSetupAssistanceName[] = "Enable improved printer setup experience for the Print Management App"; const char kPrintManagementSetupAssistanceDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 2012d55..6380119 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -3765,12 +3765,12 @@ extern const char kFilesTrashDriveName[]; extern const char kFilesTrashDriveDescription[]; +extern const char kFileSystemProviderCloudFileSystemName[]; +extern const char kFileSystemProviderCloudFileSystemDescription[]; + extern const char kFileSystemProviderContentCacheName[]; extern const char kFileSystemProviderContentCacheDescription[]; -extern const char kFirmwareUpdateJellyName[]; -extern const char kFirmwareUpdateJellyDescription[]; - extern const char kFirmwareUpdateUIV2Name[]; extern const char kFirmwareUpdateUIV2Description[]; @@ -4023,9 +4023,6 @@ extern const char kPrintingPpdChannelName[]; extern const char kPrintingPpdChannelDescription[]; -extern const char kPrintManagementJellyName[]; -extern const char kPrintManagementJellyDescription[]; - extern const char kPrintManagementSetupAssistanceName[]; extern const char kPrintManagementSetupAssistanceDescription[];
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn index da057dc..60103a4d 100644 --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn
@@ -338,10 +338,14 @@ "providers/dial/dial_media_route_provider_unittest.cc", "providers/wired_display/wired_display_media_route_provider_unittest.cc", ] + if (is_win) { + sources += [ "discovery/discovery_network_list_win_unittest.cc" ] + } deps += [ ":logger_list", ":test_support", "//chrome/browser/media/router/discovery", + "//chrome/browser/media/router/discovery:test_support", "//chrome/browser/media/router/discovery/access_code:access_code_cast_feature", "//chrome/browser/media/router/discovery/access_code:access_code_sink_service", "//chrome/browser/media/router/discovery/access_code:discovery_resources_proto", @@ -374,7 +378,7 @@ } # TODO(crbug.com/1290541): Fails to link on Fuchsia builds. -# TODO(https://issuetracker.google.com/236160471): CDDL compiler doesn't build +# TODO(issuetracker.google.com/236160471): CDDL compiler doesn't build # on Windows. if (!is_fuchsia && !is_win) { test("openscreen_unittests") { @@ -383,8 +387,12 @@ "//components/media_router/common/providers/cast/certificate:openscreen_certificate_verifier", "//components/openscreen_platform", "//testing/gmock", - "//third_party/openscreen/src:openscreen_unittests_all", ] + + # TODO(issues.chromium.org/41496044): Re-enable for MSAN once fixed. + if (!is_msan) { + deps += [ "//third_party/openscreen/src:openscreen_unittests_all" ] + } } }
diff --git a/chrome/browser/media/router/discovery/BUILD.gn b/chrome/browser/media/router/discovery/BUILD.gn index e2440c0..2f3c1aa3 100644 --- a/chrome/browser/media/router/discovery/BUILD.gn +++ b/chrome/browser/media/router/discovery/BUILD.gn
@@ -103,7 +103,46 @@ } if (is_win) { - sources += [ "discovery_network_list_win.cc" ] + sources += [ + "discovery_network_list_win.cc", + "discovery_network_list_win.h", + ] libs = [ "iphlpapi.lib" ] } } + +source_set("test_support") { + testonly = true + + cflags = [] + + sources = [] + + if (is_win) { + # Disable warnings about deprecated declarations in Windows SDK headers. + # FakeConnectionProfile implements the WinRT interface IConnectionProfile, + # which contains a few deprecated functions that are not used by Chromium. + cflags += [ "-Wno-deprecated-declarations" ] + + sources += [ + "test_support/win/fake_connection_profile.cc", + "test_support/win/fake_connection_profile.h", + "test_support/win/fake_ip_adapter_addresses.cc", + "test_support/win/fake_ip_adapter_addresses.h", + "test_support/win/fake_ip_helper.cc", + "test_support/win/fake_ip_helper.h", + "test_support/win/fake_mib_table.cc", + "test_support/win/fake_mib_table.h", + "test_support/win/fake_network_adapter.cc", + "test_support/win/fake_network_adapter.h", + "test_support/win/fake_network_information_statics.cc", + "test_support/win/fake_network_information_statics.h", + "test_support/win/fake_vector_view.h", + "test_support/win/fake_winrt_network_environment.cc", + "test_support/win/fake_winrt_network_environment.h", + "test_support/win/fake_wlan_connection_profile_details.cc", + "test_support/win/fake_wlan_connection_profile_details.h", + ] + } + deps = [ "//base" ] +}
diff --git a/chrome/browser/media/router/discovery/discovery_network_list_win.cc b/chrome/browser/media/router/discovery/discovery_network_list_win.cc index 312fd938..aa955ce 100644 --- a/chrome/browser/media/router/discovery/discovery_network_list_win.cc +++ b/chrome/browser/media/router/discovery/discovery_network_list_win.cc
@@ -2,41 +2,58 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/media/router/discovery/discovery_network_list.h" +#include "chrome/browser/media/router/discovery/discovery_network_list_win.h" #include <winsock2.h> -#include <ws2tcpip.h> +#include <wrl/client.h> -#include <iphlpapi.h> // NOLINT #include <windot11.h> // NOLINT #include <wlanapi.h> // NOLINT #include <algorithm> #include <cstring> -#include <map> + #include <utility> #include <vector> #include "base/check.h" -#include "base/containers/small_map.h" + #include "base/memory/ptr_util.h" +#include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" +#include "base/win/hstring_reference.h" +#include "base/win/scoped_hstring.h" +#include "base/win/windows_version.h" +#include "chrome/browser/media/router/discovery/discovery_network_list.h" + +namespace WinrtConnectivity = ABI::Windows::Networking::Connectivity; +namespace WinrtCollections = ABI::Windows::Foundation::Collections; + +using Microsoft::WRL::ComPtr; namespace media_router { namespace { -struct GuidOperatorLess { - bool operator()(const GUID& guid1, const GUID& guid2) const { - return memcmp(&guid1, &guid2, sizeof(GUID)) < 0; - } -}; +bool g_requires_network_location_permission_for_testing = false; + +WindowsOsApi& GetWindowsOsApi() { + static base::NoDestructor<WindowsOsApi> windows_os_api; + return *windows_os_api; +} void IfTable2Deleter(PMIB_IF_TABLE2 interface_table) { if (interface_table) { - FreeMibTable(interface_table); + GetWindowsOsApi().ip_helper_api.free_mib_table_callback.Run( + interface_table); } } +} // namespace + +bool GuidOperatorLess::operator()(const GUID& guid1, const GUID& guid2) const { + return memcmp(&guid1, &guid2, sizeof(GUID)) < 0; +} + typedef DWORD(WINAPI* WlanOpenHandleFunction)(DWORD dwClientVersion, PVOID pReserved, PDWORD pdwNegotiatedVersion, @@ -132,7 +149,8 @@ base::small_map<std::map<GUID, std::string, GuidOperatorLess>> GetInterfaceGuidMacMap() { PMIB_IF_TABLE2 interface_table_raw = nullptr; - auto result = GetIfTable2(&interface_table_raw); + auto result = GetWindowsOsApi().ip_helper_api.get_if_table2_callback.Run( + &interface_table_raw); if (result != ERROR_SUCCESS) { return {}; } @@ -228,7 +246,176 @@ return mac_ssid_map; } -} // namespace +// Returns true when running on a Windows version that prompts for network +// location permission. At the time of this writing, the permission prompt +// exists in Win11 24H2 only, which does not have a final build yet, but is +// shipping publicly to Windows Insiders. +// +// See the following documentation for more detail: +// +// Changes to API behavior for Wi-Fi access and location +// https://learn.microsoft.com/en-us/windows/win32/nativewifi/wi-fi-access-location-changes +// +// Announcing Windows 11 Insider Preview Build 25977 (Canary Channel) +// https://blogs.windows.com/windows-insider/2023/10/18/announcing-windows-11-insider-preview-build-25977-canary-channel/ +[[nodiscard]] bool RequiresNetworkLocationPermission() { + const base::win::OSInfo::VersionNumber& os_version = + base::win::OSInfo::GetInstance()->version_number(); + + // Win11 uses 10 for its major version number. + const bool is_24h2_or_greater = + (os_version.major > 10) || + (os_version.major == 10 && os_version.build >= 25977); + return is_24h2_or_greater || + g_requires_network_location_permission_for_testing; +} + +// Returns true when `connection_profile` is connected to a local network or the +// internet. +bool IsProfileConnectedToNetwork( + WinrtConnectivity::IConnectionProfile* connection_profile) { + WinrtConnectivity::NetworkConnectivityLevel connectivity; + HRESULT hr = connection_profile->GetNetworkConnectivityLevel(&connectivity); + if (hr != S_OK) { + return false; + } + return connectivity != WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_None; +} + +// Returns the GUID for the network interface adapter used by +// `connection_profile`. +HRESULT GetProfileNetworkAdapterId( + WinrtConnectivity::IConnectionProfile* connection_profile, + GUID* network_adapter_id) { + ComPtr<WinrtConnectivity::INetworkAdapter> network_adapter; + HRESULT hr = connection_profile->get_NetworkAdapter(&network_adapter); + if (hr != S_OK) { + return hr; + } + return network_adapter->get_NetworkAdapterId(network_adapter_id); +} + +// Returns the WiFi SSID used by the`connection_profile` for network +// connectivity. Returns an error when `connection_profile` does not use a WiFi +// network adapter. +HRESULT GetProfileWifiSSID( + WinrtConnectivity::IConnectionProfile* connection_profile, + HSTRING* out_ssid) { + ComPtr<WinrtConnectivity::IConnectionProfile2> connection_profile2; + HRESULT hr = + connection_profile->QueryInterface(IID_PPV_ARGS(&connection_profile2)); + if (hr != S_OK) { + return hr; + } + + ComPtr<WinrtConnectivity::IWlanConnectionProfileDetails> + wlan_connection_details; + hr = connection_profile2->get_WlanConnectionProfileDetails( + &wlan_connection_details); + if (hr != S_OK) { + return hr; + } + + if (wlan_connection_details == nullptr) { + // `connection_profile` is not using WiFi. + return kWifiNotSupported; + } + return wlan_connection_details->GetConnectedSsid(out_ssid); +} + +HRESULT GetAllConnectionProfiles( + ComPtr<WinrtCollections::IVectorView< + WinrtConnectivity::ConnectionProfile*>>* out_connection_profiles, + uint32_t* out_connection_profiles_size) { + ComPtr<WinrtConnectivity::INetworkInformationStatics> + network_information_statics; + HRESULT hr = + GetWindowsOsApi().winrt_api.ro_get_activation_factory_callback.Run( + base::win::HStringReference( + RuntimeClass_Windows_Networking_Connectivity_NetworkInformation) + .Get(), + IID_PPV_ARGS(&network_information_statics)); + if (hr != S_OK) { + return hr; + } + + ComPtr<WinrtCollections::IVectorView<WinrtConnectivity::ConnectionProfile*>> + connection_profiles; + hr = network_information_statics->GetConnectionProfiles(&connection_profiles); + if (hr != S_OK) { + return hr; + } + + uint32_t connection_profiles_size; + hr = connection_profiles->get_Size(&connection_profiles_size); + if (hr != S_OK) { + return hr; + } + + *out_connection_profiles = connection_profiles; + *out_connection_profiles_size = connection_profiles_size; + return S_OK; +} + +// Returns a map from a network adapter's MAC address to its currently +// associated WiFi SSID using WinRT Network APIs instead of Win32 WLAN APIS. +// In particular, uses IWlanConnectionProfileDetails::GetConnectedSsid() to get +// the SSID without prompting the user for network location permission. The +// Win32 version uses WlanQueryInterface(), which prompts for permission in +// Win11 24H2. +base::small_map<std::map<std::string, std::string>> GetMacSsidMapUsingWinrt() { + ComPtr<WinrtCollections::IVectorView<WinrtConnectivity::ConnectionProfile*>> + connection_profiles; + uint32_t connection_profiles_size = 0u; + HRESULT hr = + GetAllConnectionProfiles(&connection_profiles, &connection_profiles_size); + if (hr != S_OK) { + return {}; + } + + auto guid_mac_map = GetInterfaceGuidMacMap(); + base::small_map<std::map<std::string, std::string>> mac_ssid_map; + + // This loop finds each connected wireless interface, mapping its MAC address + // to its SSID. + for (uint32_t i = 0u; i < connection_profiles_size; ++i) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile; + hr = connection_profiles->GetAt(i, &connection_profile); + if (hr != S_OK) { + continue; + } + + if (!IsProfileConnectedToNetwork(connection_profile.Get())) { + // Skip disconnected profiles. + continue; + } + + HSTRING ssid_hstring; + hr = GetProfileWifiSSID(connection_profile.Get(), &ssid_hstring); + if (hr != S_OK) { + // Skip ethernet and cellular profiles. + continue; + } + base::win::ScopedHString ssid(ssid_hstring); + + GUID network_adapter_id; + hr = GetProfileNetworkAdapterId(connection_profile.Get(), + &network_adapter_id); + if (hr != S_OK) { + continue; + } + + const auto mac_entry = guid_mac_map.find(network_adapter_id); + if (mac_entry == guid_mac_map.end()) { + continue; + } + + mac_ssid_map.emplace(/*wifi_network_adapter_mac_address=*/mac_entry->second, + ssid.GetAsUTF8()); + } + return mac_ssid_map; +} std::vector<DiscoveryNetworkInfo> GetDiscoveryNetworkInfoList() { // Max number of times to retry GetAdaptersAddresses due to @@ -236,10 +423,6 @@ // due to an unforeseen reason, we don't want to be stuck in an endless loop. constexpr int kMaxGetAdaptersAddressTries = 10; - // Use an initial buffer size of 15KB, as recommended by MSDN. See: - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx - constexpr int kInitialAddressBufferSize = 15000; - constexpr ULONG kAddressFlags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; @@ -251,7 +434,7 @@ // the required size. Although it's very unlikely that two successive calls // will both require increasing the buffer size, there's no guarantee that // this won't happen; this is what the maximum retry count guards against. - ULONG addresses_buffer_size = kInitialAddressBufferSize; + ULONG addresses_buffer_size = kGetAdaptersAddressesInitialBufferSize; std::unique_ptr<char[]> addresses_buffer; PIP_ADAPTER_ADDRESSES adapter_addresses = nullptr; ULONG result = ERROR_BUFFER_OVERFLOW; @@ -261,8 +444,10 @@ addresses_buffer.reset(new char[addresses_buffer_size]); adapter_addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(addresses_buffer.get()); - result = GetAdaptersAddresses(AF_UNSPEC, kAddressFlags, nullptr, - adapter_addresses, &addresses_buffer_size); + result = + GetWindowsOsApi().ip_helper_api.get_adapters_addresses_callback.Run( + AF_UNSPEC, kAddressFlags, nullptr, adapter_addresses, + &addresses_buffer_size); } if (result != NO_ERROR) { @@ -270,7 +455,12 @@ } std::vector<DiscoveryNetworkInfo> network_ids; - auto mac_ssid_map = GetMacSsidMap(); + base::small_map<std::map<std::string, std::string>> mac_ssid_map; + if (RequiresNetworkLocationPermission()) { + mac_ssid_map = GetMacSsidMapUsingWinrt(); + } else { + mac_ssid_map = GetMacSsidMap(); + } for (const IP_ADAPTER_ADDRESSES* current_adapter = adapter_addresses; current_adapter != nullptr; current_adapter = current_adapter->Next) { // We only want adapters which are up and either Ethernet or wireless, so we @@ -315,4 +505,25 @@ return network_ids; } +WindowsOsApi::WindowsOsApi() = default; +WindowsOsApi::WindowsOsApi(const WindowsOsApi& source) = default; +WindowsOsApi::~WindowsOsApi() = default; + +WindowsOsApi::IpHelperApi::IpHelperApi() = default; +WindowsOsApi::IpHelperApi::IpHelperApi(const IpHelperApi& source) = default; +WindowsOsApi::IpHelperApi::~IpHelperApi() = default; + +WindowsOsApi::WinrtApi::WinrtApi() = default; +WindowsOsApi::WinrtApi::WinrtApi(const WinrtApi& source) = default; +WindowsOsApi::WinrtApi::~WinrtApi() = default; + +void OverrideWindowsOsApiForTesting(WindowsOsApi overridden_api) { + GetWindowsOsApi() = overridden_api; +} + +void OverrideRequiresNetworkLocationPermissionForTesting( // IN-TEST + bool requires_permission) { + g_requires_network_location_permission_for_testing = requires_permission; +} + } // namespace media_router
diff --git a/chrome/browser/media/router/discovery/discovery_network_list_win.h b/chrome/browser/media/router/discovery/discovery_network_list_win.h new file mode 100644 index 0000000..d58a80c --- /dev/null +++ b/chrome/browser/media/router/discovery/discovery_network_list_win.h
@@ -0,0 +1,129 @@ +// 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_MEDIA_ROUTER_DISCOVERY_DISCOVERY_NETWORK_LIST_WIN_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DISCOVERY_NETWORK_LIST_WIN_H_ + +#include <roapi.h> +#include <windows.networking.connectivity.h> +#include <ws2tcpip.h> + +// iphlpapi.h must be included after ws2tcpip.h to use MIB_IF_TABLE2. +#include <iphlpapi.h> // NOLINT + +#include <map> +#include <memory> +#include <string> + +#include "base/containers/small_map.h" +#include "base/functional/callback.h" +#include "base/win/core_winrt_util.h" + +namespace media_router { +// Declares helper functions and constants used to implement +// GetDiscoveryNetworkInfoList() on Windows. Exposes these helpers for unit +// testing. + +// To receive the output from GetAdaptersAddresses(), use an initial buffer size +// of 15KB, as recommended by MSDN. See: +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx +inline constexpr int kGetAdaptersAddressesInitialBufferSize = 15000; + +// Returned by GetProfileWifiSSID() for network profiles that do not use WiFi. +inline constexpr HRESULT kWifiNotSupported = + HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + +struct GuidOperatorLess { + bool operator()(const GUID& guid1, const GUID& guid2) const; +}; + +base::small_map<std::map<GUID, std::string, GuidOperatorLess>> +GetInterfaceGuidMacMap(); + +[[nodiscard]] bool IsProfileConnectedToNetwork( + ABI::Windows::Networking::Connectivity::IConnectionProfile* + connection_profile); + +[[nodiscard]] HRESULT GetProfileNetworkAdapterId( + ABI::Windows::Networking::Connectivity::IConnectionProfile* + connection_profile, + GUID* network_adapter_id); + +[[nodiscard]] HRESULT GetProfileWifiSSID( + ABI::Windows::Networking::Connectivity::IConnectionProfile* + connection_profile, + HSTRING* out_ssid); + +[[nodiscard]] HRESULT GetAllConnectionProfiles( + Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Networking::Connectivity::ConnectionProfile*>>* + out_connection_profiles, + uint32_t* out_connection_profiles_size); + +base::small_map<std::map<std::string, std::string>> GetMacSsidMapUsingWinrt(); + +// Enable tests to override Windows OS APIs to simulate different networking +// environments. Contains callbacks for each OS API function used by +// GetDiscoveryNetworkInfoList(). By default, the callbacks bind to the actual +// OS API function. Tests may bind these callbacks to fake implementations of +// the OS APIs and then call OverrideWindowsOsApiForTesting(). +struct WindowsOsApi { + WindowsOsApi(); + WindowsOsApi(const WindowsOsApi& source); + ~WindowsOsApi(); + + // Override Win32 functions declared in iphlpapi.h. + struct IpHelperApi { + IpHelperApi(); + IpHelperApi(const IpHelperApi& source); + ~IpHelperApi(); + + // Callbacks for GetAdaptersAddresses, GetIfTable2, and FreeMibTable. + // https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses + using GetAdaptersAddressesCallback = + base::RepeatingCallback<ULONG(ULONG family, + ULONG flags, + void* reserved, + IP_ADAPTER_ADDRESSES* adapter_addresses, + ULONG* size_pointer)>; + GetAdaptersAddressesCallback get_adapters_addresses_callback = + base::BindRepeating(&GetAdaptersAddresses); + + // https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getiftable2 + using GetIfTable2Callback = + base::RepeatingCallback<DWORD(MIB_IF_TABLE2** out_table)>; + GetIfTable2Callback get_if_table2_callback = + base::BindRepeating(&GetIfTable2); + + // https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-freemibtable + using FreeMibTableCallback = base::RepeatingCallback<void(void* table)>; + FreeMibTableCallback free_mib_table_callback = + base::BindRepeating(&FreeMibTable); + }; + IpHelperApi ip_helper_api; + + // Override RoGetActivationFactory() to return fake WinRT objects. + struct WinrtApi { + WinrtApi(); + WinrtApi(const WinrtApi& source); + ~WinrtApi(); + + // https://learn.microsoft.com/en-us/windows/win32/api/roapi/nf-roapi-rogetactivationfactory + using RoGetActivationFactoryCallback = + base::RepeatingCallback<HRESULT(HSTRING, const IID&, void**)>; + RoGetActivationFactoryCallback ro_get_activation_factory_callback = + base::BindRepeating(&base::win::RoGetActivationFactory); + }; + WinrtApi winrt_api; +}; +void OverrideWindowsOsApiForTesting(WindowsOsApi overridden_api); + +// Set to true to always use the WinRT implementation of +// GetDiscoveryNetworkInfoList(). +void OverrideRequiresNetworkLocationPermissionForTesting( + bool requires_permission); + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DISCOVERY_NETWORK_LIST_WIN_H_
diff --git a/chrome/browser/media/router/discovery/discovery_network_list_win_unittest.cc b/chrome/browser/media/router/discovery/discovery_network_list_win_unittest.cc new file mode 100644 index 0000000..95b234f --- /dev/null +++ b/chrome/browser/media/router/discovery/discovery_network_list_win_unittest.cc
@@ -0,0 +1,594 @@ +// 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/media/router/discovery/discovery_network_list_win.h" + +#include <wrl/client.h> + +#include <optional> + +#include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/win/scoped_hstring.h" +#include "chrome/browser/media/router/discovery/discovery_network_list.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_ip_helper.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace WinrtConnectivity = ABI::Windows::Networking::Connectivity; +namespace WinrtCollections = ABI::Windows::Foundation::Collections; + +using Microsoft::WRL::ComPtr; + +namespace media_router { + +namespace { + +constexpr const char kWiredAdapterName[] = "fake_wired_adapter"; +constexpr GUID kWiredNetworkAdapterId = { + 0xf8eb6b9e, + 0xa77e, + 0x44c8, + {0xa2, 0xf0, 0x4, 0x44, 0x84, 0xc6, 0xb6, 0xcd}}; +constexpr uint8_t kWiredMacAddress[] = {0x00, 0x21, 0x02, 0x43, 0x14, 0x05}; + +constexpr const char kWifiAdapterName[] = "fake_wifi_adapter"; +constexpr GUID kWifiNetworkAdapterId = { + 0xf494958d, + 0x661a, + 0x45f1, + {0x9e, 0x91, 0xb6, 0x58, 0x38, 0x77, 0x7f, 0xe1}}; +constexpr uint8_t kWifiMacAddress[] = {0x08, 0xf2, 0x06, 0xc4, 0xa1, 0x07}; +constexpr const char kWifiSsid[] = "fake_wifi_ssid"; + +} // namespace + +class DiscoveryNetworkListWinTest : public testing::Test { + public: + DiscoveryNetworkListWinTest() = default; + ~DiscoveryNetworkListWinTest() override = default; + + void SetUp() override; + void TearDown() override; + + // Add network adapters and connection profiles to the fake Windows OS API + // implementations. AddWiredConnectionProfile() can be called once to setup a + // network adapter using the kWired* constants defined above. + // AddWifiConnectionProfile() can be called once to setup a network adapter + // using the kWifi* constants defined above. If a test requires more + // adapters, it can call AddConnectionProfile() with test defined values. + ComPtr<WinrtConnectivity::IConnectionProfile> AddWiredConnectionProfile( + WinrtConnectivity::NetworkConnectivityLevel connectivity); + ComPtr<WinrtConnectivity::IConnectionProfile> AddWifiConnectionProfile( + WinrtConnectivity::NetworkConnectivityLevel connectivity); + ComPtr<WinrtConnectivity::IConnectionProfile> AddConnectionProfile( + const std::string& adapter_name, + const GUID& network_adapter_id, + const std::vector<uint8_t>& mac_address, + std::optional<std::string> ssid, + WinrtConnectivity::NetworkConnectivityLevel connectivity); + + // Returns a random 6-byte MAC address. + std::vector<uint8_t> GenerateRandomMacAddress() const; + + DiscoveryNetworkListWinTest(const DiscoveryNetworkListWinTest&) = delete; + DiscoveryNetworkListWinTest& operator=(const DiscoveryNetworkListWinTest&) = + delete; + + protected: + const std::vector<uint8_t> kWiredMacAddressVector{ + kWiredMacAddress, kWiredMacAddress + std::size(kWiredMacAddress)}; + + const std::vector<uint8_t> kWifiMacAddressVector{ + kWifiMacAddress, kWifiMacAddress + std::size(kWifiMacAddress)}; + + // Contains the fake Windows OS API implementations along with the network + // adapters and connection profiles setup through Add*ConnectionProfile(). + FakeIpHelper fake_ip_helper_; + FakeWinrtNetworkEnvironment fake_winrt_network_environment_; +}; + +void DiscoveryNetworkListWinTest::SetUp() { + // Use the fake Windows OS APIs to simulate different networking environments. + WindowsOsApi os_api_override; + + // Override the WinRT networking connectivity APIs. + os_api_override.winrt_api.ro_get_activation_factory_callback = + base::BindRepeating( + &FakeWinrtNetworkEnvironment::FakeRoGetActivationFactory, + base::Unretained(&fake_winrt_network_environment_)); + + // Override the IP Helper Win32 APIs. + os_api_override.ip_helper_api.get_adapters_addresses_callback = + base::BindRepeating(&FakeIpHelper::GetAdaptersAddresses, + base::Unretained(&fake_ip_helper_)); + os_api_override.ip_helper_api.get_if_table2_callback = base::BindRepeating( + &FakeIpHelper::GetIfTable2, base::Unretained(&fake_ip_helper_)); + os_api_override.ip_helper_api.free_mib_table_callback = base::BindRepeating( + &FakeIpHelper::FreeMibTable, base::Unretained(&fake_ip_helper_)); + + OverrideWindowsOsApiForTesting(os_api_override); + + // Force GetDiscoveryNetworkInfoList() to use the WinRT code path that avoids + // prompting for network location permission on Windows 24H2. + OverrideRequiresNetworkLocationPermissionForTesting(true); +} + +void DiscoveryNetworkListWinTest::TearDown() { + // Remove the overrides to start using the actual OS APIs again. + OverrideWindowsOsApiForTesting({}); + OverrideRequiresNetworkLocationPermissionForTesting(false); +} + +ComPtr<WinrtConnectivity::IConnectionProfile> +DiscoveryNetworkListWinTest::AddWiredConnectionProfile( + WinrtConnectivity::NetworkConnectivityLevel connectivity) { + return AddConnectionProfile(kWiredAdapterName, kWiredNetworkAdapterId, + kWiredMacAddressVector, + /*ssid=*/std::nullopt, connectivity); +} + +ComPtr<WinrtConnectivity::IConnectionProfile> +DiscoveryNetworkListWinTest::AddWifiConnectionProfile( + WinrtConnectivity::NetworkConnectivityLevel connectivity) { + return AddConnectionProfile(kWifiAdapterName, kWifiNetworkAdapterId, + kWifiMacAddressVector, kWifiSsid, connectivity); +} + +ComPtr<WinrtConnectivity::IConnectionProfile> +DiscoveryNetworkListWinTest::AddConnectionProfile( + const std::string& adapter_name, + const GUID& network_adapter_id, + const std::vector<uint8_t>& mac_address, + std::optional<std::string> ssid, + WinrtConnectivity::NetworkConnectivityLevel connectivity) { + IFTYPE adapter_type; + if (ssid) { + adapter_type = IF_TYPE_IEEE80211; + } else { + adapter_type = IF_TYPE_ETHERNET_CSMACD; + } + fake_ip_helper_.AddNetworkInterface(adapter_name, network_adapter_id, + mac_address, adapter_type, + IfOperStatusUp); + + return fake_winrt_network_environment_.AddConnectionProfile( + network_adapter_id, connectivity, ssid); +} + +std::vector<uint8_t> DiscoveryNetworkListWinTest::GenerateRandomMacAddress() + const { + std::vector<uint8_t> mac_address(6); + base::RandBytes(mac_address.data(), mac_address.size()); + return mac_address; +} + +TEST_F(DiscoveryNetworkListWinTest, GetInterfaceGuidMacMapEmpty) { + auto interface_guid_mac_map = GetInterfaceGuidMacMap(); + EXPECT_EQ(interface_guid_mac_map.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, GetInterfaceGuidMacMap) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + auto interface_guid_mac_map = GetInterfaceGuidMacMap(); + ASSERT_EQ(interface_guid_mac_map.size(), 2u); + + auto it = interface_guid_mac_map.find(kWiredNetworkAdapterId); + ASSERT_NE(it, interface_guid_mac_map.end()); + + const std::string kExpectedWiredMacAddress(kWiredMacAddressVector.begin(), + kWiredMacAddressVector.end()); + EXPECT_EQ(it->second, kExpectedWiredMacAddress); + + it = interface_guid_mac_map.find(kWifiNetworkAdapterId); + ASSERT_NE(it, interface_guid_mac_map.end()); + + const std::string kExpectedWifiMacAddress(kWifiMacAddressVector.begin(), + kWifiMacAddressVector.end()); + EXPECT_EQ(it->second, kExpectedWifiMacAddress); +} + +TEST_F(DiscoveryNetworkListWinTest, GetInterfaceGuidMacMapError) { + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + fake_ip_helper_.SimulateError(FakeIpHelperStatus::kErrorGetIfTable2Failed); + + auto interface_guid_mac_map = GetInterfaceGuidMacMap(); + EXPECT_EQ(interface_guid_mac_map.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, IsProfileConnectedToNetworkWhenOnline) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + EXPECT_TRUE(IsProfileConnectedToNetwork(connection_profile.Get())); +} + +TEST_F(DiscoveryNetworkListWinTest, IsProfileConnectedToNetworkWhenOffline) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_None); + + EXPECT_FALSE(IsProfileConnectedToNetwork(connection_profile.Get())); +} + +TEST_F(DiscoveryNetworkListWinTest, IsProfileConnectedNetworkError) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + fake_winrt_network_environment_.SimulateError( + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetNetworkConnectivityLevelFailed); + + // `IsProfileConnectedToNetwork()` must return false when an error occurs. + EXPECT_FALSE(IsProfileConnectedToNetwork(connection_profile.Get())); +} + +TEST_F(DiscoveryNetworkListWinTest, GetProfileNetworkAdapterId) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + GUID network_adapter_id; + HRESULT hr = + GetProfileNetworkAdapterId(connection_profile.Get(), &network_adapter_id); + + EXPECT_EQ(hr, S_OK); + EXPECT_EQ(network_adapter_id, kWiredNetworkAdapterId); +} + +TEST_F(DiscoveryNetworkListWinTest, GetProfileNetworkAdapterIdErrors) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + constexpr FakeWinrtNetworkStatus kErrorStatusList[] = { + FakeWinrtNetworkStatus::kErrorConnectionProfileGetNetworkAdapterFailed, + FakeWinrtNetworkStatus::kErrorGetNetworkAdapterIdFailed, + }; + for (const FakeWinrtNetworkStatus error_status : kErrorStatusList) { + fake_winrt_network_environment_.SimulateError(error_status); + + GUID network_adapter_id = {0}; + HRESULT hr = GetProfileNetworkAdapterId(connection_profile.Get(), + &network_adapter_id); + + EXPECT_EQ(hr, fake_winrt_network_environment_.MakeHresult(error_status)) + << " for error_status: " << static_cast<int>(error_status); + EXPECT_EQ(network_adapter_id, GUID_NULL) + << " for error_status: " << static_cast<int>(error_status); + } +} + +TEST_F(DiscoveryNetworkListWinTest, GetProfileWifiSSID) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + HSTRING ssid_hstring; + HRESULT hr = GetProfileWifiSSID(connection_profile.Get(), &ssid_hstring); + ASSERT_EQ(hr, S_OK); + + base::win::ScopedHString ssid(ssid_hstring); + EXPECT_EQ(ssid.GetAsUTF8(), kWifiSsid); +} + +TEST_F(DiscoveryNetworkListWinTest, GetProfileWifiSSIDWhenNotWifi) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + HSTRING ssid_hstring = nullptr; + HRESULT hr = GetProfileWifiSSID(connection_profile.Get(), &ssid_hstring); + EXPECT_EQ(hr, kWifiNotSupported); + EXPECT_EQ(ssid_hstring, nullptr); +} + +TEST_F(DiscoveryNetworkListWinTest, GetProfileWifiSsidErrors) { + ComPtr<WinrtConnectivity::IConnectionProfile> connection_profile = + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + constexpr FakeWinrtNetworkStatus kErrorStatusList[] = { + FakeWinrtNetworkStatus::kErrorConnectionProfileQueryInterfaceFailed, + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetWlanConnectionProfileDetailsFailed, + FakeWinrtNetworkStatus:: + kErrorWlanConnectionProfileDetailsGetConnectedSsidFailed, + }; + for (const FakeWinrtNetworkStatus error_status : kErrorStatusList) { + fake_winrt_network_environment_.SimulateError(error_status); + + HSTRING ssid_hstring = nullptr; + HRESULT hr = GetProfileWifiSSID(connection_profile.Get(), &ssid_hstring); + + EXPECT_EQ(hr, fake_winrt_network_environment_.MakeHresult(error_status)) + << " for error_status: " << static_cast<int>(error_status); + EXPECT_EQ(ssid_hstring, nullptr) + << " for error_status: " << static_cast<int>(error_status); + } +} + +TEST_F(DiscoveryNetworkListWinTest, GetAllConnectionProfilesEmpty) { + ComPtr<WinrtCollections::IVectorView<WinrtConnectivity::ConnectionProfile*>> + connection_profiles; + uint32_t connection_profiles_size = 0u; + + HRESULT hr = + GetAllConnectionProfiles(&connection_profiles, &connection_profiles_size); + + EXPECT_EQ(hr, S_OK); + EXPECT_NE(connection_profiles, nullptr); + EXPECT_EQ(connection_profiles_size, 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, GetAllConnectionProfiles) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_LocalAccess); + + ComPtr<WinrtCollections::IVectorView<WinrtConnectivity::ConnectionProfile*>> + connection_profiles; + uint32_t connection_profiles_size = 0u; + + HRESULT hr = + GetAllConnectionProfiles(&connection_profiles, &connection_profiles_size); + + EXPECT_EQ(hr, S_OK); + EXPECT_NE(connection_profiles, nullptr); + EXPECT_EQ(connection_profiles_size, 2u); +} + +TEST_F(DiscoveryNetworkListWinTest, GetAllConnectionProfilesError) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + constexpr FakeWinrtNetworkStatus kErrorStatusList[] = { + FakeWinrtNetworkStatus::kErrorRoGetActivationFactoryFailed, + FakeWinrtNetworkStatus:: + kErrorNetworkInformationStaticsGetConnectionProfilesFailed, + FakeWinrtNetworkStatus::kErrorVectorViewGetSizeFailed, + }; + + for (const FakeWinrtNetworkStatus error_status : kErrorStatusList) { + fake_winrt_network_environment_.SimulateError(error_status); + + ComPtr<WinrtCollections::IVectorView<WinrtConnectivity::ConnectionProfile*>> + connection_profiles; + uint32_t connection_profiles_size = 0u; + + HRESULT hr = GetAllConnectionProfiles(&connection_profiles, + &connection_profiles_size); + + EXPECT_EQ(hr, fake_winrt_network_environment_.MakeHresult(error_status)) + << " for error_status: " << static_cast<int>(error_status); + EXPECT_EQ(connection_profiles, nullptr) + << " for error_status: " << static_cast<int>(error_status); + EXPECT_EQ(connection_profiles_size, 0u) + << " for error_status: " << static_cast<int>(error_status); + } +} + +TEST_F(DiscoveryNetworkListWinTest, + DiscoveryNetworkListWinTest_GetMacSsidMapUsingWinrtWhenEmpty) { + auto mac_ssid_map = GetMacSsidMapUsingWinrt(); + EXPECT_EQ(mac_ssid_map.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, GetMacSsidMapUsingWinrt) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + auto mac_ssid_map = GetMacSsidMapUsingWinrt(); + EXPECT_EQ(mac_ssid_map.size(), 1u); + + const std::string kExpectedWifiMacAddress(kWifiMacAddressVector.begin(), + kWifiMacAddressVector.end()); + + auto it = mac_ssid_map.find(kExpectedWifiMacAddress); + ASSERT_NE(it, mac_ssid_map.end()); + EXPECT_EQ(it->second, kWifiSsid); +} + +TEST_F(DiscoveryNetworkListWinTest, GetMacSsidMapUsingWinrtWhenDisconnected) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_None); + + auto mac_ssid_map = GetMacSsidMapUsingWinrt(); + EXPECT_EQ(mac_ssid_map.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, GetMacSsidMapUsingWinrtErrors) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + constexpr FakeWinrtNetworkStatus kErrorStatusList[] = { + FakeWinrtNetworkStatus:: + kErrorNetworkInformationStaticsGetConnectionProfilesFailed, + FakeWinrtNetworkStatus::kErrorVectorViewGetAtFailed, + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetNetworkConnectivityLevelFailed, + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetWlanConnectionProfileDetailsFailed, + FakeWinrtNetworkStatus::kErrorGetNetworkAdapterIdFailed, + }; + for (const FakeWinrtNetworkStatus error_status : kErrorStatusList) { + fake_winrt_network_environment_.SimulateError(error_status); + + auto mac_ssid_map = GetMacSsidMapUsingWinrt(); + EXPECT_EQ(mac_ssid_map.size(), 0u) + << " for error_status: " << static_cast<int>(error_status); + } +} + +TEST_F(DiscoveryNetworkListWinTest, GetMacSsidMapUsingWinrtWithIpHelperErrors) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + fake_ip_helper_.SimulateError(FakeIpHelperStatus::kErrorGetIfTable2Failed); + + auto mac_ssid_map = GetMacSsidMapUsingWinrt(); + EXPECT_EQ(mac_ssid_map.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, + GetMacSsidMapUsingWinrtWithMissingMacAddress) { + fake_winrt_network_environment_.AddConnectionProfile( + kWifiNetworkAdapterId, + WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess, + kWifiSsid); + + auto mac_ssid_map = GetMacSsidMapUsingWinrt(); + EXPECT_EQ(mac_ssid_map.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, GetDiscoveryNetworkInfoListEmpty) { + std::vector<DiscoveryNetworkInfo> network_info_list = + GetDiscoveryNetworkInfoList(); + EXPECT_EQ(network_info_list.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, GetDiscoveryNetworkInfoList) { + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + std::vector<DiscoveryNetworkInfo> network_info_list = + GetDiscoveryNetworkInfoList(); + ASSERT_EQ(network_info_list.size(), 2u); + + EXPECT_EQ(network_info_list[0].name, kWiredAdapterName); + EXPECT_EQ(network_info_list[0].network_id, + base::HexEncode(kWiredMacAddress, std::size(kWiredMacAddress))); + + EXPECT_EQ(network_info_list[1].name, kWifiAdapterName); + EXPECT_EQ(network_info_list[1].network_id, kWifiSsid); +} + +TEST_F(DiscoveryNetworkListWinTest, + GetDiscoveryNetworkInfoListWithBufferOverflow) { + // Calculate the number of network adapters that we need to add to the fake + // environment to cause the first call to GetAdaptersAddresses() to fail with + // ERROR_BUFFER_OVERFLOW.. + const size_t kMaxAdapterCount = + (kGetAdaptersAddressesInitialBufferSize / sizeof(IP_ADAPTER_ADDRESSES)); + + const size_t kOverflowAdapterCount = (kMaxAdapterCount + 1); + std::vector<DiscoveryNetworkInfo> expected_network_info_list; + + // Setup the fake environment with the required number of network adapters. + for (size_t i = 0u; i < kOverflowAdapterCount; ++i) { + const std::string kAdapterName = + ("fake_adapter_name_" + base::NumberToString(i)); + + GUID network_adapter_id; + ASSERT_HRESULT_SUCCEEDED(CoCreateGuid(&network_adapter_id)); + + const std::vector<uint8_t> kMacAddress = GenerateRandomMacAddress(); + + const std::string kSsid = ("fake_ssid_" + base::NumberToString(i)); + + AddConnectionProfile(kAdapterName, network_adapter_id, kMacAddress, kSsid, + WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + expected_network_info_list.emplace_back(kAdapterName, kSsid); + } + StableSortDiscoveryNetworkInfo(expected_network_info_list.begin(), + expected_network_info_list.end()); + + std::vector<DiscoveryNetworkInfo> actual_network_info_list = + GetDiscoveryNetworkInfoList(); + ASSERT_EQ(actual_network_info_list, expected_network_info_list); +} + +TEST_F(DiscoveryNetworkListWinTest, + GetDiscoveryNetworkInfoListWithBufferOverflowRepeated) { + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + fake_ip_helper_.SimulateError( + FakeIpHelperStatus::kErrorGetAdaptersAddressesBufferOverflow); + + std::vector<DiscoveryNetworkInfo> network_info_list = + GetDiscoveryNetworkInfoList(); + EXPECT_EQ(network_info_list.size(), 0u); +} + +TEST_F(DiscoveryNetworkListWinTest, + GetDiscoveryNetworkInfoListWithMissingSsid) { + AddWiredConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + // Force GetAdaptersAddresses() to always fail with ERROR_BUFFER_OVERFLOW. + fake_winrt_network_environment_.SimulateError( + FakeWinrtNetworkStatus:: + kErrorNetworkInformationStaticsGetConnectionProfilesFailed); + + std::vector<DiscoveryNetworkInfo> network_info_list = + GetDiscoveryNetworkInfoList(); + ASSERT_EQ(network_info_list.size(), 2u); + + EXPECT_EQ(network_info_list[0].name, kWiredAdapterName); + EXPECT_EQ(network_info_list[0].network_id, + base::HexEncode(kWiredMacAddress, std::size(kWiredMacAddress))); + + EXPECT_EQ(network_info_list[1].name, kWifiAdapterName); + EXPECT_EQ(network_info_list[1].network_id, + base::HexEncode(kWifiMacAddress, std::size(kWifiMacAddress))); +} + +TEST_F(DiscoveryNetworkListWinTest, + GetDiscoveryNetworkInfoListWithAdapterStatusDown) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + // Adapters with the IfOperStatusDown status must be ignored. + fake_ip_helper_.AddNetworkInterface( + kWiredAdapterName, kWiredNetworkAdapterId, kWiredMacAddressVector, + IF_TYPE_ETHERNET_CSMACD, IfOperStatusDown); + + std::vector<DiscoveryNetworkInfo> network_info_list = + GetDiscoveryNetworkInfoList(); + ASSERT_EQ(network_info_list.size(), 1u); + + EXPECT_EQ(network_info_list[0].name, kWifiAdapterName); + EXPECT_EQ(network_info_list[0].network_id, kWifiSsid); +} + +TEST_F(DiscoveryNetworkListWinTest, + GetDiscoveryNetworkInfoListWithUnwantedAdapterType) { + AddWifiConnectionProfile(WinrtConnectivity::NetworkConnectivityLevel:: + NetworkConnectivityLevel_InternetAccess); + + // Adapters that are not ethernet or wifi must be ignored. + fake_ip_helper_.AddNetworkInterface(kWiredAdapterName, kWiredNetworkAdapterId, + kWiredMacAddressVector, IF_TYPE_TUNNEL, + IfOperStatusUp); + + std::vector<DiscoveryNetworkInfo> network_info_list = + GetDiscoveryNetworkInfoList(); + ASSERT_EQ(network_info_list.size(), 1u); + + EXPECT_EQ(network_info_list[0].name, kWifiAdapterName); + EXPECT_EQ(network_info_list[0].network_id, kWifiSsid); +} + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_connection_profile.cc b/chrome/browser/media/router/discovery/test_support/win/fake_connection_profile.cc new file mode 100644 index 0000000..ee64c6b --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_connection_profile.cc
@@ -0,0 +1,190 @@ +// 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/media/router/discovery/test_support/win/fake_connection_profile.h" + +#include "base/notimplemented.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_network_adapter.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.h" + +namespace WinrtConnectivity = ABI::Windows::Networking::Connectivity; +namespace WinrtFoundation = ABI::Windows::Foundation; + +using Microsoft::WRL::Make; + +namespace media_router { + +FakeConnectionProfile::FakeConnectionProfile( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment, + const GUID& network_adapter_id, + WinrtConnectivity::NetworkConnectivityLevel connectivity_level, + const std::optional<std::string>& ssid) + : fake_network_environment_(fake_network_environment), + network_adapter_(Make<FakeNetworkAdapter>(fake_network_environment, + network_adapter_id)), + connectivity_level_(connectivity_level) { + if (ssid) { + wlan_connection_profile_details_ = + Make<FakeWlanConnectionProfileDetails>(fake_network_environment, *ssid); + } +} + +HRESULT FakeConnectionProfile::QueryInterface(const IID& interface_id, + void** result) { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus::kErrorConnectionProfileQueryInterfaceFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus::kErrorConnectionProfileQueryInterfaceFailed); + } + + // Call the base class implementation. + return Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>, + WinrtConnectivity::IConnectionProfile, + WinrtConnectivity::IConnectionProfile2>::QueryInterface(interface_id, + result); +} + +HRESULT FakeConnectionProfile::GetNetworkConnectivityLevel( + WinrtConnectivity::NetworkConnectivityLevel* value) { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetNetworkConnectivityLevelFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetNetworkConnectivityLevelFailed); + } + + *value = connectivity_level_; + return S_OK; +} + +HRESULT FakeConnectionProfile::get_ProfileName(HSTRING* value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::get_NetworkAdapter( + WinrtConnectivity::INetworkAdapter** value) { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus::kErrorConnectionProfileGetNetworkAdapterFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus::kErrorConnectionProfileGetNetworkAdapterFailed); + } + + return network_adapter_.CopyTo(value); +} + +HRESULT FakeConnectionProfile::get_WlanConnectionProfileDetails( + WinrtConnectivity::IWlanConnectionProfileDetails** value) { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetWlanConnectionProfileDetailsFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus:: + kErrorConnectionProfileGetWlanConnectionProfileDetailsFailed); + } + return wlan_connection_profile_details_.CopyTo(value); +} + +HRESULT FakeConnectionProfile::GetNetworkNames( + WinrtFoundation::Collections::IVectorView<HSTRING>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetConnectionCost( + WinrtConnectivity::IConnectionCost** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetDataPlanStatus( + WinrtConnectivity::IDataPlanStatus** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetLocalUsage( + WinrtFoundation::DateTime StartTime, + WinrtFoundation::DateTime EndTime, + WinrtConnectivity::IDataUsage** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetLocalUsagePerRoamingStates( + WinrtFoundation::DateTime StartTime, + WinrtFoundation::DateTime EndTime, + WinrtConnectivity::RoamingStates States, + WinrtConnectivity::IDataUsage** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::get_NetworkSecuritySettings( + WinrtConnectivity::INetworkSecuritySettings** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::get_IsWwanConnectionProfile(boolean* value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::get_IsWlanConnectionProfile(boolean* value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::get_WwanConnectionProfileDetails( + WinrtConnectivity::IWwanConnectionProfileDetails** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::get_ServiceProviderGuid( + WinrtFoundation::IReference<GUID>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetSignalBars( + WinrtFoundation::IReference<byte>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetDomainConnectivityLevel( + WinrtConnectivity::DomainConnectivityLevel* value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetNetworkUsageAsync( + WinrtFoundation::DateTime startTime, + WinrtFoundation::DateTime endTime, + WinrtConnectivity::DataUsageGranularity granularity, + WinrtConnectivity::NetworkUsageStates states, + WinrtFoundation::IAsyncOperation<WinrtFoundation::Collections::IVectorView< + WinrtConnectivity::NetworkUsage*>*>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeConnectionProfile::GetConnectivityIntervalsAsync( + WinrtFoundation::DateTime startTime, + WinrtFoundation::DateTime endTime, + WinrtConnectivity::NetworkUsageStates states, + WinrtFoundation::IAsyncOperation<WinrtFoundation::Collections::IVectorView< + WinrtConnectivity::ConnectivityInterval*>*>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +FakeConnectionProfile::~FakeConnectionProfile() = default; + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_connection_profile.h b/chrome/browser/media/router/discovery/test_support/win/fake_connection_profile.h new file mode 100644 index 0000000..bd4a9b709 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_connection_profile.h
@@ -0,0 +1,118 @@ +// 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_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_CONNECTION_PROFILE_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_CONNECTION_PROFILE_H_ + +#include <windows.networking.connectivity.h> +#include <wrl.h> + +#include <optional> +#include <string> + +#include "base/memory/weak_ptr.h" + +namespace media_router { +class FakeWinrtNetworkEnvironment; + +class FakeConnectionProfile final + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>, + ABI::Windows::Networking::Connectivity::IConnectionProfile, + ABI::Windows::Networking::Connectivity::IConnectionProfile2> { + public: + FakeConnectionProfile( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment, + const GUID& network_adapter_id, + ABI::Windows::Networking::Connectivity::NetworkConnectivityLevel + connectivity_level, + const std::optional<std::string>& ssid); + + // Override the IUnknown interface to simulate failures. + HRESULT __stdcall QueryInterface(const IID& interface_id, + void** result) final; + + // Implement the IConnectionProfile & IConnectionProfile2 interfaces. + HRESULT __stdcall GetNetworkConnectivityLevel( + ABI::Windows::Networking::Connectivity::NetworkConnectivityLevel* value) + final; + HRESULT __stdcall get_ProfileName(HSTRING* value) final; + HRESULT __stdcall get_NetworkAdapter( + ABI::Windows::Networking::Connectivity::INetworkAdapter** value) final; + HRESULT __stdcall get_IsWlanConnectionProfile(boolean* value) final; + // The following are not implemented because they are not used: + HRESULT __stdcall GetNetworkNames( + ABI::Windows::Foundation::Collections::IVectorView<HSTRING>** value) + final; + HRESULT __stdcall GetConnectionCost( + ABI::Windows::Networking::Connectivity::IConnectionCost** value) final; + HRESULT __stdcall GetDataPlanStatus( + ABI::Windows::Networking::Connectivity::IDataPlanStatus** value) final; + HRESULT __stdcall GetLocalUsage( + ABI::Windows::Foundation::DateTime StartTime, + ABI::Windows::Foundation::DateTime EndTime, + ABI::Windows::Networking::Connectivity::IDataUsage** value) final; + HRESULT __stdcall GetLocalUsagePerRoamingStates( + ABI::Windows::Foundation::DateTime StartTime, + ABI::Windows::Foundation::DateTime EndTime, + ABI::Windows::Networking::Connectivity::RoamingStates States, + ABI::Windows::Networking::Connectivity::IDataUsage** value) final; + HRESULT __stdcall get_NetworkSecuritySettings( + ABI::Windows::Networking::Connectivity::INetworkSecuritySettings** value) + final; + HRESULT __stdcall get_IsWwanConnectionProfile(boolean* value) final; + HRESULT __stdcall get_WwanConnectionProfileDetails( + ABI::Windows::Networking::Connectivity::IWwanConnectionProfileDetails** + value) final; + HRESULT __stdcall get_WlanConnectionProfileDetails( + ABI::Windows::Networking::Connectivity::IWlanConnectionProfileDetails** + value) final; + HRESULT __stdcall get_ServiceProviderGuid( + ABI::Windows::Foundation::IReference<GUID>** value) final; + HRESULT __stdcall GetSignalBars( + ABI::Windows::Foundation::IReference<byte>** value) final; + HRESULT __stdcall GetDomainConnectivityLevel( + ABI::Windows::Networking::Connectivity::DomainConnectivityLevel* value) + final; + HRESULT __stdcall GetNetworkUsageAsync( + ABI::Windows::Foundation::DateTime startTime, + ABI::Windows::Foundation::DateTime endTime, + ABI::Windows::Networking::Connectivity::DataUsageGranularity granularity, + ABI::Windows::Networking::Connectivity::NetworkUsageStates states, + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Networking::Connectivity::NetworkUsage*>*>** value) + final; + HRESULT __stdcall GetConnectivityIntervalsAsync( + ABI::Windows::Foundation::DateTime startTime, + ABI::Windows::Foundation::DateTime endTime, + ABI::Windows::Networking::Connectivity::NetworkUsageStates states, + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Networking::Connectivity::ConnectivityInterval*>*>** + value) final; + + FakeConnectionProfile(const FakeConnectionProfile&) = delete; + FakeConnectionProfile& operator=(const FakeConnectionProfile&) = delete; + + private: + ~FakeConnectionProfile() final; + + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment_; + + Microsoft::WRL::ComPtr< + ABI::Windows::Networking::Connectivity::INetworkAdapter> + network_adapter_; + + ABI::Windows::Networking::Connectivity::NetworkConnectivityLevel + connectivity_level_; + + Microsoft::WRL::ComPtr< + ABI::Windows::Networking::Connectivity::IWlanConnectionProfileDetails> + wlan_connection_profile_details_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_CONNECTION_PROFILE_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.cc b/chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.cc new file mode 100644 index 0000000..4dbb2263 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.cc
@@ -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. + +#include "chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.h" + +#include "base/check_op.h" + +namespace media_router { + +FakeIpAdapterAddresses::FakeIpAdapterAddresses( + const std::string& adapter_name, + const std::vector<uint8_t>& physical_address, + IFTYPE adapter_type, + IF_OPER_STATUS adapter_status) + : adapter_name_(adapter_name) { + // Only populate struct members that are used by Chromium. + value_ = {}; + value_.Length = sizeof(IP_ADAPTER_ADDRESSES); + value_.IfType = adapter_type; + value_.OperStatus = adapter_status; + value_.AdapterName = const_cast<char*>(adapter_name_.c_str()); + + CHECK_LE(physical_address.size(), + static_cast<size_t>(MAX_ADAPTER_ADDRESS_LENGTH)); + + value_.PhysicalAddressLength = physical_address.size(); + memcpy(value_.PhysicalAddress, physical_address.data(), + physical_address.size()); +} + +FakeIpAdapterAddresses::FakeIpAdapterAddresses( + const FakeIpAdapterAddresses& source) { + adapter_name_ = source.adapter_name_; + value_ = source.value_; + value_.AdapterName = const_cast<char*>(adapter_name_.c_str()); +} + +FakeIpAdapterAddresses::~FakeIpAdapterAddresses() = default; + +IP_ADAPTER_ADDRESSES* FakeIpAdapterAddresses::Get() { + return &value_; +} + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.h b/chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.h new file mode 100644 index 0000000..96524e8 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.h
@@ -0,0 +1,41 @@ +// 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_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_IP_ADAPTER_ADDRESSES_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_IP_ADAPTER_ADDRESSES_H_ + +#include <ws2tcpip.h> + +// iphlpapi.h must be included after ws2tcpip.h to use MIB_IF_TABLE2. +#include <iphlpapi.h> // NOLINT + +#include <string> +#include <vector> + +namespace media_router { + +// Implements the IP_ADAPTER_ADDRESSES structure returned by the fake +// implementation of GetAdaptersAddresses in FakeIpHelper. +class FakeIpAdapterAddresses final { + public: + FakeIpAdapterAddresses(const std::string& adapter_name, + const std::vector<uint8_t>& physical_address, + IFTYPE adapter_type, + IF_OPER_STATUS adapter_status); + FakeIpAdapterAddresses(const FakeIpAdapterAddresses& source); + ~FakeIpAdapterAddresses(); + + IP_ADAPTER_ADDRESSES* Get(); + + private: + // In `value_`, the struct member, `IP_ADAPTER_ADDRESSES::AdapterName`, points + // to this string. + std::string adapter_name_; + + IP_ADAPTER_ADDRESSES value_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_IP_ADAPTER_ADDRESSES_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_ip_helper.cc b/chrome/browser/media/router/discovery/test_support/win/fake_ip_helper.cc new file mode 100644 index 0000000..e55a70a --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_ip_helper.cc
@@ -0,0 +1,110 @@ +// 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/media/router/discovery/test_support/win/fake_ip_helper.h" + +#include "base/check_op.h" +#include "base/notreached.h" + +namespace media_router { + +FakeIpHelper::FakeIpHelper() = default; + +FakeIpHelper::~FakeIpHelper() { + CHECK_EQ(mib_tables_.size(), 0u); +} + +void FakeIpHelper::SimulateError(FakeIpHelperStatus error_status) { + error_status_ = error_status; +} + +void FakeIpHelper::AddNetworkInterface( + const std::string& adapter_name, + const GUID& network_interface_guid, + const std::vector<uint8_t>& physical_address, + IFTYPE adapter_type, + IF_OPER_STATUS adapter_status) { + AddMibTableRow(network_interface_guid, physical_address); + AddIpAdapterAddresses(adapter_name, physical_address, adapter_type, + adapter_status); +} + +ULONG FakeIpHelper::GetAdaptersAddresses( + ULONG family, + ULONG flags, + void* reserved, + IP_ADAPTER_ADDRESSES* adapter_addresses, + ULONG* size_pointer) { + if (error_status_ == + FakeIpHelperStatus::kErrorGetAdaptersAddressesBufferOverflow) { + return ERROR_BUFFER_OVERFLOW; + } + + if (ip_adapter_addresses_.empty()) { + return ERROR_NO_DATA; + } + + const ULONG adapter_addresses_byte_count = + (ip_adapter_addresses_.size() * sizeof(IP_ADAPTER_ADDRESSES)); + + if (*size_pointer < adapter_addresses_byte_count) { + *size_pointer = adapter_addresses_byte_count; + return ERROR_BUFFER_OVERFLOW; + } + + for (size_t i = 0; i < ip_adapter_addresses_.size(); ++i) { + adapter_addresses[i] = *ip_adapter_addresses_[i].Get(); + if (i > 0) { + adapter_addresses[i - 1].Next = &adapter_addresses[i]; + } + } + return ERROR_SUCCESS; +} + +DWORD FakeIpHelper::GetIfTable2(MIB_IF_TABLE2** out_table) { + if (error_status_ == FakeIpHelperStatus::kErrorGetIfTable2Failed) { + return ERROR_NOT_FOUND; + } + + mib_tables_.emplace_back(mib_table_rows_); + *out_table = mib_tables_.back().Get(); + return ERROR_SUCCESS; +} + +void FakeIpHelper::FreeMibTable(void* table) { + for (auto it = mib_tables_.begin(); it != mib_tables_.end(); ++it) { + if (it->Get() == table) { + mib_tables_.erase(it); + return; + } + } + NOTREACHED(); +} + +void FakeIpHelper::AddIpAdapterAddresses( + const std::string& adapter_name, + const std::vector<uint8_t>& physical_address, + IFTYPE adapter_type, + IF_OPER_STATUS adapter_status) { + ip_adapter_addresses_.emplace_back(adapter_name, physical_address, + adapter_type, adapter_status); +} + +void FakeIpHelper::AddMibTableRow( + const GUID& network_interface_guid, + const std::vector<uint8_t>& physical_address) { + MIB_IF_ROW2 network_interface = {}; + network_interface.InterfaceGuid = network_interface_guid; + + CHECK_LE(physical_address.size(), + static_cast<size_t>(IF_MAX_PHYS_ADDRESS_LENGTH)); + + network_interface.PhysicalAddressLength = physical_address.size(); + memcpy(network_interface.PhysicalAddress, &physical_address[0], + physical_address.size()); + + mib_table_rows_.push_back(network_interface); +} + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_ip_helper.h b/chrome/browser/media/router/discovery/test_support/win/fake_ip_helper.h new file mode 100644 index 0000000..7bfba009 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_ip_helper.h
@@ -0,0 +1,85 @@ +// 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_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_IP_HELPER_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_IP_HELPER_H_ + +#include <ws2tcpip.h> + +// iphlpapi.h must be included after ws2tcpip.h to use MIB_IF_TABLE2. +#include <iphlpapi.h> // NOLINT + +#include <string> +#include <vector> + +#include "chrome/browser/media/router/discovery/test_support/win/fake_ip_adapter_addresses.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_mib_table.h" + +namespace media_router { + +// Each value represents a different IP Helper Win32 API that can fail during +// GetDiscoveryNetworkInfoList(). Use with +// `FakeIpHelper::SimulateError` to simulate Win32 API failures +// that return Windows system error codes. +enum class FakeIpHelperStatus { + kOk = 0, + kErrorGetIfTable2Failed = 1, + kErrorGetAdaptersAddressesBufferOverflow = 2, +}; + +// Provides a fake implementation of the Win32 APIs used to enumerate network +// adapters. Tests should use this class to simulate different +// network environments with different types of adapters and different statuses. +class FakeIpHelper final { + public: + FakeIpHelper(); + ~FakeIpHelper(); + + void SimulateError(FakeIpHelperStatus error_status); + + // Sets up the fake network environment by creating fake network adapters. + // Stores fake network adapters in the `mib_table_rows_` and + // `ip_adapter_addresses_` members. + void AddNetworkInterface(const std::string& adapter_name, + const GUID& network_interface_guid, + const std::vector<uint8_t>& physical_address, + IFTYPE adapter_type, + IF_OPER_STATUS adapter_status); + + // Implements the `GetAdaptersAddresses()` Win32 API. Copies + // `ip_adapter_addresses_` to `adapter_addresses`. + ULONG GetAdaptersAddresses(ULONG family, + ULONG flags, + void* reserved, + IP_ADAPTER_ADDRESSES* adapter_addresses, + ULONG* size_pointer); + + // Implements the `GetIfTable2()` Win32 API. Creates a new `FakeMibTable` + // stored in `mib_tables_` that is returned through `out_table`. + // `FreeMibTable()` removes the `FakeMibTable` from `mib_tables_`. + DWORD GetIfTable2(MIB_IF_TABLE2** out_table); + void FreeMibTable(void* table); + + private: + // Adds a fake network adapter to `ip_adapter_addresses_`. + void AddIpAdapterAddresses(const std::string& adapter_name, + const std::vector<uint8_t>& physical_address, + IFTYPE adapter_type, + IF_OPER_STATUS adapter_status); + + // Adds a fake network adapter to `mib_table_rows_`. + void AddMibTableRow(const GUID& network_interface_guid, + const std::vector<uint8_t>& physical_address); + + FakeIpHelperStatus error_status_ = FakeIpHelperStatus::kOk; + + std::vector<FakeIpAdapterAddresses> ip_adapter_addresses_; + + std::vector<MIB_IF_ROW2> mib_table_rows_; + std::vector<FakeMibTable> mib_tables_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_IP_HELPER_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_mib_table.cc b/chrome/browser/media/router/discovery/test_support/win/fake_mib_table.cc new file mode 100644 index 0000000..4ce08481 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_mib_table.cc
@@ -0,0 +1,35 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/router/discovery/test_support/win/fake_mib_table.h" + +namespace media_router { + +FakeMibTable::FakeMibTable( + const std::vector<MIB_IF_ROW2>& source_network_interfaces) { + size_t mib_table_byte_count = sizeof(MIB_IF_TABLE2); + if (source_network_interfaces.size() > 1) { + // MIB_IF_TABLE2 contains one MIB_IF_ROW2, so we need to add space for the + // rest of the array. + mib_table_byte_count += + (source_network_interfaces.size() - 1) * sizeof(MIB_IF_ROW2); + } + mib_table_bytes_.resize(mib_table_byte_count); + + MIB_IF_TABLE2* mib_table = Get(); + mib_table->NumEntries = source_network_interfaces.size(); + for (size_t i = 0; i < source_network_interfaces.size(); ++i) { + mib_table->Table[i] = source_network_interfaces[i]; + } +} + +FakeMibTable::FakeMibTable(const FakeMibTable& source) = default; + +FakeMibTable::~FakeMibTable() = default; + +MIB_IF_TABLE2* FakeMibTable::Get() { + return reinterpret_cast<MIB_IF_TABLE2*>(&mib_table_bytes_[0]); +} + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_mib_table.h b/chrome/browser/media/router/discovery/test_support/win/fake_mib_table.h new file mode 100644 index 0000000..ef95352d --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_mib_table.h
@@ -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. + +#ifndef CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_MIB_TABLE_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_MIB_TABLE_H_ + +#include <ws2tcpip.h> + +// iphlpapi.h must be included after ws2tcpip.h to use MIB_IF_TABLE2. +#include <iphlpapi.h> // NOLINT + +#include <vector> + +namespace media_router { + +// Contains the `MIB_IF_TABLE2` structure returned by the fake implementation of +// `GetIfTable2()` in `FakeIpHelper`. +class FakeMibTable final { + public: + explicit FakeMibTable( + const std::vector<MIB_IF_ROW2>& source_network_interfaces); + FakeMibTable(const FakeMibTable& source); + ~FakeMibTable(); + + MIB_IF_TABLE2* Get(); + + private: + // A blob which makes up the `MIB_IF_TABLE2` structure. The `MIB_IF_TABLE2` is + // a length prefixed array of `MIB_IF_ROW2` structures with some additional + // padding in between the length and the array. Here's the format: + // <ULONG> NumEntries + // <Padding> + // <MIB_IF_ROW2> Array[NumEntries] + std::vector<uint8_t> mib_table_bytes_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_MIB_TABLE_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_network_adapter.cc b/chrome/browser/media/router/discovery/test_support/win/fake_network_adapter.cc new file mode 100644 index 0000000..6f603cc --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_network_adapter.cc
@@ -0,0 +1,61 @@ +// 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/media/router/discovery/test_support/win/fake_network_adapter.h" + +#include "base/notreached.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h" + +namespace WinrtConnectivity = ABI::Windows::Networking::Connectivity; +namespace WinrtFoundation = ABI::Windows::Foundation; + +namespace media_router { + +FakeNetworkAdapter::FakeNetworkAdapter( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment, + const GUID& network_adapter_id) + : fake_network_environment_(fake_network_environment), + network_adapter_id_(network_adapter_id) {} + +HRESULT FakeNetworkAdapter::get_NetworkAdapterId(GUID* value) { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus::kErrorGetNetworkAdapterIdFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus::kErrorGetNetworkAdapterIdFailed); + } + *value = network_adapter_id_; + return S_OK; +} + +HRESULT FakeNetworkAdapter::get_OutboundMaxBitsPerSecond(UINT64* value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkAdapter::get_InboundMaxBitsPerSecond(UINT64* value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkAdapter::get_IanaInterfaceType(UINT32* value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkAdapter::get_NetworkItem( + WinrtConnectivity::INetworkItem** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkAdapter::GetConnectedProfileAsync( + WinrtFoundation::IAsyncOperation<WinrtConnectivity::ConnectionProfile*>** + value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +FakeNetworkAdapter::~FakeNetworkAdapter() = default; + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_network_adapter.h b/chrome/browser/media/router/discovery/test_support/win/fake_network_adapter.h new file mode 100644 index 0000000..674e475 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_network_adapter.h
@@ -0,0 +1,50 @@ +// 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_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_NETWORK_ADAPTER_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_NETWORK_ADAPTER_H_ + +#include <windows.networking.connectivity.h> +#include <wrl.h> + +#include "base/memory/weak_ptr.h" + +namespace media_router { +class FakeWinrtNetworkEnvironment; + +class FakeNetworkAdapter final + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>, + ABI::Windows::Networking::Connectivity::INetworkAdapter> { + public: + FakeNetworkAdapter( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment, + const GUID& network_adapter_id); + + // Implement the INetworkAdapter interface. + HRESULT __stdcall get_NetworkAdapterId(GUID* value) final; + // The following are not implemented because they are not used: + HRESULT __stdcall get_OutboundMaxBitsPerSecond(UINT64* value) final; + HRESULT __stdcall get_InboundMaxBitsPerSecond(UINT64* value) final; + HRESULT __stdcall get_IanaInterfaceType(UINT32* value) final; + HRESULT __stdcall get_NetworkItem( + ABI::Windows::Networking::Connectivity::INetworkItem** value) final; + HRESULT __stdcall GetConnectedProfileAsync( + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Networking::Connectivity::ConnectionProfile*>** value) + final; + + FakeNetworkAdapter(const FakeNetworkAdapter&) = delete; + FakeNetworkAdapter& operator=(const FakeNetworkAdapter&) = delete; + + private: + ~FakeNetworkAdapter() final; + + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment_; + GUID network_adapter_id_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_NETWORK_ADAPTER_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_network_information_statics.cc b/chrome/browser/media/router/discovery/test_support/win/fake_network_information_statics.cc new file mode 100644 index 0000000..b1073b0 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_network_information_statics.cc
@@ -0,0 +1,97 @@ +// 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/media/router/discovery/test_support/win/fake_network_information_statics.h" + +#include "base/notreached.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_vector_view.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h" + +namespace WinrtConnectivity = ABI::Windows::Networking::Connectivity; +namespace WinrtCollections = ABI::Windows::Foundation::Collections; +namespace WinrtNetworking = ABI::Windows::Networking; +namespace WinrtFoundation = ABI::Windows::Foundation; + +using Microsoft::WRL::ComPtr; +using Microsoft::WRL::Make; + +namespace media_router { + +FakeNetworkInformationStatics::FakeNetworkInformationStatics( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment) + : fake_network_environment_(fake_network_environment) {} + +HRESULT FakeNetworkInformationStatics::GetConnectionProfiles( + WinrtCollections::IVectorView<WinrtConnectivity::ConnectionProfile*>** + value) { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus:: + kErrorNetworkInformationStaticsGetConnectionProfilesFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus:: + kErrorNetworkInformationStaticsGetConnectionProfilesFailed); + } + + ComPtr<WinrtCollections::IVectorView<WinrtConnectivity::ConnectionProfile*>> + new_vector_view = + Make<FakeVectorView<WinrtConnectivity::IConnectionProfile, + WinrtConnectivity::ConnectionProfile>>( + fake_network_environment_); + + *value = new_vector_view.Detach(); + return S_OK; +} + +HRESULT FakeNetworkInformationStatics::GetInternetConnectionProfile( + WinrtConnectivity::IConnectionProfile** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkInformationStatics::GetLanIdentifiers( + WinrtCollections::IVectorView<WinrtConnectivity::LanIdentifier*>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkInformationStatics::GetHostNames( + WinrtCollections::IVectorView<WinrtNetworking::HostName*>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkInformationStatics::GetProxyConfigurationAsync( + WinrtFoundation::IUriRuntimeClass* uri, + WinrtFoundation::IAsyncOperation<WinrtConnectivity::ProxyConfiguration*>** + value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkInformationStatics::GetSortedEndpointPairs( + WinrtCollections::IIterable<WinrtNetworking::EndpointPair*>* + destination_list, + WinrtNetworking::HostNameSortOptions sort_options, + WinrtCollections::IVectorView<WinrtNetworking::EndpointPair*>** value) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkInformationStatics::add_NetworkStatusChanged( + WinrtConnectivity::INetworkStatusChangedEventHandler* + network_status_handler, + EventRegistrationToken* event_cookie) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +HRESULT FakeNetworkInformationStatics::remove_NetworkStatusChanged( + EventRegistrationToken event_cookie) { + NOTIMPLEMENTED(); + return E_NOTIMPL; +} + +FakeNetworkInformationStatics::~FakeNetworkInformationStatics() = default; + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_network_information_statics.h b/chrome/browser/media/router/discovery/test_support/win/fake_network_information_statics.h new file mode 100644 index 0000000..a3f25938 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_network_information_statics.h
@@ -0,0 +1,69 @@ +// 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_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_NETWORK_INFORMATION_STATICS_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_NETWORK_INFORMATION_STATICS_H_ + +#include <windows.networking.connectivity.h> +#include <wrl.h> + +#include "base/memory/weak_ptr.h" + +namespace media_router { +class FakeWinrtNetworkEnvironment; + +class FakeNetworkInformationStatics final + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>, + ABI::Windows::Networking::Connectivity::INetworkInformationStatics> { + public: + FakeNetworkInformationStatics( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment); + + // Implement the INetworkInformationStatics interface. + HRESULT __stdcall GetConnectionProfiles( + ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Networking::Connectivity::ConnectionProfile*>** value) + final; + // The following are not implemented because they are not used: + HRESULT __stdcall GetInternetConnectionProfile( + ABI::Windows::Networking::Connectivity::IConnectionProfile** value) final; + HRESULT __stdcall GetLanIdentifiers( + ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Networking::Connectivity::LanIdentifier*>** value) + final; + HRESULT __stdcall GetHostNames( + ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Networking::HostName*>** value) final; + HRESULT __stdcall GetProxyConfigurationAsync( + ABI::Windows::Foundation::IUriRuntimeClass* uri, + ABI::Windows::Foundation::IAsyncOperation< + ABI::Windows::Networking::Connectivity::ProxyConfiguration*>** value) + final; + HRESULT __stdcall GetSortedEndpointPairs( + ABI::Windows::Foundation::Collections::IIterable< + ABI::Windows::Networking::EndpointPair*>* destination_list, + ABI::Windows::Networking::HostNameSortOptions sort_options, + ABI::Windows::Foundation::Collections::IVectorView< + ABI::Windows::Networking::EndpointPair*>** value) final; + HRESULT __stdcall add_NetworkStatusChanged( + ABI::Windows::Networking::Connectivity::INetworkStatusChangedEventHandler* + network_status_handler, + EventRegistrationToken* event_cookie) final; + HRESULT __stdcall remove_NetworkStatusChanged( + EventRegistrationToken event_cookie) final; + + FakeNetworkInformationStatics(const FakeNetworkInformationStatics&) = delete; + FakeNetworkInformationStatics& operator=( + const FakeNetworkInformationStatics&) = delete; + + private: + ~FakeNetworkInformationStatics() final; + + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_NETWORK_INFORMATION_STATICS_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_vector_view.h b/chrome/browser/media/router/discovery/test_support/win/fake_vector_view.h new file mode 100644 index 0000000..62d6f0d --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_vector_view.h
@@ -0,0 +1,86 @@ +// 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_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_VECTOR_VIEW_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_VECTOR_VIEW_H_ + +#include <windows.foundation.h> +#include <wrl.h> + +#include <vector> + +#include "base/memory/weak_ptr.h" +#include "base/notreached.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h" + +namespace media_router { + +template <typename TInterface, typename TClass> +class FakeVectorView final + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>, + ABI::Windows::Foundation::Collections::IVectorView<TClass*>> { + public: + FakeVectorView( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment) + : fake_network_environment_(fake_network_environment), + view_(fake_network_environment->GetConnectionProfiles()) {} + + // Implement the IVectorView interface. + HRESULT __stdcall GetAt(unsigned index, TInterface** item) final { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus::kErrorVectorViewGetAtFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus::kErrorVectorViewGetAtFailed); + } + + if (index >= view_.size()) { + return E_BOUNDS; + } + + view_[index].CopyTo(item); + return S_OK; + } + + HRESULT __stdcall get_Size(unsigned* size) final { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus::kErrorVectorViewGetSizeFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus::kErrorVectorViewGetSizeFailed); + } + + *size = view_.size(); + return S_OK; + } + + // The following are not implemented because they are not used. + HRESULT __stdcall IndexOf(TInterface* value, + unsigned* index, + boolean* found) final { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + HRESULT __stdcall GetMany(unsigned start_index, + unsigned capacity, + TInterface** value, + unsigned* actual) final { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + FakeVectorView(const FakeVectorView&) = delete; + FakeVectorView& operator=(const FakeVectorView&) = delete; + + private: + ~FakeVectorView() final = default; + + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment_; + + std::vector<Microsoft::WRL::ComPtr<TInterface>> view_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_VECTOR_VIEW_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.cc b/chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.cc new file mode 100644 index 0000000..76c88f4 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.cc
@@ -0,0 +1,85 @@ +// 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/media/router/discovery/test_support/win/fake_winrt_network_environment.h" + +#include <tuple> + +#include "base/notreached.h" +#include "base/win/scoped_hstring.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_connection_profile.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_network_information_statics.h" + +namespace WinrtConnectivity = ABI::Windows::Networking::Connectivity; + +using Microsoft::WRL::ComPtr; +using Microsoft::WRL::Make; + +namespace media_router { + +FakeWinrtNetworkEnvironment::FakeWinrtNetworkEnvironment() = default; + +FakeWinrtNetworkEnvironment::~FakeWinrtNetworkEnvironment() = default; + +FakeWinrtNetworkStatus FakeWinrtNetworkEnvironment::GetErrorStatus() const { + return error_status_; +} + +HRESULT FakeWinrtNetworkEnvironment::MakeHresult( + FakeWinrtNetworkStatus error_status) const { + return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, + /*base=*/0x800 + static_cast<int>(error_status)); +} + +void FakeWinrtNetworkEnvironment::SimulateError( + FakeWinrtNetworkStatus error_status) { + error_status_ = error_status; +} + +const std::vector<ComPtr<WinrtConnectivity::IConnectionProfile>>& +FakeWinrtNetworkEnvironment::GetConnectionProfiles() const { + return connection_profiles_; +} + +ComPtr<WinrtConnectivity::IConnectionProfile> +FakeWinrtNetworkEnvironment::AddConnectionProfile( + const GUID& network_adapter_id, + WinrtConnectivity::NetworkConnectivityLevel connectivity_level, + const std::optional<std::string>& ssid) { + ComPtr<WinrtConnectivity::IConnectionProfile> new_connection_profile = + Make<FakeConnectionProfile>(weak_ptr_factory_.GetWeakPtr(), + network_adapter_id, connectivity_level, ssid); + + connection_profiles_.push_back(new_connection_profile); + return new_connection_profile; +} + +HRESULT FakeWinrtNetworkEnvironment::FakeRoGetActivationFactory( + HSTRING class_id, + const IID& iid, + void** factory) { + if (error_status_ == + FakeWinrtNetworkStatus::kErrorRoGetActivationFactoryFailed) { + return MakeHresult( + FakeWinrtNetworkStatus::kErrorRoGetActivationFactoryFailed); + } + + base::win::ScopedHString class_id_hstring(class_id); + + if (class_id_hstring.Get() == + RuntimeClass_Windows_Networking_Connectivity_NetworkInformation) { + ComPtr<FakeNetworkInformationStatics> network_info_statics = + Make<FakeNetworkInformationStatics>(weak_ptr_factory_.GetWeakPtr()); + *factory = network_info_statics.Detach(); + } + std::ignore = class_id_hstring.release(); + + if (*factory == nullptr) { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + return S_OK; +} + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h b/chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h new file mode 100644 index 0000000..504f346b5 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h
@@ -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. + +#ifndef CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_WINRT_NETWORK_ENVIRONMENT_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_WINRT_NETWORK_ENVIRONMENT_H_ + +#include <roapi.h> +#include <windows.networking.connectivity.h> +#include <wrl/client.h> + +#include <optional> +#include <vector> + +#include "base/memory/weak_ptr.h" + +namespace media_router { + +// Each value represents a different WinRT API that can fail during +// GetDiscoveryNetworkInfoList(). Use with +// `FakeWinrtNetworkEnvironment::SimulateError` to simulate WinRT API failures +// that return error HRESULTS. +enum class FakeWinrtNetworkStatus { + kOk = 0, + kErrorRoGetActivationFactoryFailed = 1, + kErrorNetworkInformationStaticsGetConnectionProfilesFailed = 2, + kErrorVectorViewGetAtFailed = 3, + kErrorVectorViewGetSizeFailed = 4, + kErrorConnectionProfileQueryInterfaceFailed = 5, + kErrorConnectionProfileGetNetworkConnectivityLevelFailed = 6, + kErrorConnectionProfileGetNetworkAdapterFailed = 7, + kErrorConnectionProfileGetWlanConnectionProfileDetailsFailed = 8, + kErrorWlanConnectionProfileDetailsGetConnectedSsidFailed = 9, + kErrorGetNetworkAdapterIdFailed = 10, +}; + +// Provides a fake implementation of RoGetActivationFactory() to creates a fake +// implementation of INetworkInformationStatics, which is used to enumerate fake +// connection profiles. Tests should use this class to simulate different +// network environments with different types of adapters and different levels +// of connectivity. +class FakeWinrtNetworkEnvironment final { + public: + FakeWinrtNetworkEnvironment(); + ~FakeWinrtNetworkEnvironment(); + + FakeWinrtNetworkStatus GetErrorStatus() const; + void SimulateError(FakeWinrtNetworkStatus error_status); + + // Gets the fake HRESULT that the fake OS API implementation will return for + // `error_status`. + HRESULT MakeHresult(FakeWinrtNetworkStatus error_status) const; + + // Sets up the fake network environment by creating fake network adapters. Use + // `std::nullopt` for `ssid` to create a wired network adapter. Stores + // fake network adapters in the `connection_profiles_` member. + Microsoft::WRL::ComPtr< + ABI::Windows::Networking::Connectivity::IConnectionProfile> + AddConnectionProfile( + const GUID& network_adapter_id, + ABI::Windows::Networking::Connectivity::NetworkConnectivityLevel + connectivity_level, + const std::optional<std::string>& ssid); + + const std::vector<Microsoft::WRL::ComPtr< + ABI::Windows::Networking::Connectivity::IConnectionProfile>>& + GetConnectionProfiles() const; + + HRESULT FakeRoGetActivationFactory(HSTRING class_id, + const IID& iid, + void** factory); + + FakeWinrtNetworkEnvironment(const FakeWinrtNetworkEnvironment&) = delete; + FakeWinrtNetworkEnvironment& operator=(const FakeWinrtNetworkEnvironment&) = + delete; + + private: + // Specifies which error the fake WinRT network environment should simulate. + FakeWinrtNetworkStatus error_status_ = FakeWinrtNetworkStatus::kOk; + + // Contains the fake network adapters enumerated by the WinRT API. + std::vector<Microsoft::WRL::ComPtr< + ABI::Windows::Networking::Connectivity::IConnectionProfile>> + connection_profiles_; + + base::WeakPtrFactory<FakeWinrtNetworkEnvironment> weak_ptr_factory_{this}; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_WINRT_NETWORK_ENVIRONMENT_H_
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.cc b/chrome/browser/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.cc new file mode 100644 index 0000000..3e4a481 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.cc
@@ -0,0 +1,33 @@ +// 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/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.h" + +#include "base/win/scoped_hstring.h" +#include "chrome/browser/media/router/discovery/test_support/win/fake_winrt_network_environment.h" + +namespace media_router { + +FakeWlanConnectionProfileDetails::FakeWlanConnectionProfileDetails( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment, + const std::string& ssid) + : fake_network_environment_(fake_network_environment), ssid_(ssid) {} + +HRESULT FakeWlanConnectionProfileDetails::GetConnectedSsid(HSTRING* value) { + if (fake_network_environment_->GetErrorStatus() == + FakeWinrtNetworkStatus:: + kErrorWlanConnectionProfileDetailsGetConnectedSsidFailed) { + return fake_network_environment_->MakeHresult( + FakeWinrtNetworkStatus:: + kErrorWlanConnectionProfileDetailsGetConnectedSsidFailed); + } + + base::win::ScopedHString ssid_copy(base::win::ScopedHString::Create(ssid_)); + *value = ssid_copy.release(); + return S_OK; +} + +FakeWlanConnectionProfileDetails::~FakeWlanConnectionProfileDetails() = default; + +} // namespace media_router
diff --git a/chrome/browser/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.h b/chrome/browser/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.h new file mode 100644 index 0000000..d4d53540 --- /dev/null +++ b/chrome/browser/media/router/discovery/test_support/win/fake_wlan_connection_profile_details.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 CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_WLAN_CONNECTION_PROFILE_DETAILS_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_WLAN_CONNECTION_PROFILE_DETAILS_H_ + +#include <windows.networking.connectivity.h> +#include <wrl.h> + +#include <string> + +#include "base/memory/weak_ptr.h" + +namespace media_router { +class FakeWinrtNetworkEnvironment; + +class FakeWlanConnectionProfileDetails final + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>, + ABI::Windows::Networking::Connectivity:: + IWlanConnectionProfileDetails> { + public: + FakeWlanConnectionProfileDetails( + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment, + const std::string& ssid); + + // Implement the IWlanConnectionProfileDetails interface. + HRESULT __stdcall GetConnectedSsid(HSTRING* value) final; + + FakeWlanConnectionProfileDetails(const FakeWlanConnectionProfileDetails&) = + delete; + FakeWlanConnectionProfileDetails& operator=( + const FakeWlanConnectionProfileDetails&) = delete; + + private: + ~FakeWlanConnectionProfileDetails() final; + + base::WeakPtr<FakeWinrtNetworkEnvironment> fake_network_environment_; + std::string ssid_; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_TEST_SUPPORT_WIN_FAKE_WLAN_CONNECTION_PROFILE_DETAILS_H_
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc index 139d318..9eb3d3f 100644 --- a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc +++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
@@ -33,6 +33,7 @@ #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_state_manager.h" #include "components/prefs/pref_service.h" +#include "components/variations/service/limited_entropy_synthetic_trial.h" #include "components/variations/service/variations_service.h" #include "components/variations/variations_associated_data.h" #include "components/version_info/version_info.h" @@ -303,6 +304,12 @@ auto* init_params = chromeos::BrowserParamsProxy::Get(); if (init_params->MetricsServiceClientId().has_value()) client_id = init_params->MetricsServiceClientId().value(); + + // Sync the randomization seed from Ash Chrome so that the group assignment + // is the same on Lacros. + variations::LimitedEntropySyntheticTrial::SetSeedFromAsh( + local_state_, init_params->LimitedEntropySyntheticTrialSeed()); + // Beginning M120 this should always be there. Note: // The LES numbers are kept stable over the lifetime of the session. // They get read when the system is statrting up in Ash. So they do not
diff --git a/chrome/browser/metrics/structured/ash_event_storage.cc b/chrome/browser/metrics/structured/ash_event_storage.cc index 2835f7c..2a2fe81 100644 --- a/chrome/browser/metrics/structured/ash_event_storage.cc +++ b/chrome/browser/metrics/structured/ash_event_storage.cc
@@ -208,8 +208,11 @@ } } - (*pre_user_events_)->Clear(); - pre_user_events_->QueueWrite(); + // Regardless of if there are any events cleanup the storage. + if (pre_user_events()) { + (*pre_user_events_)->Clear(); + pre_user_events_->QueueWrite(); + } // The write is fine because it will add to a task that is not tied to the // lifetime of |pre_user_events_|.
diff --git a/chrome/browser/metrics/structured/ash_event_storage_unittest.cc b/chrome/browser/metrics/structured/ash_event_storage_unittest.cc index c456263..945682f2 100644 --- a/chrome/browser/metrics/structured/ash_event_storage_unittest.cc +++ b/chrome/browser/metrics/structured/ash_event_storage_unittest.cc
@@ -46,11 +46,14 @@ } std::unique_ptr<AshEventStorage> BuildTestStorage() { - return std::make_unique<AshEventStorage>( + auto storage = std::make_unique<AshEventStorage>( /*write_delay=*/base::Seconds(0), GetTestDirectory() .Append(FILE_PATH_LITERAL("structured_metrics")) .Append(FILE_PATH_LITERAL("events"))); + // Wait for the device events to be loaded. + Wait(); + return storage; } StructuredDataProto GetReport(AshEventStorage* storage) {
diff --git a/chrome/browser/metrics/variations/variations_service_browsertest.cc b/chrome/browser/metrics/variations/variations_service_browsertest.cc new file mode 100644 index 0000000..5a091df6 --- /dev/null +++ b/chrome/browser/metrics/variations/variations_service_browsertest.cc
@@ -0,0 +1,46 @@ +// 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/variations/service/variations_service.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/metrics_services_manager/metrics_services_manager.h" +#include "components/prefs/pref_service.h" +#include "content/public/test/browser_test.h" + +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/startup/browser_params_proxy.h" +#endif + +namespace variations { + +class VariationsServiceBrowserTest : public InProcessBrowserTest { + public: + VariationsServiceBrowserTest() = default; + + VariationsServiceBrowserTest(const VariationsServiceBrowserTest&) = delete; + VariationsServiceBrowserTest& operator=(const VariationsServiceBrowserTest&) = + delete; + + PrefService* local_state() { return g_browser_process->local_state(); } +}; + +#if BUILDFLAG(IS_CHROMEOS_LACROS) +IN_PROC_BROWSER_TEST_F(VariationsServiceBrowserTest, + LimitedEntropySyntheticTrialSeedTransfer) { + auto* ash_params = chromeos::BrowserParamsProxy::Get(); + variations::VariationsService* variations_service = + g_browser_process->GetMetricsServicesManager()->GetVariationsService(); + // Due to version skew, the Ash chrome version used in test might not have + // this field yet. + if (ash_params->LimitedEntropySyntheticTrialSeed() != 0u) { + EXPECT_EQ(variations_service->limited_entropy_synthetic_trial_ + .GetRandomizationSeed(local_state()), + ash_params->LimitedEntropySyntheticTrialSeed()); + } +} +#endif + +} // namespace variations
diff --git a/chrome/browser/pdf/pdf_extension_printing_test.cc b/chrome/browser/pdf/pdf_extension_printing_test.cc index 62332ce..a1a8800 100644 --- a/chrome/browser/pdf/pdf_extension_printing_test.cc +++ b/chrome/browser/pdf/pdf_extension_printing_test.cc
@@ -233,19 +233,6 @@ std::make_unique<printing::PrinterBasicInfo>(printer_info)); } - content::WebContents* GetEmbedderWebContents() { - content::WebContents* contents = GetActiveWebContents(); - - // OOPIF PDF viewer only has a single `WebContents`. - if (UseOopif()) { - return contents; - } - - MimeHandlerViewGuest* guest = - pdf_extension_test_util::GetOnlyMimeHandlerView(contents); - return guest ? guest->embedder_web_contents() : nullptr; - } - void SetupPrintViewManagerForJobMonitoring(content::RenderFrameHost* frame) { auto* web_contents = content::WebContents::FromRenderFrameHost(frame); auto manager = std::make_unique<printing::TestPrintViewManager>(
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 401464be..502a5b9 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -1110,13 +1110,14 @@ GTEST_SKIP(); } - MimeHandlerViewGuest* guest_view = LoadPdfGetMimeHandlerView( - embedded_test_server()->GetURL("/pdf/test.pdf")); - ASSERT_TRUE(guest_view); - EXPECT_EQ(u"test.pdf", guest_view->GetController() - .GetLastCommittedEntry() - ->GetTitleForDisplay()); - EXPECT_EQ(u"test.pdf", GetActiveWebContents()->GetTitle()); + ASSERT_TRUE(LoadPdf(embedded_test_server()->GetURL("/pdf/test.pdf"))); + + const std::u16string kExpectedTitle = u"test.pdf"; + EXPECT_EQ(kExpectedTitle, GetEmbedderWebContents() + ->GetController() + .GetLastCommittedEntry() + ->GetTitleForDisplay()); + EXPECT_EQ(kExpectedTitle, GetActiveWebContents()->GetTitle()); } // This test ensures that titles are set properly for PDFs with /Title. @@ -1126,17 +1127,19 @@ GTEST_SKIP(); } - MimeHandlerViewGuest* guest_view = LoadPdfGetMimeHandlerView( - embedded_test_server()->GetURL("/pdf/test-title.pdf")); - ASSERT_TRUE(guest_view); - EXPECT_EQ(u"PDF title test", guest_view->GetController() - .GetLastCommittedEntry() - ->GetTitleForDisplay()); - EXPECT_EQ(u"PDF title test", GetActiveWebContents()->GetTitle()); + ASSERT_TRUE(LoadPdf(embedded_test_server()->GetURL("/pdf/test-title.pdf"))); + + const std::u16string kExpectedTitle = u"PDF title test"; + EXPECT_EQ(kExpectedTitle, GetEmbedderWebContents() + ->GetController() + .GetLastCommittedEntry() + ->GetTitleForDisplay()); + EXPECT_EQ(kExpectedTitle, GetActiveWebContents()->GetTitle()); } -// This test ensures that titles are set properly for embedded PDFs with /Title. -IN_PROC_BROWSER_TEST_P(PDFExtensionTest, TabTitleWithEmbeddedPdf) { +// This test ensures that titles are set properly for embedded PDFs (using data +// URL). PDF /Title should be ignored for embedded PDFs. +IN_PROC_BROWSER_TEST_P(PDFExtensionTest, TabTitleWithEmbeddedPdfDataUrl) { // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. if (UseOopif()) { GTEST_SKIP(); @@ -1154,6 +1157,19 @@ EXPECT_EQ(u"TabTitleWithEmbeddedPdf", GetActiveWebContents()->GetTitle()); } +// This test ensures that tab titles are set properly for embedded PDFs. +// PDF /Title should be ignored for embedded PDFs. +IN_PROC_BROWSER_TEST_P(PDFExtensionTest, TabTitleWithEmbeddedPdf) { + // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. + if (UseOopif()) { + GTEST_SKIP(); + } + + ASSERT_TRUE(LoadPdf(embedded_test_server()->GetURL("/pdf/pdf_embed.html"))); + + EXPECT_EQ(u"TabWithEmbeddedPdf", GetActiveWebContents()->GetTitle()); +} + // Flaky, http://crbug.com/767427 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) #define MAYBE_PdfZoomWithoutBubble DISABLED_PdfZoomWithoutBubble @@ -3666,8 +3682,8 @@ if (UseOopif()) { // Verify the pdf has loaded. The test will timeout if the PDF fails to // load. - GetTestPdfViewerStreamManager(incognito_contents) - ->WaitUntilPdfLoaded(incognito_primary_main_frame); + ASSERT_TRUE(GetTestPdfViewerStreamManager(incognito_contents) + ->WaitUntilPdfLoaded(incognito_primary_main_frame)); } else { ASSERT_TRUE(pdf_extension_test_util::EnsurePDFHasLoaded( incognito_primary_main_frame)); @@ -3685,8 +3701,8 @@ if (UseOopif()) { // Verify the pdf has loaded. The test will timeout if the PDF fails to // load. - GetTestPdfViewerStreamManager(incognito_contents) - ->WaitUntilPdfLoadedInFirstChild(); + ASSERT_TRUE(GetTestPdfViewerStreamManager(incognito_contents) + ->WaitUntilPdfLoadedInFirstChild()); } else { ASSERT_TRUE(pdf_extension_test_util::EnsurePDFHasLoaded( incognito_contents->GetPrimaryMainFrame())); @@ -3707,8 +3723,8 @@ // Verify the pdf has loaded. The test will timeout if the PDF fails to // load. auto* incognito_contents = GetIncognitoActiveWebContents(); - GetTestPdfViewerStreamManager(incognito_contents) - ->WaitUntilPdfLoadedInFirstChild(); + ASSERT_TRUE(GetTestPdfViewerStreamManager(incognito_contents) + ->WaitUntilPdfLoadedInFirstChild()); } // PDF extension tests for the OOPIF PDF viewer. @@ -3745,49 +3761,50 @@ // `EnsurePDFHasLoaded()` uses postMessage() to check that the PDF has loaded, // so calling it is sufficient to check that a postMessage() connection has // been established. - ASSERT_TRUE(pdf_extension_test_util::EnsurePDFHasLoaded( - GetActiveWebContents()->GetPrimaryMainFrame())); + content::RenderFrameHost* embedder_host = + ChildFrameAt(GetActiveWebContents()->GetPrimaryMainFrame(), 0); + ASSERT_TRUE(embedder_host); + ASSERT_TRUE(pdf_extension_test_util::EnsurePDFHasLoaded(embedder_host)); } // This test verifies the correctness of util `FindFullPagePdfExtensionHost`. IN_PROC_BROWSER_TEST_F(PDFExtensionOopifTest, OopifPdfFindFullPagePdfExtensionHost) { + auto* web_contents = GetActiveWebContents(); { // Navigate to a non-PDF page. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/title1.html"))); // Verify that there is no full-page pdf extension host on non-PDF page. - EXPECT_FALSE( - pdf_frame_util::FindFullPagePdfExtensionHost(GetActiveWebContents())); + EXPECT_FALSE(pdf_frame_util::FindFullPagePdfExtensionHost(web_contents)); } { // Load page with embedded PDF and make sure it succeeds. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/pdf/pdf_embed.html"))); - GetTestPdfViewerStreamManager(GetActiveWebContents()) - ->WaitUntilPdfLoadedInFirstChild(); + ASSERT_TRUE(GetTestPdfViewerStreamManager(web_contents) + ->WaitUntilPdfLoadedInFirstChild()); // Verify that there is no full-page pdf extension host on embedded PDF. - EXPECT_FALSE( - pdf_frame_util::FindFullPagePdfExtensionHost(GetActiveWebContents())); + EXPECT_FALSE(pdf_frame_util::FindFullPagePdfExtensionHost(web_contents)); } { // Load a full-page PDF and make sure it succeeds. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/pdf/test.pdf"))); - GetTestPdfViewerStreamManager(GetActiveWebContents()) - ->WaitUntilPdfLoaded(GetActiveWebContents()->GetPrimaryMainFrame()); + ASSERT_TRUE(GetTestPdfViewerStreamManager(web_contents) + ->WaitUntilPdfLoaded(web_contents->GetPrimaryMainFrame())); content::RenderFrameHost* child_frame = - content::ChildFrameAt(GetActiveWebContents()->GetPrimaryMainFrame(), 0); + content::ChildFrameAt(web_contents->GetPrimaryMainFrame(), 0); ASSERT_TRUE(child_frame); // Verify that `FindFullPagePdfExtensionHost` returns the correct frame. - EXPECT_EQ(child_frame, pdf_frame_util::FindFullPagePdfExtensionHost( - GetActiveWebContents())); + EXPECT_EQ(child_frame, + pdf_frame_util::FindFullPagePdfExtensionHost(web_contents)); } }
diff --git a/chrome/browser/pdf/pdf_extension_test_base.cc b/chrome/browser/pdf/pdf_extension_test_base.cc index 481a1e7..d8bd2d5 100644 --- a/chrome/browser/pdf/pdf_extension_test_base.cc +++ b/chrome/browser/pdf/pdf_extension_test_base.cc
@@ -168,6 +168,19 @@ return browser()->tab_strip_model()->GetActiveWebContents(); } +content::WebContents* PDFExtensionTestBase::GetEmbedderWebContents() { + content::WebContents* contents = GetActiveWebContents(); + + // OOPIF PDF viewer only has a single `WebContents`. + if (UseOopif()) { + return contents; + } + + MimeHandlerViewGuest* guest = + pdf_extension_test_util::GetOnlyMimeHandlerView(contents); + return guest ? guest->embedder_web_contents() : nullptr; +} + TestGuestViewManager* PDFExtensionTestBase::GetGuestViewManager( content::BrowserContext* profile) { if (!profile) { @@ -254,7 +267,9 @@ PDFExtensionTestBase::EnsurePDFHasLoadedWithValidFrameTree() { content::WebContents* contents = GetActiveWebContents(); testing::AssertionResult result = - pdf_extension_test_util::EnsurePDFHasLoaded(contents); + UseOopif() ? GetTestPdfViewerStreamManager(contents)->WaitUntilPdfLoaded( + contents->GetPrimaryMainFrame()) + : pdf_extension_test_util::EnsurePDFHasLoaded(contents); // Ensure the frame tree contains a PDF extension host and a PDF plugin frame. EXPECT_TRUE(pdf_extension_test_util::GetOnlyPdfExtensionHost(contents));
diff --git a/chrome/browser/pdf/pdf_extension_test_base.h b/chrome/browser/pdf/pdf_extension_test_base.h index acbbd8511..4312e91 100644 --- a/chrome/browser/pdf/pdf_extension_test_base.h +++ b/chrome/browser/pdf/pdf_extension_test_base.h
@@ -70,6 +70,11 @@ content::WebContents* GetActiveWebContents(); + // For OOPIF PDF viewer, returns the active `WebContents`, as there is only a + // single `WebContents`. For GuestView PDF viewer, returns the embedder + // `WebContents`. + content::WebContents* GetEmbedderWebContents(); + protected: guest_view::TestGuestViewManager* GetGuestViewManager( content::BrowserContext* profile = nullptr);
diff --git a/chrome/browser/pdf/pdf_extension_test_util.cc b/chrome/browser/pdf/pdf_extension_test_util.cc index f95b9257..ea28443c 100644 --- a/chrome/browser/pdf/pdf_extension_test_util.cc +++ b/chrome/browser/pdf/pdf_extension_test_util.cc
@@ -9,7 +9,9 @@ #include <vector> #include "base/containers/flat_set.h" +#include "base/feature_list.h" #include "base/functional/bind.h" +#include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -40,6 +42,21 @@ } // namespace +content::RenderFrameHost* GetPdfExtensionHostFromEmbedder( + content::RenderFrameHost* embedder_host) { + // PDF embedder hosts should have one child, which is the extension host. + if (content::ChildFrameAt(embedder_host, 1)) { + return nullptr; + } + + content::RenderFrameHost* child_host = + content::ChildFrameAt(embedder_host, 0); + return child_host && + IsPdfExtensionOrigin(child_host->GetLastCommittedOrigin()) + ? child_host + : nullptr; +} + content::RenderFrameHost* GetOnlyPdfExtensionHost( content::WebContents* contents) { std::vector<content::RenderFrameHost*> extension_hosts = @@ -95,26 +112,52 @@ const content::ToRenderFrameHost& frame, bool wait_for_hit_test_data, const std::string& pdf_element) { - bool load_success = content::EvalJs(frame, content::JsReplace(R"( - new Promise(resolve => { - window.addEventListener('message', event => { - if (event.origin !== - 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai') { - return; - } - if (event.data.type === 'documentLoaded') { - resolve( - event.data.load_state === 'success'); - } else if (event.data.type === 'passwordPrompted') { - resolve(true); - } - }); - document.getElementsByTagName($1)[0].postMessage( - {type: 'initialize'}); - }); - )", - pdf_element)) - .ExtractBool(); + // OOPIF PDF intentionally doesn't support postMessage() API for embedders. + // postMessage() can still be used if the script is injected into the + // extension frame. + static constexpr char kEnsurePdfHasLoadedScript[] = R"( + new Promise(resolve => { + window.addEventListener('message', event => { + if (event.origin !== + 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai') { + return; + } + if (event.data.type === 'documentLoaded') { + resolve(event.data.load_state === 'success'); + } else if (event.data.type === 'passwordPrompted') { + resolve(true); + } + }); + %s.postMessage( + {type: 'initialize'}); + }); + )"; + + static constexpr char kOopifPostMessageTarget[] = "window"; + static constexpr char kGuestViewPostMessageTarget[] = + "document.getElementsByTagName($1)[0]"; + + bool use_oopif = + base::FeatureList::IsEnabled(chrome_pdf::features::kPdfOopif); + + // For OOPIF PDF viewer, the target frame should be the PDF extension frame. + // Otherwise, it should be whatever frame was given. + content::RenderFrameHost* frame_rfh = frame.render_frame_host(); + content::RenderFrameHost* target_frame = + use_oopif ? GetPdfExtensionHostFromEmbedder(frame_rfh) : frame_rfh; + + if (use_oopif && !target_frame) { + return testing::AssertionFailure() << "Failed to get PDF extension frame."; + } + + const std::string post_message_target = + use_oopif ? kOopifPostMessageTarget + : content::JsReplace(kGuestViewPostMessageTarget, pdf_element); + bool load_success = + content::EvalJs(target_frame, + base::StringPrintf(kEnsurePdfHasLoadedScript, + post_message_target.c_str())) + .ExtractBool(); if (wait_for_hit_test_data) { frame.render_frame_host()->ForEachRenderFrameHost(
diff --git a/chrome/browser/pdf/pdf_extension_test_util.h b/chrome/browser/pdf/pdf_extension_test_util.h index 00eeedc0..e834727 100644 --- a/chrome/browser/pdf/pdf_extension_test_util.h +++ b/chrome/browser/pdf/pdf_extension_test_util.h
@@ -29,6 +29,11 @@ namespace pdf_extension_test_util { +// Gets the PDF extension host that is the child of `embedder_host`. The +// embedder host should only have one child, otherwise returns nullptr. +content::RenderFrameHost* GetPdfExtensionHostFromEmbedder( + content::RenderFrameHost* embedder_host); + // Gets the PDF extension host for a given `WebContents`. There should only be // one extension host in `contents`, otherwise returns nullptr. content::RenderFrameHost* GetOnlyPdfExtensionHost( @@ -54,6 +59,9 @@ // successfully, otherwise it indicates failure. If it doesn't finish loading, // the test will hang. // +// In order to ensure an OOPIF PDF has loaded, `frame` must be an embedder host, +// and the extension host must have already been created. +// // Tests that attempt to send mouse/pointer events should pass `true` for // `wait_for_hit_test_data`, otherwise the necessary hit test data may not be // available by the time this function returns. (This behavior is the default,
diff --git a/chrome/browser/pdf/pdf_viewer_stream_manager.cc b/chrome/browser/pdf/pdf_viewer_stream_manager.cc index 5e07484..0649c46a 100644 --- a/chrome/browser/pdf/pdf_viewer_stream_manager.cc +++ b/chrome/browser/pdf/pdf_viewer_stream_manager.cc
@@ -196,22 +196,30 @@ void PdfViewerStreamManager::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { - // If this is an unrelated host, ignore. - StreamInfo* claimed_stream_info = GetClaimedStreamInfo(render_frame_host); - if (!claimed_stream_info && - !ContainsUnclaimedStreamInfo(render_frame_host->GetFrameTreeNodeId())) { + // When the PDF embeder frame is deleted, delete its stream. + if (GetClaimedStreamInfo(render_frame_host)) { + DeleteClaimedStreamInfo(render_frame_host); + // DO NOT add code past this point. `this` may have been deleted. return; } - // An unclaimed `StreamInfo`'s FrameTreeNode may delete a speculative - // `content::RenderFrameHost` before the embedder `content::RenderFrameHost` - // commits and claims the stream. The speculative `content::RenderFrameHost` - // won't be considered active, and shouldn't cause the stream to be deleted. - if (!claimed_stream_info && !render_frame_host->IsActive()) { + // If `render_frame_host` isn't active, ignore. An unclaimed `StreamInfo`'s + // FrameTreeNode may delete a speculative `content::RenderFrameHost` before + // the embedder `content::RenderFrameHost` commits and claims the stream. The + // speculative `content::RenderFrameHost` won't be considered active, and + // shouldn't cause the stream to be deleted. + if (!render_frame_host->IsActive()) { return; } - DeleteStreamInfo(render_frame_host); + // If `render_frame_host` is an unrelated host (there isn't an unclaimed + // stream), ignore. + int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId(); + if (!ContainsUnclaimedStreamInfo(frame_tree_node_id)) { + return; + } + + DeleteUnclaimedStreamInfo(frame_tree_node_id); // DO NOT add code past this point. `this` may have been deleted. } @@ -234,7 +242,8 @@ // embedder host is navigating to another PDF URL, then a new `StreamInfo` // should have already been created and claimed by `new_host`, so it's still // safe to delete `old_host`'s `StreamInfo`. - DeleteStreamInfo(old_host); + DeleteClaimedStreamInfo(old_host); + // DO NOT add code past this point. `this` may have been deleted. } void PdfViewerStreamManager::FrameDeleted(int frame_tree_node_id) { @@ -388,7 +397,7 @@ return stream_info; } -void PdfViewerStreamManager::DeleteStreamInfo( +void PdfViewerStreamManager::DeleteClaimedStreamInfo( content::RenderFrameHost* embedder_host) { auto iter = stream_infos_.find(GetEmbedderHostInfo(embedder_host)); CHECK(iter != stream_infos_.end()); @@ -407,6 +416,15 @@ } } +void PdfViewerStreamManager::DeleteUnclaimedStreamInfo(int frame_tree_node_id) { + CHECK(stream_infos_.erase(GetUnclaimedEmbedderHostInfo(frame_tree_node_id))); + + if (stream_infos_.empty()) { + web_contents()->RemoveUserData(UserDataKey()); + // DO NOT add code past this point. RemoveUserData() deleted `this`. + } +} + bool PdfViewerStreamManager::MaybeRegisterPdfSubresourceOverride( content::NavigationHandle* navigation_handle) { // Only register the subresource override if `navigation_handle` is for the @@ -418,8 +436,6 @@ return false; } - // The stream container is no longer needed after registering the subresource - // override. navigation_handle->RegisterSubresourceOverride( claimed_stream_info->stream()->TakeTransferrableURLLoader());
diff --git a/chrome/browser/pdf/pdf_viewer_stream_manager.h b/chrome/browser/pdf/pdf_viewer_stream_manager.h index 9be440b..c3e0edc 100644 --- a/chrome/browser/pdf/pdf_viewer_stream_manager.h +++ b/chrome/browser/pdf/pdf_viewer_stream_manager.h
@@ -244,9 +244,13 @@ // `ContainsUnclaimedStreamInfo()` before calling this. StreamInfo* ClaimStreamInfo(content::RenderFrameHost* embedder_host); - // Deletes the stream info associated with `embedder_host`, and deletes - // `this` if there are no remaining stream infos. - void DeleteStreamInfo(content::RenderFrameHost* embedder_host); + // Deletes the claimed stream info associated with `embedder_host`, and + // deletes `this` if there are no remaining stream infos. + void DeleteClaimedStreamInfo(content::RenderFrameHost* embedder_host); + + // Deletes the unclaimed stream info associated with `frame_tree_node_id`, and + // deletes `this` if there are no remaining stream infos. + void DeleteUnclaimedStreamInfo(int frame_tree_node_id); // Intended to be called during the PDF content frame's // `ReadyToCommitNavigation()` event. Registers navigations occurring in a PDF
diff --git a/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc b/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc index b5f084c..447b51f 100644 --- a/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc +++ b/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc
@@ -218,7 +218,7 @@ } // If the embedder render frame is deleted, the stream should be deleted. -TEST_F(PdfViewerStreamManagerTest, RenderFrameDeleted) { +TEST_F(PdfViewerStreamManagerTest, RenderFrameDeletedWithClaimedStream) { auto* actual_host = CreateChildRenderFrameHost(main_rfh(), "actual host"); actual_host = NavigateAndCommit(actual_host, GURL(kOriginalUrl1)); @@ -232,9 +232,36 @@ manager->RenderFrameDeleted(main_rfh()); ASSERT_EQ(manager, pdf_viewer_stream_manager()); + // `PdfViewerStreamManager::RenderFrameDeleted()` should cause the stream + // associated with `actual_host` to be deleted. + manager->RenderFrameDeleted(actual_host); + // There are no remaining streams, so `PdfViewerStreamManager` should delete // itself. + EXPECT_FALSE(pdf_viewer_stream_manager()); +} + +TEST_F(PdfViewerStreamManagerTest, RenderFrameDeletedWithUnclaimedStream) { + auto* actual_host = CreateChildRenderFrameHost(main_rfh(), "actual host"); + actual_host = NavigateAndCommit(actual_host, GURL(kOriginalUrl1)); + + PdfViewerStreamManager* manager = pdf_viewer_stream_manager(); + manager->AddStreamContainer(actual_host->GetFrameTreeNodeId(), "internal_id", + pdf_test_util::GenerateSampleStreamContainer(1)); + + // The stream hasn't been claimed, so the stream container can't be retrieved. + ASSERT_FALSE(manager->GetStreamContainer(actual_host)); + + // Unrelated hosts should be ignored. + manager->RenderFrameDeleted(main_rfh()); + ASSERT_EQ(manager, pdf_viewer_stream_manager()); + + // `PdfViewerStreamManager::RenderFrameDeleted()` should cause the stream + // associated with `actual_host` to be deleted. manager->RenderFrameDeleted(actual_host); + + // There are no remaining streams, so `PdfViewerStreamManager` should delete + // itself. EXPECT_FALSE(pdf_viewer_stream_manager()); }
diff --git a/chrome/browser/pdf/test_pdf_viewer_stream_manager.cc b/chrome/browser/pdf/test_pdf_viewer_stream_manager.cc index ac6456b5..5bc875d 100644 --- a/chrome/browser/pdf/test_pdf_viewer_stream_manager.cc +++ b/chrome/browser/pdf/test_pdf_viewer_stream_manager.cc
@@ -9,11 +9,13 @@ #include "base/check.h" #include "base/containers/flat_set.h" #include "base/run_loop.h" +#include "chrome/browser/pdf/pdf_extension_test_util.h" #include "chrome/browser/pdf/pdf_viewer_stream_manager.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" #include "content/public/test/browser_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" namespace pdf { @@ -52,7 +54,7 @@ std::move(on_pdf_loaded_).Run(); } -void TestPdfViewerStreamManager::WaitUntilPdfLoaded( +testing::AssertionResult TestPdfViewerStreamManager::WaitUntilPdfLoaded( content::RenderFrameHost* embedder_host) { // If all of the PDF frames haven't navigated, wait. auto* claimed_stream_info = GetClaimedStreamInfo(embedder_host); @@ -62,16 +64,16 @@ run_loop.Run(); } - // TODO(crbug.com/1445746): Currently, this only waits until all of the PDF - // frames finished navigating. Wait until the PDF extension and content has - // finished loading, too. + // Wait until the PDF extension and content are loaded. + return pdf_extension_test_util::EnsurePDFHasLoaded(embedder_host); } -void TestPdfViewerStreamManager::WaitUntilPdfLoadedInFirstChild() { +testing::AssertionResult +TestPdfViewerStreamManager::WaitUntilPdfLoadedInFirstChild() { content::RenderFrameHost* embedder_host = ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0); CHECK(embedder_host); - WaitUntilPdfLoaded(embedder_host); + return WaitUntilPdfLoaded(embedder_host); } TestPdfViewerStreamManagerFactory::TestPdfViewerStreamManagerFactory() {
diff --git a/chrome/browser/pdf/test_pdf_viewer_stream_manager.h b/chrome/browser/pdf/test_pdf_viewer_stream_manager.h index 0fce2bf..20db7b1 100644 --- a/chrome/browser/pdf/test_pdf_viewer_stream_manager.h +++ b/chrome/browser/pdf/test_pdf_viewer_stream_manager.h
@@ -9,6 +9,7 @@ #include "base/functional/callback_forward.h" #include "chrome/browser/pdf/pdf_viewer_stream_manager.h" #include "content/public/browser/web_contents_user_data.h" +#include "testing/gtest/include/gtest/gtest.h" namespace content { class NavigationHandle; @@ -35,14 +36,16 @@ void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; - // Wait until the PDF has finished loading. `embedder_host` must be a PDF - // embedder host, otherwise this will hang the test. - void WaitUntilPdfLoaded(content::RenderFrameHost* embedder_host); + // Wait until the PDF has finished loading. Returns true if the PDF loads + // successfully, false otherwise. The test will hang if `embedder_host` is not + // a PDF, or if the PDF frames never finish navigating. + [[nodiscard]] testing::AssertionResult WaitUntilPdfLoaded( + content::RenderFrameHost* embedder_host); // Same as `WaitUntilPdfLoaded()`, but the first child of the primary main // frame should be the embedder. This is a common case where an HTML page only // embeds a single PDF. - void WaitUntilPdfLoadedInFirstChild(); + [[nodiscard]] testing::AssertionResult WaitUntilPdfLoadedInFirstChild(); private: base::OnceClosure on_pdf_loaded_;
diff --git a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc index f9e13dda..738af9a1 100644 --- a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc +++ b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/check_is_test.h" #include "base/functional/bind.h" #include "base/json/json_writer.h" #include "base/memory/scoped_refptr.h" @@ -37,11 +38,128 @@ #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/reporting/util/statusor.h" #include "content/public/browser/browser_thread.h" +#include "net/base/backoff_entry.h" +#include "net/http/http_status_code.h" #include "services/network/public/cpp/shared_url_loader_factory.h" namespace reporting { namespace { + +// Returns `true` if HTTP response code indicates an irrecoverable error. +bool IsIrrecoverableError(int response_code) { + return response_code >= ::net::HTTP_BAD_REQUEST && + response_code < ::net::HTTP_INTERNAL_SERVER_ERROR && + response_code != + ::net::HTTP_CONFLICT; // Overlapping seq_id ranges detected +} + +// Generates new backoff entry. +std::unique_ptr<::net::BackoffEntry> GetBackoffEntry( + ::reporting::Priority priority) { + // Retry policy for SECURITY queue. + static const ::net::BackoffEntry::Policy kSecurityUploadBackoffPolicy = { + // Number of initial errors to ignore before applying + // exponential back-off rules. + /*num_errors_to_ignore=*/0, + + // Initial delay is 10 seconds. + /*initial_delay_ms=*/10 * 1000, + + // Factor by which the waiting time will be multiplied. + /*multiply_factor=*/2, + + // Fuzzing percentage. + /*jitter_factor=*/0.1, + + // Maximum delay is 1 minute. + /*maximum_backoff_ms=*/1 * 60 * 1000, + + // It's up to the caller to reset the backoff time. + /*entry_lifetime_ms=*/-1, + + /*always_use_initial_delay=*/true, + }; + // Retry policy for all other queues, including initial key delivery. + static const ::net::BackoffEntry::Policy kDefaultUploadBackoffPolicy = { + // Number of initial errors to ignore before applying + // exponential back-off rules. + /*num_errors_to_ignore=*/0, + + // Initial delay is 10 seconds. + /*initial_delay_ms=*/10 * 1000, + + // Factor by which the waiting time will be multiplied. + /*multiply_factor=*/2, + + // Fuzzing percentage. + /*jitter_factor=*/0.1, + + // Maximum delay is 24 hours. + /*maximum_backoff_ms=*/24 * 60 * 60 * 1000, + + // It's up to the caller to reset the backoff time. + /*entry_lifetime_ms=*/-1, + + /*always_use_initial_delay=*/true, + }; + // Maximum backoff is set per priority. Current proposal is to set SECURITY + // events to be backed off only slightly: max delay is set to 1 minute. + // For all other priorities max delay is set to 24 hours. + auto backoff_entry = std::make_unique<::net::BackoffEntry>( + priority == ::reporting::SECURITY ? &kSecurityUploadBackoffPolicy + : &kDefaultUploadBackoffPolicy); + return backoff_entry; +} + +// State of single priority queue uploads. +// It is a singleton, protected implicitly by the fact that all relevant +// EncryptedReportingJobConfiguration actions are called on the sequenced task +// runner. +struct UploadState { + // Highest sequence id that has been posted for upload. + int64_t last_sequence_id; + // Generation id that has been posted for upload. + int64_t last_generation_id; + + // Time when the next request will be allowed. + // This is essentially the cache value of the backoff->GetReleaseTime(). + // When the time is reached, one request is allowed, backoff is updated as if + // the request failed, and the new release time is cached. + base::TimeTicks earliest_retry_timestamp; + + // Current backoff entry for this priority. + std::unique_ptr<::net::BackoffEntry> backoff_entry; +}; +// Map of all the queues states. +using UploadStateMap = base::flat_map<::reporting::Priority, UploadState>; + +UploadStateMap* state_map() { + static base::NoDestructor<UploadStateMap> map; + return map.get(); +} + +UploadState* GetState(::reporting::Priority priority, + int64_t generation_id, + int64_t sequence_id) { + auto state_it = state_map()->find(priority); + if (state_it == state_map()->end() || + state_it->second.last_generation_id != generation_id) { + // This priority pops up for the first time or (rare case) generation has + // changed. Record new state and allow upload. + state_it = state_map() + ->insert_or_assign( + priority, + UploadState{.last_sequence_id = sequence_id, + .last_generation_id = generation_id, + .backoff_entry = GetBackoffEntry(priority)}) + .first; + state_it->second.earliest_retry_timestamp = + state_it->second.backoff_entry->GetReleaseTime(); + } + return &state_it->second; +} + // Builds uploading payload. // Returns dictionary (null in case of failure) and matching memory reservation. void BuildPayload( @@ -196,15 +314,12 @@ // static std::unique_ptr<EncryptedReportingClient> EncryptedReportingClient::Create( std::unique_ptr<Delegate> delegate) { - return base::WrapUnique(new EncryptedReportingClient( - GenerationGuidIsRequired(), std::move(delegate))); + return base::WrapUnique(new EncryptedReportingClient(std::move(delegate))); } EncryptedReportingClient::EncryptedReportingClient( - bool is_generation_guid_required, std::unique_ptr<Delegate> delegate) - : is_generation_guid_required_(is_generation_guid_required), - delegate_(std::move(delegate)) {} + : delegate_(std::move(delegate)) {} EncryptedReportingClient::~EncryptedReportingClient() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -219,15 +334,37 @@ policy::CloudPolicyClient* cloud_policy_client, ResponseCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + const base::TimeDelta delay = WhenIsAllowedToProceed(records); + if (delay.is_positive()) { + // Reject upload. + std::move(callback).Run(base::unexpected( + Status(error::OUT_OF_RANGE, "Too many upload requests"))); + return; + } + // Accept upload. + AccountForAllowedJob(records); + // Construct payload on thread pool, then resume action on the current thread. // Perform Build on a thread pool, and upload result on UI. - auto create_job_cb = base::BindPostTaskToCurrentDefault( - base::BindOnce(&EncryptedReportingClient::CreateUploadJob, - weak_ptr_factory_.GetWeakPtr(), std::move(context), - cloud_policy_client, std::move(callback))); + Priority priority = Priority::UNDEFINED_PRIORITY; + int64_t last_generation_id = -1L; + int64_t last_sequence_id = -1L; + if (!records.empty()) { + const auto& last_sequence_info = records.crbegin()->sequence_information(); + priority = last_sequence_info.priority(); + last_generation_id = last_sequence_info.generation_id(); + last_sequence_id = last_sequence_info.sequencing_id(); + } + auto create_job_cb = base::BindPostTaskToCurrentDefault(base::BindOnce( + &EncryptedReportingClient::CreateUploadJob, + weak_ptr_factory_.GetWeakPtr(), std::move(context), cloud_policy_client, + base::BindOnce(&EncryptedReportingClient::AccountForUploadResponse, + priority, last_generation_id, last_sequence_id), + std::move(callback))); base::ThreadPool::PostTask( FROM_HERE, {}, - base::BindOnce(&BuildPayload, is_generation_guid_required_, + base::BindOnce(&BuildPayload, GenerationGuidIsRequired(), need_encryption_key, config_file_version, std::move(records), std::move(scoped_reservation), std::move(create_job_cb))); @@ -236,6 +373,8 @@ void EncryptedReportingClient::CreateUploadJob( std::optional<base::Value::Dict> context, policy::CloudPolicyClient* cloud_policy_client, + policy::EncryptedReportingJobConfiguration::UploadResponseCallback + response_cb, ResponseCallback callback, std::optional<base::Value::Dict> payload_result, ScopedReservation scoped_reservation) { @@ -278,6 +417,7 @@ device_management_service->configuration() ->GetEncryptedReportingServerUrl(), std::move(payload_result.value()), cloud_policy_client, + std::move(response_cb), base::BindOnce(&EncryptedReportingClient::OnReportUploadCompleted, weak_ptr_factory_.GetWeakPtr(), std::move(scoped_reservation), request_payload_size, @@ -287,14 +427,6 @@ if (context.has_value()) { config->UpdateContext(std::move(context.value())); } - const base::TimeDelta delay = config->WhenIsAllowedToProceed(); - if (delay.is_positive()) { - // Reject upload. - config->CancelNotAllowedJob(); // Invokes callback to response back. - return; - } - // Accept upload. - config->AccountForAllowedJob(); std::unique_ptr<policy::DeviceManagementService::Job> job = device_management_service->CreateJob(std::move(config)); request_jobs_.emplace(std::move(job)); @@ -314,12 +446,12 @@ if (job) { request_jobs_.erase(job); } - if (response_code == ::policy::DeviceManagementService::kTooManyRequests) { + if (response_code == ::net::HTTP_TOO_MANY_REQUESTS) { std::move(callback).Run(base::unexpected( Status(error::OUT_OF_RANGE, "Too many upload requests"))); return; } - if (response_code != ::policy::DeviceManagementService::kSuccess) { + if (response_code != ::net::HTTP_OK) { std::move(callback).Run(base::unexpected( Status(error::DATA_LOSS, base::StrCat( @@ -360,6 +492,97 @@ std::move(callback).Run(std::move(response.value())); } +// static +base::TimeDelta EncryptedReportingClient::WhenIsAllowedToProceed( + const std::vector<EncryptedRecord>& records) { + // If there are no records, allow upload (it will not overload the server). + if (records.empty()) { + return base::TimeDelta(); // 0 - allowed right away. + } + // Now pick up the state. + const auto& last_sequence_info = records.crbegin()->sequence_information(); + const auto* const state = GetState(last_sequence_info.priority(), + last_sequence_info.generation_id(), + last_sequence_info.sequencing_id()); + // Use and update previously recorded state, base upload decision on it. + if (state->last_sequence_id > last_sequence_info.sequencing_id()) { + // Sequence id decreased, the upload is outdated, reject it forever. + return base::TimeDelta::Max(); + } + if (state->last_sequence_id < last_sequence_info.sequencing_id()) { + // Sequence id increased, keep validating. + switch (last_sequence_info.priority()) { + case Priority::SECURITY: + // For SECURITY events the request is allowed. + return base::TimeDelta(); // 0 - allowed right away. + default: { + // For all other priorities we will act like in case of request’s + // last_sequence_id is == last_sequence_id above - observing the + // backoff time expiration. + } + } + } + // Allow upload only if earliest retry time has passed. + // Return delta till the allowed time - if positive, upload is going to be + // rejected. + return state->earliest_retry_timestamp - + state->backoff_entry->GetTimeTicksNow(); +} + +// static +void EncryptedReportingClient::AccountForAllowedJob( + const std::vector<EncryptedRecord>& records) { + Priority priority = Priority::UNDEFINED_PRIORITY; + int64_t last_generation_id = -1L; + int64_t last_sequence_id = -1L; + if (!records.empty()) { + const auto& last_sequence_info = records.crbegin()->sequence_information(); + priority = last_sequence_info.priority(); + last_generation_id = last_sequence_info.generation_id(); + last_sequence_id = last_sequence_info.sequencing_id(); + } + auto* const state = GetState(priority, last_generation_id, last_sequence_id); + // Update state to reflect highest sequence_id_ (we never allow upload with + // lower sequence_id_). + state->last_sequence_id = last_sequence_id; + // Calculate delay as exponential backoff (based on the retry_count). + // Update backoff under assumption that this request fails. + // If it is responded successfully, we will reset it. + state->backoff_entry->InformOfRequest(/*succeeded=*/false); + state->earliest_retry_timestamp = state->backoff_entry->GetReleaseTime(); +} + +// static +void EncryptedReportingClient::AccountForUploadResponse(Priority priority, + int64_t generation_id, + int64_t sequence_id, + int net_error, + int response_code) { + // Analyze the net error and update upload state for possible future retries. + auto* const state = GetState(priority, generation_id, sequence_id); + if (net_error != ::net::OK) { + // Network error + } else if (IsIrrecoverableError(response_code)) { + // Irrecoverable error code returned by server, + // impose artificial 24h backoff. + state->backoff_entry->SetCustomReleaseTime( + state->backoff_entry->GetTimeTicksNow() + base::Days(1)); + } + // For all other cases keep the currently set retry time. + // In case of success, inform backoff entry about that. + if (net_error == ::net::OK && response_code == ::net::HTTP_OK) { + state->backoff_entry->InformOfRequest(/*succeeded=*/true); + } + // Cache earliest retry time based on the current backoff entry. + state->earliest_retry_timestamp = state->backoff_entry->GetReleaseTime(); +} + +// static +void EncryptedReportingClient::ResetUploadsStateForTest() { + CHECK_IS_TEST(); + state_map()->clear(); +} + // ======== PayloadSizePerHourUmaReporter ========== // static
diff --git a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h index 61bda0e..ad5d436 100644 --- a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h +++ b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h
@@ -19,6 +19,7 @@ #include "base/values.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/device_management_service.h" +#include "components/policy/core/common/cloud/encrypted_reporting_job_configuration.h" #include "components/reporting/proto/synced/record.pb.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/reporting/resources/resource_manager.h" @@ -116,24 +117,39 @@ policy::CloudPolicyClient* cloud_policy_client, ResponseCallback callback); + // Test-only method that resets collected uploads state. + static void ResetUploadsStateForTest(); + private: + friend class EncryptedReportingClientTest; + FRIEND_TEST_ALL_PREFIXES(EncryptedReportingClientTest, + IdenticalUploadRetriesThrottled); + FRIEND_TEST_ALL_PREFIXES(EncryptedReportingClientTest, + UploadsSequenceThrottled); + FRIEND_TEST_ALL_PREFIXES(EncryptedReportingClientTest, + SecurityUploadsSequenceNotThrottled); + FRIEND_TEST_ALL_PREFIXES(EncryptedReportingClientTest, + FailedUploadsSequenceThrottled); + using JobSet = base::flat_set<std::unique_ptr<policy::DeviceManagementService::Job>, base::UniquePtrComparator>; // Constructor called by factory only. - EncryptedReportingClient(bool is_generation_guid_required, - std::unique_ptr<Delegate> delegate); + explicit EncryptedReportingClient(std::unique_ptr<Delegate> delegate); // Constructs upload job after the data is converted into JSON, assigned to // `payload_result` (`nullopt` if there was an error). Calls `callback` once // the job has been responded or if an error has been detected, and releases // `scoped_reservation`. - void CreateUploadJob(std::optional<base::Value::Dict> context, - policy::CloudPolicyClient* cloud_policy_client, - ResponseCallback callback, - std::optional<base::Value::Dict> payload_result, - ScopedReservation scoped_reservation); + void CreateUploadJob( + std::optional<base::Value::Dict> context, + policy::CloudPolicyClient* cloud_policy_client, + policy::EncryptedReportingJobConfiguration::UploadResponseCallback + response_cb, + ResponseCallback callback, + std::optional<base::Value::Dict> payload_result, + ScopedReservation scoped_reservation); // Callback for encrypted report upload requests. void OnReportUploadCompleted(ScopedReservation scoped_reservation, @@ -146,11 +162,26 @@ int response_code, std::optional<base::Value::Dict> response); + // Checks the new job against the history, determines how soon the upload will + // be allowed. Returns positive value if not allowed, and 0 or negative + // otherwise. + static base::TimeDelta WhenIsAllowedToProceed( + const std::vector<EncryptedRecord>& records); + + // Account for the job, that was allowed to proceed. + static void AccountForAllowedJob(const std::vector<EncryptedRecord>& records); + + // Accounts for net error and response code of the upload. + static void AccountForUploadResponse(Priority priority, + int64_t generation_id, + int64_t sequence_id, + int net_error, + int response_code); + SEQUENCE_CHECKER(sequence_checker_); JobSet request_jobs_ GUARDED_BY_CONTEXT(sequence_checker_); - const bool is_generation_guid_required_; const std::unique_ptr<Delegate> delegate_; // Reports accumulated payload sizes per hour via UMA.
diff --git a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc index e79e475..936e7ff 100644 --- a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc
@@ -21,11 +21,11 @@ #include "base/values.h" #include "chrome/browser/enterprise/browser_management/management_service_factory.h" #include "chrome/browser/policy/device_management_service_configuration.h" +#include "chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h" #include "chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/ash/components/system/statistics_provider.h" #include "components/policy/core/common/cloud/device_management_service.h" -#include "components/policy/core/common/cloud/encrypted_reporting_job_configuration.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/policy/core/common/management/scoped_management_service_override_for_testing.h" #include "components/reporting/proto/synced/record_constants.pb.h" @@ -45,6 +45,7 @@ #endif using testing::Eq; +using testing::Ge; using testing::Property; using testing::SizeIs; using testing::StartsWith; @@ -107,34 +108,33 @@ device_management_service_->ScheduleInitialization(0); TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory( url_loader_factory_.GetSafeWeakWrapper()); - BuildPayload(); cloud_policy_client_.SetDMToken(kDmToken); cloud_policy_client_.client_id_ = kClientId; + + context_.SetByDottedPath("browser.userAgent", "agent-test-value"); } void TearDown() override { - policy::EncryptedReportingJobConfiguration::ResetUploadsStateForTest(); + EncryptedReportingClient::ResetUploadsStateForTest(); EXPECT_THAT(memory_resource_->GetUsed(), Eq(0uL)); } - void BuildPayload() { - context_.SetByDottedPath("browser.userAgent", "agent-test-value"); + void AddRecordToPayload(Priority priority = Priority::SLOW_BATCH) { + payload_records_.emplace_back(); - EncryptedRecord encrypted_record; + EncryptedRecord& encrypted_record = payload_records_.back(); encrypted_record.set_encrypted_wrapped_record(kEncryptedRecord); SequenceInformation* const sequence_information = encrypted_record.mutable_sequence_information(); sequence_information->set_generation_id(kGenerationId); - sequence_information->set_sequencing_id(sequence_id_); - sequence_information->set_priority(Priority::SLOW_BATCH); - - payload_records_.emplace_back(encrypted_record); + sequence_information->set_sequencing_id(sequence_id_++); + sequence_information->set_priority(priority); } - void DecrementSequenceId() { --sequence_id_; } + void DecrementSequenceId(int64_t by = 0L) { sequence_id_ -= (by + 1L); } content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; @@ -166,14 +166,15 @@ std::make_unique<FakeDelegate>(device_management_service_.get())); { + AddRecordToPayload(); ScopedReservation scoped_reservation(RecordsSize(payload_records_), memory_resource_); ASSERT_TRUE(scoped_reservation.reserved()); test::TestEvent<StatusOr<base::Value::Dict>> response_event; encrypted_reporting_client->UploadReport( need_encryption_key_, config_file_version_, payload_records_, - std::move(scoped_reservation), std::move(context_), - &cloud_policy_client_, response_event.cb()); + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, + response_event.cb()); task_environment_.RunUntilIdle(); ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); @@ -208,19 +209,18 @@ // Avoid rate limiting by time, but still reject the upload because of lower // sequence id. task_environment_.FastForwardBy(base::Minutes(1)); - DecrementSequenceId(); + DecrementSequenceId(1L); { - BuildPayload(); - + AddRecordToPayload(); ScopedReservation scoped_reservation(RecordsSize(payload_records_), memory_resource_); ASSERT_TRUE(scoped_reservation.reserved()); test::TestEvent<StatusOr<base::Value::Dict>> response_event; encrypted_reporting_client->UploadReport( need_encryption_key_, config_file_version_, payload_records_, - std::move(scoped_reservation), std::move(context_), - &cloud_policy_client_, response_event.cb()); + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, + response_event.cb()); // Sequence ID decreased, upload is rejected. const auto actual_response = response_event.result(); @@ -228,7 +228,8 @@ Property(&StatusOr<base::Value::Dict>::error, AllOf(Property(&Status::code, Eq(error::OUT_OF_RANGE)), Property(&Status::error_message, - StrEq("Too many upload requests"))))); + StrEq("Too many upload requests"))))) + << actual_response.error(); } } @@ -236,13 +237,14 @@ auto encrypted_reporting_client = EncryptedReportingClient::Create(std::make_unique<FakeDelegate>(nullptr)); + AddRecordToPayload(); ScopedReservation scoped_reservation(RecordsSize(payload_records_), memory_resource_); ASSERT_TRUE(scoped_reservation.reserved()); test::TestEvent<StatusOr<base::Value::Dict>> response_event; encrypted_reporting_client->UploadReport( need_encryption_key_, config_file_version_, payload_records_, - std::move(scoped_reservation), std::move(context_), &cloud_policy_client_, + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, response_event.cb()); const auto actual_response = response_event.result(); EXPECT_THAT( @@ -262,6 +264,7 @@ std::make_unique<FakeDelegate>(device_management_service_.get())); { + AddRecordToPayload(); ScopedReservation scoped_reservation(RecordsSize(payload_records_), memory_resource_); ASSERT_TRUE(scoped_reservation.reserved()); @@ -304,20 +307,22 @@ // Repeat the same upload, get it rejected by rate limiter. task_environment_.FastForwardBy(base::Seconds(1)); { + AddRecordToPayload(); ScopedReservation scoped_reservation(RecordsSize(payload_records_), memory_resource_); ASSERT_TRUE(scoped_reservation.reserved()); test::TestEvent<StatusOr<base::Value::Dict>> response_event; encrypted_reporting_client->UploadReport( need_encryption_key_, config_file_version_, payload_records_, - std::move(scoped_reservation), std::move(context_), - &cloud_policy_client_, response_event.cb()); + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, + response_event.cb()); const auto actual_response = response_event.result(); EXPECT_THAT(actual_response, Property(&StatusOr<base::Value::Dict>::error, AllOf(Property(&Status::code, Eq(error::OUT_OF_RANGE)), Property(&Status::error_message, - StrEq("Too many upload requests"))))); + StrEq("Too many upload requests"))))) + << actual_response.error(); } } @@ -329,13 +334,14 @@ // the request headers. auto encrypted_reporting_client = EncryptedReportingClient::Create( std::make_unique<FakeDelegate>(device_management_service_.get())); + AddRecordToPayload(); ScopedReservation scoped_reservation(RecordsSize(payload_records_), memory_resource_); ASSERT_TRUE(scoped_reservation.reserved()); test::TestEvent<StatusOr<base::Value::Dict>> response_event; encrypted_reporting_client->UploadReport( need_encryption_key_, config_file_version_, payload_records_, - std::move(scoped_reservation), std::move(context_), nullptr, + std::move(scoped_reservation), context_.Clone(), nullptr, base::DoNothing()); task_environment_.RunUntilIdle(); @@ -346,4 +352,231 @@ (*url_loader_factory_.pending_requests())[0].request.headers.ToString(), kDmToken)); } + +TEST_F(EncryptedReportingClientTest, IdenticalUploadRetriesThrottled) { + const size_t kTotalRetries = 10; + + auto encrypted_reporting_client = EncryptedReportingClient::Create( + std::make_unique<FakeDelegate>(device_management_service_.get())); + + base::TimeDelta expected_delay_after = base::Seconds(10); + for (size_t i = 0; i < kTotalRetries; ++i) { + AddRecordToPayload(); + ScopedReservation scoped_reservation(RecordsSize(payload_records_), + memory_resource_); + ASSERT_TRUE(scoped_reservation.reserved()); + + auto allowed_delay = + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_); + if (i == 0) { + // First upload allowed immediately. + EXPECT_FALSE(allowed_delay.is_positive()); + } else { + // Further uploads allowed with delay. + EXPECT_THAT(allowed_delay, Ge(expected_delay_after)); + // Double the expectation for the next retry. + expected_delay_after *= 2; + // Move forward to allow. + task_environment_.FastForwardBy(allowed_delay - base::Seconds(1)); + EXPECT_TRUE( + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_) + .is_positive()); + task_environment_.FastForwardBy(base::Seconds(1)); + } + + EXPECT_FALSE( + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_) + .is_positive()); + + test::TestEvent<StatusOr<base::Value::Dict>> response_event; + encrypted_reporting_client->UploadReport( + need_encryption_key_, config_file_version_, payload_records_, + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, + response_event.cb()); + task_environment_.RunUntilIdle(); + + ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); + + const std::string& pending_request_url = + (*url_loader_factory_.pending_requests())[0].request.url.spec(); + EXPECT_THAT(pending_request_url, StartsWith(kServerUrl)); + + url_loader_factory_.SimulateResponseForPendingRequest( + pending_request_url, + base::StringPrintf(R"({"%s" : "%s"})", kResponseKey, kResponseValue)); + + const auto actual_response = response_event.result(); + ASSERT_TRUE(actual_response.has_value()); + ASSERT_THAT(actual_response.value(), SizeIs(1)); + ASSERT_TRUE(actual_response.value().FindString(kResponseKey)); + EXPECT_THAT(*(actual_response.value().FindString(kResponseKey)), + StrEq(kResponseValue)); + + encrypted_reporting_client->AccountForAllowedJob(payload_records_); + } +} + +TEST_F(EncryptedReportingClientTest, UploadsSequenceThrottled) { + const size_t kTotalRetries = 10; + + auto encrypted_reporting_client = EncryptedReportingClient::Create( + std::make_unique<FakeDelegate>(device_management_service_.get())); + + base::TimeDelta expected_delay_after = base::Seconds(10); + for (size_t i = 0; i < kTotalRetries; ++i) { + AddRecordToPayload(); + ScopedReservation scoped_reservation(RecordsSize(payload_records_), + memory_resource_); + ASSERT_TRUE(scoped_reservation.reserved()); + + auto allowed_delay = + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_); + if (i == 0) { + // First upload allowed immediately. + EXPECT_FALSE(allowed_delay.is_positive()); + } else { + // Further uploads allowed with delay. + EXPECT_THAT(allowed_delay, Ge(expected_delay_after)); + // Double the expectation for the next retry. + expected_delay_after *= 2; + // Move forward to allow. + task_environment_.FastForwardBy(allowed_delay - base::Seconds(1)); + EXPECT_TRUE( + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_) + .is_positive()); + task_environment_.FastForwardBy(base::Seconds(1)); + } + + EXPECT_FALSE( + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_) + .is_positive()); + + test::TestEvent<StatusOr<base::Value::Dict>> response_event; + encrypted_reporting_client->UploadReport( + need_encryption_key_, config_file_version_, payload_records_, + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, + response_event.cb()); + task_environment_.RunUntilIdle(); + + ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); + + const std::string& pending_request_url = + (*url_loader_factory_.pending_requests())[0].request.url.spec(); + EXPECT_THAT(pending_request_url, StartsWith(kServerUrl)); + + url_loader_factory_.SimulateResponseForPendingRequest( + pending_request_url, + base::StringPrintf(R"({"%s" : "%s"})", kResponseKey, kResponseValue)); + + const auto actual_response = response_event.result(); + ASSERT_TRUE(actual_response.has_value()); + ASSERT_THAT(actual_response.value(), SizeIs(1)); + ASSERT_TRUE(actual_response.value().FindString(kResponseKey)); + EXPECT_THAT(*(actual_response.value().FindString(kResponseKey)), + StrEq(kResponseValue)); + + encrypted_reporting_client->AccountForAllowedJob(payload_records_); + } +} + +TEST_F(EncryptedReportingClientTest, SecurityUploadsSequenceNotThrottled) { + const size_t kTotalRetries = 10; + + auto encrypted_reporting_client = EncryptedReportingClient::Create( + std::make_unique<FakeDelegate>(device_management_service_.get())); + + for (size_t i = 0; i < kTotalRetries; ++i) { + AddRecordToPayload(Priority::SECURITY); + ScopedReservation scoped_reservation(RecordsSize(payload_records_), + memory_resource_); + ASSERT_TRUE(scoped_reservation.reserved()); + + // New SECURITY event upload is allowed immediately. + EXPECT_FALSE( + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_) + .is_positive()); + + test::TestEvent<StatusOr<base::Value::Dict>> response_event; + encrypted_reporting_client->UploadReport( + need_encryption_key_, config_file_version_, payload_records_, + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, + response_event.cb()); + task_environment_.RunUntilIdle(); + + ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); + + const std::string& pending_request_url = + (*url_loader_factory_.pending_requests())[0].request.url.spec(); + EXPECT_THAT(pending_request_url, StartsWith(kServerUrl)); + + url_loader_factory_.SimulateResponseForPendingRequest( + pending_request_url, + base::StringPrintf(R"({"%s" : "%s"})", kResponseKey, kResponseValue)); + + const auto actual_response = response_event.result(); + ASSERT_TRUE(actual_response.has_value()); + ASSERT_THAT(actual_response.value(), SizeIs(1)); + ASSERT_TRUE(actual_response.value().FindString(kResponseKey)); + EXPECT_THAT(*(actual_response.value().FindString(kResponseKey)), + StrEq(kResponseValue)); + + encrypted_reporting_client->AccountForAllowedJob(payload_records_); + } +} + +TEST_F(EncryptedReportingClientTest, FailedUploadsSequenceThrottled) { + const size_t kTotalRetries = 10; + + auto encrypted_reporting_client = EncryptedReportingClient::Create( + std::make_unique<FakeDelegate>(device_management_service_.get())); + + for (size_t i = 0; i < kTotalRetries; ++i) { + AddRecordToPayload(); + ScopedReservation scoped_reservation(RecordsSize(payload_records_), + memory_resource_); + ASSERT_TRUE(scoped_reservation.reserved()); + + auto allowed_delay = + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_); + if (i == 0) { + // The very first upload is allowed. + EXPECT_FALSE(allowed_delay.is_positive()); + } else { + // Delay after permanent error is 1 day. + EXPECT_THAT(allowed_delay, Ge(base::Days(1))); + // Move forward to allow. + task_environment_.FastForwardBy(allowed_delay - base::Seconds(1)); + EXPECT_TRUE( + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_) + .is_positive()); + task_environment_.FastForwardBy(base::Seconds(1)); + } + + EXPECT_FALSE( + encrypted_reporting_client->WhenIsAllowedToProceed(payload_records_) + .is_positive()); + + test::TestEvent<StatusOr<base::Value::Dict>> response_event; + encrypted_reporting_client->UploadReport( + need_encryption_key_, config_file_version_, payload_records_, + std::move(scoped_reservation), context_.Clone(), &cloud_policy_client_, + response_event.cb()); + task_environment_.RunUntilIdle(); + + ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); + + const std::string& pending_request_url = + (*url_loader_factory_.pending_requests())[0].request.url.spec(); + EXPECT_THAT(pending_request_url, StartsWith(kServerUrl)); + + url_loader_factory_.SimulateResponseForPendingRequest( + pending_request_url, "", + /*status=*/::net::HTTP_UNAUTHORIZED); // Permanent error. + + const auto actual_response = response_event.result(); + ASSERT_FALSE(actual_response.has_value()); + + encrypted_reporting_client->AccountForAllowedJob(payload_records_); + } +} } // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc index 9bf3f4f3..b197e64c 100644 --- a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc +++ b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc
@@ -27,7 +27,6 @@ #include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/cloud/device_management_service.h" #include "components/policy/core/common/cloud/dm_token.h" -#include "components/policy/core/common/cloud/encrypted_reporting_job_configuration.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/policy/core/common/cloud/mock_cloud_policy_service.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" @@ -110,7 +109,7 @@ } ReportingServerConnector::TestEnvironment::~TestEnvironment() { - policy::EncryptedReportingJobConfiguration::ResetUploadsStateForTest(); + EncryptedReportingClient::ResetUploadsStateForTest(); base::Singleton<ReportingServerConnector>::OnExit(nullptr); }
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 6efdc4bd..690f748 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -550,38 +550,6 @@ // Please keep the list of deprecated prefs in chronological order. i.e. Add to // the bottom of the list, not here at the top. -// Deprecated 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) -const char kArcTermsShownInOobe[] = "arc.terms.shown_in_oobe"; -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) - -// Deprecated 02/2023. -const char kSyncInvalidationVersions[] = "sync.invalidation_versions"; -const char kSyncInvalidationVersions2[] = "sync.invalidation_versions2"; - -// Deprecated 02/2023. -const char kClearPluginLSODataEnabled[] = "browser.clear_lso_data_enabled"; -const char kContentSettingsPluginAllowlist[] = - "profile.content_settings.plugin_whitelist"; -const char kPepperFlashSettingsEnabled[] = - "browser.pepper_flash_settings_enabled"; -const char kPluginsAllowOutdated[] = "plugins.allow_outdated"; -const char kPluginsLastInternalDirectory[] = "plugins.last_internal_directory"; -const char kPluginsPluginsList[] = "plugins.plugins_list"; -const char kPluginsShowDetails[] = "plugins.show_details"; - -// Deprecated 02/2023. -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) -const char kWebAppsUrlHandlerInfo[] = "web_apps.url_handler_info"; -#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) - -// Deprecated 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) -const char kHasSeenSmartLockSignInRemovedNotification[] = - "easy_unlock.has_seen_smart_lock_sign_in_removed_notification"; -const char kEasyUnlockLocalStateTpmKeys[] = "easy_unlock.public_tpm_keys"; -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - // Deprecated 03/2023. const char kGoogleSearchDomainMixingMetricsEmitterLastMetricsTime[] = "browser.last_google_search_domain_mixing_metrics_time"; @@ -1013,16 +981,6 @@ // Register local state used only for migration (clearing or moving to a new // key). void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) { -// Deprecated 02/2023. -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) - registry->RegisterDictionaryPref(kWebAppsUrlHandlerInfo); -#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) - -// Deprecated 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) - registry->RegisterDictionaryPref(kEasyUnlockLocalStateTpmKeys); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - // Deprecated 03/2023. #if BUILDFLAG(IS_CHROMEOS_ASH) registry->RegisterTimeDeltaPref(kGlanceablesSignoutScreenshotDuration, @@ -1140,31 +1098,6 @@ user_prefs::PrefRegistrySyncable* registry) { chrome_browser_net::secure_dns::RegisterProbesSettingBackupPref(registry); -// Deprecated 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) - registry->RegisterBooleanPref(kArcTermsShownInOobe, false); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - - // Deprecated 02/2023. - registry->RegisterDictionaryPref(kSyncInvalidationVersions); - registry->RegisterDictionaryPref(kSyncInvalidationVersions2); - - // Deprecated 02/2023. - registry->RegisterBooleanPref(kClearPluginLSODataEnabled, false); - registry->RegisterDictionaryPref(kContentSettingsPluginAllowlist); - registry->RegisterBooleanPref(kPepperFlashSettingsEnabled, false); - registry->RegisterBooleanPref(kPluginsAllowOutdated, false); - registry->RegisterFilePathPref(kPluginsLastInternalDirectory, - base::FilePath()); - registry->RegisterListPref(kPluginsPluginsList); - registry->RegisterBooleanPref(kPluginsShowDetails, false); - -// Deprecated 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) - registry->RegisterBooleanPref(kHasSeenSmartLockSignInRemovedNotification, - false); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - // Deprecated 03/2023. registry->RegisterTimePref( kGoogleSearchDomainMixingMetricsEmitterLastMetricsTime, base::Time()); @@ -2198,16 +2131,6 @@ // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS // Please don't delete the preceding line. It is used by PRESUBMIT.py. -// Added 02/2023. -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) - local_state->ClearPref(kWebAppsUrlHandlerInfo); -#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) - -// Added 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) - local_state->ClearPref(kEasyUnlockLocalStateTpmKeys); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - // Added 03/2023. #if BUILDFLAG(IS_CHROMEOS_ASH) local_state->ClearPref(kGlanceablesSignoutScreenshotDuration); @@ -2364,29 +2287,6 @@ } } -// Added 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) - profile_prefs->ClearPref(kArcTermsShownInOobe); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - - // Added 02/2023. - profile_prefs->ClearPref(kSyncInvalidationVersions); - profile_prefs->ClearPref(kSyncInvalidationVersions2); - - // Added 02/2023. - profile_prefs->ClearPref(kClearPluginLSODataEnabled); - profile_prefs->ClearPref(kContentSettingsPluginAllowlist); - profile_prefs->ClearPref(kPepperFlashSettingsEnabled); - profile_prefs->ClearPref(kPluginsAllowOutdated); - profile_prefs->ClearPref(kPluginsLastInternalDirectory); - profile_prefs->ClearPref(kPluginsPluginsList); - profile_prefs->ClearPref(kPluginsShowDetails); - -// Added 02/2023. -#if BUILDFLAG(IS_CHROMEOS_ASH) - profile_prefs->ClearPref(kHasSeenSmartLockSignInRemovedNotification); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - // Added 03/2023. #if BUILDFLAG(IS_CHROMEOS_ASH) ash::ambient::prefs::MigrateDeprecatedPrefs(*profile_prefs);
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index 7f0f101..4dd3da39 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -294,6 +294,7 @@ #include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/browser/ash/file_manager/cloud_upload_prefs_watcher.h" #include "chrome/browser/ash/input_method/editor_mediator_factory.h" +#include "chrome/browser/ash/language_packs/language_pack_font_service_factory.h" #include "chrome/browser/ash/policy/dlp/files_policy_notification_manager_factory.h" #include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h" #include "chrome/browser/push_notification/push_notification_service_factory.h" @@ -602,6 +603,9 @@ if (chromeos::features::IsOrcaEnabled()) { ash::input_method::EditorMediatorFactory::GetInstance(); } + if (base::FeatureList::IsEnabled(ash::features::kLanguagePacksFonts)) { + ash::language_packs::LanguagePackFontServiceFactory::GetInstance(); + } #endif AutocompleteClassifierFactory::GetInstance(); AutocompleteControllerEmitter::EnsureFactoryBuilt();
diff --git a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc index 687307e2..85002bc 100644 --- a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc +++ b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc
@@ -83,6 +83,8 @@ return out << "kOsIntegrationForceUnregistration"; case ProfileKeepAliveOrigin::kRemoteDebugging: return out << "kRemoteDebugging"; + case ProfileKeepAliveOrigin::kHeadlessCommand: + return out << "kHeadlessCommand"; } NOTREACHED(); return out << static_cast<int>(origin);
diff --git a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h index c3f4739..25c496f 100644 --- a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h +++ b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h
@@ -165,9 +165,13 @@ // closed. kRemoteDebugging = 38, - kMaxValue = kRemoteDebugging, + // Used by Headless Command Processor to retain the profile used by the + // command handler, which does not belong to any window. + kHeadlessCommand = 39, + + kMaxValue = kHeadlessCommand, }; -// LINT.ThenChange(/tools/metrics/histograms/enums.xml) +// LINT.ThenChange(/tools/metrics/histograms/metadata/profile/enums.xml) std::ostream& operator<<(std::ostream& out, const ProfileKeepAliveOrigin& origin);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index 94331fe..afbb4b3c 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -584,8 +584,8 @@ // frame. content::RenderFrameHost* frame; if (UseOopif()) { - GetTestPdfViewerStreamManager(web_contents) - ->WaitUntilPdfLoadedInFirstChild(); + ASSERT_TRUE(GetTestPdfViewerStreamManager(web_contents) + ->WaitUntilPdfLoadedInFirstChild()); frame = pdf_extension_test_util::GetOnlyPdfExtensionHost(web_contents); } else { auto* guest_view =
diff --git a/chrome/browser/resources/ash/settings/controls/settings_radio_group.html b/chrome/browser/resources/ash/settings/controls/settings_radio_group.html index 3003a754..3638615 100644 --- a/chrome/browser/resources/ash/settings/controls/settings_radio_group.html +++ b/chrome/browser/resources/ash/settings/controls/settings_radio_group.html
@@ -6,6 +6,7 @@ <cr-radio-group selected="[[selected]]" on-selected-changed="onSelectedChanged_" aria-label$="[[groupAriaLabel]]" - selectable-elements="[[selectableElements]]"> + selectable-elements="[[selectableElements]]" + disabled="[[disabled]]"> <slot></slot> </cr-radio-group>
diff --git a/chrome/browser/resources/ash/settings/controls/settings_radio_group.ts b/chrome/browser/resources/ash/settings/controls/settings_radio_group.ts index 3ee7bd0..ced6062b 100644 --- a/chrome/browser/resources/ash/settings/controls/settings_radio_group.ts +++ b/chrome/browser/resources/ash/settings/controls/settings_radio_group.ts
@@ -34,6 +34,11 @@ static get properties() { return { + disabled: { + type: Boolean, + value: false, + }, + groupAriaLabel: String, /** @@ -61,6 +66,7 @@ ]; } + disabled: boolean; groupAriaLabel: string; noSetPref: boolean; selected: string;
diff --git a/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.html b/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.html index 9bfbbc1..77360cc 100644 --- a/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.html +++ b/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.html
@@ -22,7 +22,8 @@ <div id="timezoneRadioContainer" class="settings-box first"> <settings-radio-group id="timeZoneRadioGroup" pref="{{prefs.generated.resolve_timezone_by_geolocation_on_off}}" - deep-link-focus-id$="[[Setting.kChangeTimeZone]]"> + deep-link-focus-id$="[[Setting.kChangeTimeZone]]" + disabled="[[isGuest_]]"> <controlled-radio-button id="timeZoneAutoDetectOn" name="true"
diff --git a/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.ts b/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.ts index f8e5497f..8196bb6 100644 --- a/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.ts +++ b/chrome/browser/resources/ash/settings/date_time_page/timezone_subpage.ts
@@ -63,6 +63,13 @@ notify: true, }, + isGuest_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('isGuest'); + }, + }, + /** * Used by DeepLinkingMixin to focus this page's deep links. */ @@ -91,6 +98,7 @@ } activeTimeZoneDisplayName: string; + private isGuest_: boolean; private browserProxy_: TimeZoneBrowserProxy; private showEnableSystemGeolocationDialog_: boolean; private shouldShowGeolocationWarningText_: boolean;
diff --git a/chrome/browser/resources/ash/settings/device_page/customize_button_row.ts b/chrome/browser/resources/ash/settings/device_page/customize_button_row.ts index f4a1cdc..0bdb84d 100644 --- a/chrome/browser/resources/ash/settings/device_page/customize_button_row.ts +++ b/chrome/browser/resources/ash/settings/device_page/customize_button_row.ts
@@ -10,8 +10,9 @@ import '../controls/settings_dropdown_menu.js'; import '../os_settings_icons.html.js'; -import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; +import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; +import {assert} from 'chrome://resources/js/assert.js'; import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -127,6 +128,11 @@ this.$.remappingActionDropdown!.focus(); } + override focus(): void { + assert(this.$.remappingActionDropdown); + this.$.remappingActionDropdown.focus(); + } + private observeButtonPresses(): void { if (this.inputDeviceSettingsProvider_ instanceof FakeInputDeviceSettingsProvider) {
diff --git a/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.html b/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.html index 66cbf4a..0256ac9 100644 --- a/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.html +++ b/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.html
@@ -28,7 +28,7 @@ width: 256px; } </style> -<div class="subsection"> +<div class="subsection" id="subsection"> <template is="dom-repeat" items="{{buttonRemappingList}}" index-as="index"> @@ -85,5 +85,6 @@ id="keyCombinationInputDialog" button-remapping-list="{{buttonRemappingList}}" remapping-index="[[selectedButtonIndex_]]" - has-launcher-button="[[hasLauncherButton]]"> + has-launcher-button="[[hasLauncherButton]]" + on-close="onKeyCombinationDialogClose_"> </key-combination-input-dialog>
diff --git a/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.ts b/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.ts index 44b8820e4..d9019ab 100644 --- a/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.ts +++ b/chrome/browser/resources/ash/settings/device_page/customize_buttons_subsection.ts
@@ -16,6 +16,7 @@ import './key_combination_input_dialog.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; +import {assert} from 'chrome://resources/js/assert.js'; import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -28,6 +29,7 @@ export interface CustomizeButtonsSubsectionElement { $: { keyCombinationInputDialog: KeyCombinationInputDialogElement, + subsection: HTMLDivElement, }; } @@ -121,10 +123,14 @@ this.addEventListener( 'show-key-combination-dialog', this.showKeyCombinationDialog_); this.dragAndDropManager.init(this, this.onDrop_.bind(this)); + this.addEventListener( + 'key-combination-dialog-close', this.onKeyCombinationDialogClose_); } override disconnectedCallback(): void { this.dragAndDropManager.destroy(); + this.removeEventListener( + 'key-combination-dialog-close', this.onKeyCombinationDialogClose_); } private showRenamingDialog_(e: ShowRenamingDialogEvent): void { @@ -243,6 +249,14 @@ composed: true, })); }; + + private onKeyCombinationDialogClose_(): void { + const buttonRows = + this.$.subsection.querySelectorAll('customize-button-row'); + + assert(!!buttonRows && buttonRows.length > this.selectedButtonIndex_); + buttonRows[this.selectedButtonIndex_].focus(); + } } declare global {
diff --git a/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.html b/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.html index b383aa15..ecf4f0eea 100644 --- a/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.html +++ b/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.html
@@ -25,7 +25,7 @@ label="$i18n{appNotificationsTitle}" on-click="onClickAppNotifications_" role-description="$i18n{subpageArrowRoleDescription}" - sub-label="[[getAppListCountDescription_( + sub-label="[[getAppNotificationsRowSublabel_( appsWithNotifications_.*, isDndEnabled_)]]"> </cr-link-row> </template>
diff --git a/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.ts b/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.ts index 9c0e2a7..e3e299c4 100644 --- a/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.ts +++ b/chrome/browser/resources/ash/settings/os_apps_page/os_apps_page.ts
@@ -370,9 +370,13 @@ this.isDndEnabled_ = enabled; } - private getAppListCountDescription_(): string { + private getAppNotificationsRowSublabel_(): string { + if (this.isRevampWayfindingEnabled_) { + return this.i18n('appNotificationsRowSublabel'); + } + return this.isDndEnabled_ ? - this.i18n('appNotificationsDoNotDisturbDescription') : + this.i18n('appNotificationsDoNotDisturbEnabledDescription') : this.i18n( 'appNotificationsCountDescription', this.appsWithNotifications_.length);
diff --git a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js index 0330b11..369b70a 100644 --- a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js +++ b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
@@ -46,7 +46,9 @@ 'HTML[A-Za-z]{0,}Element|' + // Exclude native DOM interfaces. 'UIEvent|UIEventInit|DOMError|' + - // Exclude the SACache and SACommands classes. + // Exclude ISearchUI. + 'ISearchUI|' + + // Exclude the SA* classes. 'SACache|SACommands|SAChildNode|SANode|SARootNode)$', match: false, },
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index e7335d6..f82b219 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -54,6 +54,7 @@ "background/logging/log_manager.ts", "common/msgs.ts", "common/tts_types.ts", + "panel/i_search_ui.ts", "panel/panel.ts", "panel/panel_captions.ts", "panel/panel_menu_item.ts", @@ -166,7 +167,6 @@ "learn_mode/learn_mode.js", "log_page/log.js", "log_page/log_loader.js", - "panel/i_search_ui.js", "panel/menu_manager.js", "panel/panel_interface.js", "panel/panel_menu.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.ts similarity index 71% rename from chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.js rename to chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.ts index 0f9e987..8a5c109 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.ts
@@ -14,10 +14,16 @@ const Dir = constants.Dir; export class ISearchUI { - /** @param {!Element} input */ - constructor(input) { + static instance?: ISearchUI; + + onKeyDown: (event: KeyboardEvent) => boolean; + onTextInput: (event: Event) => boolean; + + private input_: HTMLInputElement | null; + private dir_ = Dir.FORWARD; + + constructor(input: HTMLInputElement) { this.input_ = input; - this.dir_ = Dir.FORWARD; this.onKeyDown = event => this.onKeyDown_(event); this.onTextInput = event => this.onTextInput_(event); @@ -26,11 +32,7 @@ input.addEventListener('textInput', this.onTextInput, false); } - /** - * @param {!Element} input - * @return {!Promise<ISearchUI>} - */ - static async init(input) { + static async init(input: HTMLInputElement): Promise<ISearchUI> { if (ISearchUI.instance) { ISearchUI.instance.destroy(); } @@ -42,13 +44,7 @@ return ISearchUI.instance; } - /** - * Listens to key down events. - * @param {Event} evt - * @return {boolean} - * @private - */ - onKeyDown_(evt) { + private onKeyDown_(evt: KeyboardEvent): boolean { switch (evt.key) { case 'ArrowUp': this.dir_ = Dir.BACKWARD; @@ -68,34 +64,27 @@ default: return false; } + // TODO(b/314203187): Not null asserted, check that this is correct. BackgroundBridge.PanelBackground.incrementalSearch( - this.input_.value, this.dir_, true); + this.input_!.value, this.dir_, true); evt.preventDefault(); evt.stopPropagation(); return false; } - /** - * Listens to text input events. - * @param {Event} evt - * @return {boolean} - * @private - */ - onTextInput_(evt) { - const searchStr = evt.target.value + evt.data; + private onTextInput_(evt: Event): boolean { + const searchStr = + (evt.target as HTMLInputElement).value + (evt as InputEvent).data; BackgroundBridge.PanelBackground.incrementalSearch(searchStr, this.dir_); return true; } /** Unregisters event handlers. */ - destroy() { + destroy(): void { BackgroundBridge.PanelBackground.destroyISearch(); const input = this.input_; this.input_ = null; - input.removeEventListener('keydown', this.onKeyDown, true); - input.removeEventListener('textInput', this.onTextInput, false); + input?.removeEventListener('keydown', this.onKeyDown, true); + input?.removeEventListener('textInput', this.onTextInput, false); } -} - -/** @type {ISearchUI} */ -ISearchUI.instance; +} \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.ts b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.ts index 9576f43..18a6f469d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.ts +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.ts
@@ -43,7 +43,7 @@ private brailleTableElement_ = $('braille-table') as HTMLTableElement; private brailleTableElement2_ = $('braille-table2') as HTMLTableElement; private searchContainer_ = $('search-container'); - private searchInput_: HTMLElement = $('search')!; + private searchInput_ = $('search') as HTMLInputElement; private speechContainer_ = $('speech-container'); private speechElement_ = $('speech'); private tutorialReadyForTesting_ = false;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn index b72f7f0..cc7ac5e 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
@@ -41,6 +41,7 @@ "nodes/switch_access_node.ts", "point_scan_manager.ts", "settings_manager.ts", + "switch_access.ts", "switch_access_constants.ts", "switch_access_loader.ts", ] @@ -61,7 +62,6 @@ "nodes/slider_node.js", "nodes/tab_node.js", "nodes/window_node.js", - "switch_access.js", "switch_access_predicate.js", "text_navigation_manager.js", ]
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.ts similarity index 65% rename from chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js rename to chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.ts index 33b8ac58..2f8d7a0 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.ts
@@ -2,21 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {AsyncUtil} from '../common/async_util.js'; -import {EventHandler} from '../common/event_handler.js'; -import {FlagName, Flags} from '../common/flags.js'; +import {AsyncUtil} from '/common/async_util.js'; +import {EventHandler} from '/common/event_handler.js'; +import {FlagName, Flags} from '/common/flags.js'; import {Navigator} from './navigator.js'; import {KeyboardRootNode} from './nodes/keyboard_node.js'; import {ErrorType, Mode} from './switch_access_constants.js'; -const AutomationNode = chrome.automation.AutomationNode; +type AutomationEvent = chrome.automation.AutomationEvent; +type AutomationNode = chrome.automation.AutomationNode; const EventType = chrome.automation.EventType; -const FindParams = chrome.automation.FindParams; +type FindParams = chrome.automation.FindParams; const RoleType = chrome.automation.RoleType; -let readyCallback; -const readyPromise = new Promise(resolve => readyCallback = resolve); +let readyCallback: VoidFunction; +const readyPromise: Promise<void> = + new Promise(resolve => readyCallback = resolve); /** * The top-level class for the Switch Access accessibility feature. Handles @@ -24,14 +26,11 @@ * codebase. */ export class SwitchAccess { - /** @private */ - constructor() { - /* @private {!Mode} */ - this.mode_ = Mode.ITEM_SCAN; - } + static instance?: SwitchAccess; + static mode = Mode.ITEM_SCAN; + private constructor() {} - /** @param {!AutomationNode} desktop */ - static async init(desktop) { + static async init(desktop: AutomationNode): Promise<void> { if (SwitchAccess.instance) { throw new Error('Cannot create two SwitchAccess.instances'); } @@ -42,43 +41,32 @@ } /** Starts Switch Access behavior. */ - static start() { + static start(): void { KeyboardRootNode.startWatchingVisibility(); readyCallback(); } - /** @return {!Promise} */ - static async ready() { + static async ready(): Promise<void> { return readyPromise; } /** * Returns whether or not the feature flag * for improved text input is enabled. - * @return {boolean} */ - static improvedTextInputEnabled() { - return Flags.isEnabled(FlagName.SWITCH_ACCESS_TEXT); - } - - /** @return {!Mode} */ - static get mode() { - return SwitchAccess.instance.mode_; - } - - /** @param {!Mode} newMode */ - static set mode(newMode) { - SwitchAccess.instance.mode_ = newMode; + static improvedTextInputEnabled(): boolean { + // TODO(b/314203187): Not null asserted, check that this is correct. + return Flags.isEnabled(FlagName.SWITCH_ACCESS_TEXT)!; } /** * Helper function to robustly find a node fitting a given FindParams, even if * that node has not yet been created. * Used to find the menu and back button. - * @param {!FindParams} findParams - * @param {!function(!AutomationNode): void} foundCallback */ - static findNodeMatching(findParams, foundCallback) { + static findNodeMatching( + findParams: FindParams, + foundCallback: (node: AutomationNode) => void): void { const desktop = Navigator.byItem.desktopNode; // First, check if the node is currently in the tree. let node = desktop.find(findParams); @@ -89,9 +77,9 @@ // If it's not currently in the tree, listen for changes to the desktop // tree. const eventHandler = new EventHandler( - desktop, EventType.CHILDREN_CHANGED, null /** callback */); + desktop, EventType.CHILDREN_CHANGED, (_evt: AutomationEvent) => {}); - const onEvent = event => { + const onEvent = (event: AutomationEvent): void => { if (event.target.matches(findParams)) { // If the event target is the node we're looking for, we've found it. eventHandler.stop(); @@ -110,30 +98,23 @@ eventHandler.start(); } - /** - * Creates and records the specified error. - * @param {ErrorType} errorType - * @param {string} errorString - * @param {boolean} shouldRecover - * @return {!Error} - */ - static error(errorType, errorString, shouldRecover = false) { + /** Creates and records the specified error. */ + static error( + errorType: ErrorType, errorString: string, + shouldRecover = false): Error { if (shouldRecover) { setTimeout(Navigator.byItem.moveToValidNode.bind(Navigator.byItem), 0); } const errorTypeCountForUMA = Object.keys(ErrorType).length; chrome.metricsPrivate.recordEnumerationValue( - 'Accessibility.CrosSwitchAccess.Error', - /** @type {number} */ (errorType), errorTypeCountForUMA); + 'Accessibility.CrosSwitchAccess.Error', errorType, + errorTypeCountForUMA); return new Error(errorString); } - /** - * @param {!AutomationNode} desktop - * @param {AutomationNode} currentFocus - * @private - */ - async waitForFocus_(desktop, currentFocus) { + private async waitForFocus_( + desktop: AutomationNode, + currentFocus: AutomationNode | undefined): Promise<void> { return new Promise(resolve => { // Focus is available. Finish init without waiting for further events. // Disallow web view nodes, which indicate a root web area is still @@ -147,7 +128,7 @@ // guaranteed. Otherwise, also set a timed callback to ensure we do // eventually init. let callbackId = 0; - const listener = maybeEvent => { + const listener = (maybeEvent: AutomationEvent | undefined): void => { if (maybeEvent && maybeEvent.target.role === RoleType.WEB_VIEW) { return; } @@ -162,7 +143,4 @@ callbackId = setTimeout(listener, 5000); }); } -} - -/** @type {SwitchAccess} */ -SwitchAccess.instance; +} \ No newline at end of file
diff --git a/chrome/browser/resources/settings/privacy_page/cookies_page.html b/chrome/browser/resources/settings/privacy_page/cookies_page.html index 6cfc37b8..abd8a53 100644 --- a/chrome/browser/resources/settings/privacy_page/cookies_page.html +++ b/chrome/browser/resources/settings/privacy_page/cookies_page.html
@@ -204,7 +204,7 @@ </settings-radio-group> </div> </template> - <template is="dom-if" if="[[is3pcdRedesignEnabled_]"> + <template is="dom-if" if="[[is3pcdRedesignEnabled_]]"> <div id="explanationText" class="secondary"> $i18n{trackingProtectionPageDescription} </div> @@ -230,7 +230,7 @@ </div> </div> </template> - <template is="dom-if" if="[[isCookiesUiV2_]"> + <template is="dom-if" if="[[isCookiesUiV2_]]"> <h2 id="advancedHeader">$i18n{trackingProtectionAdvancedLabel}</h2> <settings-toggle-button id="blockThirdPartyToggle"
diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index 0c42a45..7713cce 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc
@@ -1459,7 +1459,18 @@ } #if BUILDFLAG(IS_CHROMEOS) -TEST_F(SessionServiceTest, OpenedWindowNotRestoredInKiosk) { +class SessionServiceKioskTest : public SessionServiceTest { + public: + void LogIn(const std::string& email) override { + chromeos::SetUpFakeKioskSession(email); +#if BUILDFLAG(IS_CHROMEOS_ASH) + ash_test_helper()->test_session_controller_client()->AddUserSession( + email, user_manager::UserType::kKioskApp); +#endif + } +}; + +TEST_F(SessionServiceTest, OpenedWindowNotRestored) { // These preparation is necessary for `ShouldRestore` function to return true // in the regular user session. helper_.SetHasOpenTrackableBrowsers(false); @@ -1467,8 +1478,13 @@ service()->WindowClosed(window_id); // Make sure `ShouldRestore` returns true for the regular user session. EXPECT_TRUE(session_service_->ShouldRestore(browser())); +} - chromeos::SetUpFakeKioskSession(); +TEST_F(SessionServiceKioskTest, OpenedWindowNotRestored) { + helper_.SetHasOpenTrackableBrowsers(false); + service()->WindowClosing(window_id); + service()->WindowClosed(window_id); + // Make sure `ShouldRestore` returns true for the kiosk user session. EXPECT_FALSE(session_service_->ShouldRestore(browser())); } #endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc index 15fb707..6a0dc14 100644 --- a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc +++ b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
@@ -397,7 +397,8 @@ ASSERT_TRUE(subframe_main_host); content::RenderFrameHost* embedder_host = ChildFrameAt(subframe_main_host, 0); ASSERT_TRUE(embedder_host); - GetTestPdfViewerStreamManager()->WaitUntilPdfLoaded(embedder_host); + ASSERT_TRUE( + GetTestPdfViewerStreamManager()->WaitUntilPdfLoaded(embedder_host)); // The primary main frame shouldn't be the PDF embedder and shouldn't have a // PDF stream.
diff --git a/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc b/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc index 6887b98b..6a439028 100644 --- a/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc +++ b/chrome/browser/site_isolation/site_per_process_interactive_browsertest.cc
@@ -1521,7 +1521,8 @@ void WaitUntilPdfLoaded(content::RenderFrameHost* embedder_host) { if (UseOopif()) { - GetTestPdfViewerStreamManager()->WaitUntilPdfLoaded(embedder_host); + ASSERT_TRUE( + GetTestPdfViewerStreamManager()->WaitUntilPdfLoaded(embedder_host)); } else { auto* guest_view = GetTestGuestViewManager()->WaitForSingleGuestViewCreated();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 82003ffa..6436e06f 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2990,6 +2990,8 @@ "views/select_file_dialog_extension.h", "views/select_file_dialog_extension_factory.cc", "views/select_file_dialog_extension_factory.h", + "webui/app_management/app_management_page_handler_chromeos.cc", + "webui/app_management/app_management_page_handler_chromeos.h", "webui/app_management/app_management_shelf_delegate_chromeos.cc", "webui/app_management/app_management_shelf_delegate_chromeos.h", "webui/ash/account_manager/account_manager_error_ui.cc", @@ -4168,6 +4170,8 @@ "webui/app_home/app_home_page_handler.h", "webui/app_home/app_home_ui.cc", "webui/app_home/app_home_ui.h", + "webui/app_management/web_app_settings_page_handler.cc", + "webui/app_management/web_app_settings_page_handler.h", "webui/app_settings/web_app_settings_navigation_throttle.cc", "webui/app_settings/web_app_settings_navigation_throttle.h", "webui/app_settings/web_app_settings_ui.cc",
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java index 6214abbb..28792e9 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java
@@ -28,7 +28,8 @@ "use_toolbar_bg_color_for_strip_transition_scrim"; /** - * Whether the toolbar bg color will be used as the scrim overlay during a tab strip transition. + * Whether the toolbar bg color will be used as the scrim overlay on the tab strip / status bar + * during a tab strip transition. */ public static final BooleanCachedFieldTrialParameter USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM = @@ -58,4 +59,12 @@ public static boolean shouldRecordSuppressionMetrics() { return ChromeFeatureList.sRecordSuppressionMetrics.isEnabled(); } + + /** + * @return Whether the toolbar bg color will be used as the scrim overlay on the tab strip and + * status bar during a tab strip transition. + */ + public static boolean shouldUseToolbarBgColorForStripTransitionScrim() { + return USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM.getValue(); + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java index 6d36a61..fc6d875 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
@@ -533,6 +533,13 @@ mLocationBar.getTabletCoordinator().tintBackground(textBoxColor); mLocationBar.updateVisualsForState(); setToolbarHairlineColor(color); + + // Notify the StatusBarColorController of the toolbar color change. This is to match the + // status bar's color with the toolbar color when the tab strip is hidden on a tablet when + // DYNAMIC_TOP_CHROME is enabled. + if (ToolbarFeatures.shouldUseToolbarBgColorForStripTransitionScrim()) { + notifyToolbarColorChanged(color); + } } /** Called when the currently visible New Tab Page changes. */
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java index e1fd15a..11059ea41 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java
@@ -16,6 +16,7 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.app.Activity; +import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Looper; import android.view.View; @@ -55,10 +56,12 @@ import org.chromium.chrome.browser.toolbar.ButtonData.ButtonSpec; import org.chromium.chrome.browser.toolbar.ButtonDataImpl; import org.chromium.chrome.browser.toolbar.R; +import org.chromium.chrome.browser.toolbar.ToolbarFeatures; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant; import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator; import org.chromium.chrome.browser.toolbar.top.CaptureReadinessResult.TopToolbarAllowCaptureReason; import org.chromium.chrome.browser.toolbar.top.CaptureReadinessResult.TopToolbarBlockCaptureReason; +import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator.ToolbarColorObserver; import org.chromium.ui.widget.ToastManager; import java.util.ArrayList; @@ -74,6 +77,7 @@ @Mock private StatusCoordinator mStatusCoordinator; @Mock private MenuButtonCoordinator mMenuButtonCoordinator; @Mock private TabStripTransitionCoordinator mTabStripTransitionCoordinator; + @Mock private ToolbarColorObserver mToolbarColorObserver; private Activity mActivity; private ToolbarTablet mToolbarTablet; private LinearLayout mToolbarTabletLayout; @@ -102,6 +106,7 @@ locationBarLayout.setStatusCoordinatorForTesting(mStatusCoordinator); mToolbarTablet.setMenuButtonCoordinatorForTesting(mMenuButtonCoordinator); mToolbarTablet.setTabStripTransitionCoordinator(mTabStripTransitionCoordinator); + mToolbarTablet.setToolbarColorObserver(mToolbarColorObserver); mToolbarTabletLayout = (LinearLayout) mToolbarTablet.findViewById(R.id.toolbar_tablet_layout); mHomeButton = mToolbarTablet.findViewById(R.id.home_button); @@ -588,6 +593,16 @@ Assert.assertEquals("Long press callback not triggered.", 1, callback.getCallCount()); } + @Test + public void testThemeColorChange() { + ToolbarFeatures.USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM.setForTesting(true); + int color = Color.BLACK; + mToolbarTablet.onThemeColorChanged(color, false); + // Verify that ToolbarColorObserver is notified of the color change. + verify(mToolbarColorObserver).onToolbarColorChanged(color); + ToolbarFeatures.USE_TOOLBAR_BG_COLOR_FOR_STRIP_TRANSITION_SCRIM.setForTesting(false); + } + private void longClickAndVerifyToast(int viewId, int stringId) { mToolbarTablet.onLongClick(mToolbarTablet.findViewById(viewId)); assertTrue(
diff --git a/chrome/browser/ui/ash/calendar/calendar_keyed_service_unittest.cc b/chrome/browser/ui/ash/calendar/calendar_keyed_service_unittest.cc index bdbf178f..dd97bf15 100644 --- a/chrome/browser/ui/ash/calendar/calendar_keyed_service_unittest.cc +++ b/chrome/browser/ui/ash/calendar/calendar_keyed_service_unittest.cc
@@ -11,13 +11,12 @@ #include "ash/shell.h" #include "base/test/bind.h" #include "base/time/time.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/account_id/account_id.h" #include "components/sync_preferences/pref_service_syncable.h" -#include "components/user_manager/scoped_user_manager.h" #include "google_apis/common/api_error_codes.h" #include "google_apis/common/dummy_auth_service.h" #include "google_apis/common/test_util.h" @@ -45,41 +44,22 @@ delete; ~CalendarKeyedServiceTest() override = default; + void SetUp() override { + ProfileHelper::SetProfileToUserForTestingEnabled(true); + BrowserWithTestWindowTest::SetUp(); + } + + void TearDown() override { + BrowserWithTestWindowTest::TearDown(); + ProfileHelper::SetProfileToUserForTestingEnabled(false); + } + std::string GetDefaultProfileName() override { return kPrimaryProfileName; } - void LogIn(const std::string& email) override { - const AccountId account_id = AccountId::FromUserEmail(email); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - GetSessionControllerClient()->AddUserSession(email); - GetSessionControllerClient()->SwitchActiveUser(account_id); - } - TestingProfile* CreateSecondaryProfile() { - const AccountId account_id(AccountId::FromUserEmail(kSecondaryProfileName)); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - return profile_manager()->CreateTestingProfile( - kSecondaryProfileName, - std::unique_ptr<sync_preferences::PrefServiceSyncable>(), - u"Test profile", - /*avatar_id=*/1, - /*testing_factories=*/{}); + LogIn(kSecondaryProfileName); + return CreateProfile(kSecondaryProfileName); } - - void ActivateSecondaryProfile() { - const AccountId account_id(AccountId::FromUserEmail(kSecondaryProfileName)); - GetSessionControllerClient()->AddUserSession(kSecondaryProfileName); - GetSessionControllerClient()->SwitchActiveUser(account_id); - } - - TestSessionControllerClient* GetSessionControllerClient() { - return ash_test_helper()->test_session_controller_client(); - } - - private: - user_manager::TypedScopedUserManager<FakeChromeUserManager> - fake_user_manager_{std::make_unique<FakeChromeUserManager>()}; }; class CalendarKeyedServiceIOTest : public testing::Test { @@ -197,7 +177,7 @@ // Switching the active user should change the active client (multi-user // support). - ActivateSecondaryProfile(); + SwitchActiveUser(kSecondaryProfileName); EXPECT_EQ(ash::Shell::Get()->calendar_controller()->GetClient(), secondary_calendar_service->client()); }
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index c689a35a..adb1075 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -367,7 +367,8 @@ ash::switches::kForceRefreshRateThrottle); if (auto* picker_controller = ash::Shell::Get()->picker_controller()) { - picker_client_ = std::make_unique<PickerClientImpl>(picker_controller); + picker_client_ = std::make_unique<PickerClientImpl>( + picker_controller, user_manager::UserManager::Get()); } oobe_dialog_util_ = std::make_unique<ash::OobeDialogUtilImpl>();
diff --git a/chrome/browser/ui/ash/clipboard_history_url_title_fetcher_impl_unittest.cc b/chrome/browser/ui/ash/clipboard_history_url_title_fetcher_impl_unittest.cc index dd2886e..22f34e5 100644 --- a/chrome/browser/ui/ash/clipboard_history_url_title_fetcher_impl_unittest.cc +++ b/chrome/browser/ui/ash/clipboard_history_url_title_fetcher_impl_unittest.cc
@@ -12,12 +12,11 @@ #include "base/task/cancelable_task_tracker.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/test_future.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/history/core/browser/history_service.h" -#include "components/user_manager/scoped_user_manager.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -81,24 +80,15 @@ class ClipboardHistoryUrlTitleFetcherTest : public BrowserWithTestWindowTest { public: - ClipboardHistoryUrlTitleFetcherTest() { - auto fake_user_manager = std::make_unique<FakeChromeUserManager>(); - fake_user_manager_ = fake_user_manager.get(); - user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( - std::move(fake_user_manager)); - } + ClipboardHistoryUrlTitleFetcherTest() = default; protected: void CreateAndSwitchToSecondaryProfile() { const std::string kSecondaryProfileName = "secondary_profile@test"; - const AccountId account_id(AccountId::FromUserEmail(kSecondaryProfileName)); - - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - fake_user_manager_->SwitchActiveUser(account_id); - - profile_manager()->CreateTestingProfile(kSecondaryProfileName, - GetTestingFactories()); + LogIn(kSecondaryProfileName); + CreateProfile(kSecondaryProfileName); + user_manager()->SwitchActiveUser( + AccountId::FromUserEmail(kSecondaryProfileName)); } ClipboardHistoryUrlTitleFetcherImpl& fetcher() { return fetcher_; } @@ -106,11 +96,17 @@ private: // BrowserWithTestWindowTest: + void SetUp() override { + ash::ProfileHelper::SetProfileToUserForTestingEnabled(true); + BrowserWithTestWindowTest::SetUp(); + } + void TearDown() override { // Reset `history_service_` so that it does not dangle after the keyed // service is destroyed during `BrowserWithTestWindowTest::TearDown()`. history_service_ = nullptr; BrowserWithTestWindowTest::TearDown(); + ash::ProfileHelper::SetProfileToUserForTestingEnabled(false); } TestingProfile::TestingFactories GetTestingFactories() override { @@ -120,13 +116,6 @@ base::Unretained(this))}}; } - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindowTest. - const AccountId account_id = AccountId::FromUserEmail(email); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - } - std::unique_ptr<KeyedService> BuildHistoryService( content::BrowserContext* context) { auto history_service = @@ -136,9 +125,6 @@ } ClipboardHistoryUrlTitleFetcherImpl fetcher_; - std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_; - // Owned by, and therefore must be cleaned up before, `user_manager_enabler_`. - raw_ptr<FakeChromeUserManager> fake_user_manager_ = nullptr; // Owned by `KeyedServiceFactory`. Must be cleaned up before `TearDown()`. raw_ptr<MockHistoryService> history_service_ = nullptr; };
diff --git a/chrome/browser/ui/ash/faster_split_screen_browsertest.cc b/chrome/browser/ui/ash/faster_split_screen_browsertest.cc index 1349ec4d..b3b2837 100644 --- a/chrome/browser/ui/ash/faster_split_screen_browsertest.cc +++ b/chrome/browser/ui/ash/faster_split_screen_browsertest.cc
@@ -8,6 +8,7 @@ #include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_test_util.h" +#include "ash/wm/splitview/faster_split_view.h" #include "ash/wm/window_state.h" #include "ash/wm/wm_event.h" #include "base/test/scoped_feature_list.h" @@ -78,11 +79,9 @@ ash::OverviewController::Get()->overview_session()->GetGridWithRootWindow( window->GetRootWindow()); ASSERT_TRUE(overview_grid); - auto* faster_splitview_widget = - overview_grid->faster_splitview_widget_for_testing(); - ASSERT_TRUE(faster_splitview_widget); - auto* settings_button = views::AsViewClass<ash::IconButton>( - faster_splitview_widget->GetContentsView()->children()[1]); + auto* faster_split_view = overview_grid->GetFasterSplitView(); + ASSERT_TRUE(faster_split_view); + auto* settings_button = faster_split_view->settings_button(); ASSERT_TRUE(settings_button); // Setup navigation observer to wait for the OS Settings page.
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc index d362e8c..0337308 100644 --- a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc +++ b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc
@@ -9,52 +9,26 @@ #include "ash/constants/ash_features.h" #include "base/test/scoped_feature_list.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" -#include "components/user_manager/scoped_user_manager.h" -#include "components/user_manager/user_manager.h" #include "testing/gtest/include/gtest/gtest.h" namespace ash { class GlanceablesKeyedServiceFactoryTest : public BrowserWithTestWindowTest { public: - GlanceablesKeyedServiceFactoryTest() - : scoped_user_manager_(std::make_unique<FakeChromeUserManager>()) {} - - void LogIn(const std::string& email) override { - const auto account_id = AccountId::FromUserEmail(email); - fake_chrome_user_manager()->AddUser(account_id); - fake_chrome_user_manager()->LoginUser(account_id); - session_controller_client()->AddUserSession(email); - session_controller_client()->SwitchActiveUser(account_id); - } - TestingProfile* CreateProfile(const std::string& profile_name) override { - return profile_manager()->CreateTestingProfile(profile_name, - /*is_main_profile=*/true); - } - - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. - FakeChromeUserManager* fake_chrome_user_manager() { - return static_cast<FakeChromeUserManager*>( - user_manager::UserManager::Get()); - } - - TestSessionControllerClient* session_controller_client() { - return ash_test_helper()->test_session_controller_client(); - } - - TestingProfileManager* profile_manager() { - return BrowserWithTestWindowTest::profile_manager(); + auto* profile = + profile_manager()->CreateTestingProfile(profile_name, + /*is_main_profile=*/true); + OnUserProfileCreated(profile_name, profile); + return profile; } protected: base::test::ScopedFeatureList feature_list_{features::kGlanceablesV2}; - user_manager::ScopedUserManager scoped_user_manager_; }; TEST_F(GlanceablesKeyedServiceFactoryTest, NoSupportWhenFeatureIsDisabled) {
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_unittest.cc b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_unittest.cc index 6617579bf..9dc0f85f4 100644 --- a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_unittest.cc +++ b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_unittest.cc
@@ -34,36 +34,21 @@ class GlanceablesKeyedServiceTest : public BrowserWithTestWindowTest { public: - GlanceablesKeyedServiceTest() - : scoped_user_manager_(std::make_unique<FakeChromeUserManager>()) {} - // BrowserWithTestWindowTest: std::string GetDefaultProfileName() override { return kPrimaryProfileName; } - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. - const auto account_id = AccountId::FromUserEmail(email); - fake_chrome_user_manager()->AddUser(account_id); - fake_chrome_user_manager()->LoginUser(account_id); - session_controller_client()->AddUserSession(email); - session_controller_client()->SwitchActiveUser(account_id); - } - TestingProfile* CreateProfile(const std::string& profile_name) override { auto prefs = std::make_unique<sync_preferences::TestingPrefServiceSyncable>(); RegisterUserProfilePrefs(prefs->registry()); profile_prefs_ = prefs.get(); - return profile_manager()->CreateTestingProfile( + auto* profile = profile_manager()->CreateTestingProfile( profile_name, std::move(prefs), u"Test profile", /*avatar_id=*/0, TestingProfile::TestingFactories(), /*is_supervised_profile=*/false, /*is_new_profile=*/std::nullopt, /*policy_service=*/std::nullopt, /*is_main_profile=*/true); - } - - FakeChromeUserManager* fake_chrome_user_manager() { - return static_cast<FakeChromeUserManager*>( - user_manager::UserManager::Get()); + OnUserProfileCreated(profile_name, profile); + return profile; } TestSessionControllerClient* session_controller_client() { @@ -76,7 +61,6 @@ // the profile. raw_ptr<sync_preferences::TestingPrefServiceSyncable, DanglingUntriaged> profile_prefs_ = nullptr; - user_manager::ScopedUserManager scoped_user_manager_; }; TEST_F(GlanceablesKeyedServiceTest, RegistersClientsInAsh) { @@ -104,15 +88,15 @@ const auto first_account_id = AccountId::FromUserEmail(kPrimaryProfileName); const auto second_account_id = AccountId::FromUserEmail(kSecondaryProfileName); - fake_chrome_user_manager()->AddUser(second_account_id); - fake_chrome_user_manager()->LoginUser(second_account_id); + LogIn(kSecondaryProfileName); auto* secondary_profile = profile_manager()->CreateTestingProfile(kSecondaryProfileName, /*is_main_profile=*/false); - session_controller_client()->AddUserSession(kSecondaryProfileName); + OnUserProfileCreated(kSecondaryProfileName, secondary_profile); + + SwitchActiveUser(kSecondaryProfileName); auto service_secondary = std::make_unique<GlanceablesKeyedService>(secondary_profile); - session_controller_client()->SwitchActiveUser(second_account_id); auto* const classroom_client_secondary = controller->GetClassroomClient(); auto* const tasks_client_secondary = controller->GetTasksClient(); @@ -121,7 +105,7 @@ EXPECT_NE(classroom_client_primary, classroom_client_secondary); EXPECT_NE(tasks_client_primary, tasks_client_secondary); - session_controller_client()->SwitchActiveUser(first_account_id); + SwitchActiveUser(kPrimaryProfileName); EXPECT_EQ(classroom_client_primary, controller->GetClassroomClient()); EXPECT_EQ(tasks_client_primary, controller->GetTasksClient()); }
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc index 211c5424..cc347ac 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/components/arc/session/arc_service_manager.h" #include "ash/constants/ash_features.h" +#include "ash/constants/ash_switches.h" #include "ash/public/cpp/holding_space/holding_space_client.h" #include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_controller.h" @@ -43,7 +44,7 @@ #include "chrome/browser/ash/file_suggest/file_suggest_test_util.h" #include "chrome/browser/ash/file_suggest/file_suggest_util.h" #include "chrome/browser/ash/file_suggest/mock_file_suggest_keyed_service.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/file_system_access/chrome_file_system_access_permission_context.h" #include "chrome/browser/file_system_access/file_system_access_permission_context_factory.h" #include "chrome/browser/nearby_sharing/common/nearby_share_features.h" @@ -63,7 +64,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/sync_preferences/pref_service_mock_factory.h" #include "components/sync_preferences/pref_service_syncable.h" -#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/user_names.h" #include "components/vector_icons/vector_icons.h" #include "content/public/test/fake_download_item.h" #include "content/public/test/mock_download_manager.h" @@ -543,9 +544,7 @@ public: HoldingSpaceKeyedServiceTest() : BrowserWithTestWindowTest( - base::test::TaskEnvironment::TimeSource::MOCK_TIME), - fake_user_manager_(new FakeChromeUserManager), - user_manager_enabler_(base::WrapUnique(fake_user_manager_.get())) { + base::test::TaskEnvironment::TimeSource::MOCK_TIME) { HoldingSpaceImage::SetUseZeroInvalidationDelayForTesting(true); } @@ -559,6 +558,8 @@ // BrowserWithTestWindowTest: void SetUp() override { + ash::ProfileHelper::SetProfileToUserForTestingEnabled(true); + // The test's task environment starts with a mock time close to the Unix // epoch, but the files that back holding space items are created with // accurate timestamps. Advance the clock so that the test's mock time and @@ -582,6 +583,8 @@ void TearDown() override { BrowserWithTestWindowTest::TearDown(); disks::DiskMountManager::Shutdown(); + + ash::ProfileHelper::SetProfileToUserForTestingEnabled(false); } TestingProfile::TestingFactories GetTestingFactories() override { @@ -595,15 +598,6 @@ temp_dir_.GetPath())}}; } - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindowTest. - void LogIn(const std::string& email) override { - const AccountId account_id = AccountId::FromUserEmail(email); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - GetSessionControllerClient()->AddUserSession(email); - GetSessionControllerClient()->SwitchActiveUser(account_id); - } - TestingProfile* CreateProfile(const std::string& profile_name) override { auto* profile = BrowserWithTestWindowTest::CreateProfile(profile_name); SetUpDownloadManager(profile); @@ -612,14 +606,12 @@ TestingProfile* CreateSecondaryProfile( std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs = nullptr) { - const std::string kSecondaryProfileName = "secondary_profile"; - const AccountId account_id(AccountId::FromUserEmail(kSecondaryProfileName)); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->LoginUser(account_id); - TestingProfile* profile = profile_manager()->CreateTestingProfile( - kSecondaryProfileName, std::move(prefs), u"Test profile", - 1 /*avatar_id*/, GetTestingFactories()); - SetUpDownloadManager(profile); + constexpr char kSecondaryProfileName[] = "secondary_profile"; + LogIn(kSecondaryProfileName); + auto* profile = profile_manager()->CreateTestingProfile( + kSecondaryProfileName, std::move(prefs), /*user_name=*/std::u16string(), + /*avatar_id=*/0, GetTestingFactories()); + OnUserProfileCreated(kSecondaryProfileName, profile); return profile; } @@ -734,8 +726,6 @@ } private: - raw_ptr<FakeChromeUserManager, DanglingUntriaged> fake_user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; std::map<Profile*, testing::NiceMock<MockDownloadManager>*> download_managers_; arc::ArcServiceManager arc_service_manager_; @@ -769,28 +759,90 @@ All, HoldingSpaceKeyedServiceWithExperimentalFeatureTest, testing::Combine(/*enable_camera_app_integration=*/testing::Bool(), - /*enable_predictability*/ testing::Bool(), + /*enable_predictability=*/testing::Bool(), /*enabled_suggestions=*/testing::Bool())); -TEST_P(HoldingSpaceKeyedServiceWithExperimentalFeatureTest, GuestUserProfile) { - // Construct a guest session profile. - TestingProfile::Builder guest_profile_builder; - guest_profile_builder.SetGuestSession(); - guest_profile_builder.SetProfileName("guest_profile"); - guest_profile_builder.AddTestingFactories( - {{arc::ArcFileSystemBridge::GetFactory(), - base::BindRepeating(&BuildArcFileSystemBridge)}, - {file_manager::VolumeManagerFactory::GetInstance(), - base::BindRepeating(&BuildVolumeManager)}}); - std::unique_ptr<TestingProfile> guest_profile = guest_profile_builder.Build(); +class HoldingSpaceKeyedServiceWithExperimentalFeatureForGuestTest + : public HoldingSpaceKeyedServiceWithExperimentalFeatureTest { + public: + HoldingSpaceKeyedServiceWithExperimentalFeatureForGuestTest() { + // To let ProfileHelper::GetUserByProfile() directly return + // the created guest user, without faking directory paths. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ash::switches::kIgnoreUserProfileMappingForTests); + } + + void TearDown() override { + profile_.reset(); + HoldingSpaceKeyedServiceWithExperimentalFeatureTest::TearDown(); + } + + std::string GetDefaultProfileName() override { + return user_manager::kGuestUserName; + } + + void LogIn(const std::string& email) override { + CHECK_EQ(email, user_manager::kGuestUserName); + auto account_id = user_manager::GuestAccountId(); + + user_manager()->AddGuestUser(account_id); + user_manager()->UserLoggedIn( + account_id, + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); + } + + TestingProfile* CreateProfile(const std::string& profile_name) override { + CHECK_EQ(profile_name, user_manager::kGuestUserName); + CHECK(!profile_); + + // Construct a guest session profile. + // Profile is created outside of TestingProfileManager management + // to inject more factories. + TestingProfile::Builder guest_profile_builder; + guest_profile_builder.SetGuestSession(); + guest_profile_builder.SetProfileName(profile_name); + guest_profile_builder.AddTestingFactories( + {{arc::ArcFileSystemBridge::GetFactory(), + base::BindRepeating(&BuildArcFileSystemBridge)}, + {file_manager::VolumeManagerFactory::GetInstance(), + base::BindRepeating(&BuildVolumeManager)}}); + profile_ = guest_profile_builder.Build(); + OnUserProfileCreated(profile_name, profile_.get()); + return profile_.get(); + } + + std::unique_ptr<Browser> CreateBrowser( + Profile* profile, + Browser::Type browser_type, + bool hosted_app, + BrowserWindow* browser_window) override { + // Do not create browser. + return nullptr; + } + + private: + std::unique_ptr<TestingProfile> profile_; +}; + +INSTANTIATE_TEST_SUITE_P( + All, + HoldingSpaceKeyedServiceWithExperimentalFeatureForGuestTest, + testing::Combine(/*enable_camera_app_integration=*/testing::Bool(), + /*enable_predictability=*/testing::Bool(), + /*enabled_suggestions=*/testing::Bool())); + +TEST_P(HoldingSpaceKeyedServiceWithExperimentalFeatureForGuestTest, + GuestUserProfile) { + auto* guest_profile = profile(); // Service instances should be created for guest sessions but note that the // service factory will redirect to use the primary OTR profile. ASSERT_TRUE(guest_profile); ASSERT_FALSE(guest_profile->IsOffTheRecord()); HoldingSpaceKeyedService* const guest_profile_service = - HoldingSpaceKeyedServiceFactory::GetInstance()->GetService( - guest_profile.get()); + HoldingSpaceKeyedServiceFactory::GetInstance()->GetService(guest_profile); ASSERT_TRUE(guest_profile_service); // Since the service factory redirects to use the primary OTR profile in the @@ -810,7 +862,7 @@ guest_profile->GetProfileUserName()); TestingProfile* const secondary_otr_guest_profile = secondary_otr_guest_profile_builder.BuildOffTheRecord( - guest_profile.get(), Profile::OTRProfileID::CreateUniqueForTesting()); + guest_profile, Profile::OTRProfileID::CreateUniqueForTesting()); ASSERT_TRUE(secondary_otr_guest_profile); ASSERT_TRUE(secondary_otr_guest_profile->IsOffTheRecord());
diff --git a/chrome/browser/ui/ash/picker/picker_client_impl.cc b/chrome/browser/ui/ash/picker/picker_client_impl.cc index b09899c..6b0f3c8 100644 --- a/chrome/browser/ui/ash/picker/picker_client_impl.cc +++ b/chrome/browser/ui/ash/picker/picker_client_impl.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/ash/picker/picker_client_impl.h" +#include <cstdint> #include <memory> #include <string> #include <utility> @@ -14,8 +15,14 @@ #include "base/check.h" #include "base/functional/bind.h" #include "base/functional/callback.h" +#include "base/notimplemented.h" +#include "chrome/browser/ash/app_list/app_list_controller_delegate.h" #include "chrome/browser/ash/app_list/search/chrome_search_result.h" +#include "chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h" +#include "chrome/browser/ash/app_list/search/omnibox/omnibox_provider.h" #include "chrome/browser/ash/app_list/search/search_engine.h" +#include "chrome/browser/ash/crosapi/browser_util.h" +#include "chrome/browser/ash/crosapi/crosapi_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/ash_web_view_impl.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" @@ -24,6 +31,8 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/simple_url_loader.h" +#include "ui/base/page_transition_types.h" +#include "ui/base/window_open_disposition.h" #include "url/url_constants.h" namespace ash { @@ -60,21 +69,19 @@ } // namespace -PickerClientImpl::PickerClientImpl(ash::PickerController* controller) +PickerClientImpl::PickerClientImpl(ash::PickerController* controller, + user_manager::UserManager* user_manager) : controller_(controller) { controller_->SetClient(this); - auto* user_manager = user_manager::UserManager::Get(); // As `PickerClientImpl` is initialised in // `ChromeBrowserMainExtraPartsAsh::PostProfileInit`, the user manager does // not notify us of the first user "change". ActiveUserChanged(user_manager->GetActiveUser()); - user_manager->AddSessionStateObserver(this); + user_session_state_observation_.Observe(user_manager); } PickerClientImpl::~PickerClientImpl() { - user_manager::UserManager::Get()->RemoveSessionStateObserver(this); - controller_->SetClient(nullptr); } @@ -166,4 +173,77 @@ profile_ = profile; search_engine_ = std::make_unique<app_list::SearchEngine>(profile_); + if (crosapi::browser_util::IsLacrosEnabled()) { + search_engine_->AddProvider( + std::make_unique<app_list::OmniboxLacrosProvider>( + profile_, &app_list_controller_delegate_, + crosapi::CrosapiManager::Get())); + } else { + search_engine_->AddProvider(std::make_unique<app_list::OmniboxProvider>( + profile_, &app_list_controller_delegate_)); + } +} + +PickerClientImpl::PickerAppListControllerDelegate:: + PickerAppListControllerDelegate() = default; +PickerClientImpl::PickerAppListControllerDelegate:: + ~PickerAppListControllerDelegate() = default; + +void PickerClientImpl::PickerAppListControllerDelegate::DismissView() { + NOTIMPLEMENTED_LOG_ONCE(); +} + +aura::Window* +PickerClientImpl::PickerAppListControllerDelegate::GetAppListWindow() { + NOTIMPLEMENTED_LOG_ONCE(); + return nullptr; +} + +int64_t +PickerClientImpl::PickerAppListControllerDelegate::GetAppListDisplayId() { + NOTIMPLEMENTED_LOG_ONCE(); + return 0; +} + +bool PickerClientImpl::PickerAppListControllerDelegate::IsAppPinned( + const std::string& app_id) { + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +bool PickerClientImpl::PickerAppListControllerDelegate::IsAppOpen( + const std::string& app_id) const { + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +void PickerClientImpl::PickerAppListControllerDelegate::PinApp( + const std::string& app_id) { + NOTIMPLEMENTED_LOG_ONCE(); +} + +void PickerClientImpl::PickerAppListControllerDelegate::UnpinApp( + const std::string& app_id) { + NOTIMPLEMENTED_LOG_ONCE(); +} + +AppListControllerDelegate::Pinnable +PickerClientImpl::PickerAppListControllerDelegate::GetPinnable( + const std::string& app_id) { + NOTIMPLEMENTED_LOG_ONCE(); + return AppListControllerDelegate::NO_PIN; +} + +void PickerClientImpl::PickerAppListControllerDelegate::CreateNewWindow( + bool incognito, + bool should_trigger_session_restore) { + NOTIMPLEMENTED_LOG_ONCE(); +} + +void PickerClientImpl::PickerAppListControllerDelegate::OpenURL( + Profile* profile, + const GURL& url, + ui::PageTransition transition, + WindowOpenDisposition disposition) { + NOTIMPLEMENTED_LOG_ONCE(); }
diff --git a/chrome/browser/ui/ash/picker/picker_client_impl.h b/chrome/browser/ui/ash/picker/picker_client_impl.h index ccac318..505a7b9 100644 --- a/chrome/browser/ui/ash/picker/picker_client_impl.h +++ b/chrome/browser/ui/ash/picker/picker_client_impl.h
@@ -5,12 +5,17 @@ #ifndef CHROME_BROWSER_UI_ASH_PICKER_PICKER_CLIENT_IMPL_H_ #define CHROME_BROWSER_UI_ASH_PICKER_PICKER_CLIENT_IMPL_H_ +#include <cstdint> #include <memory> #include <string> #include "ash/public/cpp/picker/picker_client.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/ash/app_list/app_list_controller_delegate.h" #include "chrome/browser/ash/login/session/user_session_manager.h" +#include "ui/base/page_transition_types.h" +#include "ui/base/window_open_disposition.h" +#include "url/gurl.h" class Profile; @@ -22,6 +27,10 @@ class PickerController; } +namespace aura { +class Window; +} + namespace user_manager { class User; } @@ -33,7 +42,9 @@ public: // Sets this instance as the client of `controller`. // Automatically unsets the client when this instance is destroyed. - explicit PickerClientImpl(ash::PickerController* controller); + // `manager` needs to outlive this class. + explicit PickerClientImpl(ash::PickerController* controller, + user_manager::UserManager* user_manager); PickerClientImpl(const PickerClientImpl&) = delete; PickerClientImpl& operator=(const PickerClientImpl&) = delete; ~PickerClientImpl() override; @@ -50,6 +61,29 @@ void ActiveUserChanged(user_manager::User* active_user) override; private: + // Implements `AppListControllerDelegate` with empty methods. Used only for + // constructing search engine providers. + class PickerAppListControllerDelegate : public AppListControllerDelegate { + public: + PickerAppListControllerDelegate(); + ~PickerAppListControllerDelegate() override; + + // AppListControllerDelegate overrides: + void DismissView() override; + aura::Window* GetAppListWindow() override; + int64_t GetAppListDisplayId() override; + bool IsAppPinned(const std::string& app_id) override; + bool IsAppOpen(const std::string& app_id) const override; + void PinApp(const std::string& app_id) override; + void UnpinApp(const std::string& app_id) override; + Pinnable GetPinnable(const std::string& app_id) override; + void CreateNewWindow(bool incognito, + bool should_trigger_session_restore) override; + void OpenURL(Profile* profile, + const GURL& url, + ui::PageTransition transition, + WindowOpenDisposition disposition) override; + }; void SetProfileByUser(const user_manager::User* user); void SetProfile(Profile* profile); @@ -57,6 +91,11 @@ raw_ptr<Profile> profile_ = nullptr; std::unique_ptr<app_list::SearchEngine> search_engine_; + PickerAppListControllerDelegate app_list_controller_delegate_; + + base::ScopedObservation<user_manager::UserManager, + user_manager::UserManager::UserSessionStateObserver> + user_session_state_observation_{this}; base::WeakPtrFactory<PickerClientImpl> weak_factory_{this}; };
diff --git a/chrome/browser/ui/ash/picker/picker_client_impl_unittest.cc b/chrome/browser/ui/ash/picker/picker_client_impl_unittest.cc new file mode 100644 index 0000000..f104914 --- /dev/null +++ b/chrome/browser/ui/ash/picker/picker_client_impl_unittest.cc
@@ -0,0 +1,133 @@ +// 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/ui/ash/picker/picker_client_impl.h" + +#include <memory> +#include <utility> + +#include "ash/picker/picker_controller.h" +#include "base/functional/bind.h" +#include "base/test/test_future.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/user_manager/fake_user_manager.h" +#include "components/user_manager/scoped_user_manager.h" +#include "content/public/test/browser_task_environment.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/network/test/test_shared_url_loader_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +struct TestServerSetup { + std::unique_ptr<net::test_server::EmbeddedTestServer> server; + net::test_server::EmbeddedTestServerHandle handle; +}; + +TestServerSetup CreateAndStartTestServer( + net::test_server::EmbeddedTestServer::HandleRequestCallback + handle_request_callback) { + auto test_server = std::make_unique<net::test_server::EmbeddedTestServer>(); + test_server->RegisterRequestHandler(std::move(handle_request_callback)); + net::test_server::EmbeddedTestServerHandle handle = + test_server->StartAndReturnHandle(); + return { + .server = std::move(test_server), + .handle = std::move(handle), + }; +} + +class PickerClientImplTest : public testing::Test { + public: + PickerClientImplTest() + : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), + test_shared_url_loader_factory_( + base::MakeRefCounted<network::TestSharedURLLoaderFactory>()), + fake_user_manager_(std::make_unique<user_manager::FakeUserManager>()), + testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {} + + void SetUp() override { ASSERT_TRUE(testing_profile_manager_.SetUp()); } + void TearDown() override { + for (const user_manager::User* user : fake_user_manager_->GetUsers()) { + fake_user_manager_->OnUserProfileWillBeDestroyed(user->GetAccountId()); + } + } + + // Returns the user manager used in this test, logged into a fake user. + user_manager::UserManager* GetUserManagerLoggedInAsFakeUser() { + AccountId account_id = AccountId::FromUserEmail("test@test"); + + const user_manager::User* user = fake_user_manager_->AddUser(account_id); + fake_user_manager_->UserLoggedIn(account_id, user->username_hash(), + /*browser_restart=*/false, + /*is_child=*/false); + TestingProfile* profile = CreateTestingProfileForAccount(account_id); + fake_user_manager_->OnUserProfileCreated(account_id, profile->GetPrefs()); + return fake_user_manager_.Get(); + } + + private: + TestingProfile* CreateTestingProfileForAccount(const AccountId& account_id) { + return testing_profile_manager_.CreateTestingProfile( + account_id.GetUserEmail(), /*is_main_profile=*/false, + test_shared_url_loader_factory_); + } + + content::BrowserTaskEnvironment task_environment_; + scoped_refptr<network::SharedURLLoaderFactory> + test_shared_url_loader_factory_; + // Keep `fake_user_manager_` before `testing_profile_manager_` to match + // destruction order in production: + // https://crsrc.org/c/chrome/browser/ash/chrome_browser_main_parts_ash.cc;l=1668;drc=c7da8fba0e20c71d61e5c78ecd6a3872c4c56e6c + // https://crsrc.org/c/chrome/browser/ash/chrome_browser_main_parts_ash.cc;l=1719;drc=c7da8fba0e20c71d61e5c78ecd6a3872c4c56e6c + user_manager::TypedScopedUserManager<user_manager::FakeUserManager> + fake_user_manager_; + TestingProfileManager testing_profile_manager_; +}; + +TEST_F(PickerClientImplTest, DownloadGifReturnsGifOnSuccess) { + ash::PickerController controller; + PickerClientImpl client(&controller, GetUserManagerLoggedInAsFakeUser()); + TestServerSetup server_setup = CreateAndStartTestServer(base::BindRepeating( + [](const net::test_server::HttpRequest& request) + -> std::unique_ptr<net::test_server::HttpResponse> { + auto http_response = + std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HTTP_OK); + http_response->set_content("hello"); + http_response->set_content_type("text/plain"); + return http_response; + })); + + base::test::TestFuture<const std::string&> future; + client.DownloadGifToString(ash::ValidGifUrl::CreateForTesting( + server_setup.server->GetURL("/test.gif")), + future.GetCallback()); + + EXPECT_EQ(future.Get(), "hello"); +} + +TEST_F(PickerClientImplTest, DownloadGifReturnsEmptyOnFailure) { + ash::PickerController controller; + PickerClientImpl client(&controller, GetUserManagerLoggedInAsFakeUser()); + TestServerSetup server_setup = CreateAndStartTestServer(base::BindRepeating( + [](const net::test_server::HttpRequest& request) + -> std::unique_ptr<net::test_server::HttpResponse> { + auto http_response = + std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HTTP_NOT_FOUND); + return http_response; + })); + + base::test::TestFuture<const std::string&> future; + client.DownloadGifToString(ash::ValidGifUrl::CreateForTesting( + server_setup.server->GetURL("/test.gif")), + future.GetCallback()); + + EXPECT_EQ(future.Get(), ""); +} + +} // namespace
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.cc b/chrome/browser/ui/ash/session_controller_client_impl.cc index f37a4fd..a9edff1 100644 --- a/chrome/browser/ui/ash/session_controller_client_impl.cc +++ b/chrome/browser/ui/ash/session_controller_client_impl.cc
@@ -444,8 +444,8 @@ if (static_cast<ash::ChromeUserManager*>(user_manager) ->GetMultiProfileUserController() - ->GetPrimaryUserPolicy() != - ash::MultiProfileUserController::ALLOWED) { + ->GetPrimaryUserPolicy() == + user_manager::MultiUserSignInPolicy::kNotAllowed) { return ash::AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER; }
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc index 379f73d..70ce411 100644 --- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -93,7 +93,6 @@ #include "chrome/browser/ash/eche_app/app_id.h" #include "chrome/browser/ash/file_manager/app_id.h" #include "chrome/browser/ash/login/demo_mode/demo_mode_test_helper.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ash/system_web_apps/apps/camera_app/camera_system_web_app_info.h" #include "chrome/browser/ash/system_web_apps/apps/os_flags_system_web_app_info.h" @@ -148,6 +147,7 @@ #include "chrome/test/base/test_browser_window_aura.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" #include "chromeos/ash/components/standalone_browser/feature_refs.h" #include "chromeos/constants/chromeos_features.h" @@ -177,8 +177,6 @@ #include "components/sync/test/test_sync_service.h" #include "components/sync_preferences/pref_model_associator.h" #include "components/sync_preferences/testing_pref_service_syncable.h" -#include "components/user_manager/fake_user_manager.h" -#include "components/user_manager/scoped_user_manager.h" #include "components/viz/test/test_gpu_service_holder.h" #include "components/webapps/common/web_app_id.h" #include "content/public/browser/web_contents.h" @@ -610,17 +608,6 @@ StartWebAppProvider(profile()); } - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. - AccountId account_id = AccountId::FromUserEmail(email); - user_manager()->AddUser(account_id); - user_manager()->UserLoggedIn( - account_id, - user_manager::FakeUserManager::GetFakeUsernameHash(account_id), - /*browser_restart=*/false, - /*is_child=*/false); - } - virtual bool StartWebAppProviderForMainProfile() const { return true; } void StartWebAppProvider(Profile* profile) { @@ -1653,8 +1640,9 @@ return CreateProfile(email); } - // Switch to another user. - void SwitchActiveUser(const AccountId& account_id) { + // Switch to another user by AccountId. + // TODO(b/40286020): Migrate into SwitchActiveUser(). + void SwitchActiveUserByAccountId(const AccountId& account_id) { user_manager()->SwitchActiveUser(account_id); ash::MultiUserWindowManagerImpl::Get()->SetAnimationSpeedForTest( ash::MultiUserWindowManagerImpl::ANIMATION_SPEED_DISABLED); @@ -2858,7 +2846,7 @@ EXPECT_TRUE(shelf_controller_->GetItem(ash::ShelfID(arc_app_id2))); shelf_controller_->SetProfileForTest(profile2); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_FALSE(shelf_controller_->GetItem(ash::ShelfID(arc_app_id1))); EXPECT_FALSE(shelf_controller_->GetItem(ash::ShelfID(arc_app_id2))); @@ -2873,7 +2861,7 @@ arc_test_.app_instance()->SendTaskDestroyed(2); shelf_controller_->SetProfileForTest(profile()); - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_TRUE(shelf_controller_->GetItem(ash::ShelfID(arc_app_id1))); EXPECT_FALSE(shelf_controller_->GetItem(ash::ShelfID(arc_app_id2))); @@ -3340,11 +3328,11 @@ multi_user_util::GetAccountIdFromProfile(profile2)); const AccountId account_id( multi_user_util::GetAccountIdFromProfile(profile())); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); // After switching back the item should be back. - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(2, model_->item_count()); // Note we destroy now the gmail app with the closure end. } @@ -3371,19 +3359,19 @@ EXPECT_EQ(1, model_->item_count()); // However - switching to the user should show it. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(2, model_->item_count()); // Second test: Remove the app when the user is not active and see that it // works. - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(1, model_->item_count()); // Note: the closure ends and the browser will go away. } EXPECT_EQ(1, model_->item_count()); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(1, model_->item_count()); } @@ -3405,11 +3393,11 @@ std::unique_ptr<V1App> v1_app(CreateRunningV1App( profile(), extension_misc::kGmailAppId, kGmailLaunchURL)); EXPECT_EQ(2, model_->item_count()); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); } // After the app was destroyed, switch back. (which caused already a crash). - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); // Create the same app again - which was also causing the crash. EXPECT_EQ(1, model_->item_count()); @@ -3419,7 +3407,7 @@ profile(), extension_misc::kGmailAppId, kGmailLaunchURL)); EXPECT_EQ(2, model_->item_count()); } - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); } @@ -3436,7 +3424,7 @@ multi_user_util::GetAccountIdFromProfile(profile())); const AccountId account_id2( multi_user_util::GetAccountIdFromProfile(profile2)); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); { // Create a "windowed gmail app". std::unique_ptr<V1App> v1_app( @@ -3444,19 +3432,19 @@ EXPECT_EQ(1, model_->item_count()); // However - switching to the user should show it. - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(2, model_->item_count()); // Second test: Remove the app when the user is not active and see that it // works. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); v1_app.reset(); } EXPECT_EQ(1, model_->item_count()); - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(1, model_->item_count()); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); } @@ -3535,7 +3523,7 @@ // Switch to the secondary user, and verify the app only installed in the // primary profile is removed from the model. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(std::vector<std::string>({app_constants::kChromeAppId}), GetAppsShownInShelf()); @@ -4177,7 +4165,7 @@ // Switch to the other user and make sure that only that browser window gets // shown. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); CheckAppMenu(shelf_controller_.get(), item_browser, 1, one_menu_item2); // Transferred browsers of other users should not show up in the list. @@ -4288,7 +4276,7 @@ TestingProfile* profile2 = CreateMultiUserProfile(user2); const AccountId account_id2( multi_user_util::GetAccountIdFromProfile(profile2)); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); // No item should have content yet. CheckAppMenu(shelf_controller_.get(), item_browser, 0, nullptr); @@ -4323,11 +4311,11 @@ multi_user_util::GetAccountIdFromProfile(profile2)); // After switching users the item should go away. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); // And it should come back when switching back. - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(2, model_->item_count()); } @@ -4347,7 +4335,7 @@ EXPECT_EQ(1, model_->item_count()); // Switch to an inactive user. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); // Add the v2 app to the inactive user and check that no item was added to @@ -4358,12 +4346,12 @@ EXPECT_EQ(1, model_->item_count()); // Switch to the primary user and check that the item is shown. - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(2, model_->item_count()); // Switch to the second user and check that the item goes away - even if the // item gets closed. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); } @@ -4372,7 +4360,7 @@ // Switching then back to the default user should not show the additional // item anymore. - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(1, model_->item_count()); } @@ -4457,14 +4445,14 @@ base::CommandLine::ForCurrentProcess(), base::FilePath(), false); extension_service1->Init(); - SwitchActiveUser(account_id1); + SwitchActiveUserByAccountId(account_id1); // A v2 app for user #1 should be shown first and get hidden when switching // to desktop #2. extension_service1->AddExtension(extension1_.get()); V2App v2_app_1(profile1, extension1_.get()); EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible()); - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible()); // Add a v2 app for user #1 while on desktop #2 should not be shown. @@ -4487,7 +4475,7 @@ // Switching back to desktop#1 and creating an app for user #1 should move // the app on desktop #1. - SwitchActiveUser(account_id1); + SwitchActiveUserByAccountId(account_id1); V2App v2_app_4(profile1, extension1_.get()); EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible()); EXPECT_TRUE(v2_app_2.window()->GetNativeWindow()->IsVisible()); @@ -4496,15 +4484,15 @@ // Switching to desktop #3 and creating an app for user #1 should place it // on that user's desktop (#1). - SwitchActiveUser(account_id3); + SwitchActiveUserByAccountId(account_id3); V2App v2_app_5(profile1, extension1_.get()); EXPECT_FALSE(v2_app_5.window()->GetNativeWindow()->IsVisible()); - SwitchActiveUser(account_id1); + SwitchActiveUserByAccountId(account_id1); EXPECT_TRUE(v2_app_5.window()->GetNativeWindow()->IsVisible()); // Switching to desktop #2, hiding the app window and creating an app should // teleport there automatically. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); v2_app_1.window()->Hide(); V2App v2_app_6(profile1, extension1_.get()); EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible()); @@ -4524,11 +4512,11 @@ // If switch to account_id2 is not run, the following switch to account_id // is invalid, because the user account is not changed, so switch to // account_id2 first. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); const AccountId account_id( multi_user_util::GetAccountIdFromProfile(profile())); - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(1, model_->item_count()); AddExtension(extension1_.get()); @@ -4544,7 +4532,7 @@ } { // Switch user, hide and show the app and switch back. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); v2_app_1.window()->Hide(); @@ -4553,18 +4541,18 @@ v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE); EXPECT_EQ(1, model_->item_count()); - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(2, model_->item_count()); } { // Switch user, hide the app, switch back and then show it again. - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); v2_app_1.window()->Hide(); EXPECT_EQ(1, model_->item_count()); - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); // The following expectation does not work in current impl. It was working // before because MultiProfileSupport is not attached to user associated // with profile() hence not actually handling windows for the user. It is @@ -4616,12 +4604,12 @@ EXPECT_TRUE(shelf_controller_->GetShelfSpinnerController()->HasApp(app_id)); // Switch to a new profile - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_EQ(1, model_->item_count()); EXPECT_FALSE(shelf_controller_->GetShelfSpinnerController()->HasApp(app_id)); // Switch back - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_EQ(2, model_->item_count()); EXPECT_TRUE(shelf_controller_->GetShelfSpinnerController()->HasApp(app_id)); @@ -4664,13 +4652,13 @@ EXPECT_TRUE(shelf_controller_->GetShelfSpinnerController()->HasApp(app_id)); // Switch to a new profile - SwitchActiveUser(account_id2); + SwitchActiveUserByAccountId(account_id2); EXPECT_FALSE(shelf_controller_->IsAppPinned(app_id)); EXPECT_EQ(1, model_->item_count()); EXPECT_FALSE(shelf_controller_->GetShelfSpinnerController()->HasApp(app_id)); // Switch back - SwitchActiveUser(account_id); + SwitchActiveUserByAccountId(account_id); EXPECT_TRUE(shelf_controller_->IsAppPinned(app_id)); EXPECT_EQ(2, model_->item_count()); EXPECT_TRUE(shelf_controller_->GetShelfSpinnerController()->HasApp(app_id));
diff --git a/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc b/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc index b436aa7..4b49779 100644 --- a/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc +++ b/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc
@@ -81,10 +81,6 @@ // Base class for tests of the `ChromeUserEducationDelegate`. class ChromeUserEducationDelegateTest : public BrowserWithTestWindowTest { public: - ChromeUserEducationDelegateTest() - : user_manager_(new ash::FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(user_manager_.get())) {} - // Returns the `AccountId` for the primary `profile()`. const AccountId& account_id() const { return ash::BrowserContextHelper::Get() @@ -105,23 +101,6 @@ delegate_ = std::make_unique<ChromeUserEducationDelegate>(); } - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. - void LogIn(const std::string& email) override { - const AccountId account_id = AccountId::FromUserEmail(email); - // Register user. - user_manager_->AddUser(account_id); - user_manager_->LoginUser(account_id); - - // Activate session. - auto* client = ash_test_helper()->test_session_controller_client(); - client->AddUserSession(email); - client->SwitchActiveUser(account_id); - } - - // User management. - const raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; - // The delegate instance under test. std::unique_ptr<ChromeUserEducationDelegate> delegate_; };
diff --git a/chrome/browser/ui/browser_command_controller_unittest.cc b/chrome/browser/ui/browser_command_controller_unittest.cc index c25d56c..d781eef1 100644 --- a/chrome/browser/ui/browser_command_controller_unittest.cc +++ b/chrome/browser/ui/browser_command_controller_unittest.cc
@@ -220,25 +220,18 @@ chrome::BrowserCommandController command_controller(browser()); const CommandUpdater* command_updater = &command_controller; - bool enabled = true; - size_t profiles_count = 1U; -#if BUILDFLAG(IS_CHROMEOS_ASH) // Chrome OS uses system tray menu to handle multi-profiles. - enabled = false; - profiles_count = 2U; -#endif + bool enabled = !BUILDFLAG(IS_CHROMEOS_ASH); - ASSERT_EQ(profiles_count, profile_manager->GetNumberOfProfiles()); + ASSERT_EQ(1u, profile_manager->GetNumberOfProfiles()); EXPECT_EQ(enabled, command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU)); testing_profile_manager->CreateTestingProfile("p2"); - profiles_count++; - ASSERT_EQ(profiles_count, profile_manager->GetNumberOfProfiles()); + ASSERT_EQ(2u, profile_manager->GetNumberOfProfiles()); EXPECT_EQ(enabled, command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU)); testing_profile_manager->DeleteTestingProfile("p2"); - profiles_count--; - ASSERT_EQ(profiles_count, profile_manager->GetNumberOfProfiles()); + ASSERT_EQ(1u, profile_manager->GetNumberOfProfiles()); EXPECT_EQ(enabled, command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU)); }
diff --git a/chrome/browser/ui/browser_finder_chromeos_unittest.cc b/chrome/browser/ui/browser_finder_chromeos_unittest.cc index ab0cfc95..bc31a8ce 100644 --- a/chrome/browser/ui/browser_finder_chromeos_unittest.cc +++ b/chrome/browser/ui/browser_finder_chromeos_unittest.cc
@@ -7,7 +7,6 @@ #include "ash/public/cpp/multi_user_window_manager.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ui/ash/multi_user/multi_profile_support.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" @@ -15,7 +14,6 @@ #include "chrome/test/base/test_browser_window_aura.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/account_id/account_id.h" -#include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" #include "ui/base/ui_base_features.h" @@ -30,10 +28,7 @@ class BrowserFinderChromeOSTest : public BrowserWithTestWindowTest { protected: - BrowserFinderChromeOSTest() - : fake_user_manager_(new ash::FakeChromeUserManager), - user_manager_enabler_(base::WrapUnique(fake_user_manager_.get())) {} - + BrowserFinderChromeOSTest() = default; BrowserFinderChromeOSTest(const BrowserFinderChromeOSTest&) = delete; BrowserFinderChromeOSTest& operator=(const BrowserFinderChromeOSTest&) = delete; @@ -64,20 +59,9 @@ // BrowserWithTestWindow: std::string GetDefaultProfileName() override { return kTestAccount1; } - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindowTest. - const AccountId account_id = AccountId::FromUserEmail(email); - fake_user_manager_->AddUser(account_id); - fake_user_manager_->UserLoggedIn( - account_id, - user_manager::FakeUserManager::GetFakeUsernameHash(account_id), - /*browser_restart=*/false, - /*is_child=*/false); - } - TestingProfile* CreateProfile(const std::string& profile_name) override { auto* profile = BrowserWithTestWindowTest::CreateProfile(profile_name); - auto* user = fake_user_manager_->FindUserAndModify( + auto* user = user_manager()->FindUserAndModify( AccountId::FromUserEmail(profile_name)); ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, profile); // Force creation of MultiProfileSupport. @@ -87,10 +71,6 @@ } raw_ptr<TestingProfile> second_profile_; - - // |fake_user_manager_| is owned by |user_manager_enabler_| - raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> fake_user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; }; TEST_F(BrowserFinderChromeOSTest, IncognitoBrowserMatchTest) {
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc index 8b5fc77..7109bcc 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -33,6 +33,8 @@ #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h" #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h" +#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h" +#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_io_data.h" #include "chrome/browser/sessions/app_session_service.h" @@ -243,6 +245,7 @@ profile_ = browser->profile(); if (!browser || !browser->is_type_normal()) { + CHECK(profile_); // In some conditions a new browser object cannot be created. The most // common reason for not being able to create browser is having this call // when the browser process is shutting down. This can also fail if the @@ -269,12 +272,12 @@ browser = Browser::Create(params); } + CHECK(profile_); bool first_tab = true; bool process_headless_commands = headless::ShouldProcessHeadlessCommands(); custom_handlers::ProtocolHandlerRegistry* registry = - profile_ ? ProtocolHandlerRegistryFactory::GetForBrowserContext(profile_) - : nullptr; + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile_); for (auto& tab : tabs) { // We skip URLs that we'd have to launch an external protocol handler for. // This avoids us getting into an infinite loop asking ourselves to open @@ -300,10 +303,13 @@ // Headless mode is restricted to only one url in the command line, so // just grab the first one assuming it's the target. if (first_tab && process_headless_commands) { + auto profile_keepalive = std::make_unique<ScopedProfileKeepAlive>( + profile_, ProfileKeepAliveOrigin::kHeadlessCommand); headless::ProcessHeadlessCommands( profile_, tab.url, base::BindOnce( [](base::WeakPtr<Browser> browser, + std::unique_ptr<ScopedProfileKeepAlive> profile_keepalive, headless::HeadlessCommandHandler::Result result) { if (browser && browser->window()) { #if BUILDFLAG(IS_MAC) @@ -316,7 +322,7 @@ browser->window()->Close(); } }, - browser->AsWeakPtr())); + browser->AsWeakPtr(), std::move(profile_keepalive))); continue; }
diff --git a/chrome/browser/ui/tab_contents/chrome_web_contents_menu_helper_unittest.cc b/chrome/browser/ui/tab_contents/chrome_web_contents_menu_helper_unittest.cc index 4a54b2c3..e419cbe 100644 --- a/chrome/browser/ui/tab_contents/chrome_web_contents_menu_helper_unittest.cc +++ b/chrome/browser/ui/tab_contents/chrome_web_contents_menu_helper_unittest.cc
@@ -35,9 +35,13 @@ RegisterUserProfilePrefs(prefs->registry()); pref_service_ = prefs.get(); - return profile_manager()->CreateTestingProfile( + auto* profile = profile_manager()->CreateTestingProfile( profile_name, std::move(prefs), std::u16string(), 0, TestingProfile::TestingFactories()); +#if BUILDFLAG(IS_CHROMEOS_ASH) + OnUserProfileCreated(profile_name, profile); +#endif + return profile; } sync_preferences::PrefServiceSyncable* pref_service() {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc index 8aedd4f..66baa44 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
@@ -88,8 +88,7 @@ } // namespace class AppInfoDialogViewsTest : public BrowserWithTestWindowTest, - public views::WidgetObserver, - public ProfileObserver { + public views::WidgetObserver { public: AppInfoDialogViewsTest() = default; @@ -149,50 +148,12 @@ BrowserWithTestWindowTest::TearDown(); } -#if BUILDFLAG(IS_CHROMEOS_ASH) - // BrowserWithTestWindowTest: - void LogIn(const std::string& email) override { - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. - AccountId account_id = AccountId::FromUserEmail(email); - CHECK(user_manager()); - user_manager()->AddUser(account_id); - user_manager()->UserLoggedIn( - account_id, - user_manager::FakeUserManager::GetFakeUsernameHash(account_id), - /*browser_restart=*/false, - /*is_child=*/false); - } -#endif - TestingProfile* CreateProfile(const std::string& profile_name) override { auto* profile = BrowserWithTestWindowTest::CreateProfile(profile_name); - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. -#if BUILDFLAG(IS_CHROMEOS_ASH) - auto account_id = AccountId::FromUserEmail(profile_name); - ash::AnnotatedAccountId::Set(profile, account_id); - user_manager()->OnUserProfileCreated(account_id, profile->GetPrefs()); - auto observation = - std::make_unique<base::ScopedObservation<Profile, ProfileObserver>>( - this); - observation->Observe(profile); - profile_observations_.push_back(std::move(observation)); -#endif extension_environment_.SetProfile(profile); return profile; } - // TODO(crbug.com/1494005): merge into BrowserWithTestWindowTest. -#if BUILDFLAG(IS_CHROMEOS_ASH) - void OnProfileWillBeDestroyed(Profile* profile) override { - CHECK(base::EraseIf(profile_observations_, [profile](auto& observation) { - return observation->IsObservingSource(profile); - })); - const auto* account_id = ash::AnnotatedAccountId::Get(profile); - CHECK(account_id); - user_manager()->OnUserProfileWillBeDestroyed(*account_id); - } -#endif - protected: void ShowAppInfo(const std::string& app_id) { ShowAppInfoForProfile(app_id, extension_environment_.profile()); @@ -249,9 +210,6 @@ #endif }; #if BUILDFLAG(IS_CHROMEOS_ASH) - std::vector< - std::unique_ptr<base::ScopedObservation<Profile, ProfileObserver>>> - profile_observations_; std::unique_ptr<ash::ShelfModel> shelf_model_; std::unique_ptr<ChromeShelfController> chrome_shelf_controller_; std::unique_ptr<ArcAppTest> arc_test_;
diff --git a/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc b/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc index 2473bd6..ecbd729 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc
@@ -25,7 +25,9 @@ #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/omnibox/browser/vector_icons.h" +#include "ui/color/color_id.h" #include "ui/gfx/geometry/size.h" +#include "ui/views/style/typography.h" #if BUILDFLAG(GOOGLE_CHROME_BRANDING) #include "components/plus_addresses/resources/vector_icons.h" #endif @@ -518,19 +520,31 @@ int non_primary_text_style = ShouldApplyNewAutofillPopupStyle() ? views::style::TextStyle::STYLE_BODY_3 : views::style::TextStyle::STYLE_PRIMARY; - return std::make_unique<views::Label>( + auto label = std::make_unique<views::Label>( main_text.value, views::style::CONTEXT_DIALOG_BODY_TEXT, main_text.is_primary ? primary_text_style : non_primary_text_style); + + if (!main_text.is_primary && ShouldApplyNewAutofillPopupStyle()) { + label->SetEnabledColorId(ui::kColorLabelForegroundSecondary); + } + + return label; } // Creates a label for the suggestion's minor text. std::unique_ptr<views::Label> CreateMinorTextLabel( const Suggestion::Text& minor_text) { - return minor_text.value.empty() - ? nullptr - : std::make_unique<views::Label>( - minor_text.value, views::style::CONTEXT_DIALOG_BODY_TEXT, - GetSecondaryTextStyle()); + if (minor_text.value.empty()) { + return nullptr; + } + + auto label = std::make_unique<views::Label>( + minor_text.value, views::style::CONTEXT_DIALOG_BODY_TEXT, + GetSecondaryTextStyle()); + if (ShouldApplyNewAutofillPopupStyle()) { + label->SetEnabledColorId(ui::kColorLabelForegroundSecondary); + } + return label; } int GetMaxPopupAddressProfileWidth() { @@ -572,6 +586,9 @@ label_text.value, ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL, text_style ? *text_style : GetSecondaryTextStyle())); + if (ShouldApplyNewAutofillPopupStyle()) { + label->SetEnabledColorId(ui::kColorLabelForegroundSecondary); + } content_view.TrackLabel(label); // TODO(crbug.com/1459990): Remove feature check as part of the clean up. if (!base::FeatureList::IsEnabled(
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_content_view.cc b/chrome/browser/ui/views/autofill/popup/popup_row_content_view.cc index 4cce5ac..815dc96 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_row_content_view.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_row_content_view.cc
@@ -42,19 +42,21 @@ SetBackground(nullptr); } - // Set style for each label in this cell depending on its current selection - // state. - for (views::Label* label : tracked_labels_) { - label->SetAutoColorReadabilityEnabled(false); + if (!ShouldApplyNewAutofillPopupStyle()) { + // Set style for each label in this cell depending on its current selection + // state. + for (views::Label* label : tracked_labels_) { + label->SetAutoColorReadabilityEnabled(false); - // If the current suggestion is selected or the label is disabled, - // override the style. Otherwise, use the color that corresponds to the - // actual style of the label. - int style = label->GetEnabled() ? (selected ? views::style::STYLE_SELECTED - : label->GetTextStyle()) - : views::style::STYLE_DISABLED; - label->SetEnabledColorId(views::TypographyProvider::Get().GetColorId( - label->GetTextContext(), style)); + // If the current suggestion is selected or the label is disabled, + // override the style. Otherwise, use the color that corresponds to the + // actual style of the label. + int style = label->GetEnabled() ? (selected ? views::style::STYLE_SELECTED + : label->GetTextStyle()) + : views::style::STYLE_DISABLED; + label->SetEnabledColorId(views::TypographyProvider::Get().GetColorId( + label->GetTextContext(), style)); + } } SchedulePaint();
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_content_view_unittest.cc b/chrome/browser/ui/views/autofill/popup/popup_row_content_view_unittest.cc index 2d48ba7..08ffc1a2 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_row_content_view_unittest.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_row_content_view_unittest.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/memory/raw_ptr.h" +#include "chrome/browser/ui/views/autofill/popup/popup_view_utils.h" #include "chrome/test/views/chrome_views_test_base.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/color/color_id.h" @@ -108,16 +109,19 @@ untracked_label->GetEnabledColor(), get_expected_color(*untracked_label, untracked_label->GetTextStyle())); - // On select updates only the tracked label's style. - view().UpdateStyle(/*selected=*/true); - EXPECT_NE( - tracked_label->GetEnabledColor(), - get_expected_color(*tracked_label, untracked_label->GetTextStyle())); - EXPECT_EQ(tracked_label->GetEnabledColor(), - get_expected_color(*tracked_label, views::style::STYLE_SELECTED)); - EXPECT_EQ( - untracked_label->GetEnabledColor(), - get_expected_color(*untracked_label, untracked_label->GetTextStyle())); + // The label styles don't get changed with selection for the new style. + if (!ShouldApplyNewAutofillPopupStyle()) { + // On select updates only the tracked label's style. + view().UpdateStyle(/*selected=*/true); + EXPECT_NE( + tracked_label->GetEnabledColor(), + get_expected_color(*tracked_label, untracked_label->GetTextStyle())); + EXPECT_EQ(tracked_label->GetEnabledColor(), + get_expected_color(*tracked_label, views::style::STYLE_SELECTED)); + EXPECT_EQ( + untracked_label->GetEnabledColor(), + get_expected_color(*untracked_label, untracked_label->GetTextStyle())); + } } } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc index e6f02a5d..a63156a 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_row_factory_utils.cc
@@ -105,6 +105,9 @@ suggestion.main_text, ShouldApplyNewAutofillPopupStyle() ? views::style::TextStyle::STYLE_BODY_3 : views::style::TextStyle::STYLE_SECONDARY); + if (ShouldApplyNewAutofillPopupStyle()) { + main_text_label->SetEnabledColorId(ui::kColorLabelForegroundSecondary); + } main_text_label->SetEnabled(!suggestion.is_loading); view->TrackLabel(view->AddChildView(std::move(main_text_label)));
diff --git a/chrome/browser/ui/views/bubble/bubble_contents_wrapper_unittest.cc b/chrome/browser/ui/views/bubble/bubble_contents_wrapper_unittest.cc index 08d6a90..38e418bf 100644 --- a/chrome/browser/ui/views/bubble/bubble_contents_wrapper_unittest.cc +++ b/chrome/browser/ui/views/bubble/bubble_contents_wrapper_unittest.cc
@@ -62,9 +62,7 @@ base::WeakPtrFactory<MockHost> weak_ptr_factory_{this}; }; -class TestBubbleContentsWrapper - : public BubbleContentsWrapper, - public base::SupportsWeakPtr<TestBubbleContentsWrapper> { +class TestBubbleContentsWrapper final : public BubbleContentsWrapper { public: explicit TestBubbleContentsWrapper(Profile* profile) : BubbleContentsWrapper(GURL(""), profile, 0, true, true, "Test") {} @@ -73,8 +71,11 @@ // BubbleContentsWrapper: void ReloadWebContents() override {} base::WeakPtr<BubbleContentsWrapper> GetWeakPtr() override { - return AsWeakPtr(); + return weak_ptr_factory_.GetWeakPtr(); } + + private: + base::WeakPtrFactory<TestBubbleContentsWrapper> weak_ptr_factory_{this}; }; } // namespace
diff --git a/chrome/browser/ui/views/bubble/webui_bubble_dialog_view_unittest.cc b/chrome/browser/ui/views/bubble/webui_bubble_dialog_view_unittest.cc index fc929cd..6d65707 100644 --- a/chrome/browser/ui/views/bubble/webui_bubble_dialog_view_unittest.cc +++ b/chrome/browser/ui/views/bubble/webui_bubble_dialog_view_unittest.cc
@@ -18,17 +18,18 @@ #include "ui/views/widget/unique_widget_ptr.h" namespace { -class TestBubbleContentsWrapper - : public BubbleContentsWrapper, - public base::SupportsWeakPtr<TestBubbleContentsWrapper> { +class TestBubbleContentsWrapper final : public BubbleContentsWrapper { public: explicit TestBubbleContentsWrapper(Profile* profile) : BubbleContentsWrapper(GURL(""), profile, 0, true, true, "Test") {} void ReloadWebContents() override {} base::WeakPtr<BubbleContentsWrapper> GetWeakPtr() override { - return AsWeakPtr(); + return weak_ptr_factory_.GetWeakPtr(); } + + private: + base::WeakPtrFactory<TestBubbleContentsWrapper> weak_ptr_factory_{this}; }; } // namespace
diff --git a/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc b/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc index 9bc09e3..6e5a0d7 100644 --- a/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc +++ b/chrome/browser/ui/views/bubble/webui_bubble_manager_browsertest.cc
@@ -51,10 +51,8 @@ WEB_UI_CONTROLLER_TYPE_IMPL(TestWebUIController) template <> -class BubbleContentsWrapperT<TestWebUIController> - : public BubbleContentsWrapper, - public base::SupportsWeakPtr< - BubbleContentsWrapperT<TestWebUIController>> { +class BubbleContentsWrapperT<TestWebUIController> final + : public BubbleContentsWrapper { public: BubbleContentsWrapperT(const GURL& webui_url, content::BrowserContext* browser_context, @@ -69,8 +67,11 @@ "Test") {} void ReloadWebContents() override {} base::WeakPtr<BubbleContentsWrapper> GetWeakPtr() override { - return AsWeakPtr(); + return weak_ptr_factory_.GetWeakPtr(); } + + private: + base::WeakPtrFactory<BubbleContentsWrapper> weak_ptr_factory_{this}; }; class WebUIBubbleManagerBrowserTest : public InProcessBrowserTest {
diff --git a/chrome/browser/ui/views/bubble/webui_bubble_manager_unittest.cc b/chrome/browser/ui/views/bubble/webui_bubble_manager_unittest.cc index 0bfe8c3f..72b3431 100644 --- a/chrome/browser/ui/views/bubble/webui_bubble_manager_unittest.cc +++ b/chrome/browser/ui/views/bubble/webui_bubble_manager_unittest.cc
@@ -28,10 +28,8 @@ WEB_UI_CONTROLLER_TYPE_IMPL(TestWebUIController) template <> -class BubbleContentsWrapperT<TestWebUIController> - : public BubbleContentsWrapper, - public base::SupportsWeakPtr< - BubbleContentsWrapperT<TestWebUIController>> { +class BubbleContentsWrapperT<TestWebUIController> final + : public BubbleContentsWrapper { public: BubbleContentsWrapperT(const GURL& webui_url, content::BrowserContext* browser_context, @@ -46,8 +44,11 @@ "Test") {} void ReloadWebContents() override {} base::WeakPtr<BubbleContentsWrapper> GetWeakPtr() override { - return AsWeakPtr(); + return weak_ptr_factory_.GetWeakPtr(); } + + private: + base::WeakPtrFactory<BubbleContentsWrapper> weak_ptr_factory_{this}; }; class WebUIBubbleManagerTest : public ChromeViewsTestBase {
diff --git a/chrome/browser/ui/views/page_info/page_info_cookies_content_view_unittest.cc b/chrome/browser/ui/views/page_info/page_info_cookies_content_view_unittest.cc index c84ad6d1..da29f0c 100644 --- a/chrome/browser/ui/views/page_info/page_info_cookies_content_view_unittest.cc +++ b/chrome/browser/ui/views/page_info/page_info_cookies_content_view_unittest.cc
@@ -77,12 +77,6 @@ AddTab(browser(), url); auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); -#if BUILDFLAG(IS_CHROMEOS_ASH) - fake_user_manager_->AddUserWithAffiliation( - AccountId::FromUserEmail(profile()->GetProfileUserName()), - /*is_affiliated=*/true); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - presenter_ = std::make_unique<PageInfo>( std::make_unique<ChromePageInfoDelegate>(web_contents), web_contents, url); @@ -96,6 +90,19 @@ TestWithBrowserView::TearDown(); } +#if BUILDFLAG(IS_CHROMEOS_ASH) + void LogIn(const std::string& email) override { + const AccountId account_id = AccountId::FromUserEmail(email); + user_manager()->AddUserWithAffiliation(account_id, /*is_affiliated=*/true); + ash_test_helper()->test_session_controller_client()->AddUserSession(email); + user_manager()->UserLoggedIn( + account_id, + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); + } +#endif + PageInfoCookiesContentView* content_view() { return content_view_.get(); } views::StyledLabel* third_party_cookies_description_label() { @@ -146,11 +153,6 @@ base::test::ScopedFeatureList feature_list_; std::unique_ptr<PageInfo> presenter_; std::unique_ptr<PageInfoCookiesContentView> content_view_; - -#if BUILDFLAG(IS_CHROMEOS_ASH) - user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> - fake_user_manager_{std::make_unique<ash::FakeChromeUserManager>()}; -#endif }; class PageInfoCookiesContentViewPre3pcdTest
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc b/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc index 06d6c66c..4b227d89f 100644 --- a/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc +++ b/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc
@@ -26,11 +26,9 @@ #include "ash/constants/ash_switches.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h" #include "chrome/common/pref_names.h" -#include "components/user_manager/scoped_user_manager.h" #endif #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_CHROMEOS_ASH) @@ -41,11 +39,6 @@ namespace { -#if BUILDFLAG(IS_CHROMEOS_ASH) -constexpr char kFakeUserName[] = "test@example.com"; -constexpr char kFakeGaiaId[] = "1234567890"; -#endif - const char kFirstTestFeatureId[] = "feature-1"; BASE_FEATURE(kTestFeature1, "FeatureName1", base::FEATURE_ENABLED_BY_DEFAULT); const char kSecondTestFeatureId[] = "feature-2"; @@ -59,10 +52,6 @@ public: ChromeLabsButtonTest() : -#if BUILDFLAG(IS_CHROMEOS_ASH) - user_manager_(new ash::FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(user_manager_.get())), -#endif #if BUILDFLAG(GOOGLE_CHROME_BRANDING) channel_override_(chrome::ScopedChannelOverride( chrome::ScopedChannelOverride::Channel::kDev)), @@ -74,12 +63,6 @@ { } void SetUp() override { -#if BUILDFLAG(IS_CHROMEOS_ASH) - const AccountId account_id( - AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId)); - user_manager_->AddUser(account_id); - user_manager_->LoginUser(account_id); -#endif scoped_feature_list_.InitAndEnableFeatureWithParameters( features::kChromeLabs, {{features::kChromeLabsActivationPercentage.name, "100"}}); @@ -92,12 +75,6 @@ chrome_labs_prefs::kBrowserLabsEnabledEnterprisePolicy, true); } -#if BUILDFLAG(IS_CHROMEOS_ASH) - protected: - raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; -#endif - private: #if BUILDFLAG(GOOGLE_CHROME_BRANDING) chrome::ScopedChannelOverride channel_override_; @@ -189,14 +166,11 @@ public: ChromeLabsButtonTestSecondaryUser() : ChromeLabsButtonTest() {} - void SetUp() override { - // Set the email of |secondary_user| to - // |TestingProfile::kDefaultProfileUserName| so - // |ProfileHelperImpl::GetUserByProfile| returns this user. - AccountId secondary_user = - AccountId::FromUserEmail(TestingProfile::kDefaultProfileUserName); - user_manager_->AddUser(secondary_user); - ChromeLabsButtonTest::SetUp(); + void LogIn(const std::string& email) override { + // Fake primary user log-in, so that the created profile will be interpreted + // as secondary user's profile. + ChromeLabsButtonTest::LogIn("primary-user@domain.com"); + ChromeLabsButtonTest::LogIn(email); } };
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc b/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc index c30d565..469455b 100644 --- a/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc +++ b/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc
@@ -39,13 +39,11 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "base/memory/ptr_util.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h" #include "chrome/browser/ash/settings/about_flags.h" #include "chromeos/ash/components/cryptohome/cryptohome_parameters.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" -#include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_manager.h" #endif @@ -57,11 +55,6 @@ namespace { -#if BUILDFLAG(IS_CHROMEOS_ASH) -constexpr char kFakeUserName[] = "test@example.com"; -constexpr char kFakeGaiaId[] = "1234567890"; -#endif - const char kFirstTestFeatureId[] = "feature-1"; const char kTestFeatureWithVariationId[] = "feature-2"; const char kThirdTestFeatureId[] = "feature-3"; @@ -107,10 +100,6 @@ ChromeLabsCoordinatorTest() : TestWithBrowserView( base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME), -#if BUILDFLAG(IS_CHROMEOS_ASH) - user_manager_(new ash::FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(user_manager_.get())), -#endif #if BUILDFLAG(GOOGLE_CHROME_BRANDING) channel_override_(chrome::ScopedChannelOverride( chrome::ScopedChannelOverride::Channel::kDev)), @@ -136,13 +125,6 @@ } void SetUp() override { -#if BUILDFLAG(IS_CHROMEOS_ASH) - const AccountId account_id( - AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId)); - user_manager_->AddUser(account_id); - user_manager_->LoginUser(account_id); -#endif - scoped_feature_list_.InitAndEnableFeatureWithParameters( features::kChromeLabs, {{features::kChromeLabsActivationPercentage.name, "100"}}); @@ -183,11 +165,6 @@ std::unique_ptr<ChromeLabsCoordinator> chrome_labs_coordinator_; private: -#if BUILDFLAG(IS_CHROMEOS_ASH) - raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; -#endif - #if BUILDFLAG(GOOGLE_CHROME_BRANDING) chrome::ScopedChannelOverride channel_override_; #endif @@ -252,10 +229,6 @@ ChromeLabsViewControllerTest() : TestWithBrowserView( base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME), -#if BUILDFLAG(IS_CHROMEOS_ASH) - user_manager_(new ash::FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(user_manager_.get())), -#endif #if BUILDFLAG(GOOGLE_CHROME_BRANDING) channel_override_(chrome::ScopedChannelOverride( chrome::ScopedChannelOverride::Channel::kDev)), @@ -281,13 +254,6 @@ } void SetUp() override { -#if BUILDFLAG(IS_CHROMEOS_ASH) - const AccountId account_id( - AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId)); - user_manager_->AddUser(account_id); - user_manager_->LoginUser(account_id); -#endif - scoped_feature_list_.InitAndEnableFeatureWithParameters( features::kChromeLabs, {{features::kChromeLabsActivationPercentage.name, "100"}}); @@ -400,10 +366,6 @@ raw_ptr<views::Widget, DanglingUntriaged> bubble_widget_; private: -#if BUILDFLAG(IS_CHROMEOS_ASH) - raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; -#endif #if BUILDFLAG(GOOGLE_CHROME_BRANDING) chrome::ScopedChannelOverride channel_override_; #endif @@ -481,21 +443,10 @@ class ChromeLabsAshFeatureTest : public ChromeLabsFeatureTest { public: - ChromeLabsAshFeatureTest() - : ChromeLabsFeatureTest(), - user_manager_(new FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(user_manager_.get())) { + ChromeLabsAshFeatureTest() { SessionManagerClient::InitializeFakeInMemory(); FakeSessionManagerClient::Get()->set_supports_browser_restart(true); - const AccountId account_id( - AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId)); - user_manager_->AddUser(account_id); - user_manager_->LoginUser(account_id); } - - private: - raw_ptr<FakeChromeUserManager, DanglingUntriaged> user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; }; TEST_P(ChromeLabsAshFeatureTest, ChangeSelectedOption) {
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index b3cb3ba8..36163ca 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -79,7 +79,6 @@ #include "chrome/browser/ui/web_applications/web_app_dialogs.h" #include "chrome/browser/ui/web_applications/web_app_launch_utils.h" #include "chrome/browser/ui/web_applications/web_app_menu_model.h" -#include "chrome/browser/ui/webui/app_management/app_management_page_handler_base.h" #include "chrome/browser/ui/webui/app_settings/web_app_settings_ui.h" #include "chrome/browser/ui/webui/web_app_internals/web_app_internals_handler.h" #include "chrome/browser/web_applications/app_service/web_app_publisher_helper.h" @@ -157,6 +156,7 @@ #else #include "chrome/browser/ui/webui/app_home/app_home.mojom.h" #include "chrome/browser/ui/webui/app_home/app_home_page_handler.h" +#include "chrome/browser/ui/webui/app_management/web_app_settings_page_handler.h" #endif #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -698,14 +698,14 @@ } #if !BUILDFLAG(IS_CHROMEOS) -AppManagementPageHandlerBase CreateAppManagementPageHandler(Profile* profile) { +WebAppSettingsPageHandler CreateAppManagementPageHandler(Profile* profile) { mojo::PendingReceiver<app_management::mojom::Page> page; mojo::Remote<app_management::mojom::PageHandler> handler; static auto delegate = WebAppSettingsUI::CreateAppManagementPageHandlerDelegate(profile); - return AppManagementPageHandlerBase(handler.BindNewPipeAndPassReceiver(), - page.InitWithNewPipeAndPassRemote(), - profile, *delegate); + return WebAppSettingsPageHandler(handler.BindNewPipeAndPassReceiver(), + page.InitWithNewPipeAndPassRemote(), profile, + *delegate); } #endif @@ -1557,6 +1557,11 @@ if (!BeforeStateChangeAction(__FUNCTION__)) { return; } + base::RunLoop run_loop; + WebAppProvider::GetForTest(profile()) + ->policy_manager() + .SetRefreshPolicySettingsCompletedCallbackForTesting( + run_loop.QuitClosure()); GURL url = GetUrlForSite(site); { ScopedListPrefUpdate update_list(profile()->GetPrefs(), @@ -1565,6 +1570,7 @@ return *item.GetDict().FindString(kManifestId) == url.spec(); }); } + run_loop.Run(); AfterStateChangeAction(); } @@ -4185,6 +4191,11 @@ void WebAppIntegrationTestDriver::ApplyRunOnOsLoginPolicy(Site site, const char* policy) { + base::RunLoop run_loop; + WebAppProvider::GetForTest(profile()) + ->policy_manager() + .SetRefreshPolicySettingsCompletedCallbackForTesting( + run_loop.QuitClosure()); GURL url = GetUrlForSite(site); { ScopedListPrefUpdate update(profile()->GetPrefs(), prefs::kWebAppSettings); @@ -4199,6 +4210,7 @@ update_list.Append(std::move(dict_item)); } + run_loop.Run(); } void WebAppIntegrationTestDriver::UninstallPolicyAppById(
diff --git a/chrome/browser/ui/web_applications/sub_apps_service_impl.cc b/chrome/browser/ui/web_applications/sub_apps_service_impl.cc index 5343450..601b0d9 100644 --- a/chrome/browser/ui/web_applications/sub_apps_service_impl.cc +++ b/chrome/browser/ui/web_applications/sub_apps_service_impl.cc
@@ -8,9 +8,9 @@ #include <utility> #include <vector> -#include "base/barrier_callback.h" #include "base/check.h" #include "base/functional/bind.h" +#include "base/functional/concurrent_callbacks.h" #include "base/i18n/message_formatter.h" #include "base/strings/utf_string_conversions.h" #include "base/types/expected.h" @@ -256,13 +256,11 @@ int add_call_id, std::vector<SubAppInstallParams> requested_installs, webapps::ManifestId parent_manifest_id) { - const auto install_info_collector = base::BarrierCallback< - std::pair<webapps::ManifestId, std::unique_ptr<WebAppInstallInfo>>>( - requested_installs.size(), - base::BindOnce(&SubAppsServiceImpl::ProcessInstallData, - weak_ptr_factory_.GetWeakPtr(), add_call_id)); - WebAppProvider* provider = GetWebAppProvider(render_frame_host()); + base::ConcurrentCallbacks< + std::pair<webapps::ManifestId, std::unique_ptr<WebAppInstallInfo>>> + concurrent; + // Schedule data collection for each requested install for (const auto& [manifest_id, url_to_load] : requested_installs) { // Check if app is the parent app itself @@ -271,7 +269,6 @@ .results.emplace_back(SubAppsServiceAddResult::New( ConvertUrlToPath(manifest_id), blink::mojom::SubAppsServiceResultCode::kFailure)); - install_info_collector.Run(std::pair(GURL(), nullptr)); continue; } @@ -282,7 +279,6 @@ .results.emplace_back(SubAppsServiceAddResult::New( ConvertUrlToPath(manifest_id), blink::mojom::SubAppsServiceResultCode::kSuccess)); - install_info_collector.Run(std::pair(GURL(), nullptr)); continue; } @@ -294,8 +290,12 @@ return std::pair(manifest_app_id, std::move(install_info)); }, manifest_id) - .Then(install_info_collector)); + .Then(concurrent.CreateCallback())); } + + std::move(concurrent) + .Done(base::BindOnce(&SubAppsServiceImpl::ProcessInstallData, + weak_ptr_factory_.GetWeakPtr(), add_call_id)); } void SubAppsServiceImpl::ProcessInstallData( @@ -375,14 +375,9 @@ void SubAppsServiceImpl::ScheduleSubAppInstalls(int add_call_id) { AddCallInfo& add_call_info = add_call_info_.at(add_call_id); - const auto install_results_collector = - base::BarrierCallback<SubAppInstallResult>( - add_call_info.install_infos.size(), - base::BindOnce(&SubAppsServiceImpl::FinishAddCall, - weak_ptr_factory_.GetWeakPtr(), add_call_id)); - // Schedule install for each install_info that was collected WebAppProvider* provider = GetWebAppProvider(render_frame_host()); + base::ConcurrentCallbacks<SubAppInstallResult> concurrent; for (auto& install_info : add_call_info.install_infos) { webapps::ManifestId manifest_id = install_info->manifest_id; provider->scheduler().InstallFromInfo( @@ -394,8 +389,11 @@ return SubAppInstallResult(manifest_id, app_id, result_code); }, manifest_id) - .Then(install_results_collector)); + .Then(concurrent.CreateCallback())); } + std::move(concurrent) + .Done(base::BindOnce(&SubAppsServiceImpl::FinishAddCall, + weak_ptr_factory_.GetWeakPtr(), add_call_id)); } void SubAppsServiceImpl::FinishAddCall( @@ -468,17 +466,16 @@ return std::move(result_callback).Run(std::move(result)); } - auto remove_barrier_callback = - base::BarrierCallback<SubAppsServiceRemoveResultPtr>( - manifest_id_paths.size(), - base::BindOnce(&SubAppsServiceImpl::NotifyUninstall, - weak_ptr_factory_.GetWeakPtr(), - std::move(result_callback))); - + // Take weak pointer early as this may get deleted by RemoveSubApp(). + base::WeakPtr<SubAppsServiceImpl> weak_ptr = weak_ptr_factory_.GetWeakPtr(); + base::ConcurrentCallbacks<SubAppsServiceRemoveResultPtr> concurrent; for (const std::string& manifest_id_path : manifest_id_paths) { - RemoveSubApp(manifest_id_path, remove_barrier_callback, + RemoveSubApp(manifest_id_path, concurrent.CreateCallback(), GetAppId(render_frame_host())); } + std::move(concurrent) + .Done(base::BindOnce(&SubAppsServiceImpl::NotifyUninstall, weak_ptr, + std::move(result_callback))); } void SubAppsServiceImpl::RemoveSubApp(
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc index 41110c5b..041232c 100644 --- a/chrome/browser/ui/web_applications/web_app_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_browsertest.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 "chrome/browser/web_applications/web_app.h" + #include <stddef.h> + #include <memory> #include <optional> #include <set> @@ -11,12 +14,12 @@ #include <utility> #include <vector> -#include "base/barrier_callback.h" #include "base/check.h" #include "base/check_op.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback.h" +#include "base/functional/concurrent_callbacks.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" @@ -70,7 +73,6 @@ #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/browser/web_applications/test/web_app_test_observers.h" #include "chrome/browser/web_applications/test/web_app_test_utils.h" -#include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_command_manager.h" #include "chrome/browser/web_applications/web_app_command_scheduler.h" #include "chrome/browser/web_applications/web_app_constants.h" @@ -1752,9 +1754,13 @@ base::HistogramTester tester; base::test::TestFuture<Result> result; - auto synchronize_barrier = base::BarrierCallback<Result>( - /*num_callbacks=*/2, - base::BindOnce( + base::ConcurrentCallbacks<Result> concurrent; + provider->os_integration_manager().UpdateShortcuts( + app_id, "Manifest test app", concurrent.CreateCallback()); + provider->os_integration_manager().Synchronize( + app_id, base::BindOnce(concurrent.CreateCallback(), Result::kOk)); + std::move(concurrent) + .Done(base::BindOnce( [&](base::OnceCallback<void(Result)> result_callback, std::vector<Result> final_results) { DCHECK_EQ(2u, final_results.size()); @@ -1767,10 +1773,6 @@ }, result.GetCallback())); - provider->os_integration_manager().UpdateShortcuts( - app_id, "Manifest test app", synchronize_barrier); - provider->os_integration_manager().Synchronize( - app_id, base::BindOnce(synchronize_barrier, Result::kOk)); ASSERT_TRUE(result.Wait()); EXPECT_THAT(result.Get(), testing::Eq(Result::kOk));
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_base.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler_base.cc index b9d343b3..cb9ee7e 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler_base.cc +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_base.cc
@@ -18,6 +18,7 @@ #include "base/functional/callback_helpers.h" #include "base/i18n/message_formatter.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -69,7 +70,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/components/arc/session/connection_holder.h" #include "chrome/browser/ash/app_list/arc/arc_app_utils.h" -#include "chrome/browser/ash/apps/apk_web_app_service.h" #include "chrome/browser/ash/crosapi/crosapi_ash.h" #include "chrome/browser/ash/crosapi/crosapi_manager.h" #include "chrome/browser/ash/crosapi/web_app_service_ash.h" @@ -281,32 +281,6 @@ } // namespace -AppManagementPageHandlerBase::AppManagementPageHandlerBase( - mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, - mojo::PendingRemote<app_management::mojom::Page> page, - Profile* profile, - Delegate& delegate) - : receiver_(this, std::move(receiver)), - page_(std::move(page)), - profile_(profile), -#if BUILDFLAG(IS_CHROMEOS_ASH) - shelf_delegate_(this, profile), -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - delegate_(delegate) { - apps::AppServiceProxy* proxy = - apps::AppServiceProxyFactory::GetForProfile(profile_); - app_registry_cache_observer_.Observe(&proxy->AppRegistryCache()); - preferred_apps_list_handle_observer_.Observe(&proxy->PreferredAppsList()); - - // On Chrome OS, file handler updates are already plumbed through - // App Service since the change will also affect the intent filters. - // There's no need to update twice. -#if !BUILDFLAG(IS_CHROMEOS) - auto* provider = web_app::WebAppProvider::GetForWebApps(profile_); - registrar_observation_.Observe(&provider->registrar_unsafe()); -#endif -} - AppManagementPageHandlerBase::~AppManagementPageHandlerBase() {} void AppManagementPageHandlerBase::OnPinnedChanged(const std::string& app_id, @@ -439,16 +413,6 @@ app_id, std::move(permission)); } -void AppManagementPageHandlerBase::SetResizeLocked(const std::string& app_id, - bool locked) { -#if BUILDFLAG(IS_CHROMEOS_ASH) - apps::AppServiceProxyFactory::GetForProfile(profile_)->SetResizeLocked( - app_id, locked); -#else - NOTIMPLEMENTED(); -#endif -} - void AppManagementPageHandlerBase::Uninstall(const std::string& app_id) { apps::AppServiceProxyFactory::GetForProfile(profile_)->Uninstall( app_id, apps::UninstallSource::kAppManagement, @@ -461,98 +425,11 @@ app_id); } -void AppManagementPageHandlerBase::SetPreferredApp(const std::string& app_id, - bool is_preferred_app) { -#if BUILDFLAG(IS_CHROMEOS) - auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); - bool is_preferred_app_for_supported_links = - proxy->PreferredAppsList().IsPreferredAppForSupportedLinks(app_id); - - if (is_preferred_app && !is_preferred_app_for_supported_links) { - proxy->SetSupportedLinksPreference(app_id); - } else if (!is_preferred_app && is_preferred_app_for_supported_links) { - proxy->RemoveSupportedLinksPreference(app_id); - } -#else - web_app::WebAppProvider* provider = - web_app::WebAppProvider::GetForWebApps(profile_); - - provider->scheduler().SetAppCapturesSupportedLinksDisableOverlapping( - app_id, is_preferred_app, base::DoNothing()); -#endif // BUILDFLAG(IS_CHROMEOS) -} - -void AppManagementPageHandlerBase::GetOverlappingPreferredApps( - const std::string& app_id, - GetOverlappingPreferredAppsCallback callback) { -#if BUILDFLAG(IS_CHROMEOS) - auto intent_filters = GetSupportedLinkIntentFilters(profile_, app_id); - auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); - base::flat_set<std::string> app_ids = - proxy->PreferredAppsList().FindPreferredAppsForFilters(intent_filters); - app_ids.erase(app_id); - - // Erase all IDs that do not correspond to installed apps in App Service. Such - // IDs could be apps that have been uninstalled but did not have their - // preference updated correctly, or the legacy "use_browser" preference. This - // prevents attempting to show an overlapping app dialog for an app that - // doesn't currently exist. - base::EraseIf(app_ids, [proxy](const std::string& app_id) { - return !proxy->AppRegistryCache().IsAppInstalled(app_id); - }); - std::move(callback).Run(std::move(app_ids).extract()); -#else - web_app::WebAppProvider* provider = - web_app::WebAppProvider::GetForWebApps(profile_); - provider->scheduler().ScheduleCallbackWithResult( - "AppManagementPageHandlerBase::GetOverlappingPreferredApps", - web_app::AllAppsLockDescription(), - base::BindOnce( - [](const webapps::AppId& app_id, web_app::AllAppsLock& all_apps_lock, - base::Value::Dict& debug_value) { - return all_apps_lock.registrar().GetOverlappingAppsMatchingScope( - app_id); - }, - app_id), - std::move(callback), /*arg_for_shutdown=*/std::vector<std::string>()); -#endif // BUILDFLAG(IS_CHROMEOS) -} - void AppManagementPageHandlerBase::UpdateAppSize(const std::string& app_id) { auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); proxy->UpdateAppSize(app_id); } -void AppManagementPageHandlerBase::SetWindowMode(const std::string& app_id, - apps::WindowMode window_mode) { - // On ChromeOS, apps should always open in a new window, - // hence window mode changes are not allowed. -#if BUILDFLAG(IS_CHROMEOS) - NOTIMPLEMENTED(); -#else - auto* provider = web_app::WebAppProvider::GetForLocalAppsUnchecked(profile_); - - // Changing window mode is not allowed for isolated web apps. - if (provider->registrar_unsafe().IsIsolated(app_id)) { - return; - } - - apps::AppServiceProxyFactory::GetForProfile(profile_)->SetWindowMode( - app_id, window_mode); -#endif -} - -void AppManagementPageHandlerBase::SetRunOnOsLoginMode( - const std::string& app_id, - apps::RunOnOsLoginMode run_on_os_login_mode) { -#if BUILDFLAG(IS_CHROMEOS) - NOTIMPLEMENTED(); -#else - apps::AppServiceProxyFactory::GetForProfile(profile_)->SetRunOnOsLoginMode( - app_id, run_on_os_login_mode); -#endif -} - void AppManagementPageHandlerBase::SetFileHandlingEnabled( const std::string& app_id, bool enabled) { @@ -563,18 +440,24 @@ app_id, std::move(permission)); } -void AppManagementPageHandlerBase::ShowDefaultAppAssociationsUi() { - DCHECK(CanShowDefaultAppAssociationsUi()); -#if BUILDFLAG(IS_WIN) - base::win::LaunchDefaultAppsSettingsModernDialog({}); -#endif +AppManagementPageHandlerBase::AppManagementPageHandlerBase( + mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, + mojo::PendingRemote<app_management::mojom::Page> page, + Profile* profile, + Delegate& delegate) + : receiver_(this, std::move(receiver)), + page_(std::move(page)), + profile_(profile), +#if BUILDFLAG(IS_CHROMEOS_ASH) + shelf_delegate_(this, profile), +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + delegate_(delegate) { + apps::AppServiceProxy* proxy = + apps::AppServiceProxyFactory::GetForProfile(profile_); + app_registry_cache_observer_.Observe(&proxy->AppRegistryCache()); } -void AppManagementPageHandlerBase::OnWebAppFileHandlerApprovalStateChanged( - const webapps::AppId& app_id) { -#if BUILDFLAG(IS_CHROMEOS) - NOTREACHED(); -#endif +void AppManagementPageHandlerBase::NotifyAppChanged(const std::string& app_id) { app_management::mojom::AppPtr app; apps::AppServiceProxyFactory::GetForProfile(profile_) @@ -585,6 +468,7 @@ } }); + // If an app with this id is not already installed, do nothing. if (!app) { return; } @@ -592,18 +476,6 @@ page_->OnAppChanged(std::move(app)); } -void AppManagementPageHandlerBase::OnAppRegistrarDestroyed() { - registrar_observation_.Reset(); -} - -#if !BUILDFLAG(IS_CHROMEOS) -void AppManagementPageHandlerBase::OnWebAppUserLinkCapturingPreferencesChanged( - const webapps::AppId& app_id, - bool is_preferred) { - OnPreferredAppChanged(app_id, is_preferred); -} -#endif // !BUILDFLAG(IS_CHROMEOS) - app_management::mojom::AppPtr AppManagementPageHandlerBase::CreateUIAppPtr( const apps::AppUpdate& update) { auto app = app_management::mojom::App::New(); @@ -780,43 +652,6 @@ return app; } -void AppManagementPageHandlerBase::OpenStorePage(const std::string& app_id) { -#if BUILDFLAG(IS_CHROMEOS_ASH) - auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); - auto* apk_service = ash::ApkWebAppService::Get(profile_); - proxy->AppRegistryCache().ForOneApp( - app_id, [&proxy, &apk_service](const apps::AppUpdate& update) { - if (update.InstallSource() == apps::InstallSource::kPlayStore) { - std::string package_name = update.PublisherId(); - if (apk_service->IsWebAppInstalledFromArc(update.AppId())) { - package_name = - apk_service->GetPackageNameForWebApp(update.AppId()).value(); - } - GURL url("https://play.google.com/store/apps/details?id=" + - package_name); - proxy->LaunchAppWithUrl(arc::kPlayStoreAppId, ui::EF_NONE, url, - apps::LaunchSource::kFromChromeInternal); - } else if (update.InstallSource() == - apps::InstallSource::kChromeWebStore) { - GURL url("https://chrome.google.com/webstore/detail/" + - update.AppId()); - proxy->LaunchAppWithUrl(extensions::kWebStoreAppId, ui::EF_NONE, url, - apps::LaunchSource::kFromChromeInternal); - } - }); -#endif -} - -void AppManagementPageHandlerBase::SetAppLocale(const std::string& app_id, - const std::string& locale_tag) { -#if BUILDFLAG(IS_CHROMEOS_ASH) - apps::AppServiceProxyFactory::GetForProfile(profile_)->SetAppLocale( - app_id, locale_tag); -#else - NOTIMPLEMENTED(); -#endif -} - void AppManagementPageHandlerBase::OnAppUpdate(const apps::AppUpdate& update) { if (update.ShowInManagementChanged() || update.ReadinessChanged()) { if (update.ShowInManagement().value_or(false) && @@ -837,31 +672,3 @@ apps::AppRegistryCache* cache) { cache->RemoveObserver(this); } - -void AppManagementPageHandlerBase::OnPreferredAppChanged( - const std::string& app_id, - bool is_preferred_app) { - app_management::mojom::AppPtr app; - - apps::AppServiceProxyFactory::GetForProfile(profile_) - ->AppRegistryCache() - .ForOneApp(app_id, [this, &app](const apps::AppUpdate& update) { - if (update.Readiness() == apps::Readiness::kReady) { - app = CreateUIAppPtr(update); - } - }); - - // If an app with this id is not already installed, do nothing. - if (!app) { - return; - } - - app->is_preferred_app = is_preferred_app; - - page_->OnAppChanged(std::move(app)); -} - -void AppManagementPageHandlerBase::OnPreferredAppsListWillBeDestroyed( - apps::PreferredAppsListHandle* handle) { - preferred_apps_list_handle_observer_.Reset(); -}
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_base.h b/chrome/browser/ui/webui/app_management/app_management_page_handler_base.h index 3551444..cbb2471 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler_base.h +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_base.h
@@ -11,12 +11,9 @@ #include "base/scoped_observation.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/web_applications/locks/all_apps_lock.h" -#include "chrome/browser/web_applications/web_app_registrar.h" -#include "chrome/browser/web_applications/web_app_registrar_observer.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/permission.h" -#include "components/services/app_service/public/cpp/preferred_apps_list_handle.h" #include "components/services/app_service/public/cpp/run_on_os_login_types.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -31,11 +28,8 @@ class Profile; -class AppManagementPageHandlerBase - : public app_management::mojom::PageHandler, - public apps::AppRegistryCache::Observer, - public apps::PreferredAppsListHandle::Observer, - public web_app::WebAppRegistrarObserver { +class AppManagementPageHandlerBase : public app_management::mojom::PageHandler, + public apps::AppRegistryCache::Observer { public: // Handles platform specific tasks. class Delegate { @@ -49,12 +43,6 @@ virtual gfx::NativeWindow GetUninstallAnchorWindow() const = 0; }; - AppManagementPageHandlerBase( - mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, - mojo::PendingRemote<app_management::mojom::Page> page, - Profile* profile, - Delegate& delegate); - AppManagementPageHandlerBase(const AppManagementPageHandlerBase&) = delete; AppManagementPageHandlerBase& operator=(const AppManagementPageHandlerBase&) = delete; @@ -73,39 +61,23 @@ void SetPinned(const std::string& app_id, bool pinned) override; void SetPermission(const std::string& app_id, apps::PermissionPtr permission) override; - void SetResizeLocked(const std::string& app_id, bool locked) override; void Uninstall(const std::string& app_id) override; void OpenNativeSettings(const std::string& app_id) override; - void SetPreferredApp(const std::string& app_id, - bool is_preferred_app) override; - void GetOverlappingPreferredApps( - const std::string& app_id, - GetOverlappingPreferredAppsCallback callback) override; void UpdateAppSize(const std::string& app_id) override; - void SetWindowMode(const std::string& app_id, - apps::WindowMode window_mode) override; - void SetRunOnOsLoginMode( - const std::string& app_id, - apps::RunOnOsLoginMode run_on_os_login_mode) override; void SetFileHandlingEnabled(const std::string& app_id, bool enabled) override; - void ShowDefaultAppAssociationsUi() override; - void OpenStorePage(const std::string& app_id) override; - void SetAppLocale(const std::string& app_id, - const std::string& locale_tag) override; - // web_app::WebAppRegistrarObserver: - void OnWebAppFileHandlerApprovalStateChanged( - const webapps::AppId& app_id) override; - void OnAppRegistrarDestroyed() override; + protected: + AppManagementPageHandlerBase( + mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, + mojo::PendingRemote<app_management::mojom::Page> page, + Profile* profile, + Delegate& delegate); - // The following observers are used for user link capturing on W/M/L platforms - // to observe user link capturing preferences being changed - // in the registrar, so as to propagate the changes to the app-settings/ page - // to change the UI dynamically. -#if !BUILDFLAG(IS_CHROMEOS) - void OnWebAppUserLinkCapturingPreferencesChanged(const webapps::AppId& app_id, - bool is_preferred) override; -#endif // !BUILDFLAG(IS_CHROMEOS) + // Notify the WebUI frontend that the app with a given `app_id` has changed on + // the backend. Will generate a new AppPtr and send it to the frontend. + void NotifyAppChanged(const std::string& app_id); + + Profile* profile() { return profile_; } private: app_management::mojom::AppPtr CreateUIAppPtr(const apps::AppUpdate& update); @@ -115,12 +87,6 @@ void OnAppRegistryCacheWillBeDestroyed( apps::AppRegistryCache* cache) override; - // apps::PreferredAppsListHandle::Observer overrides: - void OnPreferredAppChanged(const std::string& app_id, - bool is_preferred_app) override; - void OnPreferredAppsListWillBeDestroyed( - apps::PreferredAppsListHandle* handle) override; - mojo::Receiver<app_management::mojom::PageHandler> receiver_; mojo::Remote<app_management::mojom::Page> page_; @@ -137,14 +103,6 @@ apps::AppRegistryCache::Observer> app_registry_cache_observer_{this}; - base::ScopedObservation<apps::PreferredAppsListHandle, - apps::PreferredAppsListHandle::Observer> - preferred_apps_list_handle_observer_{this}; - - base::ScopedObservation<web_app::WebAppRegistrar, - web_app::WebAppRegistrarObserver> - registrar_observation_{this}; - base::WeakPtrFactory<AppManagementPageHandlerBase> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.cc new file mode 100644 index 0000000..949ce60 --- /dev/null +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.cc
@@ -0,0 +1,158 @@ +// 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/ui/webui/app_management/app_management_page_handler_chromeos.h" + +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/ash/app_list/arc/arc_app_utils.h" +#include "chrome/browser/ash/apps/apk_web_app_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/app_management/app_management_page_handler_base.h" +#include "components/services/app_service/public/cpp/intent_filter_util.h" +#include "components/services/app_service/public/cpp/preferred_apps_list_handle.h" +#include "extensions/common/constants.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" + +namespace { + +// Returns a list of intent filters that support http/https given an app ID. +apps::IntentFilters GetSupportedLinkIntentFilters(Profile* profile, + const std::string& app_id) { + apps::IntentFilters intent_filters; + apps::AppServiceProxyFactory::GetForProfile(profile) + ->AppRegistryCache() + .ForOneApp(app_id, + [&app_id, &intent_filters](const apps::AppUpdate& update) { + if (update.Readiness() == apps::Readiness::kReady) { + for (auto& filter : update.IntentFilters()) { + if (apps_util::IsSupportedLinkForApp(app_id, filter)) { + intent_filters.emplace_back(std::move(filter)); + } + } + } + }); + return intent_filters; +} + +} // namespace + +AppManagementPageHandlerChromeOs::AppManagementPageHandlerChromeOs( + mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, + mojo::PendingRemote<app_management::mojom::Page> page, + Profile* profile, + AppManagementPageHandlerBase::Delegate& delegate) + : AppManagementPageHandlerBase(std::move(receiver), + std::move(page), + profile, + delegate) { + apps::AppServiceProxy* proxy = + apps::AppServiceProxyFactory::GetForProfile(profile); + preferred_apps_list_handle_observer_.Observe(&proxy->PreferredAppsList()); +} + +AppManagementPageHandlerChromeOs::~AppManagementPageHandlerChromeOs() = default; + +void AppManagementPageHandlerChromeOs::SetResizeLocked( + const std::string& app_id, + bool locked) { + apps::AppServiceProxyFactory::GetForProfile(profile())->SetResizeLocked( + app_id, locked); +} + +void AppManagementPageHandlerChromeOs::SetPreferredApp( + const std::string& app_id, + bool is_preferred_app) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile()); + bool is_preferred_app_for_supported_links = + proxy->PreferredAppsList().IsPreferredAppForSupportedLinks(app_id); + + if (is_preferred_app && !is_preferred_app_for_supported_links) { + proxy->SetSupportedLinksPreference(app_id); + } else if (!is_preferred_app && is_preferred_app_for_supported_links) { + proxy->RemoveSupportedLinksPreference(app_id); + } +} + +void AppManagementPageHandlerChromeOs::GetOverlappingPreferredApps( + const std::string& app_id, + GetOverlappingPreferredAppsCallback callback) { + auto intent_filters = GetSupportedLinkIntentFilters(profile(), app_id); + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile()); + base::flat_set<std::string> app_ids = + proxy->PreferredAppsList().FindPreferredAppsForFilters(intent_filters); + app_ids.erase(app_id); + + // Erase all IDs that do not correspond to installed apps in App Service. Such + // IDs could be apps that have been uninstalled but did not have their + // preference updated correctly, or the legacy "use_browser" preference. This + // prevents attempting to show an overlapping app dialog for an app that + // doesn't currently exist. + base::EraseIf(app_ids, [proxy](const std::string& app_id) { + return !proxy->AppRegistryCache().IsAppInstalled(app_id); + }); + std::move(callback).Run(std::move(app_ids).extract()); +} + +void AppManagementPageHandlerChromeOs::SetWindowMode( + const std::string& app_id, + apps::WindowMode window_mode) { + NOTIMPLEMENTED(); +} + +void AppManagementPageHandlerChromeOs::SetRunOnOsLoginMode( + const std::string& app_id, + apps::RunOnOsLoginMode run_on_os_login_mode) { + NOTIMPLEMENTED(); +} + +void AppManagementPageHandlerChromeOs::ShowDefaultAppAssociationsUi() { + NOTIMPLEMENTED(); +} + +void AppManagementPageHandlerChromeOs::OpenStorePage( + const std::string& app_id) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile()); + auto* apk_service = ash::ApkWebAppService::Get(profile()); + proxy->AppRegistryCache().ForOneApp( + app_id, [&proxy, &apk_service](const apps::AppUpdate& update) { + if (update.InstallSource() == apps::InstallSource::kPlayStore) { + std::string package_name = update.PublisherId(); + if (apk_service->IsWebAppInstalledFromArc(update.AppId())) { + package_name = + apk_service->GetPackageNameForWebApp(update.AppId()).value(); + } + GURL url("https://play.google.com/store/apps/details?id=" + + package_name); + proxy->LaunchAppWithUrl(arc::kPlayStoreAppId, ui::EF_NONE, url, + apps::LaunchSource::kFromChromeInternal); + } else if (update.InstallSource() == + apps::InstallSource::kChromeWebStore) { + GURL url("https://chrome.google.com/webstore/detail/" + + update.AppId()); + proxy->LaunchAppWithUrl(extensions::kWebStoreAppId, ui::EF_NONE, url, + apps::LaunchSource::kFromChromeInternal); + } + }); +} + +void AppManagementPageHandlerChromeOs::SetAppLocale( + const std::string& app_id, + const std::string& locale_tag) { + apps::AppServiceProxyFactory::GetForProfile(profile())->SetAppLocale( + app_id, locale_tag); +} + +void AppManagementPageHandlerChromeOs::OnPreferredAppChanged( + const std::string& app_id, + bool is_preferred_app) { + NotifyAppChanged(app_id); +} + +void AppManagementPageHandlerChromeOs::OnPreferredAppsListWillBeDestroyed( + apps::PreferredAppsListHandle* handle) { + preferred_apps_list_handle_observer_.Reset(); +}
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.h b/chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.h new file mode 100644 index 0000000..72e3076f --- /dev/null +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.h
@@ -0,0 +1,65 @@ +// 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_UI_WEBUI_APP_MANAGEMENT_APP_MANAGEMENT_PAGE_HANDLER_CHROMEOS_H_ +#define CHROME_BROWSER_UI_WEBUI_APP_MANAGEMENT_APP_MANAGEMENT_PAGE_HANDLER_CHROMEOS_H_ + +#include <string> + +#include "chrome/browser/ui/webui/app_management/app_management_page_handler_base.h" +#include "components/services/app_service/public/cpp/preferred_apps_list_handle.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" + +class Profile; + +// PageHandler for the ChromeOS App Management page. +class AppManagementPageHandlerChromeOs + : public AppManagementPageHandlerBase, + public apps::PreferredAppsListHandle::Observer { + public: + AppManagementPageHandlerChromeOs( + mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, + mojo::PendingRemote<app_management::mojom::Page> page, + Profile* profile, + AppManagementPageHandlerBase::Delegate& delegate); + + AppManagementPageHandlerChromeOs(const AppManagementPageHandlerChromeOs&) = + delete; + AppManagementPageHandlerChromeOs& operator=( + const AppManagementPageHandlerChromeOs&) = delete; + + ~AppManagementPageHandlerChromeOs() override; + + // app_management::mojom::PageHandler: + void SetResizeLocked(const std::string& app_id, bool locked) override; + void SetPreferredApp(const std::string& app_id, + bool is_preferred_app) override; + void GetOverlappingPreferredApps( + const std::string& app_id, + GetOverlappingPreferredAppsCallback callback) override; + void SetWindowMode(const std::string& app_id, + apps::WindowMode window_mode) override; + void SetRunOnOsLoginMode( + const std::string& app_id, + apps::RunOnOsLoginMode run_on_os_login_mode) override; + void ShowDefaultAppAssociationsUi() override; + void OpenStorePage(const std::string& app_id) override; + void SetAppLocale(const std::string& app_id, + const std::string& locale_tag) override; + + // apps::PreferredAppsListHandle::Observer overrides: + void OnPreferredAppChanged(const std::string& app_id, + bool is_preferred_app) override; + void OnPreferredAppsListWillBeDestroyed( + apps::PreferredAppsListHandle* handle) override; + + private: + base::ScopedObservation<apps::PreferredAppsListHandle, + apps::PreferredAppsListHandle::Observer> + preferred_apps_list_handle_observer_{this}; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_APP_MANAGEMENT_APP_MANAGEMENT_PAGE_HANDLER_CHROMEOS_H_
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_factory.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler_factory.cc index 0bd5a63..280586a 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler_factory.cc +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_factory.cc
@@ -24,6 +24,12 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.h" +#else +#include "chrome/browser/ui/webui/app_management/web_app_settings_page_handler.h" +#endif + AppManagementPageHandlerFactory::AppManagementPageHandlerFactory( Profile* profile, std::unique_ptr<AppManagementPageHandlerBase::Delegate> delegate) @@ -43,6 +49,11 @@ mojo::PendingReceiver<app_management::mojom::PageHandler> receiver) { DCHECK(page); - page_handler_ = std::make_unique<AppManagementPageHandlerBase>( +#if BUILDFLAG(IS_CHROMEOS_ASH) + page_handler_ = std::make_unique<AppManagementPageHandlerChromeOs>( std::move(receiver), std::move(page), profile_, *delegate_); +#else + page_handler_ = std::make_unique<WebAppSettingsPageHandler>( + std::move(receiver), std::move(page), profile_, *delegate_); +#endif }
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc index 9bca01ca..fdc01f75 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc
@@ -2,8 +2,6 @@ // 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/app_management/app_management_page_handler_base.h" - #include <memory> #include <string> #include <vector> @@ -37,10 +35,11 @@ #include "chrome/browser/ash/app_list/arc/arc_app_test.h" #include "chrome/browser/ash/app_list/arc/arc_app_utils.h" #include "chrome/browser/ash/apps/apk_web_app_service.h" +#include "chrome/browser/ui/webui/app_management/app_management_page_handler_chromeos.h" #include "components/arc/test/fake_intent_helper_instance.h" #include "components/services/app_service/public/cpp/intent_filter_util.h" #else -#include "base/test/scoped_feature_list.h" +#include "chrome/browser/ui/webui/app_management/web_app_settings_page_handler.h" #include "chrome/common/chrome_features.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -78,10 +77,14 @@ mojo::PendingReceiver<app_management::mojom::Page> page; mojo::Remote<app_management::mojom::PageHandler> handler; - handler_ = std::make_unique<AppManagementPageHandlerBase>( +#if BUILDFLAG(IS_CHROMEOS_ASH) + handler_ = std::make_unique<AppManagementPageHandlerChromeOs>( handler.BindNewPipeAndPassReceiver(), page.InitWithNewPipeAndPassRemote(), profile(), *delegate_); -#if !BUILDFLAG(IS_CHROMEOS) +#else + handler_ = std::make_unique<WebAppSettingsPageHandler>( + handler.BindNewPipeAndPassReceiver(), + page.InitWithNewPipeAndPassRemote(), profile(), *delegate_); auto features_and_params = apps::test::GetFeaturesToEnableLinkCapturingUX( /*override_captures_by_default=*/GetParam()); features_and_params.push_back(
diff --git a/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.cc b/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.cc new file mode 100644 index 0000000..7611328 --- /dev/null +++ b/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.cc
@@ -0,0 +1,118 @@ +// 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/ui/webui/app_management/web_app_settings_page_handler.h" + +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/app_management/app_management_page_handler_base.h" +#include "chrome/browser/web_applications/web_app_command_scheduler.h" +#include "chrome/browser/web_applications/web_app_provider.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" + +#if BUILDFLAG(IS_WIN) +#include "base/win/default_apps_util.h" +#endif + +WebAppSettingsPageHandler::WebAppSettingsPageHandler( + mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, + mojo::PendingRemote<app_management::mojom::Page> page, + Profile* profile, + AppManagementPageHandlerBase::Delegate& delegate) + : AppManagementPageHandlerBase(std::move(receiver), + std::move(page), + profile, + delegate) { + auto* provider = web_app::WebAppProvider::GetForWebApps(profile); + registrar_observation_.Observe(&provider->registrar_unsafe()); +} + +WebAppSettingsPageHandler::~WebAppSettingsPageHandler() = default; + +void WebAppSettingsPageHandler::SetResizeLocked(const std::string& app_id, + bool locked) { + NOTIMPLEMENTED(); +} + +void WebAppSettingsPageHandler::SetPreferredApp(const std::string& app_id, + bool is_preferred_app) { + web_app::WebAppProvider* provider = + web_app::WebAppProvider::GetForWebApps(profile()); + + provider->scheduler().SetAppCapturesSupportedLinksDisableOverlapping( + app_id, is_preferred_app, base::DoNothing()); +} + +void WebAppSettingsPageHandler::GetOverlappingPreferredApps( + const std::string& app_id, + GetOverlappingPreferredAppsCallback callback) { + web_app::WebAppProvider* provider = + web_app::WebAppProvider::GetForWebApps(profile()); + provider->scheduler().ScheduleCallbackWithResult( + "AppManagementPageHandlerBase::GetOverlappingPreferredApps", + web_app::AllAppsLockDescription(), + base::BindOnce( + [](const webapps::AppId& app_id, web_app::AllAppsLock& all_apps_lock, + base::Value::Dict& debug_value) { + return all_apps_lock.registrar().GetOverlappingAppsMatchingScope( + app_id); + }, + app_id), + std::move(callback), /*arg_for_shutdown=*/std::vector<std::string>()); +} + +void WebAppSettingsPageHandler::SetWindowMode(const std::string& app_id, + apps::WindowMode window_mode) { + auto* provider = web_app::WebAppProvider::GetForLocalAppsUnchecked(profile()); + + // Changing window mode is not allowed for isolated web apps. + if (provider->registrar_unsafe().IsIsolated(app_id)) { + return; + } + + apps::AppServiceProxyFactory::GetForProfile(profile())->SetWindowMode( + app_id, window_mode); +} + +void WebAppSettingsPageHandler::SetRunOnOsLoginMode( + const std::string& app_id, + apps::RunOnOsLoginMode run_on_os_login_mode) { + apps::AppServiceProxyFactory::GetForProfile(profile())->SetRunOnOsLoginMode( + app_id, run_on_os_login_mode); +} + +void WebAppSettingsPageHandler::ShowDefaultAppAssociationsUi() { +#if BUILDFLAG(IS_WIN) + base::win::LaunchDefaultAppsSettingsModernDialog({}); +#else + NOTIMPLEMENTED(); +#endif +} + +void WebAppSettingsPageHandler::OpenStorePage(const std::string& app_id) { + NOTIMPLEMENTED(); +} + +void WebAppSettingsPageHandler::SetAppLocale(const std::string& app_id, + const std::string& locale_tag) { + NOTIMPLEMENTED(); +} + +void WebAppSettingsPageHandler::OnAppRegistrarDestroyed() { + registrar_observation_.Reset(); +} + +void WebAppSettingsPageHandler::OnWebAppFileHandlerApprovalStateChanged( + const webapps::AppId& app_id) { + NotifyAppChanged(app_id); +} + +void WebAppSettingsPageHandler::OnWebAppUserLinkCapturingPreferencesChanged( + const webapps::AppId& app_id, + bool is_preferred) { + NotifyAppChanged(app_id); +}
diff --git a/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.h b/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.h new file mode 100644 index 0000000..c883cc4 --- /dev/null +++ b/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.h
@@ -0,0 +1,67 @@ +// 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_UI_WEBUI_APP_MANAGEMENT_WEB_APP_SETTINGS_PAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_APP_MANAGEMENT_WEB_APP_SETTINGS_PAGE_HANDLER_H_ + +#include "chrome/browser/ui/webui/app_management/app_management_page_handler_base.h" +#include "chrome/browser/web_applications/web_app_registrar_observer.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" + +class Profile; + +namespace web_app { +class WebAppRegistrar; +} + +// PageHandler for the chrome://app-settings page. Connects directly to the +// WebAppProvider to manage settings for web apps. +class WebAppSettingsPageHandler : public AppManagementPageHandlerBase, + public web_app::WebAppRegistrarObserver { + public: + WebAppSettingsPageHandler( + mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, + mojo::PendingRemote<app_management::mojom::Page> page, + Profile* profile, + AppManagementPageHandlerBase::Delegate& delegate); + + WebAppSettingsPageHandler(const WebAppSettingsPageHandler&) = delete; + WebAppSettingsPageHandler& operator=(const WebAppSettingsPageHandler&) = + delete; + + ~WebAppSettingsPageHandler() override; + + // app_management::mojom::PageHandler: + void SetResizeLocked(const std::string& app_id, bool locked) override; + void SetPreferredApp(const std::string& app_id, + bool is_preferred_app) override; + void GetOverlappingPreferredApps( + const std::string& app_id, + GetOverlappingPreferredAppsCallback callback) override; + void SetWindowMode(const std::string& app_id, + apps::WindowMode window_mode) override; + void SetRunOnOsLoginMode( + const std::string& app_id, + apps::RunOnOsLoginMode run_on_os_login_mode) override; + void ShowDefaultAppAssociationsUi() override; + void OpenStorePage(const std::string& app_id) override; + void SetAppLocale(const std::string& app_id, + const std::string& locale_tag) override; + + // web_app::WebAppRegistrarObserver: + void OnAppRegistrarDestroyed() override; + void OnWebAppFileHandlerApprovalStateChanged( + const webapps::AppId& app_id) override; + void OnWebAppUserLinkCapturingPreferencesChanged(const webapps::AppId& app_id, + bool is_preferred) override; + + private: + base::ScopedObservation<web_app::WebAppRegistrar, + web_app::WebAppRegistrarObserver> + registrar_observation_{this}; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_APP_MANAGEMENT_WEB_APP_SETTINGS_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc index f9ecca0..93dd6dd 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc
@@ -145,6 +145,8 @@ case OfficeDriveOpenErrors::kNoDriveService: case OfficeDriveOpenErrors::kDriveAuthenticationNotReady: case OfficeDriveOpenErrors::kMeteredConnection: + case OfficeDriveOpenErrors::kDisableDrivePreferenceSet: + case OfficeDriveOpenErrors::kDriveDisabledForAccountType: break; case OfficeDriveOpenErrors::kTimeout: case OfficeDriveOpenErrors::kNoMetadata: @@ -258,6 +260,8 @@ case OfficeDriveOpenErrors::kMeteredConnection: case OfficeDriveOpenErrors::kEmptyAlternateUrl: case OfficeDriveOpenErrors::kWaitingForUpload: + case OfficeDriveOpenErrors::kDisableDrivePreferenceSet: + case OfficeDriveOpenErrors::kDriveDisabledForAccountType: break; case OfficeDriveOpenErrors::kSuccess: SetWrongValueLogged(drive_open_error); @@ -312,6 +316,8 @@ case OfficeDriveOpenErrors::kMeteredConnection: case OfficeDriveOpenErrors::kEmptyAlternateUrl: case OfficeDriveOpenErrors::kWaitingForUpload: + case OfficeDriveOpenErrors::kDisableDrivePreferenceSet: + case OfficeDriveOpenErrors::kDriveDisabledForAccountType: SetWrongValueLogged(drive_open_error); break; }
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc index b5adb6af..cfdbbf8 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc
@@ -311,9 +311,11 @@ ASSERT_EQ(1, CloudOpenMetricsTest::number_of_dump_calls()); } -// Tests that the SourceVolume companion metric is set correctly when TaskResult -// is logged as kFailedToOpen and it is logged consistently. -TEST_F(CloudOpenMetricsTest, MetricsConsistentWhenTaskResultIsFailedToOpen) { +// Tests that the OpenErrors companion metric is set correctly when TaskResult +// is logged as kFailedToOpen and it is logged consistently when opening in +// OneDrive. +TEST_F(CloudOpenMetricsTest, + MetricsConsistentWhenTaskResultIsFailedToOpenInOneDrive) { { CloudOpenMetrics cloud_open_metrics(CloudProvider::kOneDrive, /*file_count=*/1); @@ -325,9 +327,11 @@ MetricState::kCorrectlyLogged, 1); } -// Tests that the SourceVolume companion metric is set correctly when TaskResult -// is logged as kFailedToOpen and it is logged inconsistently. -TEST_F(CloudOpenMetricsTest, MetricsInconsistentWhenTaskResultIsFailedToOpen) { +// Tests that the OpenErrors companion metric is set correctly when TaskResult +// is logged as kFailedToOpen and it is logged inconsistently when opening in +// OneDrive. +TEST_F(CloudOpenMetricsTest, + MetricsInconsistentWhenTaskResultIsFailedToOpenInOneDrive) { { CloudOpenMetrics cloud_open_metrics(CloudProvider::kOneDrive, /*file_count=*/1); @@ -339,6 +343,38 @@ ASSERT_EQ(1, CloudOpenMetricsTest::number_of_dump_calls()); } +// Tests that the OpenErrors companion metric is set correctly when TaskResult +// is logged as kFailedToOpen and it is logged consistently when opening in +// Drive. +TEST_F(CloudOpenMetricsTest, + MetricsConsistentWhenTaskResultIsFailedToOpenInDrive) { + { + CloudOpenMetrics cloud_open_metrics(CloudProvider::kGoogleDrive, + /*file_count=*/1); + cloud_open_metrics.LogTaskResult(OfficeTaskResult::kFailedToOpen); + cloud_open_metrics.LogGoogleDriveOpenError( + OfficeDriveOpenErrors::kWaitingForUpload); + } + histogram_.ExpectUniqueSample(kDriveErrorMetricStateMetricName, + MetricState::kCorrectlyLogged, 1); +} + +// Tests that the OpenErrors companion metric is set correctly when TaskResult +// is logged as kFailedToOpen and it is logged inconsistently when opening in +// Drive. +TEST_F(CloudOpenMetricsTest, + MetricsInconsistentWhenTaskResultIsFailedToOpenInDrive) { + { + CloudOpenMetrics cloud_open_metrics(CloudProvider::kGoogleDrive, + /*file_count=*/1); + cloud_open_metrics.LogTaskResult(OfficeTaskResult::kFailedToOpen); + cloud_open_metrics.LogGoogleDriveOpenError(OfficeDriveOpenErrors::kSuccess); + } + histogram_.ExpectUniqueSample(kDriveErrorMetricStateMetricName, + MetricState::kWrongValueLogged, 1); + ASSERT_EQ(1, CloudOpenMetricsTest::number_of_dump_calls()); +} + // Tests that the OpenErrors, UploadResult and TransferRequired companion // metrics are set correctly when TaskResult is logged as kOpened and they are // logged consistently.
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h index 298d205..fd7d7bb 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h
@@ -95,7 +95,9 @@ kMeteredConnection = 11, kEmptyAlternateUrl = 12, kWaitingForUpload = 13, - kMaxValue = kWaitingForUpload, + kDisableDrivePreferenceSet = 14, + kDriveDisabledForAccountType = 15, + kMaxValue = kDriveDisabledForAccountType, }; // List of UMA enum values for opening Office files from OneDrive, with the
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc index 66c7090..c647fad 100644 --- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc +++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.cc
@@ -22,11 +22,16 @@ // Width of the Fallback dialog as found with the inspector tool. const int kWidth = 512; -// Height of the Fallback dialogs for different text lengths as found with the -// inspector tool. -const int kOfflineHeight = 264; -const int kDriveUnavailableHeight = 244; -const int kMeteredHeight = 264; +// Exact height of the Fallback dialogs required for different texts (in +// English) as found with the inspector tool. +const int kOfflineHeight = 244; +const int kDisableDrivePreferenceSetHeight = 268; +const int kDriveUnavailableHeight = 268; +const int kDriveDisabledForAccountType = 268; +const int kMeteredHeight = 268; + +// Height of a line of text as found with the inspector tool. +const int kLineHeight = 20; // Return the task title id for the task represented by the `action_id`. int GetTaskTitleId(const std::string& action_id) { @@ -56,34 +61,53 @@ const ash::office_fallback::FallbackReason fallback_reason, int& title_id, int& reason_message_id, + bool& include_task_in_reason_message, int& instructions_message_id, int& width, int& height) { width = kWidth; + include_task_in_reason_message = false; switch (fallback_reason) { case ash::office_fallback::FallbackReason::kOffline: + case ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady: title_id = IDS_OFFICE_FALLBACK_TITLE_OFFLINE; reason_message_id = IDS_OFFICE_FALLBACK_REASON_OFFLINE; instructions_message_id = IDS_OFFICE_FALLBACK_INSTRUCTIONS_OFFLINE; height = kOfflineHeight; break; - case ash::office_fallback::FallbackReason::kDriveDisabled: - case ash::office_fallback::FallbackReason::kNoDriveService: - case ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady: - case ash::office_fallback::FallbackReason::kDriveFsInterfaceError: + case ash::office_fallback::FallbackReason::kDisableDrivePreferenceSet: title_id = IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE; reason_message_id = IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE; instructions_message_id = - IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_UNAVAILABLE; - height = kDriveUnavailableHeight; + IDS_OFFICE_FALLBACK_INSTRUCTIONS_DISABLE_DRIVE_PREFERENCE; + height = kDisableDrivePreferenceSetHeight; + break; + case ash::office_fallback::FallbackReason::kDriveDisabledForAccountType: + title_id = IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE; + reason_message_id = IDS_OFFICE_FALLBACK_REASON_DRIVE_DISABLED_FOR_ACCOUNT; + include_task_in_reason_message = true; + instructions_message_id = + IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_DISABLED_FOR_ACCOUNT; + height = kDriveDisabledForAccountType; break; case ash::office_fallback::FallbackReason::kMeteredConnection: title_id = IDS_OFFICE_FALLBACK_TITLE_METERED; reason_message_id = IDS_OFFICE_FALLBACK_REASON_METERED; + include_task_in_reason_message = true; instructions_message_id = IDS_OFFICE_FALLBACK_INSTRUCTIONS_METERED; height = kMeteredHeight; break; + case ash::office_fallback::FallbackReason::kDriveDisabled: + case ash::office_fallback::FallbackReason::kNoDriveService: + case ash::office_fallback::FallbackReason::kDriveFsInterfaceError: + title_id = IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE; + reason_message_id = IDS_OFFICE_FALLBACK_REASON_DRIVE_UNAVAILABLE; + instructions_message_id = IDS_OFFICE_FALLBACK_INSTRUCTIONS; + height = kDriveUnavailableHeight; + break; } + // Add extra height to account for translations. + height += kLineHeight; } } // namespace @@ -131,17 +155,18 @@ // Get failure specific text to display in dialog. int title_id; int reason_message_id; + bool include_task_in_reason_message; int instructions_message_id; int width; int height; GetDialogTextIdsAndSize(fallback_reason, title_id, reason_message_id, + include_task_in_reason_message, instructions_message_id, width, height); // TODO(cassycc): Figure out how to add the web_drive to the placeholder in // IDS_OFFICE_FALLBACK_TITLE_WEB_DRIVE_UNAVAILABLE. const std::string title_text = l10n_util::GetStringFUTF8(title_id, file_name); const std::string reason_message = - fallback_reason == - ash::office_fallback::FallbackReason::kMeteredConnection + include_task_in_reason_message ? l10n_util::GetStringUTF8(reason_message_id) : l10n_util::GetStringFUTF8(reason_message_id, task_title); const std::string instructions_message =
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h index cc9d5f9..32f122d 100644 --- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h +++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog.h
@@ -20,6 +20,8 @@ kDriveAuthenticationNotReady, kDriveFsInterfaceError, kMeteredConnection, + kDisableDrivePreferenceSet, + kDriveDisabledForAccountType, }; using DialogChoiceCallback =
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc index 88f2982..d4261be4 100644 --- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc +++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_dialog_browsertest.cc
@@ -108,13 +108,13 @@ // Test which launches an `OfficeFallbackDialog` which in turn creates an // `OfficeFallbackElement`. Tests that the correct title is displayed when the -// fallback reason is that Drive is unavailable. +// fallback reason is that Drive authentication is not ready. IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, - OfficeFallbackDialogWhenDriveUnavailable) { + OfficeFallbackDialogWhenDriveAuthenticationNotReady) { // Launch Office Fallback dialog. content::WebContents* web_contents = LaunchOfficeFallbackDialogAndGetWebContents( - files_, FallbackReason::kDriveDisabled, + files_, FallbackReason::kDriveAuthenticationNotReady, file_manager::file_tasks::kActionIdWebDriveOfficeWord, base::DoNothing()); @@ -124,11 +124,73 @@ ".$('#title').innerText"); EXPECT_EQ(eval_result.ExtractString(), l10n_util::GetStringFUTF8( - IDS_OFFICE_FALLBACK_TITLE_DRIVE_UNAVAILABLE, + IDS_OFFICE_FALLBACK_TITLE_OFFLINE, files_.front().path().BaseName().LossyDisplayName())); } // Test which launches an `OfficeFallbackDialog` which in turn creates an +// `OfficeFallbackElement`. Tests that the correct instructions are displayed +// when the fallback reason is that the disable Drive preference is set. +IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, + OfficeFallbackDialogWhenDisableDrivePreferenceSet) { + // Launch Office Fallback dialog. + content::WebContents* web_contents = + LaunchOfficeFallbackDialogAndGetWebContents( + files_, FallbackReason::kDisableDrivePreferenceSet, + file_manager::file_tasks::kActionIdWebDriveOfficeWord, + base::DoNothing()); + + content::EvalJsResult eval_result = + content::EvalJs(web_contents, + "document.querySelector('office-fallback')" + ".$('#instructions-message').innerText"); + EXPECT_EQ(eval_result.ExtractString(), + l10n_util::GetStringUTF8( + IDS_OFFICE_FALLBACK_INSTRUCTIONS_DISABLE_DRIVE_PREFERENCE)); +} + +// Test which launches an `OfficeFallbackDialog` which in turn creates an +// `OfficeFallbackElement`. Tests that the correct instructions are displayed +// when the fallback reason is that Drive is unavailable for the account type. +IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, + OfficeFallbackDialogWhenDriveDisabledForAccountType) { + // Launch Office Fallback dialog. + content::WebContents* web_contents = + LaunchOfficeFallbackDialogAndGetWebContents( + files_, FallbackReason::kDriveDisabledForAccountType, + file_manager::file_tasks::kActionIdWebDriveOfficeWord, + base::DoNothing()); + + content::EvalJsResult eval_result = + content::EvalJs(web_contents, + "document.querySelector('office-fallback')" + ".$('#instructions-message').innerText"); + EXPECT_EQ(eval_result.ExtractString(), + l10n_util::GetStringUTF8( + IDS_OFFICE_FALLBACK_INSTRUCTIONS_DRIVE_DISABLED_FOR_ACCOUNT)); +} + +// Test which launches an `OfficeFallbackDialog` which in turn creates an +// `OfficeFallbackElement`. Tests that the correct instructions are displayed +// when the fallback reason is that Drive has not service. +IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, + OfficeFallbackDialogWhenNoDriveService) { + // Launch Office Fallback dialog. + content::WebContents* web_contents = + LaunchOfficeFallbackDialogAndGetWebContents( + files_, FallbackReason::kNoDriveService, + file_manager::file_tasks::kActionIdWebDriveOfficeWord, + base::DoNothing()); + + content::EvalJsResult eval_result = + content::EvalJs(web_contents, + "document.querySelector('office-fallback')" + ".$('#instructions-message').innerText"); + EXPECT_EQ(eval_result.ExtractString(), + l10n_util::GetStringUTF8(IDS_OFFICE_FALLBACK_INSTRUCTIONS)); +} + +// Test which launches an `OfficeFallbackDialog` which in turn creates an // `OfficeFallbackElement`. Tests that the cancel button works. IN_PROC_BROWSER_TEST_F(OfficeFallbackDialogBrowserTest, ClickCancel) { base::RunLoop run_loop;
diff --git a/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.cc b/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.cc index 2a0f995b..b6e866dd 100644 --- a/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.cc +++ b/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h" #include "base/run_loop.h" +#include "ui/events/test/event_generator.h" namespace ash { @@ -77,6 +78,26 @@ chrome::GetOSSettingsUrl(subpage))); } +// Enters lower-case text into the focused html input element. +ui::test::InteractiveTestApi::StepBuilder +DeviceSettingsBaseTest::EnterLowerCaseText(const std::string& text) { + return Do([&]() { + for (char c : text) { + ui::test::EventGenerator(Shell::GetPrimaryRootWindow()) + .PressKey(static_cast<ui::KeyboardCode>(ui::VKEY_A + (c - 'a')), + ui::EF_NONE, kDeviceId1); + } + }); +} + +ui::test::InteractiveTestApi::StepBuilder +DeviceSettingsBaseTest::SendKeyPressEvent(ui::KeyboardCode key, int modifier) { + return Do([key, modifier]() { + ui::test::EventGenerator(Shell::GetPrimaryRootWindow()) + .PressKey(key, modifier, kDeviceId1); + }); +} + void DeviceSettingsBaseTest::SetUpOnMainThread() { InteractiveAshTest::SetUpOnMainThread();
diff --git a/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h b/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h index 8ef756d..fcecd1f 100644 --- a/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h +++ b/chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h
@@ -58,6 +58,14 @@ void SetPointingStickDevices( const std::vector<ui::InputDevice>& pointing_sticks); + // Enters lower-case text into the focused html input element. + ui::test::InteractiveTestApi::StepBuilder EnterLowerCaseText( + const std::string& text); + + ui::test::InteractiveTestApi::StepBuilder SendKeyPressEvent( + ui::KeyboardCode key, + int modifier = ui::EF_NONE); + // Query to pierce through Shadow DOM to find the keyboard. const DeepQuery kKeyboardNameQuery{ "os-settings-ui",
diff --git a/chrome/browser/ui/webui/ash/settings/integration_tests/keyboard_modifier_remapping_interactive_uitest.cc b/chrome/browser/ui/webui/ash/settings/integration_tests/keyboard_modifier_remapping_interactive_uitest.cc new file mode 100644 index 0000000..5129e245 --- /dev/null +++ b/chrome/browser/ui/webui/ash/settings/integration_tests/keyboard_modifier_remapping_interactive_uitest.cc
@@ -0,0 +1,82 @@ +// 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/settings/public/constants/routes.mojom-forward.h" +#include "chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h" +#include "ui/events/test/event_generator.h" + +namespace ash { + +namespace { + +class DeviceKeyboardModifierRemappingTest : public DeviceSettingsBaseTest { + public: + // Query to pierce through Shadow DOM to find the touchpad row. + const DeepQuery kKeyboardRowQuery{ + "os-settings-ui", "os-settings-main", "main-page-container", + "settings-device-page", "#perDeviceKeyboardRow", + }; + + // Query to pierce through Shadow DOM to find the Settings search box. + const DeepQuery kSearchboxQuery{ + "os-settings-ui", "os-toolbar", "#searchBox", "#search", "#searchInput", + }; + + // Query to pierce through Shadow DOM to find the Keyboard header. + const DeepQuery kCustomizeKeyboardKeysInternalQuery{ + "os-settings-ui", + "os-settings-main", + "main-page-container", + "settings-device-page", + "settings-per-device-keyboard", + "settings-per-device-keyboard-subsection", + ".remap-keyboard-keys-row-internal", + }; + + const DeepQuery kCtrlDropdownQuery{ + "os-settings-ui", "os-settings-main", "main-page-container", + "settings-device-page", "#remap-keys", "#ctrlKey", + "#keyDropdown", "#dropdownMenu", + }; + + auto WaitForSearchboxContainsText(const std::string& text) { + DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kTextFound); + StateChange change; + change.event = kTextFound; + change.where = kSearchboxQuery; + change.type = StateChange::Type::kExistsAndConditionTrue; + const std::string value_check_function = + base::StringPrintf("(e) => { return e.value == '%s';}", text.c_str()); + change.test_function = value_check_function; + return WaitForStateChange(webcontents_id_, change); + } +}; + +IN_PROC_BROWSER_TEST_F(DeviceKeyboardModifierRemappingTest, + KeyboardModifierRemapping) { + RunTestSequence( + Log("Adding a fake internal keyboard"), SetupInternalKeyboard(), + LaunchSettingsApp(chromeos::settings::mojom::kDeviceSectionPath), + WaitForElementExists(webcontents_id_, kKeyboardRowQuery), + ClickElement(webcontents_id_, kKeyboardRowQuery), + WaitForElementTextContains(webcontents_id_, kKeyboardNameQuery, + "Built-in Keyboard"), + ClickElement(webcontents_id_, kCustomizeKeyboardKeysInternalQuery), + Log("Remapping the 'Ctrl' key to 'Backspace'"), + ExecuteJsAt(webcontents_id_, kCtrlDropdownQuery, + "(el) => {el.selectedIndex = 5; el.dispatchEvent(new " + "Event('change'));}"), + ExecuteJsAt(webcontents_id_, kSearchboxQuery, + "(el) => { el.focus(); el.select(); }"), + Log("Entering 'redo' into the Settings search box"), + EnterLowerCaseText("redo"), WaitForSearchboxContainsText("redo"), + Log("Pressing the 'Ctrl' key"), + SendKeyPressEvent(ui::KeyboardCode::VKEY_CONTROL), + Log("Verifying that the 'Backspace' action was performed and the search " + "box now contains the text 'red'"), + WaitForSearchboxContainsText("red")); +} + +} // namespace +} // namespace ash
diff --git a/chrome/browser/ui/webui/ash/settings/integration_tests/keyboard_six_pack_keys_interactive_uitest.cc b/chrome/browser/ui/webui/ash/settings/integration_tests/keyboard_six_pack_keys_interactive_uitest.cc index f71327a6..5290ef948 100644 --- a/chrome/browser/ui/webui/ash/settings/integration_tests/keyboard_six_pack_keys_interactive_uitest.cc +++ b/chrome/browser/ui/webui/ash/settings/integration_tests/keyboard_six_pack_keys_interactive_uitest.cc
@@ -6,6 +6,7 @@ #include "ash/webui/settings/public/constants/routes.mojom-forward.h" #include "chrome/browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h" +#include "ui/events/event_constants.h" #include "ui/events/test/event_generator.h" namespace ash { @@ -14,24 +15,6 @@ class DeviceSettingsSixPackKeysTest : public DeviceSettingsBaseTest { public: - auto SendKeyPressEvent(ui::KeyboardCode key) { - return Do([key]() { - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - generator.PressKey(key, ui::EF_NONE, kDeviceId1); - }); - } - - // Enters lower-case text into the focused html input element. - auto EnterLowerCaseText(const std::string& text) { - return Do([&]() { - for (char c : text) { - ui::test::EventGenerator(Shell::GetPrimaryRootWindow()) - .PressKey(static_cast<ui::KeyboardCode>(ui::VKEY_A + (c - 'a')), - ui::EF_NONE, kDeviceId1); - } - }); - } - // Query to pierce through Shadow DOM to find the touchpad row. const DeepQuery kKeyboardRowQuery{ "os-settings-ui", "os-settings-main", "main-page-container", @@ -54,10 +37,11 @@ ".remap-keyboard-keys-row-internal", }; - const DeepQuery kCtrlDropdownQuery{ - "os-settings-ui", "os-settings-main", "main-page-container", - "settings-device-page", "#remap-keys", "#ctrlKey", - "#keyDropdown", "#dropdownMenu", + const DeepQuery kDeleteDropdownQuery{ + "os-settings-ui", "os-settings-main", + "main-page-container", "settings-device-page", + "#remap-keys", "keyboard-six-pack-key-row:nth-child(1)", + "#keyDropdown", "#dropdownMenu", }; auto WaitForSearchboxContainsText(const std::string& text) { @@ -82,17 +66,19 @@ WaitForElementTextContains(webcontents_id_, kKeyboardNameQuery, "Built-in Keyboard"), ClickElement(webcontents_id_, kCustomizeKeyboardKeysInternalQuery), - Log("Remapping the 'Ctrl' key to 'Backspace'"), - ExecuteJsAt(webcontents_id_, kCtrlDropdownQuery, - "(el) => {el.selectedIndex = 5; el.dispatchEvent(new " + Log("Remapping the 'Delete' action to 'Alt + Backspace'"), + ExecuteJsAt(webcontents_id_, kDeleteDropdownQuery, + "(el) => {el.selectedIndex = 0; el.dispatchEvent(new " "Event('change'));}"), ExecuteJsAt(webcontents_id_, kSearchboxQuery, "(el) => { el.focus(); el.select(); }"), Log("Entering 'redo' into the Settings search box"), EnterLowerCaseText("redo"), WaitForSearchboxContainsText("redo"), - Log("Pressing the 'Ctrl' key"), - SendKeyPressEvent(ui::KeyboardCode::VKEY_CONTROL), - Log("Verifying that the 'Backspace' action was performed and the search " + Log("Pressing the 'Left' key"), + SendKeyPressEvent(ui::KeyboardCode::VKEY_LEFT), + Log("Pressing 'Alt + Backspace' to generate the 'Delete' action"), + SendKeyPressEvent(ui::KeyboardCode::VKEY_BACK, ui::EF_ALT_DOWN), + Log("Verifying that the 'Delete' action was performed and the search " "box now contains the text 'red'"), WaitForSearchboxContainsText("red")); }
diff --git a/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc b/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc index cea7156..03b0bcc2 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc
@@ -502,11 +502,11 @@ : IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION}, {"appNotificationsLinkToBrowserSettingsDescription", IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TO_BROWSER_SETTINGS_DESCRIPTION}, + {"appNotificationsRowSublabel", + IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_LINK_DESCRIPTION}, {"appNotificationsCountDescription", - kIsRevampEnabled - ? IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_LINK_DESCRIPTION - : IDS_SETTINGS_APP_NOTIFICATIONS_SUBLABEL_TEXT}, - {"appNotificationsDoNotDisturbDescription", + IDS_SETTINGS_APP_NOTIFICATIONS_SUBLABEL_TEXT}, + {"appNotificationsDoNotDisturbEnabledDescription", IDS_SETTINGS_APP_NOTIFICATIONS_DND_ENABLED_SUBLABEL_TEXT}, {"appBadgingToggleLabel", IDS_SETTINGS_APP_BADGING_TOGGLE_LABEL}, {"appBadgingToggleSublabel", IDS_SETTINGS_APP_BADGING_TOGGLE_SUBLABEL},
diff --git a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc index 08af821..78def7b 100644 --- a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc
@@ -108,6 +108,9 @@ source->AddInteger( "prerenderStartTimeThreshold", features::kNewTabPagePrerenderStartDelayOnMouseHoverByMiliSeconds.Get()); + source->AddInteger( + "preconnectStartTimeThreshold", + features::kNewTabPagePreconnectStartDelayOnMouseHoverByMiliSeconds.Get()); // Needed by <cr-most-visited> but not used in // chrome://new-tab-page-third-party/.
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 1981aeb..aa25864b 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -3121,10 +3121,6 @@ void SetUp() override { BrowserWithTestWindowTest::SetUp(); -#if BUILDFLAG(IS_CHROMEOS_ASH) - SetUpUserManager(profile()); -#endif - handler_ = std::make_unique<SiteSettingsHandler>(profile()); handler()->set_web_ui(web_ui()); handler()->AllowJavascript(); @@ -3169,21 +3165,18 @@ } #if BUILDFLAG(IS_CHROMEOS_ASH) - void SetUpUserManager(TestingProfile* profile) { - // On ChromeOS a user account is needed in order to check whether the user - // account is affiliated with the device owner for the purposes of applying - // enterprise policy. - constexpr char kTestUserGaiaId[] = "1111111111"; - auto fake_user_manager = std::make_unique<ash::FakeChromeUserManager>(); - auto* fake_user_manager_ptr = fake_user_manager.get(); - scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( - std::move(fake_user_manager)); - - auto account_id = - AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); - fake_user_manager_ptr->AddUserWithAffiliation(account_id, - /*is_affiliated=*/true); - fake_user_manager_ptr->LoginUser(account_id); + // On ChromeOS a user account is needed in order to check whether the user + // account is affiliated with the device owner for the purposes of applying + // enterprise policy. + void LogIn(const std::string& email) override { + const AccountId account_id = AccountId::FromUserEmail(email); + user_manager()->AddUserWithAffiliation(account_id, /*is_affiliated=*/true); + ash_test_helper()->test_session_controller_client()->AddUserSession(email); + user_manager()->UserLoggedIn( + account_id, + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); } #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -3218,9 +3211,6 @@ std::unique_ptr<Browser> browser2_; std::unique_ptr<BrowserWindow> window3_; std::unique_ptr<Browser> browser3_; -#if BUILDFLAG(IS_CHROMEOS_ASH) - std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; -#endif }; TEST_F(SiteSettingsHandlerInfobarTest, SettingPermissionsTriggersInfobar) {
diff --git a/chrome/browser/usb/web_usb_detector_unittest.cc b/chrome/browser/usb/web_usb_detector_unittest.cc index 180fc563..6539a9c2 100644 --- a/chrome/browser/usb/web_usb_detector_unittest.cc +++ b/chrome/browser/usb/web_usb_detector_unittest.cc
@@ -29,13 +29,6 @@ #include "ui/message_center/public/cpp/notification_delegate.h" #include "url/gurl.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" -#include "components/user_manager/scoped_user_manager.h" -#include "components/user_manager/user_manager.h" -#include "components/user_manager/user_names.h" -#endif - // These tests are disabled because WebUsbDetector::Initialize is a noop on // Windows due to jank and hangs caused by enumerating devices. // https://crbug.com/656702 @@ -63,12 +56,6 @@ ~WebUsbDetectorTest() override = default; void SetUp() override { -#if BUILDFLAG(IS_CHROMEOS_ASH) - // Inject UserManager to BrowserWithTestWindowTest. - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindow. - user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( - std::make_unique<ash::FakeChromeUserManager>()); -#endif BrowserWithTestWindowTest::SetUp(); BrowserList::SetLastActive(browser()); @@ -86,33 +73,13 @@ } void TearDown() override { - BrowserWithTestWindowTest::TearDown(); -#if BUILDFLAG(IS_CHROMEOS_ASH) - user_manager_enabler_.reset(); -#endif web_usb_detector_.reset(); + BrowserWithTestWindowTest::TearDown(); } -#if BUILDFLAG(IS_CHROMEOS_ASH) - // TODO(crbug.com/1494005): Merge into BrowserWithTestWindowTest. - void LogIn(const std::string& email) override { - const AccountId account_id = AccountId::FromUserEmail(email); - GetFakeUserManager()->AddUser(account_id); - GetFakeUserManager()->LoginUser(account_id); - } -#endif void Initialize() { web_usb_detector_->Initialize(); } protected: -#if BUILDFLAG(IS_CHROMEOS_ASH) - ash::FakeChromeUserManager* GetFakeUserManager() { - return static_cast<ash::FakeChromeUserManager*>( - user_manager::UserManager::Get()); - } - - std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_; -#endif - device::FakeUsbDeviceManager device_manager_; std::unique_ptr<WebUsbDetector> web_usb_detector_; std::unique_ptr<NotificationDisplayServiceTester> display_service_;
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc index e461bd74..6b308bc 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -15,7 +15,6 @@ #include <type_traits> #include <utility> -#include "base/barrier_callback.h" #include "base/check.h" #include "base/check_op.h" #include "base/containers/checked_iterators.h" @@ -29,6 +28,7 @@ #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/functional/concurrent_callbacks.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/scoped_refptr.h" @@ -1946,28 +1946,20 @@ // system apps. const WebApp* web_app = GetWebApp(params.app_id); bool can_multilaunch = !(web_app && web_app->IsSystemApp()); + base::ConcurrentCallbacks<content::WebContents*> concurrent; - size_t num_launches = 1; - WebAppFileHandlerManager::LaunchInfos file_launch_infos; if (can_multilaunch) { - file_launch_infos = + WebAppFileHandlerManager::LaunchInfos file_launch_infos = provider_->os_integration_manager() .file_handler_manager() .GetMatchingFileHandlerUrls(app_id, params.launch_files); - num_launches = file_launch_infos.size(); - } - - auto launch_complete_barrier = base::BarrierCallback<content::WebContents*>( - num_launches, std::move(callback)); - - if (can_multilaunch) { for (const auto& [url, files] : file_launch_infos) { apps::AppLaunchParams params_for_file_launch( app_id, params.container, params.disposition, params.launch_source, params.display_id, files, nullptr); params_for_file_launch.override_url = url; LaunchAppWithParams(std::move(params_for_file_launch), - launch_complete_barrier); + concurrent.CreateCallback()); } } else { apps::AppLaunchParams params_for_file_launch( @@ -1981,8 +1973,10 @@ params_for_file_launch.override_url = GURL(*params.intent->activity_name); } LaunchAppWithParams(std::move(params_for_file_launch), - launch_complete_barrier); + concurrent.CreateCallback()); } + + std::move(concurrent).Done(std::move(callback)); } void WebAppPublisherHelper::OnLaunchCompleted(
diff --git a/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command.cc b/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command.cc index a00e6f6a..f23d3eab 100644 --- a/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command.cc +++ b/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command.cc
@@ -8,11 +8,11 @@ #include <string> #include <unordered_set> -#include "base/barrier_closure.h" #include "base/check.h" #include "base/files/file_path.h" #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" +#include "base/functional/concurrent_closures.h" #include "base/memory/weak_ptr.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" @@ -49,21 +49,19 @@ } void GarbageCollectStoragePartitionsCommand::ResetStorageGarbageCollectPref() { - base::OnceClosure callback = - base::BindOnce(&GarbageCollectStoragePartitionsCommand::OnPrefReset, - weak_factory_.GetWeakPtr()); - - base::RepeatingClosure barrier_closure = - base::BarrierClosure(2, std::move(callback)); - + base::ConcurrentClosures concurrent; // TODO(crbug.com/1477027): change this pref to be stateful instead of // resetting to false early. profile_->GetPrefs()->SetBoolean( prefs::kShouldGarbageCollectStoragePartitions, false); // Waits for both prefs to be written to disk before proceeding to prevent // repeating crashes. - lock_->extensions_manager().ResetStorageGarbageCollectPref(barrier_closure); - profile_->GetPrefs()->CommitPendingWrite(barrier_closure); + lock_->extensions_manager().ResetStorageGarbageCollectPref( + concurrent.CreateClosure()); + profile_->GetPrefs()->CommitPendingWrite(concurrent.CreateClosure()); + std::move(concurrent) + .Done(base::BindOnce(&GarbageCollectStoragePartitionsCommand::OnPrefReset, + weak_factory_.GetWeakPtr())); } void GarbageCollectStoragePartitionsCommand::OnPrefReset() {
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc index 04321536..9bfb29d 100644 --- a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc +++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc
@@ -8,12 +8,12 @@ #include <string> #include <vector> -#include "base/barrier_closure.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_forward.h" +#include "base/functional/concurrent_closures.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" @@ -373,6 +373,12 @@ std::move(callback))); } +base::OnceClosure& +WebAppShortcutManager::OnSetCurrentAppShortcutsVersionCallbackForTesting() { + static base::NoDestructor<base::OnceClosure> callback; + return *callback; +} + void WebAppShortcutManager::OnIconsRead( const webapps::AppId& app_id, GetShortcutInfoCallback callback, @@ -496,25 +502,25 @@ if (suppress_shortcuts_for_testing_) return; - std::vector<webapps::AppId> app_ids = - provider_->registrar_unsafe().GetAppIds(); - auto done_callback = base::BarrierClosure( - app_ids.size() + 1, - base::BindOnce(&WebAppShortcutManager::SetCurrentAppShortcutsVersion, - weak_ptr_factory_.GetWeakPtr())); + base::ConcurrentClosures concurrent; - for (const auto& app_id : app_ids) { + for (const auto& app_id : provider_->registrar_unsafe().GetAppIds()) { UpdateShortcuts(app_id, /*old_name=*/{}, - base::IgnoreArgs<Result>(done_callback)); + base::IgnoreArgs<Result>(concurrent.CreateClosure())); } UpdateShortcutsForAllAppsCallback update_callback = GetUpdateShortcutsForAllAppsCallback(); if (update_callback) { - update_callback.Run(profile_, done_callback); + update_callback.Run(profile_, concurrent.CreateClosure()); } else { - done_callback.Run(); + concurrent.CreateClosure().Run(); } + + std::move(concurrent) + .Done( + base::BindOnce(&WebAppShortcutManager::SetCurrentAppShortcutsVersion, + weak_ptr_factory_.GetWeakPtr())); } void WebAppShortcutManager::SetCurrentAppShortcutsVersion() { @@ -522,6 +528,11 @@ kCurrentAppShortcutsVersion); profile_->GetPrefs()->SetString(prefs::kAppShortcutsArch, CurrentAppShortcutsArch()); + + if (base::OnceClosure& callback = + OnSetCurrentAppShortcutsVersionCallbackForTesting()) { + std::move(callback).Run(); + } } } // namespace web_app
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h index 9e9f4d42..6b7fa1e 100644 --- a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h +++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h
@@ -132,6 +132,8 @@ static void SetUpdateShortcutsForAllAppsCallback( UpdateShortcutsForAllAppsCallback callback); + static base::OnceClosure& OnSetCurrentAppShortcutsVersionCallbackForTesting(); + private: void OnIconsRead(const webapps::AppId& app_id, GetShortcutInfoCallback callback,
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc index ce940a6..0d73446 100644 --- a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc +++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc
@@ -163,7 +163,13 @@ // Make sure the updated shortcuts version is not persisted to prefs until // after we signal completion of updating. EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kAppShortcutsVersion)); - std::move(done_update_callback_).Run(); + { + base::RunLoop run_loop; + WebAppShortcutManager::OnSetCurrentAppShortcutsVersionCallbackForTesting() = + run_loop.QuitClosure(); + std::move(done_update_callback_).Run(); + run_loop.Run(); + } EXPECT_NE(0, profile()->GetPrefs()->GetInteger(prefs::kAppShortcutsVersion)); // Verify shortcut was rebuild, and shortcuts weren't created for the second
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc index e3f892a..806a1928 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -10,8 +10,6 @@ #include <utility> #include <vector> -#include "base/barrier_callback.h" -#include "base/barrier_closure.h" #include "base/check_deref.h" #include "base/containers/contains.h" #include "base/containers/flat_map.h" @@ -20,6 +18,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" +#include "base/functional/concurrent_closures.h" #include "base/metrics/histogram_functions.h" #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" @@ -160,6 +159,10 @@ weak_ptr_factory_.GetWeakPtr(), enable_pwa_support)); } +void WebAppPolicyManager::Shutdown() { + weak_ptr_factory_.InvalidateWeakPtrs(); +} + void WebAppPolicyManager::ReinstallPlaceholderAppIfNecessary( const GURL& url, ExternallyManagedAppManager::OnceInstallCallback on_complete) { @@ -453,25 +456,25 @@ // login and force unregistration, it is still safe, since both functions // invoke commands, so the Run on OS login will always be scheduled before the // force unregistration, and execution will be synchronous. - auto policy_settings_applied_callback = base::BarrierClosure( - /*num_closures=*/2, - base::BindOnce(&WebAppPolicyManager::OnSyncPolicySettingsCommandsComplete, - weak_ptr_factory_.GetWeakPtr())); - ApplyRunOnOsLoginPolicySettings(policy_settings_applied_callback); - ApplyForceOSUnregistrationPolicySettings(policy_settings_applied_callback); + base::ConcurrentClosures concurrent; + ApplyRunOnOsLoginPolicySettings(concurrent.CreateClosure()); + ApplyForceOSUnregistrationPolicySettings(concurrent.CreateClosure()); + std::move(concurrent) + .Done(base::BindOnce( + &WebAppPolicyManager::OnSyncPolicySettingsCommandsComplete, + weak_ptr_factory_.GetWeakPtr())); } void WebAppPolicyManager::ApplyRunOnOsLoginPolicySettings( base::OnceClosure policy_settings_applied_callback) { - std::vector<webapps::AppId> app_ids_to_sync = - provider_->registrar_unsafe().GetAppIds(); - auto callback_for_sync_commands = base::BarrierClosure( - app_ids_to_sync.size(), std::move(policy_settings_applied_callback)); + base::ConcurrentClosures concurrent; WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile_); - for (const webapps::AppId& app_id : app_ids_to_sync) { + for (const webapps::AppId& app_id : + provider_->registrar_unsafe().GetAppIds()) { provider->scheduler().SyncRunOnOsLoginMode(app_id, - callback_for_sync_commands); + concurrent.CreateClosure()); } + std::move(concurrent).Done(std::move(policy_settings_applied_callback)); } void WebAppPolicyManager::ApplyForceOSUnregistrationPolicySettings( @@ -481,7 +484,9 @@ return; } - base::flat_set<webapps::AppId> app_ids_for_force_unregistration; + base::ConcurrentClosures concurrent; + SynchronizeOsOptions options; + options.force_unregister_os_integration = true; for (const auto& [manifest_string, setting] : settings_by_url_) { const GURL manifest_id = GURL(manifest_string); if (!manifest_id.is_valid()) { @@ -495,24 +500,12 @@ } if (setting.force_unregister_os_integration) { - app_ids_for_force_unregistration.insert(app_id); + provider_->scheduler().SynchronizeOsIntegration( + app_id, concurrent.CreateClosure(), options); } } - if (app_ids_for_force_unregistration.empty()) { - std::move(policy_settings_applied_callback).Run(); - return; - } - - SynchronizeOsOptions options; - options.force_unregister_os_integration = true; - auto callback_for_synchronize_complete = - base::BarrierClosure(app_ids_for_force_unregistration.size(), - std::move(policy_settings_applied_callback)); - for (const auto& app_id : app_ids_for_force_unregistration) { - provider_->scheduler().SynchronizeOsIntegration( - app_id, callback_for_synchronize_complete, options); - } + std::move(concurrent).Done(std::move(policy_settings_applied_callback)); } ExternalInstallOptions WebAppPolicyManager::ParseInstallPolicyEntry(
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.h b/chrome/browser/web_applications/policy/web_app_policy_manager.h index b3b8f0d..6c61e458 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.h +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.h
@@ -72,6 +72,7 @@ // `policy_settings_and_force_installs_applied_` waits for the first // `SynchronizeInstalledApps` to finish if it's triggered on `Start`. void Start(base::OnceClosure policy_settings_and_force_installs_applied); + void Shutdown(); void ReinstallPlaceholderAppIfNecessary( const GURL& url,
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc index 677b3246..7247f82 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc +++ b/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc
@@ -1342,11 +1342,13 @@ MockAppRegistrarObserver mock_observer; app_registrar().AddObserver(&mock_observer); - base::RunLoop loop; - policy_manager().SetRefreshPolicySettingsCompletedCallbackForTesting( - loop.QuitClosure()); - SetWebAppSettingsListPref(profile(), kWebAppSettingInitialConfiguration); - loop.Run(); + { + base::RunLoop loop; + policy_manager().SetRefreshPolicySettingsCompletedCallbackForTesting( + loop.QuitClosure()); + SetWebAppSettingsListPref(profile(), kWebAppSettingInitialConfiguration); + loop.Run(); + } EXPECT_EQ(GetUrlRunOnOsLoginPolicy(kWindowedUrl), RunOnOsLoginPolicy::kBlocked); @@ -1355,7 +1357,14 @@ RunOnOsLoginPolicy::kAllowed); EXPECT_EQ(1, mock_observer.GetOnWebAppSettingsPolicyChangedCalledCount()); - SetWebAppSettingsListPref(profile(), kWebAppSettingWithDefaultConfiguration); + { + base::RunLoop loop; + policy_manager().SetRefreshPolicySettingsCompletedCallbackForTesting( + loop.QuitClosure()); + SetWebAppSettingsListPref(profile(), + kWebAppSettingWithDefaultConfiguration); + loop.Run(); + } EXPECT_EQ(GetUrlRunOnOsLoginPolicy(kWindowedUrl), RunOnOsLoginPolicy::kRunWindowed); EXPECT_EQ(GetUrlRunOnOsLoginPolicy(kTabbedUrl), RunOnOsLoginPolicy::kAllowed); @@ -1415,11 +1424,14 @@ MockAppRegistrarObserver mock_observer; app_registrar().AddObserver(&mock_observer); - base::RunLoop settings_loop; - policy_manager().SetRefreshPolicySettingsCompletedCallbackForTesting( - settings_loop.QuitClosure()); - SetWebAppSettingsListPref(profile(), kWebAppSettingWithDefaultConfiguration); - settings_loop.Run(); + { + base::RunLoop settings_loop; + policy_manager().SetRefreshPolicySettingsCompletedCallbackForTesting( + settings_loop.QuitClosure()); + SetWebAppSettingsListPref(profile(), + kWebAppSettingWithDefaultConfiguration); + settings_loop.Run(); + } EXPECT_EQ(1, mock_observer.GetOnWebAppSettingsPolicyChangedCalledCount()); EXPECT_EQ(GetUrlRunOnOsLoginPolicy(kWindowedUrl), @@ -1430,14 +1442,18 @@ EXPECT_EQ(GetUrlRunOnOsLoginPolicy("http://foo.example"), RunOnOsLoginPolicy::kBlocked); - // Now add two sites, one that opens in a window and one that opens in a tab. - base::Value::List list; - list.Append(GetWindowedItem()); - list.Append(GetTabbedItem()); - - profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, - std::move(list)); - WaitForAppsToSynchronize(); + { + base::RunLoop loop; + policy_manager().SetRefreshPolicySettingsCompletedCallbackForTesting( + loop.QuitClosure()); + // Now add two sites, one that opens in a window and one that opens in a + // tab. + profile()->GetPrefs()->SetList( + prefs::kWebAppInstallForceList, + base::Value::List().Append(GetWindowedItem()).Append(GetTabbedItem())); + loop.Run(); + } + // WaitForAppsToSynchronize(); provider()->command_manager().AwaitAllCommandsCompleteForTesting();
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.cc b/chrome/browser/web_applications/preinstalled_web_app_manager.cc index ebab2be..0acdfb4 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
@@ -10,7 +10,6 @@ #include <string> #include <utility> -#include "base/barrier_closure.h" #include "base/containers/contains.h" #include "base/containers/cxx20_erase.h" #include "base/feature_list.h" @@ -19,6 +18,7 @@ #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback.h" +#include "base/functional/concurrent_closures.h" #include "base/json/json_file_value_serializer.h" #include "base/json/json_reader.h" #include "base/memory/scoped_refptr.h" @@ -727,14 +727,12 @@ return; } - int num_barriers_issued = 2; - base::RepeatingClosure barrier_closure = base::BarrierClosure( - num_barriers_issued, std::move(load_and_synchronize)); - device_data_initialized_event_->Post(barrier_closure); - + base::ConcurrentClosures concurrent; + device_data_initialized_event_->Post(concurrent.CreateClosure()); // Make sure ExtensionSystem is ready to know if default apps new installation // will be performed. - extensions::OnExtensionSystemReady(profile_, barrier_closure); + extensions::OnExtensionSystemReady(profile_, concurrent.CreateClosure()); + std::move(concurrent).Done(std::move(load_and_synchronize)); } void PreinstalledWebAppManager::Load(ConsumeInstallOptions callback) {
diff --git a/chrome/browser/web_applications/test/fake_web_app_provider.cc b/chrome/browser/web_applications/test/fake_web_app_provider.cc index 651681f..e1ac744f 100644 --- a/chrome/browser/web_applications/test/fake_web_app_provider.cc +++ b/chrome/browser/web_applications/test/fake_web_app_provider.cc
@@ -327,6 +327,7 @@ } if (install_manager_) install_manager_->Shutdown(); + web_app_policy_manager_->Shutdown(); if (icon_manager_) icon_manager_->Shutdown(); if (install_finalizer_)
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index 49557aa..05eb0b6 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -10,12 +10,12 @@ #include <ostream> #include <utility> -#include "base/barrier_closure.h" #include "base/check.h" #include "base/check_is_test.h" #include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" +#include "base/functional/concurrent_closures.h" #include "base/location.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" @@ -314,6 +314,7 @@ manifest_update_manager_->Shutdown(); iwa_update_manager_->Shutdown(); install_manager_->Shutdown(); + web_app_policy_manager_->Shutdown(); icon_manager_->Shutdown(); install_finalizer_->Shutdown(); registrar_->Shutdown(); @@ -441,31 +442,15 @@ sync_bridge_.get()); #endif // BUILDFLAG(IS_CHROMEOS) - // Note: This does not wait for the call from the ChromeOS - // SystemWebAppManager, which is a separate keyed service. -#if BUILDFLAG(IS_CHROMEOS) - const int num_barrier_calls = 3; -#else - const int num_barrier_calls = 2; -#endif // BUILDFLAG(IS_CHROMEOS) - base::RepeatingClosure external_manager_barrier = base::BarrierClosure( - num_barrier_calls, - base::BindOnce( - [](base::WeakPtr<WebAppProvider> provider) { - if (!provider) - return; - provider->on_external_managers_synchronized_.Signal(); - }, - AsWeakPtr())); + base::ConcurrentClosures concurrent; base::OnceClosure on_web_app_policy_manager_done_callback = - external_manager_barrier; - #if BUILDFLAG(IS_CHROMEOS) - on_web_app_policy_manager_done_callback = base::BindOnce(&WebAppRunOnOsLoginManager::Start, web_app_run_on_os_login_manager_->GetWeakPtr()) - .Then(external_manager_barrier); + .Then(concurrent.CreateClosure()); +#else + concurrent.CreateClosure(); #endif // BUILDFLAG(IS_CHROMEOS) registrar_->Start(); @@ -473,7 +458,7 @@ icon_manager_->Start(); translation_manager_->Start(); install_manager_->Start(); - preinstalled_web_app_manager_->Start(external_manager_barrier); + preinstalled_web_app_manager_->Start(concurrent.CreateClosure()); web_app_policy_manager_->Start( std::move(on_web_app_policy_manager_done_callback)); isolated_web_app_installation_manager_->Start(); @@ -485,9 +470,21 @@ generated_icon_fix_manager_->Start(); command_manager_->Start(); #if BUILDFLAG(IS_CHROMEOS) - isolated_web_app_policy_manager_->Start(external_manager_barrier); + isolated_web_app_policy_manager_->Start(concurrent.CreateClosure()); #endif // BUILDFLAG(IS_CHROMEOS) + // Note: This does not wait for the call from the ChromeOS + // SystemWebAppManager, which is a separate keyed service. + std::move(concurrent) + .Done(base::BindOnce( + [](base::WeakPtr<WebAppProvider> provider) { + if (!provider) { + return; + } + provider->on_external_managers_synchronized_.Signal(); + }, + AsWeakPtr())); + on_registry_ready_.Signal(); is_registry_ready_ = true; }
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index 416e552..7fc7f7e 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1707306295-0bd73d0e5d0995d2acd72facfe27d62f9acb0fa2.profdata +chrome-chromeos-amd64-generic-main-1707350387-b81c34bb7277714ae9511fed8527263c18b9db82.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 7bf567a..2da1b69 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1707328797-1c3efd3955b677a6239ff03320de90c9ee7a2b4c.profdata +chrome-linux-main-1707350387-c53afe4b59be5e777079ad7ac205233b1e1164b5.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 299221a..53c6bfd 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1707343088-770b4a8ca743711cf1a1eab1f3fa27965e9c83f9.profdata +chrome-mac-arm-main-1707371451-dec039a3dbf2292385be97878aca13b4e4ae2ec3.profdata
diff --git a/chrome/services/speech/BUILD.gn b/chrome/services/speech/BUILD.gn index 0f27b93..4e4f114 100644 --- a/chrome/services/speech/BUILD.gn +++ b/chrome/services/speech/BUILD.gn
@@ -46,6 +46,10 @@ "cros_speech_recognition_recognizer_impl.cc", "cros_speech_recognition_recognizer_impl.h", ] + deps += [ + "//chromeos/services/machine_learning/public/mojom", + ] + } } @@ -53,12 +57,16 @@ source_set("unit_tests") { testonly = true - sources = [ "audio_source_fetcher_unittest.cc" ] + sources = [ + "audio_source_fetcher_unittest.cc", + "cros_speech_recognition_recognizer_impl_test.cc", + ] deps = [ ":lib", "//base", "//base/test:test_support", + "//chromeos/services/machine_learning/public/mojom", "//media/mojo/common", "//mojo/public/cpp/bindings", "//services/audio/public/cpp:test_support",
diff --git a/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc b/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc index 69d511f..2e75e22b 100644 --- a/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc +++ b/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc
@@ -77,6 +77,28 @@ cros_soda_client_ = std::make_unique<soda::CrosSodaClient>(); } +chromeos::machine_learning::mojom::SodaMultilangConfigPtr +CrosSpeechRecognitionRecognizerImpl::AddLiveCaptionLanguagesToConfig( + const std::string& primary_language_name, + const base::flat_map<std::string, base::FilePath>& config_paths, + const std::vector<std::string>& live_caption_languages) { + auto multi_lang_config = + chromeos::machine_learning::mojom::SodaMultilangConfig::New(); + + for (const auto& config_path : config_paths) { + if (config_path.first == primary_language_name) { + continue; + } else if (!base::Contains(live_caption_languages, config_path.first)) { + VLOG(1) << "Skipping multilang on captions of " << config_path.first + << " as it is not listed as a live caption language."; + continue; + } + multi_lang_config->locale_to_language_pack_map[config_path.first] = + config_path.second.value(); + } + return multi_lang_config; +} + void CrosSpeechRecognitionRecognizerImpl:: SendAudioToSpeechRecognitionServiceInternal( media::mojom::AudioDataS16Ptr buffer) { @@ -109,22 +131,9 @@ if (options_->recognition_mode == media::mojom::SpeechRecognitionMode::kCaption && base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) { - auto live_caption_languages = speech::GetLiveCaptionEnabledLanguages(); - auto multi_lang_config = - chromeos::machine_learning::mojom::SodaMultilangConfig::New(); - - for (const auto& config_path : config_paths()) { - if (config_path.first == primary_language_name()) { - continue; - } else if (!base::Contains(live_caption_languages, config_path.first)) { - VLOG(1) << "Skipping multilang on captions of " << config_path.first - << " as it is not listed as a live caption language."; - continue; - } - multi_lang_config->locale_to_language_pack_map[config_path.first] = - config_path.second.value(); - } - config->multi_lang_config = std::move(multi_lang_config); + config->multi_lang_config = AddLiveCaptionLanguagesToConfig( + primary_language_name(), config_paths(), + speech::GetLiveCaptionEnabledLanguages()); } config->enable_formatting =
diff --git a/chrome/services/speech/cros_speech_recognition_recognizer_impl.h b/chrome/services/speech/cros_speech_recognition_recognizer_impl.h index aaba24c..fcce2f1 100644 --- a/chrome/services/speech/cros_speech_recognition_recognizer_impl.h +++ b/chrome/services/speech/cros_speech_recognition_recognizer_impl.h
@@ -12,6 +12,7 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "chrome/services/speech/speech_recognition_recognizer_impl.h" +#include "chromeos/services/machine_learning/public/mojom/soda.mojom.h" #include "media/mojo/mojom/speech_recognition_service.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -54,6 +55,12 @@ void MarkDone() override; + static chromeos::machine_learning::mojom::SodaMultilangConfigPtr + AddLiveCaptionLanguagesToConfig( + const std::string& primary_language_name, + const base::flat_map<std::string, base::FilePath>& config_paths, + const std::vector<std::string>& live_caption_languages); + private: std::unique_ptr<soda::CrosSodaClient> cros_soda_client_;
diff --git a/chrome/services/speech/cros_speech_recognition_recognizer_impl_test.cc b/chrome/services/speech/cros_speech_recognition_recognizer_impl_test.cc new file mode 100644 index 0000000..3875928 --- /dev/null +++ b/chrome/services/speech/cros_speech_recognition_recognizer_impl_test.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 "chrome/services/speech/cros_speech_recognition_recognizer_impl.h" + +#include "chromeos/services/machine_learning/public/mojom/soda.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +class CrosSpeechRecognitionRecognizerImplTest : public testing::Test { + void SetUp() override {} +}; + +TEST_F(CrosSpeechRecognitionRecognizerImplTest, EmptyLangs) { + chromeos::machine_learning::mojom::SodaMultilangConfigPtr expected = + chromeos::machine_learning::mojom::SodaMultilangConfig::New(); + auto actual = speech::CrosSpeechRecognitionRecognizerImpl:: + AddLiveCaptionLanguagesToConfig( + "en-US", base::flat_map<std::string, base::FilePath>(), + {"en-US", "en-AU"}); + EXPECT_EQ(expected, actual); +} + +TEST_F(CrosSpeechRecognitionRecognizerImplTest, FilledLangs) { + chromeos::machine_learning::mojom::SodaMultilangConfigPtr expected = + chromeos::machine_learning::mojom::SodaMultilangConfig::New(); + base::flat_map<std::string, base::FilePath> config_paths; + config_paths["en-AU"] = base::FilePath::FromASCII("/fake/path/aus"); + config_paths["en-US"] = base::FilePath::FromASCII("/fake/path/usa"); + config_paths["es-US"] = base::FilePath::FromASCII("/fake/path/espusa"); + config_paths["es-ES"] = base::FilePath::FromASCII("/fake/path/espesp"); + config_paths["fr-FR"] = base::FilePath::FromASCII("/fake/path/frafra"); + + auto actual = speech::CrosSpeechRecognitionRecognizerImpl:: + AddLiveCaptionLanguagesToConfig("en-US", config_paths, + {"en-US", "es-US", "fr-FR"}); + expected->locale_to_language_pack_map["es-US"] = "/fake/path/espusa"; + expected->locale_to_language_pack_map["fr-FR"] = "/fake/path/frafra"; + EXPECT_EQ(expected, actual); +}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index fe0157ae..cfefc45 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2357,6 +2357,7 @@ "../browser/metrics/variations/variations_http_headers_browsertest.cc", "../browser/metrics/variations/variations_safe_mode_browsertest.cc", "../browser/metrics/variations/variations_safe_mode_end_to_end_browsertest.cc", + "../browser/metrics/variations/variations_service_browsertest.cc", "../browser/navigation_predictor/anchor_element_preloader_browsertest.cc", "../browser/navigation_predictor/navigation_predictor_browsertest.cc", "../browser/navigation_predictor/navigation_predictor_preconnect_client_browsertest.cc", @@ -4284,6 +4285,7 @@ "//components/supervised_user/core/browser/proto", "//components/supervised_user/core/common", "//components/supervised_user/core/common:test_utils", + "//components/variations/service", ] } @@ -8402,6 +8404,7 @@ "../browser/ui/ash/network/network_portal_signin_controller_unittest.cc", "../browser/ui/ash/network/network_state_notifier_unittest.cc", "../browser/ui/ash/network/tether_notification_presenter_unittest.cc", + "../browser/ui/ash/picker/picker_client_impl_unittest.cc", "../browser/ui/ash/projector/projector_client_impl_unittest.cc", "../browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc", "../browser/ui/ash/projector/projector_utils_unittest.cc", @@ -11083,6 +11086,7 @@ "../browser/ui/webui/ash/settings/integration_tests/add_new_keyboard_interactive_uitest.cc", "../browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.cc", "../browser/ui/webui/ash/settings/integration_tests/device_settings_base_test.h", + "../browser/ui/webui/ash/settings/integration_tests/keyboard_modifier_remapping_interactive_uitest.cc", "../browser/ui/webui/ash/settings/integration_tests/keyboard_six_pack_keys_interactive_uitest.cc", "../browser/ui/webui/ash/settings/integration_tests/mouse_scroll_acceleration_interactive_uitest.cc", "../browser/ui/webui/ash/settings/integration_tests/open_keyboard_subpage_interactive_uitest.cc",
diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc index dca7565..e307011 100644 --- a/chrome/test/base/browser_with_test_window_test.cc +++ b/chrome/test/base/browser_with_test_window_test.cc
@@ -42,6 +42,7 @@ #include "chrome/browser/ash/crosapi/crosapi_manager.h" #include "chrome/browser/ash/crosapi/idle_service_ash.h" #include "chrome/browser/ash/crosapi/test_crosapi_dependency_registry.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "components/user_manager/fake_user_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_manager.h" @@ -69,11 +70,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) if (!user_manager::UserManager::IsInitialized()) { - auto user_manager = std::make_unique<user_manager::FakeUserManager>( - g_browser_process->local_state()); - user_manager_ = user_manager.get(); - scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( - std::move(user_manager)); + user_manager_.Reset(std::make_unique<user_manager::FakeUserManager>( + g_browser_process->local_state())); } ash_test_helper_.SetUp(); #endif @@ -106,6 +104,9 @@ std::string profile_name = GetDefaultProfileName(); #if BUILDFLAG(IS_CHROMEOS) LogIn(profile_name); +#if BUILDFLAG(IS_CHROMEOS_ASH) + SwitchActiveUser(profile_name); +#endif #endif profile_ = CreateProfile(profile_name); @@ -155,7 +156,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash_test_helper_.TearDown(); test_views_delegate_.reset(); - user_manager_ = nullptr; + user_manager_.Reset(); #elif defined(TOOLKIT_VIEWS) views_test_helper_.reset(); #endif @@ -221,9 +222,13 @@ TestingProfile* BrowserWithTestWindowTest::CreateProfile( const std::string& profile_name) { - return profile_manager_->CreateTestingProfile( + auto* profile = profile_manager_->CreateTestingProfile( profile_name, /*prefs=*/nullptr, /*user_name=*/std::u16string(), /*avatar_id=*/0, GetTestingFactories()); +#if BUILDFLAG(IS_CHROMEOS_ASH) + OnUserProfileCreated(profile_name, profile); +#endif + return profile; } void BrowserWithTestWindowTest::DeleteProfile(const std::string& profile_name) { @@ -268,11 +273,51 @@ #if BUILDFLAG(IS_CHROMEOS) void BrowserWithTestWindowTest::LogIn(const std::string& email) { - // TODO(crbug/1494005): Log in a regular user by default. +#if BUILDFLAG(IS_CHROMEOS_ASH) + const AccountId account_id = AccountId::FromUserEmail(email); + user_manager_->AddUser(account_id); + ash_test_helper()->test_session_controller_client()->AddUserSession(email); + user_manager_->UserLoggedIn( + account_id, + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); +#endif } #endif #if BUILDFLAG(IS_CHROMEOS_ASH) +void BrowserWithTestWindowTest::OnUserProfileCreated(const std::string& email, + Profile* profile) { + AccountId account_id = AccountId::FromUserEmail(email); + ash::AnnotatedAccountId::Set(profile, account_id); + // Do not use the member directly, because another UserManager instance + // may be injected. + auto* user_manager = user_manager::UserManager::Get(); + user_manager->OnUserProfileCreated(account_id, profile->GetPrefs()); + auto observation = + std::make_unique<base::ScopedObservation<Profile, ProfileObserver>>(this); + observation->Observe(profile); + profile_observations_.push_back(std::move(observation)); +} + +void BrowserWithTestWindowTest::SwitchActiveUser(const std::string& email) { + ash_test_helper()->test_session_controller_client()->SwitchActiveUser( + AccountId::FromUserEmail(email)); +} + +void BrowserWithTestWindowTest::OnProfileWillBeDestroyed(Profile* profile) { + CHECK( + base::EraseIf(profile_observations_, [profile](const auto& observation) { + return observation->IsObservingSource(profile); + })); + const AccountId* account_id = ash::AnnotatedAccountId::Get(profile); + CHECK(account_id); + // Do not use the member directly, because another UserManager instance + // may be injected. + user_manager::UserManager::Get()->OnUserProfileWillBeDestroyed(*account_id); +} + ash::ScopedCrosSettingsTestHelper* BrowserWithTestWindowTest::GetCrosSettingsHelper() { return &cros_settings_test_helper_;
diff --git a/chrome/test/base/browser_with_test_window_test.h b/chrome/test/base/browser_with_test_window_test.h index 4d1fa37..03f9bd4 100644 --- a/chrome/test/base/browser_with_test_window_test.h +++ b/chrome/test/base/browser_with_test_window_test.h
@@ -6,12 +6,14 @@ #define CHROME_TEST_BASE_BROWSER_WITH_TEST_WINDOW_TEST_H_ #include <memory> +#include <vector> #include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/performance_manager/test_support/test_user_performance_tuning_manager_environment.h" +#include "chrome/browser/profiles/profile_observer.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_profile.h" @@ -28,6 +30,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/test/ash_test_helper.h" #include "ash/test/ash_test_views_delegate.h" +#include "base/scoped_observation.h" #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h" #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h" #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" @@ -82,7 +85,7 @@ // // Subclasses must invoke BrowserWithTestWindowTest::SetUp as it is responsible // for creating the various objects of this class. -class BrowserWithTestWindowTest : public testing::Test { +class BrowserWithTestWindowTest : public testing::Test, public ProfileObserver { public: // Trait which requests construction of a hosted app. struct HostedApp {}; @@ -149,7 +152,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::AshTestHelper* ash_test_helper() { return &ash_test_helper_; } - user_manager::FakeUserManager* user_manager() { return user_manager_; } + user_manager::FakeUserManager* user_manager() { return user_manager_.Get(); } #endif // The context to help determine desktop type when creating new Widgets. @@ -227,6 +230,16 @@ #endif #if BUILDFLAG(IS_CHROMEOS_ASH) + // Handles the post-process for the newly created Profile. + // Expected to be called on customizing CreateProfile for ash. + virtual void OnUserProfileCreated(const std::string& email, Profile* profile); + + // Switches the active user to the one specified by the email. + virtual void SwitchActiveUser(const std::string& email); + + // ProfileObserver: + void OnProfileWillBeDestroyed(Profile* profile) override; + ash::ScopedCrosSettingsTestHelper* GetCrosSettingsHelper(); ash::StubInstallAttributes* GetInstallAttributes(); #endif @@ -249,8 +262,11 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::ScopedCrosSettingsTestHelper cros_settings_test_helper_; - raw_ptr<user_manager::FakeUserManager> user_manager_ = nullptr; - std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; + user_manager::TypedScopedUserManager<user_manager::FakeUserManager> + user_manager_; + std::vector< + std::unique_ptr<base::ScopedObservation<Profile, ProfileObserver>>> + profile_observations_; std::unique_ptr<crosapi::CrosapiManager> manager_; std::unique_ptr<ash::KioskChromeAppManager> kiosk_chrome_app_manager_; #endif
diff --git a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.ts b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.ts index 74d8284..2d8f2530 100644 --- a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.ts +++ b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_test.ts
@@ -7,15 +7,16 @@ import {fakeFirmwareUpdates} from 'chrome://accessory-update/fake_data.js'; import {FakeUpdateController} from 'chrome://accessory-update/fake_update_controller.js'; import {FakeUpdateProvider} from 'chrome://accessory-update/fake_update_provider.js'; -import {FirmwareUpdate, UpdateState} from 'chrome://accessory-update/firmware_update.mojom-webui.js'; -import {FirmwareUpdateAppElement} from 'chrome://accessory-update/firmware_update_app.js'; +import {UpdateState} from 'chrome://accessory-update/firmware_update.mojom-webui.js'; +import type {FirmwareUpdate} from 'chrome://accessory-update/firmware_update.mojom-webui.js'; +import type {FirmwareUpdateAppElement} from 'chrome://accessory-update/firmware_update_app.js'; import {FirmwareUpdateDialogElement} from 'chrome://accessory-update/firmware_update_dialog.js'; import {getUpdateProvider, setUpdateControllerForTesting, setUpdateProviderForTesting} from 'chrome://accessory-update/mojo_interface_provider.js'; -import {UpdateCardElement} from 'chrome://accessory-update/update_card.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; -import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; +import type {UpdateCardElement} from 'chrome://accessory-update/update_card.js'; import {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js'; import {CrDialogElement} from 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; +import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; import {assert} from 'chrome://resources/js/assert.js'; import {mojoString16ToString} from 'chrome://resources/js/mojo_type_util.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; @@ -337,37 +338,4 @@ assertTrue(!!fakeUpdate); assertTrue(getUpdateDialog().open); }); - - test('UpdatesCSSWhenIsJellyEnabledForFirmwareAppSet', async () => { - const linkEl = document.createElement('link'); - const disabledUrl = 'chrome://resources/chromeos/colors/cros_styles.css'; - linkEl.href = disabledUrl; - document.head.appendChild(linkEl); - - // Setup for jelly disabled. - loadTimeData.overrideValues({ - isJellyEnabledForFirmwareUpdate: false, - }); - initializePage(); - await flushTasks(); - - assertTrue(linkEl.href.includes(disabledUrl), 'Has cros_styles'); - - // Clear app element. - page?.remove(); - await flushTasks(); - - // Setup for jelly disabled. - loadTimeData.overrideValues({ - isJellyEnabledForFirmwareUpdate: true, - }); - initializePage(); - await flushTasks(); - - const enabledUrl = 'chrome://theme/colors.css'; - assertTrue(linkEl.href.includes(enabledUrl), 'Has theme/colors'); - - // Clean up. - document.head.removeChild(linkEl); - }); });
diff --git a/chrome/test/data/webui/chromeos/print_management/print_management_test.ts b/chrome/test/data/webui/chromeos/print_management/print_management_test.ts index 0f4ea88..297c9aa 100644 --- a/chrome/test/data/webui/chromeos/print_management/print_management_test.ts +++ b/chrome/test/data/webui/chromeos/print_management/print_management_test.ts
@@ -5,14 +5,14 @@ import 'chrome://print-management/print_management.js'; import 'chrome://webui-test/chromeos/mojo_webui_test_support.js'; -import {IronIconElement} from '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import type {IronIconElement} from '//resources/polymer/v3_0/iron-icon/iron-icon.js'; import {setMetadataProviderForTesting, setPrintManagementHandlerForTesting} from 'chrome://print-management/mojo_interface_provider.js'; -import {PrintJobEntryElement} from 'chrome://print-management/print_job_entry.js'; -import {PrintManagementElement} from 'chrome://print-management/print_management.js'; +import type {PrintJobEntryElement} from 'chrome://print-management/print_job_entry.js'; +import type {PrintManagementElement} from 'chrome://print-management/print_management.js'; import {PrinterSetupInfoElement} from 'chrome://print-management/printer_setup_info.js'; -import {ActivePrintJobInfo, ActivePrintJobState, CompletedPrintJobInfo, LaunchSource, PrinterErrorCode, PrintingMetadataProviderInterface, PrintJobCompletionStatus, PrintJobInfo, PrintJobsObserverRemote} from 'chrome://print-management/printing_manager.mojom-webui.js'; -import {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {ActivePrintJobState, LaunchSource, PrinterErrorCode, PrintJobCompletionStatus} from 'chrome://print-management/printing_manager.mojom-webui.js'; +import type {ActivePrintJobInfo, CompletedPrintJobInfo, PrintingMetadataProviderInterface, PrintJobInfo, PrintJobsObserverRemote} from 'chrome://print-management/printing_manager.mojom-webui.js'; +import type {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -911,41 +911,6 @@ verifyPrintJobs(expectedHistoryList, getHistoryPrintJobEntries(page!)); }); - test('IsJellyEnabledForPrintManagementUpdatesCSS', async () => { - const disabledUrl = 'chrome://resources/chromeos/colors/cros_styles.css'; - const linkEl = document.createElement('link'); - linkEl.href = disabledUrl; - document.head.appendChild(linkEl); - - // Setup for disabled test. - loadTimeData.overrideValues({ - isJellyEnabledForPrintManagement: false, - }); - - await initializePrintManagementApp([]); - - assertTrue(linkEl.href.includes(disabledUrl)); - - // Clean up element. - page?.remove(); - page = null; - assert(window.trustedTypes); - document.body.innerHTML = window.trustedTypes.emptyHTML; - - // Setup for enabled test. - loadTimeData.overrideValues({ - isJellyEnabledForPrintManagement: true, - }); - - await initializePrintManagementApp([]); - - const enabledUrl = 'chrome://theme/colors.css'; - assertTrue(linkEl.href.includes(enabledUrl)); - - // Clean up test element. - document.head.removeChild(linkEl); - }); - // Verify 'manage printers' button in header does not show when setup // assistance flag is off. test('HeaderManagePrinterButton_HiddenWhenFlagOff', async () => {
diff --git a/chrome/test/data/webui/settings/chromeos/date_time_page/timezone_subpage_test.ts b/chrome/test/data/webui/settings/chromeos/date_time_page/timezone_subpage_test.ts index 989f6ee..f80d690 100644 --- a/chrome/test/data/webui/settings/chromeos/date_time_page/timezone_subpage_test.ts +++ b/chrome/test/data/webui/settings/chromeos/date_time_page/timezone_subpage_test.ts
@@ -8,40 +8,62 @@ import {CrSettingsPrefs, GeolocationAccessLevel, Router, routes} from 'chrome://os-settings/os_settings.js'; import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js'; import {assert} from 'chrome://resources/js/assert.js'; -import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; +import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {isVisible} from 'chrome://webui-test/test_util.js'; -suite('<timezone-subpage>', function() { - let timezoneSubpage: TimezoneSubpageElement; +let timezoneSubpage: TimezoneSubpageElement; - setup(async function() { - const prefElement = document.createElement('settings-prefs'); - document.body.appendChild(prefElement); +async function init(): Promise<void> { + const prefElement = document.createElement('settings-prefs'); + document.body.appendChild(prefElement); - await CrSettingsPrefs.initialized; - timezoneSubpage = document.createElement('timezone-subpage'); - timezoneSubpage.prefs = { - ...prefElement.prefs, - ash: { - user: { - geolocation_access_level: { - key: 'ash.user.geolocation_access_level', - type: chrome.settingsPrivate.PrefType.NUMBER, - value: GeolocationAccessLevel.ALLOWED, - }, + await CrSettingsPrefs.initialized; + timezoneSubpage = document.createElement('timezone-subpage'); + timezoneSubpage.prefs = { + ...prefElement.prefs, + ash: { + user: { + geolocation_access_level: { + key: 'ash.user.geolocation_access_level', + type: chrome.settingsPrivate.PrefType.NUMBER, + value: GeolocationAccessLevel.ALLOWED, }, }, - }; + }, + }; - document.body.appendChild(timezoneSubpage); + document.body.appendChild(timezoneSubpage); + await flushTasks(); +} + +function testTeardown() { + timezoneSubpage.remove(); + CrSettingsPrefs.resetForTesting(); + Router.getInstance().resetRouteForTesting(); +} + +suite('<timezone-subpage> with logged-in user', () => { + setup(async () => { + await init(); }); - teardown(function() { - timezoneSubpage.remove(); - CrSettingsPrefs.resetForTesting(); - Router.getInstance().resetRouteForTesting(); + teardown(() => { + testTeardown(); + }); + + test('timezone radio group is enabled', async () => { + // Enable automatic timezone. + timezoneSubpage.setPrefValue( + 'generated.resolve_timezone_by_geolocation_on_off', true); + await flushTasks(); + + const timezoneRadioGroup = + timezoneSubpage.shadowRoot!.querySelector<SettingsRadioGroupElement>( + '#timeZoneRadioGroup'); + assert(timezoneRadioGroup); + assertFalse(timezoneRadioGroup.disabled); }); test('Timezone autodetect by geolocation radio', async () => { @@ -53,13 +75,13 @@ // Resolve timezone by geolocation is on. timezoneSubpage.setPrefValue( 'generated.resolve_timezone_by_geolocation_on_off', true); - flush(); + await flushTasks(); assertEquals('true', timezoneRadioGroup.selected); // Resolve timezone by geolocation is off. timezoneSubpage.setPrefValue( 'generated.resolve_timezone_by_geolocation_on_off', false); - flush(); + await flushTasks(); assertEquals('false', timezoneRadioGroup.selected); // Set timezone autodetect on by clicking the 'on' radio. @@ -115,7 +137,6 @@ timezoneSubpage.setPrefValue( 'generated.resolve_timezone_by_geolocation_on_off', true); - // Geolocation is allowed by default, the warning text should be hidden. assertFalse(isVisible( timezoneSubpage.shadowRoot!.querySelector('#warningText'))); @@ -124,7 +145,31 @@ timezoneSubpage.setPrefValue( 'ash.user.geolocation_access_level', GeolocationAccessLevel.DISALLOWED); - flush(); + await flushTasks(); assertTrue(!!timezoneSubpage.shadowRoot!.querySelector('#warningText')); }); }); + +suite('<timezone-subpage> with guest user', () => { + setup(async () => { + loadTimeData.overrideValues({isGuest: true}); + await init(); + }); + + teardown(() => { + testTeardown(); + }); + + test('timezone radio group is disabled', async () => { + // Enable automatic timezone. + timezoneSubpage.setPrefValue( + 'generated.resolve_timezone_by_geolocation_on_off', true); + await flushTasks(); + + const timezoneRadioGroup = + timezoneSubpage.shadowRoot!.querySelector<SettingsRadioGroupElement>( + '#timeZoneRadioGroup'); + assert(timezoneRadioGroup); + assertTrue(timezoneRadioGroup.disabled); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_apps_page/os_apps_page_test.ts b/chrome/test/data/webui/settings/chromeos/os_apps_page/os_apps_page_test.ts index 44f6b810..abfc45ed 100644 --- a/chrome/test/data/webui/settings/chromeos/os_apps_page/os_apps_page_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_apps_page/os_apps_page_test.ts
@@ -300,20 +300,37 @@ flush(); }); + function queryAppNotificationsRow(): CrLinkRowElement|null { + return appsPage.shadowRoot!.querySelector<CrLinkRowElement>( + '#appNotificationsRow'); + } + if (isRevampWayfindingEnabled) { test('App notification row displays helpful description', async () => { - const rowLink = appsPage.shadowRoot!.querySelector<CrLinkRowElement>( - '#appNotificationsRow'); + const rowLink = queryAppNotificationsRow(); assertTrue(!!rowLink); assertTrue(isVisible(rowLink)); assertEquals( 'Manage app notifications, Do Not Disturb, and app badging', rowLink.subLabel); }); + + test( + 'App notification row has same sublabel when Do Not Disturb is on', + async () => { + appsPage.set('isDndEnabled_', true); + await flushTasks(); + + const rowLink = queryAppNotificationsRow(); + assertTrue(!!rowLink); + assertTrue(isVisible(rowLink)); + assertEquals( + 'Manage app notifications, Do Not Disturb, and app badging', + rowLink.subLabel); + }); } else { test('App notification row displays number of apps', async () => { - const rowLink = appsPage.shadowRoot!.querySelector<CrLinkRowElement>( - '#appNotificationsRow'); + const rowLink = queryAppNotificationsRow(); assertTrue(!!rowLink); assertTrue(isVisible(rowLink)); // Test default is to have 0 apps. @@ -341,6 +358,16 @@ await flushTasks(); assertEquals('1 apps', rowLink.subLabel); }); + + test('App notification row shows when Do Not Disturb is on', async () => { + appsPage.set('isDndEnabled_', true); + await flushTasks(); + + const rowLink = queryAppNotificationsRow(); + assertTrue(!!rowLink); + assertTrue(isVisible(rowLink)); + assertEquals('Do Not Disturb enabled', rowLink.subLabel); + }); } test('Manage isolated web apps row', () => {
diff --git a/chromeos/components/kiosk/kiosk_test_utils.cc b/chromeos/components/kiosk/kiosk_test_utils.cc index cb59d8c..e57fe83 100644 --- a/chromeos/components/kiosk/kiosk_test_utils.cc +++ b/chromeos/components/kiosk/kiosk_test_utils.cc
@@ -20,13 +20,13 @@ namespace chromeos { -void SetUpFakeKioskSession() { +void SetUpFakeKioskSession(const std::string& email) { #if BUILDFLAG(IS_CHROMEOS_ASH) CHECK(user_manager::UserManager::Get()); auto* user_manager = static_cast<user_manager::UserManagerBase*>( user_manager::UserManager::Get()); - auto account_id = AccountId::FromUserEmail("example@example.com"); + auto account_id = AccountId::FromUserEmail(email); auto* user = user_manager->AddKioskAppUserForTesting( account_id, user_manager::FakeUserManager::GetFakeUsernameHash(account_id));
diff --git a/chromeos/components/kiosk/kiosk_test_utils.h b/chromeos/components/kiosk/kiosk_test_utils.h index 2e8cbd62..699052b 100644 --- a/chromeos/components/kiosk/kiosk_test_utils.h +++ b/chromeos/components/kiosk/kiosk_test_utils.h
@@ -5,15 +5,17 @@ #ifndef CHROMEOS_COMPONENTS_KIOSK_KIOSK_TEST_UTILS_H_ #define CHROMEOS_COMPONENTS_KIOSK_KIOSK_TEST_UTILS_H_ +#include <string> + namespace chromeos { // Sets up a fake kiosk session for unit tests. // Make sure to enable `UserManagerBase` to be returned from // `UserManager::Get()` prior to calling this function. -extern void SetUpFakeKioskSession(); - -// Tears down a fake kiosk session for unit tests. -extern void TearDownFakeKioskSession(); +// TODO(b/40286020): remove the default parameter. That is only for transition +// purpose. +extern void SetUpFakeKioskSession( + const std::string& email = "example@example.com"); } // namespace chromeos
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index 84bcb1c..cb0b4835 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -220,7 +220,12 @@ "RoundedWindows", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables a content cache for FileSystemProvider extensions. +// Enables CloudFileSystem for FileSystemProvider extensions. +BASE_FEATURE(kFileSystemProviderCloudFileSystem, + "FileSystemProviderCloudFileSystem", + base::FEATURE_DISABLED_BY_DEFAULT); + +// Enables a content cache in CloudFileSystem for FileSystemProvider extensions. BASE_FEATURE(kFileSystemProviderContentCache, "FileSystemProviderContentCache", base::FEATURE_DISABLED_BY_DEFAULT); @@ -312,8 +317,15 @@ return base::FeatureList::IsEnabled(kEssentialSearch); } +bool IsFileSystemProviderCloudFileSystemEnabled() { + return base::FeatureList::IsEnabled(kFileSystemProviderCloudFileSystem); +} + bool IsFileSystemProviderContentCacheEnabled() { - return base::FeatureList::IsEnabled(kFileSystemProviderContentCache); + // The `ContentCache` will be owned by the `CloudFileSystem`. Thus, the + // `FileSystemProviderCloudFileSystem` flag has to be enabled too. + return IsFileSystemProviderCloudFileSystemEnabled() && + base::FeatureList::IsEnabled(kFileSystemProviderContentCache); } bool IsIWAForTelemetryExtensionAPIEnabled() {
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index 0a41962..d77863ad 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -89,6 +89,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kMicrosoftOneDriveIntegrationForEnterprise); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +BASE_DECLARE_FEATURE(kFileSystemProviderCloudFileSystem); +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kFileSystemProviderContentCache); // Keep alphabetized. @@ -114,6 +116,8 @@ bool IsDeskProfilesEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsEssentialSearchEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +bool IsFileSystemProviderCloudFileSystemEnabled(); +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsFileSystemProviderContentCacheEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsIWAForTelemetryExtensionAPIEnabled();
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index ecfd839..378107ca 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -1129,8 +1129,8 @@ // parameters here. If a new parameter is added and its value is only known // after the user has logged in, please update BrowserPostLoginParams as well. // -// Next version: 75 -// Next id: 75 +// Next version: 77 +// Next id: 77 [Stable, RenamedFrom="crosapi.mojom.LacrosInitParams"] struct BrowserInitParams { // This is ash-chrome's version of the Crosapi interface. This is used by @@ -1574,6 +1574,12 @@ // If true, "Compose" will be disabled. Only applies on chromeos devices. [MinVersion=75] bool should_disable_chrome_compose_on_chromeos@75; + + // The seed that is used to randomize the limited entropy synthetic trial. The + // group assignment of this trial needs to be the same between Lacros and ash + // chrome. + [MinVersion=76] + uint64 limited_entropy_synthetic_trial_seed@76; }; // BrowserPostLoginParams is the subset of parameters in BrowserInitParams
diff --git a/chromeos/startup/browser_params_proxy.cc b/chromeos/startup/browser_params_proxy.cc index 00a4d7ec..f82aae8 100644 --- a/chromeos/startup/browser_params_proxy.cc +++ b/chromeos/startup/browser_params_proxy.cc
@@ -162,6 +162,10 @@ return BrowserInitParams::Get()->entropy_source; } +uint64_t BrowserParamsProxy::LimitedEntropySyntheticTrialSeed() const { + return BrowserInitParams::Get()->limited_entropy_synthetic_trial_seed; +} + uint64_t BrowserParamsProxy::UkmClientId() const { return BrowserInitParams::Get()->ukm_client_id; }
diff --git a/chromeos/startup/browser_params_proxy.h b/chromeos/startup/browser_params_proxy.h index 1e1a9bf..961e542 100644 --- a/chromeos/startup/browser_params_proxy.h +++ b/chromeos/startup/browser_params_proxy.h
@@ -77,6 +77,8 @@ const std::optional<std::string>& MetricsServiceClientId() const; + uint64_t LimitedEntropySyntheticTrialSeed() const; + const crosapi::mojom::EntropySourcePtr& EntropySource() const; uint64_t UkmClientId() const;
diff --git a/clank b/clank index cbd13ba..ab0b951 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit cbd13ba3774974cb20cd7dbaf2acc4860fe6d0f4 +Subproject commit ab0b95197af40620e76f2054c376e0068d43a968
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index c919529f..35f8cc71 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -1361,13 +1361,20 @@ GetHitTestMask(mask); - SkMatrix matrix; const float scale = GetScale(); - // `matrix` should be on Widget space, so use `origin_` as an origin instead - // of the root surface origin. - matrix.setScaleTranslate(SkFloatToScalar(1.0f / scale), - SkFloatToScalar(1.0f / scale), origin_.x(), - origin_.y()); + + // `mask` should be in the Widget's coordinates, but the above + // GetHitTestMask() call returns the mask in the root_surface's coordinates. + // We need to offset the difference. + auto widget_bounds = widget_->GetWindowBoundsInScreen().origin(); + auto root_surface_bounds = + root_surface()->window()->GetBoundsInScreen().origin(); + auto offset = root_surface_bounds - widget_bounds.OffsetFromOrigin(); + + SkMatrix matrix; + matrix.setScaleTranslate( + SkFloatToScalar(1.0f / scale), SkFloatToScalar(1.0f / scale), + SkIntToScalar(offset.x()), SkIntToScalar(offset.y())); mask->transform(matrix); }
diff --git a/components/exo/shell_surface_base.h b/components/exo/shell_surface_base.h index 8c91421..6401e14d0 100644 --- a/components/exo/shell_surface_base.h +++ b/components/exo/shell_surface_base.h
@@ -465,6 +465,7 @@ raw_ptr<views::Widget> widget_ = nullptr; bool movement_disabled_ = false; + // This value is in the screen coordinates. gfx::Point origin_; // Container Window Id (see ash/public/cpp/shell_window_ids.h)
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc index 84719ad..571d2e24 100644 --- a/components/exo/shell_surface_unittest.cc +++ b/components/exo/shell_surface_unittest.cc
@@ -4499,4 +4499,16 @@ surface2->RemoveSurfaceObserver(&observer2); } +TEST_F(ShellSurfaceTest, GetWidgetHitTestMask) { + auto shell_surface = test::ShellSurfaceBuilder({256, 256}) + .SetOrigin({100, 100}) + .BuildShellSurface(); + + EXPECT_TRUE(shell_surface->WidgetHasHitTestMask()); + SkPath mask; + shell_surface->GetWidgetHitTestMask(&mask); + // Returned HitMask should be in the widget local coordinates. + EXPECT_EQ(SkRect::MakeLTRB(0, 0, 256, 256), mask.getBounds()); +} + } // namespace exo
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index a8db7f94..3561960 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -21,6 +21,8 @@ "client_tracker.h", "content_type.cc", "content_type.h", + "output_configuration_change.cc", + "output_configuration_change.h", "output_controller.cc", "output_controller.h", "output_metrics.cc", @@ -82,6 +84,8 @@ "xdg_shell.h", "zaura_output_manager.cc", "zaura_output_manager.h", + "zaura_output_manager_v2.cc", + "zaura_output_manager_v2.h", "zaura_shell.cc", "zaura_shell.h", "zcr_alpha_compositing.cc", @@ -152,6 +156,7 @@ "//chromeos/ui/base", "//chromeos/ui/frame", "//components/exo", + "//components/exo/wayland/protocol:aura_output_management_protocol", "//components/exo/wayland/protocol:aura_shell_protocol", "//components/exo/wayland/protocol:chrome_color_management_protocol", "//components/exo/wayland/protocol:overlay_prioritizer_protocol", @@ -307,6 +312,7 @@ "wayland_positioner_unittest.cc", "wl_data_device_manager_unittest.cc", "zaura_output_manager_unittest.cc", + "zaura_output_manager_v2_unittest.cc", "zaura_shell_unittest.cc", "zcr_remote_shell_impl_unittest.cc", "zcr_remote_shell_unittest.cc", @@ -324,6 +330,7 @@ "//components/exo", "//components/exo:test_support", "//components/exo/wayland/fuzzer:unit_tests", + "//components/exo/wayland/protocol:aura_output_management_protocol", "//components/exo/wayland/protocol:aura_shell_protocol", "//components/exo/wayland/protocol:overlay_prioritizer_protocol", "//components/exo/wayland/protocol:surface_augmenter_protocol", @@ -373,6 +380,7 @@ ] public_deps = [ + "//components/exo/wayland/protocol:aura_output_management_protocol", "//components/exo/wayland/protocol:aura_shell_protocol", "//components/exo/wayland/protocol:chrome_color_management_protocol", "//components/exo/wayland/protocol:overlay_prioritizer_protocol",
diff --git a/components/exo/wayland/clients/client_helper.cc b/components/exo/wayland/clients/client_helper.cc index 04f0aa4e8..dfe952c 100644 --- a/components/exo/wayland/clients/client_helper.cc +++ b/components/exo/wayland/clients/client_helper.cc
@@ -56,6 +56,7 @@ DEFAULT_DELETER(struct wp_presentation_feedback, wp_presentation_feedback_destroy) DEFAULT_DELETER(zaura_output_manager, zaura_output_manager_destroy) +DEFAULT_DELETER(zaura_output_manager_v2, zaura_output_manager_v2_destroy) DEFAULT_DELETER(zaura_shell, zaura_shell_destroy) DEFAULT_DELETER(zaura_surface, zaura_surface_destroy) DEFAULT_DELETER(zaura_toplevel, zaura_toplevel_destroy)
diff --git a/components/exo/wayland/clients/client_helper.h b/components/exo/wayland/clients/client_helper.h index e03b509..ece29c0 100644 --- a/components/exo/wayland/clients/client_helper.h +++ b/components/exo/wayland/clients/client_helper.h
@@ -6,6 +6,7 @@ #define COMPONENTS_EXO_WAYLAND_CLIENTS_CLIENT_HELPER_H_ #include <alpha-compositing-unstable-v1-client-protocol.h> +#include <aura-output-management-client-protocol.h> #include <aura-shell-client-protocol.h> #include <chrome-color-management-client-protocol.h> #include <content-type-v1-client-protocol.h> @@ -86,6 +87,7 @@ DEFAULT_DELETER_FDECL(wp_presentation) DEFAULT_DELETER_FDECL(struct wp_presentation_feedback) DEFAULT_DELETER_FDECL(zaura_output_manager) +DEFAULT_DELETER_FDECL(zaura_output_manager_v2) DEFAULT_DELETER_FDECL(zaura_shell) DEFAULT_DELETER_FDECL(zaura_surface) DEFAULT_DELETER_FDECL(zaura_toplevel)
diff --git a/components/exo/wayland/clients/globals.cc b/components/exo/wayland/clients/globals.cc index 29546b9..bed1096 100644 --- a/components/exo/wayland/clients/globals.cc +++ b/components/exo/wayland/clients/globals.cc
@@ -28,6 +28,10 @@ uint32_t version) { Globals* globals = static_cast<Globals*>(data); + if (globals->observer_for_testing_) { + globals->observer_for_testing_->OnRegistryGlobal(id, interface, version); + } + #define BIND(interface_type, global_member) \ if (strcmp(interface, #interface_type) == 0) { \ globals->global_member.reset( \ @@ -57,6 +61,7 @@ BIND(wp_presentation, presentation) BIND(zaura_shell, aura_shell) BIND(zaura_output_manager, aura_output_manager) + BIND(zaura_output_manager_v2, aura_output_manager_v2) BIND(zwp_linux_dmabuf_v1, linux_dmabuf) BIND(wl_subcompositor, subcompositor) BIND(zcr_color_manager_v1, color_manager) @@ -81,6 +86,11 @@ void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { LOG(WARNING) << "Got a registry losing event for " << id; + + Globals* globals = static_cast<Globals*>(data); + if (globals->observer_for_testing_) { + globals->observer_for_testing_->OnRegistryGlobalRemove(id); + } } wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover};
diff --git a/components/exo/wayland/clients/globals.h b/components/exo/wayland/clients/globals.h index 0ef31e9..3a6cdeb 100644 --- a/components/exo/wayland/clients/globals.h +++ b/components/exo/wayland/clients/globals.h
@@ -48,6 +48,19 @@ void Init(wl_display* display, base::flat_map<std::string, uint32_t> in_requested_versions); + // TestObserver is an interface that observes certain events for testing + // purposes. + class TestObserver { + public: + virtual void OnRegistryGlobal(uint32_t id, + const char* interface, + uint32_t version) = 0; + virtual void OnRegistryGlobalRemove(uint32_t id) = 0; + }; + void set_observer_for_testing(TestObserver* observer) { + observer_for_testing_ = observer; + } + std::unique_ptr<wl_registry> registry; std::vector<Object<wl_output>> outputs; @@ -61,6 +74,7 @@ Object<zaura_shell> aura_shell; std::vector<Object<zaura_output>> aura_outputs; Object<zaura_output_manager> aura_output_manager; + Object<zaura_output_manager_v2> aura_output_manager_v2; Object<xdg_wm_base> xdg_wm_base; Object<zwp_fullscreen_shell_v1> fullscreen_shell; Object<zwp_input_timestamps_manager_v1> input_timestamps_manager; @@ -77,6 +91,8 @@ Object<wl_data_device_manager> data_device_manager; base::flat_map<std::string, uint32_t> requested_versions; + + raw_ptr<TestObserver> observer_for_testing_; }; } // namespace exo::wayland::clients
diff --git a/components/exo/wayland/clients/test/client_version_test.cc b/components/exo/wayland/clients/test/client_version_test.cc index 05c96aa1..b10298e 100644 --- a/components/exo/wayland/clients/test/client_version_test.cc +++ b/components/exo/wayland/clients/test/client_version_test.cc
@@ -5,6 +5,7 @@ #include "components/exo/wayland/clients/test/client_version_test.h" #include <alpha-compositing-unstable-v1-client-protocol.h> +#include <aura-output-management-server-protocol.h> #include <aura-shell-server-protocol.h> #include <chrome-color-management-server-protocol.h> #include <content-type-v1-server-protocol.h> @@ -65,6 +66,7 @@ std::unique_ptr<wl_seat> wl_seat; std::unique_ptr<wp_presentation> wp_presentation; std::unique_ptr<zaura_output_manager> zaura_output_manager; + std::unique_ptr<zaura_output_manager_v2> zaura_output_manager_v2; std::unique_ptr<zaura_shell> zaura_shell; std::unique_ptr<zwp_linux_dmabuf_v1> zwp_linux_dmabuf_v1; std::unique_ptr<wl_subcompositor> wl_subcompositor; @@ -162,6 +164,7 @@ REGISTRY_CALLBACK(wl_seat, wl_seat), REGISTRY_CALLBACK(wp_presentation, wp_presentation), REGISTRY_CALLBACK(zaura_output_manager, zaura_output_manager), + REGISTRY_CALLBACK(zaura_output_manager_v2, zaura_output_manager_v2), REGISTRY_CALLBACK(zaura_shell, zaura_shell), REGISTRY_CALLBACK(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1), REGISTRY_CALLBACK(wl_subcompositor, wl_subcompositor),
diff --git a/components/exo/wayland/output_configuration_change.cc b/components/exo/wayland/output_configuration_change.cc new file mode 100644 index 0000000..23f0e0b7 --- /dev/null +++ b/components/exo/wayland/output_configuration_change.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/exo/wayland/output_configuration_change.h" + +namespace exo::wayland { + +OutputConfigurationChange::OutputConfigurationChange() = default; + +OutputConfigurationChange::OutputConfigurationChange( + OutputConfigurationChange&& other) = default; + +OutputConfigurationChange& OutputConfigurationChange::operator=( + OutputConfigurationChange&& other) = default; + +OutputConfigurationChange::~OutputConfigurationChange() = default; + +} // namespace exo::wayland
diff --git a/components/exo/wayland/output_configuration_change.h b/components/exo/wayland/output_configuration_change.h new file mode 100644 index 0000000..e3f72a7 --- /dev/null +++ b/components/exo/wayland/output_configuration_change.h
@@ -0,0 +1,44 @@ +// 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_EXO_WAYLAND_OUTPUT_CONFIGURATION_CHANGE_H_ +#define COMPONENTS_EXO_WAYLAND_OUTPUT_CONFIGURATION_CHANGE_H_ + +#include <vector> + +#include "base/memory/raw_ptr.h" + +namespace exo::wayland { + +class WaylandDisplayOutput; + +using WaylandOutputList = std::vector<raw_ptr<const WaylandDisplayOutput>>; + +// Pairs the changed output with a bitvector of DisplayMetric changes. +using WaylandOutputChangedList = + std::vector<std::pair<raw_ptr<const WaylandDisplayOutput>, uint32_t>>; + +// Encapsulates an atomic change to the output configuration tracked by Exo. +struct OutputConfigurationChange { + OutputConfigurationChange(); + OutputConfigurationChange(OutputConfigurationChange&& other); + OutputConfigurationChange& operator=(OutputConfigurationChange&& other); + OutputConfigurationChange(const OutputConfigurationChange&) = delete; + OutputConfigurationChange& operator=(const OutputConfigurationChange&) = + delete; + ~OutputConfigurationChange(); + + // New outputs for user-visible displays added to the system. + WaylandOutputList added_outputs; + + // Outputs for displays removed from the system's configuration. + WaylandOutputList removed_outputs; + + // Existing outputs updated to reflect updated display metrics. + WaylandOutputChangedList changed_outputs; +}; + +} // namespace exo::wayland + +#endif // COMPONENTS_EXO_WAYLAND_OUTPUT_CONFIGURATION_CHANGE_H_
diff --git a/components/exo/wayland/output_controller.cc b/components/exo/wayland/output_controller.cc index 80ea963..63c90c65 100644 --- a/components/exo/wayland/output_controller.cc +++ b/components/exo/wayland/output_controller.cc
@@ -4,14 +4,19 @@ #include "components/exo/wayland/output_controller.h" +#include <aura-output-management-server-protocol.h> #include <secure-output-unstable-v1-server-protocol.h> #include <wayland-server-core.h> #include <xdg-output-unstable-v1-server-protocol.h> #include "ash/shell.h" +#include "base/containers/contains.h" +#include "base/ranges/algorithm.h" +#include "components/exo/wayland/output_configuration_change.h" #include "components/exo/wayland/wayland_display_output.h" #include "components/exo/wayland/wl_output.h" #include "components/exo/wayland/zaura_output_manager.h" +#include "components/exo/wayland/zaura_output_manager_v2.h" #include "components/exo/wayland/zcr_secure_output.h" #include "components/exo/wayland/zxdg_output_manager.h" #include "ui/display/display.h" @@ -20,12 +25,16 @@ namespace exo::wayland { OutputController::OutputController(Delegate* delegate) : delegate_(delegate) { - // aura_output_manager needs to be registered before the wl_output globals to - // ensure clients can bind to the aura_output_manager before any wl_outputs. - // This is necessary to ensure aura_output_manager can send relevant output - // events immediately after an output is bound to the client and before the - // data in these events might be needed by the client. + // Clients need to bind aura output manager globals before binding any of the + // wl_output globals. This is necessary to ensure clients won't receive events + // for outputs before receiving events for the aura output manager. wl_display* display = delegate_->GetWaylandDisplay(); + aura_output_manager_v2_ = + std::make_unique<AuraOutputManagerV2>(base::BindRepeating( + &OutputController::GetActiveOutputs, base::Unretained(this))); + wl_global_create(display, &zaura_output_manager_v2_interface, + kZAuraOutputManagerV2Version, aura_output_manager_v2_.get(), + bind_aura_output_manager_v2); wl_global_create(display, &zaura_output_manager_interface, kZAuraOutputManagerVersion, nullptr, bind_aura_output_manager); @@ -63,6 +72,20 @@ outputs_.insert(std::make_pair(added_display.id(), std::move(output))); } + for (const auto& change : configuration_change.display_metrics_changes) { + if (auto* wayland_display_output = + GetWaylandDisplayOutput(change.display->id())) { + wayland_display_output->SendDisplayMetricsChanges(change.display.get(), + change.changed_metrics); + } + } + + // Propagate display configuration changes to aura output manager clients. + const bool needs_done = + ProcessDisplayChangesForAuraOutputManager(configuration_change); + + // Remove outputs after propagating config changes as the WaylandDisplayOutput + // object may be needed during change notification propagation. for (const display::Display& removed_display : configuration_change.removed_displays) { // There should always be at least one display tracked by Exo. @@ -74,12 +97,8 @@ output.release()->OnDisplayRemoved(); } - for (const auto& change : configuration_change.display_metrics_changes) { - if (auto* wayland_display_output = - GetWaylandDisplayOutput(change.display->id())) { - wayland_display_output->SendDisplayMetricsChanges(change.display.get(), - change.changed_metrics); - } + if (needs_done) { + aura_output_manager_v2_->SendDone(); } UpdateActivatedDisplayIfNecessary(); @@ -111,6 +130,45 @@ return iter == outputs_.end() ? nullptr : iter->second.get(); } +WaylandOutputList OutputController::GetActiveOutputs() const { + WaylandOutputList output_list; + base::ranges::transform(outputs_, std::back_inserter(output_list), + [](auto& pair) { return pair.second.get(); }); + return output_list; +} + +bool OutputController::ProcessDisplayChangesForAuraOutputManager( + const DisplayConfigurationChange& configuration_change) { + OutputConfigurationChange output_config_change; + + base::ranges::transform( + configuration_change.added_displays, + std::back_inserter(output_config_change.added_outputs), + [this](const display::Display& display) { + return GetWaylandDisplayOutput(display.id()); + }); + base::ranges::transform( + configuration_change.removed_displays, + std::back_inserter(output_config_change.removed_outputs), + [this](const display::Display& display) { + return GetWaylandDisplayOutput(display.id()); + }); + for (const DisplayMetricsChange& change : + configuration_change.display_metrics_changes) { + // Added displays may appear in both added and changed lists, ensure added + // outputs are not represented in both added and changed lists. + if (!base::Contains(configuration_change.added_displays, + change.display.get())) { + output_config_change.changed_outputs.emplace_back( + GetWaylandDisplayOutput(change.display->id()), + change.changed_metrics); + } + } + + return aura_output_manager_v2_->OnDidProcessDisplayChanges( + output_config_change); +} + void OutputController::UpdateActivatedDisplayIfNecessary() { const int64_t current_active_display_id = display::Screen::GetScreen()->GetDisplayForNewWindows().id();
diff --git a/components/exo/wayland/output_controller.h b/components/exo/wayland/output_controller.h index 19919b0..5ae1b4f07 100644 --- a/components/exo/wayland/output_controller.h +++ b/components/exo/wayland/output_controller.h
@@ -7,6 +7,7 @@ #include "ash/shell_observer.h" #include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" #include "ui/display/manager/display_manager.h" #include "ui/display/manager/display_manager_observer.h" @@ -17,6 +18,7 @@ namespace exo::wayland { +class AuraOutputManagerV2; class WaylandDisplayOutput; // Responsible for keeping output state consistent with system display state and @@ -26,6 +28,8 @@ public: using DisplayOutputMap = base::flat_map<int64_t, std::unique_ptr<WaylandDisplayOutput>>; + using WaylandOutputList = std::vector<raw_ptr<const WaylandDisplayOutput>>; + class Delegate { public: virtual ~Delegate() = default; @@ -55,6 +59,15 @@ // the `display_id`. WaylandDisplayOutput* GetWaylandDisplayOutput(int64_t display_id); + // Returns a list of the current active outputs tracked by the server. + WaylandOutputList GetActiveOutputs() const; + + // Sends the necessary events for a configuration change to clients of the the + // aura output manager. Returns true if update events were sent and a done is + // needed. + bool ProcessDisplayChangesForAuraOutputManager( + const DisplayConfigurationChange& configuration_change); + // Updates exo to align with the system's currently active window. void UpdateActivatedDisplayIfNecessary(); @@ -62,6 +75,7 @@ int64_t dispatched_activated_display_id_ = display::kInvalidDisplayId; DisplayOutputMap outputs_; + std::unique_ptr<AuraOutputManagerV2> aura_output_manager_v2_; // The delegate will strictly outlive the controller. const raw_ptr<Delegate> delegate_;
diff --git a/components/exo/wayland/output_metrics.cc b/components/exo/wayland/output_metrics.cc index 789032f5..025e035 100644 --- a/components/exo/wayland/output_metrics.cc +++ b/components/exo/wayland/output_metrics.cc
@@ -107,6 +107,10 @@ scale = std::ceil(display.device_scale_factor()); } +OutputMetrics::OutputMetrics(const OutputMetrics&) = default; + +OutputMetrics& OutputMetrics::operator=(const OutputMetrics&) = default; + OutputMetrics::~OutputMetrics() = default; } // namespace exo::wayland
diff --git a/components/exo/wayland/output_metrics.h b/components/exo/wayland/output_metrics.h index f33f272..bb8d3d9 100644 --- a/components/exo/wayland/output_metrics.h +++ b/components/exo/wayland/output_metrics.h
@@ -24,6 +24,8 @@ // Metrics for wl_output and supported extensions. struct OutputMetrics { explicit OutputMetrics(const display::Display& display); + OutputMetrics(const OutputMetrics&); + OutputMetrics& operator=(const OutputMetrics&); virtual ~OutputMetrics(); //////////////////////////////////////////////////////////////////////////////
diff --git a/components/exo/wayland/protocol/BUILD.gn b/components/exo/wayland/protocol/BUILD.gn index 297d76e..3217be3 100644 --- a/components/exo/wayland/protocol/BUILD.gn +++ b/components/exo/wayland/protocol/BUILD.gn
@@ -3,6 +3,10 @@ # found in the LICENSE file. import("//third_party/wayland/wayland_protocol.gni") +wayland_protocol("aura_output_management_protocol") { + sources = [ "aura-output-management.xml" ] +} + wayland_protocol("aura_shell_protocol") { sources = [ "aura-shell.xml" ] }
diff --git a/components/exo/wayland/protocol/aura-output-management.xml b/components/exo/wayland/protocol/aura-output-management.xml new file mode 100644 index 0000000..7427ead5 --- /dev/null +++ b/components/exo/wayland/protocol/aura-output-management.xml
@@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="aura_output_management"> + + <copyright> + Copyright 2024 The Chromium Authors + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </copyright> + + <interface name="zaura_output_manager_v2" version="1"> + <description summary="aura output manager singleton"> + A global responsible for propagating atomic output configuration changes + to clients. An output configuration is a union of added / removed outputs + and updated output metrics. + + Added outputs arrive at the client as wl_registry.global events, removed + outputs as wl_registry.global_remove events and updated output metrics as + a sequence of events defined on the zaura_output_manager_v2 interface. + This is followed by the manager's done event which signals the end of the + transaction. + + The change should be processed by clients in a way that transitions from + one output configuration state to another without exposing the + intermediate output state to the rest of the application. + + Participating servers should emit the zaura_output_manager_v2 global + before any wl_output globals in the sequence of wl_registry.global events. + + Participating clients should bind the zaura_output_manager_v2 before any + wl_output globals. This ordering is required to ensure clients receive all + necessary output configuration information before receiving any further + server events that may reference bound wl_outputs. + + Clients can expect that all events comprising a configuration change are + sent synchronously, one after the other, before any other server events + that leverage the output as an event param. + </description> + + <event name="done" since="1"> + <description + summary="sent all information about the output configuration change"> + This event is sent after all added, changed and removed output events + for a given wl_output have been dispatched to the client. + </description> + </event> + + <event name="display_id" since="1"> + <description summary="advertise the output's display id"> + This event describes the 64bit display id assigned to each display by + ChromeOS. The value is opaque and should not be interpreted. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="display_id_hi" type="uint" /> + <arg name="display_id_lo" type="uint" /> + </event> + + <event name="logical_position" since="1"> + <description + summary="position of the output within the global compositor space"> + The position event describes the location of the wl_output within the + global compositor space. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="x" type="int" + summary="x position within the global compositor space" /> + <arg name="y" type="int" + summary="y position within the global compositor space" /> + </event> + + <event name="logical_size" since="1"> + <description summary="size of the output in the global compositor space"> + The logical_size event describes the logical size of the output in the + global compositor space. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="width" type="int" summary="width in global compositor space" /> + <arg name="height" type="int" + summary="height in global compositor space" /> + </event> + + <event name="physical_size" since="1"> + <description summary="size of the output in pixels"> + The physical resolution of the display in pixels. The value should not + include any overscan insets or display rotation, except for any panel + orientation adjustment. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="width" type="int" + summary="width in global compositor space" /> + <arg name="height" type="int" + summary="height in global compositor space" /> + </event> + + <event name="work_area_insets" since="1"> + <description summary="advertise the work area insets for the output"> + This event describes the work area insets for the output in logical + screen coordinates, from which the work area can be calculated. + + The event is sent when binding to the output object and subsequently as + output state changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="top" type="int" /> + <arg name="left" type="int" /> + <arg name="bottom" type="int" /> + <arg name="right" type="int" /> + </event> + + <event name="device_scale_factor" since="1"> + <description summary="advertise device scale factor for the output"> + The scale factor of the output device. We reinterpret_cast the float + scale factor into a 32-bit uint and later cast back into a float. This + is because wayland does not support native transport of floats. As + different CPU architectures may use different endian representations for + IEEE 754 floats, this protocol implicitly assumes that the caller and + receiver are the same machine. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="device_scale_factor" type="uint" + summary="display scale factor, in float format" /> + </event> + + <event name="logical_transform" since="1"> + <description summary="logical transform of the output"> + This event describes the logical transform for the output. Whereas + panel transform corresponds to the display's panel rotation, the logical + transform corresponds to the display's logical rotation. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="transform" type="int" enum="wl_output.transform" + summary="transform that maps framebuffer to output" /> + </event> + + <event name="panel_transform" since="1"> + <description summary="panel transform of the output"> + This event describes the panel transform for the output, which is the + associated display's panel rotation. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="transform" type="int" enum="wl_output.transform" + summary="transform that maps framebuffer to output" /> + </event> + + <event name="name" since="1"> + <description summary="human-readable name of this output"> + The name is a UTF-8 string with no convention defined for its contents. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="name" type="string" summary="output name" /> + </event> + + <event name="description" since="1"> + <description summary="human-readable description of this output"> + The description is a UTF-8 string with no convention defined for its + contents. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="description" type="string" summary="output description" /> + </event> + + <event name="overscan_insets" since="1"> + <description summary="advertise the overscan insets for the output"> + This event describes the overscan insets for the output in physical + pixels. + + The event is sent immediately after the wl_registry.global event for the + output and subsequently in latter display configuration changes. + </description> + <arg name="output_name" type="uint" /> + <arg name="top" type="int" /> + <arg name="left" type="int" /> + <arg name="bottom" type="int" /> + <arg name="right" type="int" /> + </event> + + <event name="activated" since="1"> + <description summary="target display for new windows"> + Notifies that this output is now active output. It is typically used as + a target when a new window is created without specific bounds. + </description> + <arg name="output_name" type="uint" /> + </event> + </interface> +</protocol>
diff --git a/components/exo/wayland/protocol/aura-shell.xml b/components/exo/wayland/protocol/aura-shell.xml index e17d093..70b533ca 100644 --- a/components/exo/wayland/protocol/aura-shell.xml +++ b/components/exo/wayland/protocol/aura-shell.xml
@@ -1471,6 +1471,9 @@ <interface name="zaura_output_manager" version="3"> <description summary="aura shell interface to the output manager"> + [Deprecated] Deprecated since M122. See the zaura_output_manager_v2 + interface. + A global responsible for ensuring clients have a complete view of a given output's state immediately following the bind of wl_output, and subsequently as needed.
diff --git a/components/exo/wayland/test/test_client.h b/components/exo/wayland/test/test_client.h index a628ac3b..53e51fad 100644 --- a/components/exo/wayland/test/test_client.h +++ b/components/exo/wayland/test/test_client.h
@@ -64,6 +64,9 @@ zaura_output_manager* aura_output_manager() { return globals().aura_output_manager.get(); } + zaura_output_manager_v2* aura_output_manager_v2() { + return globals().aura_output_manager_v2.get(); + } xdg_wm_base* xdg_wm_base() { return globals().xdg_wm_base.get(); } zwp_fullscreen_shell_v1* fullscreen_shell() { return globals().fullscreen_shell.get();
diff --git a/components/exo/wayland/zaura_output_manager_v2.cc b/components/exo/wayland/zaura_output_manager_v2.cc new file mode 100644 index 0000000..35aeecb9 --- /dev/null +++ b/components/exo/wayland/zaura_output_manager_v2.cc
@@ -0,0 +1,180 @@ +// 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/exo/wayland/zaura_output_manager_v2.h" + +#include <aura-output-management-server-protocol.h> +#include <wayland-server-core.h> + +#include <memory> + +#include "base/bit_cast.h" +#include "components/exo/wayland/output_metrics.h" +#include "components/exo/wayland/server_util.h" +#include "components/exo/wayland/wayland_display_observer.h" +#include "components/exo/wayland/wayland_display_output.h" +#include "ui/display/display.h" + +namespace exo::wayland { + +void bind_aura_output_manager_v2(wl_client* client, + void* data, + uint32_t version, + uint32_t id) { + wl_resource* outout_manager_resouce = + wl_resource_create(client, &zaura_output_manager_v2_interface, + std::min(version, kZAuraOutputManagerV2Version), id); + + auto user_data = std::make_unique<AuraOutputManagerV2::UserData>( + static_cast<AuraOutputManagerV2*>(data), outout_manager_resouce); + SetImplementation(outout_manager_resouce, nullptr, std::move(user_data)); +} + +AuraOutputManagerV2::UserData::UserData(AuraOutputManagerV2* output_manager, + wl_resource* outout_manager_resouce) + : output_manager_(output_manager->GetWeakPtr()), + outout_manager_resouce_(outout_manager_resouce) { + output_manager_->Register(outout_manager_resouce); +} + +AuraOutputManagerV2::UserData::~UserData() { + if (output_manager_) { + output_manager_->Unregister(outout_manager_resouce_.get()); + } +} + +AuraOutputManagerV2::AuraOutputManagerV2( + ActiveOutputGetter active_output_getter) + : active_output_getter_(std::move(active_output_getter)) {} + +AuraOutputManagerV2::~AuraOutputManagerV2() = default; + +bool AuraOutputManagerV2::OnDidProcessDisplayChanges( + const OutputConfigurationChange& configuration_change) { + // A done event is required if any outputs have been added or removed. + bool needs_done = !configuration_change.added_outputs.empty() || + !configuration_change.removed_outputs.empty(); + + // Send metrics for any newly-added displays. + for (const WaylandDisplayOutput* added_output : + configuration_change.added_outputs) { + static constexpr uint32_t kAllDisplayChanges = 0xFFFFFFFF; + SendOutputMetrics(*added_output, kAllDisplayChanges); + } + + // Send metrics for any existing updated displays. + for (const auto& change_pair : configuration_change.changed_outputs) { + needs_done |= SendOutputMetrics(*change_pair.first, change_pair.second); + } + + return needs_done; +} + +void AuraOutputManagerV2::SendOutputActivated( + const WaylandDisplayOutput& output) { + for (wl_resource* manager_resource : manager_resources_) { + const uint32_t output_name = wl_global_get_name( + output.global(), wl_resource_get_client(manager_resource)); + zaura_output_manager_v2_send_activated(manager_resource, output_name); + } +} + +void AuraOutputManagerV2::SendDone() { + for (wl_resource* manager_resource : manager_resources_) { + zaura_output_manager_v2_send_done(manager_resource); + } +} + +void AuraOutputManagerV2::Register(wl_resource* manager_resource) { + // When a client first binds to the global the current active global outputs + // and their metrics make up the first configuration change. + manager_resources_.insert(manager_resource); + for (const WaylandDisplayOutput* output : active_output_getter_.Run()) { + SendOutputMetricsForClient(*output, manager_resource); + } + SendDone(); +} + +void AuraOutputManagerV2::Unregister(wl_resource* manager_resource) { + manager_resources_.erase(manager_resource); +} + +base::WeakPtr<AuraOutputManagerV2> AuraOutputManagerV2::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +bool AuraOutputManagerV2::SendOutputMetrics(const WaylandDisplayOutput& output, + uint32_t changed_metrics) { + if (!(changed_metrics & + (display::DisplayObserver::DISPLAY_METRIC_BOUNDS | + display::DisplayObserver::DISPLAY_METRIC_WORK_AREA | + display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR | + display::DisplayObserver::DISPLAY_METRIC_ROTATION))) { + return false; + } + + for (wl_resource* manager_resource : manager_resources_) { + SendOutputMetricsForClient(output, manager_resource); + } + return true; +} + +void AuraOutputManagerV2::SendOutputMetricsForClient( + const WaylandDisplayOutput& output, + wl_resource* manager_resource) { + const uint32_t output_name = wl_global_get_name( + output.global(), wl_resource_get_client(manager_resource)); + const OutputMetrics& output_metrics = output.metrics(); + + const ui::wayland::WaylandDisplayIdPair& display_id = + output_metrics.display_id; + zaura_output_manager_v2_send_display_id(manager_resource, output_name, + display_id.high, display_id.low); + + const auto& logical_origin = output_metrics.logical_origin; + zaura_output_manager_v2_send_logical_position( + manager_resource, output_name, logical_origin.x(), logical_origin.y()); + + const auto& logical_size = output_metrics.logical_size; + zaura_output_manager_v2_send_logical_size(manager_resource, output_name, + logical_size.width(), + logical_size.height()); + + const auto& physical_size = output_metrics.physical_size_px; + if (output_metrics.mode_flags & WL_OUTPUT_MODE_CURRENT) { + zaura_output_manager_v2_send_physical_size(manager_resource, output_name, + physical_size.width(), + physical_size.height()); + } + + const auto& insets = output_metrics.logical_insets; + zaura_output_manager_v2_send_work_area_insets( + manager_resource, output_name, insets.top(), insets.left(), + insets.bottom(), insets.right()); + + const auto& overscan = output_metrics.physical_overscan_insets; + zaura_output_manager_v2_send_overscan_insets( + manager_resource, output_name, overscan.top(), overscan.left(), + overscan.bottom(), overscan.right()); + + // The float value is bit_cast<> into a uint32_t. It must later be cast back + // into a float. This is because wayland does not support native transport of + // floats. As different CPU architectures may use different endian + // representations for IEEE 754 floats, this implicitly assumes that the + // caller and receiver are the same machine. + zaura_output_manager_v2_send_device_scale_factor( + manager_resource, output_name, + base::bit_cast<uint32_t>(output_metrics.device_scale_factor)); + + zaura_output_manager_v2_send_logical_transform( + manager_resource, output_name, output_metrics.logical_transform); + + zaura_output_manager_v2_send_panel_transform(manager_resource, output_name, + output_metrics.panel_transform); + + zaura_output_manager_v2_send_description(manager_resource, output_name, + output_metrics.description.c_str()); +} + +} // namespace exo::wayland
diff --git a/components/exo/wayland/zaura_output_manager_v2.h b/components/exo/wayland/zaura_output_manager_v2.h new file mode 100644 index 0000000..82a2671 --- /dev/null +++ b/components/exo/wayland/zaura_output_manager_v2.h
@@ -0,0 +1,95 @@ +// 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_EXO_WAYLAND_ZAURA_OUTPUT_MANAGER_V2_H_ +#define COMPONENTS_EXO_WAYLAND_ZAURA_OUTPUT_MANAGER_V2_H_ + +#include <unordered_set> + +#include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/exo/wayland/output_configuration_change.h" + +struct wl_resource; +struct wl_client; + +namespace exo::wayland { + +class WaylandDisplayOutput; + +inline constexpr uint32_t kZAuraOutputManagerV2Version = 1; + +void bind_aura_output_manager_v2(wl_client* client, + void* data, + uint32_t version, + uint32_t id); + +// This class is responsible for propagating information about display +// configuration state changes atomically to participating clients. +class AuraOutputManagerV2 { + public: + using ActiveOutputGetter = base::RepeatingCallback<WaylandOutputList()>; + + // Used to manage the lifetime of client-bound handles to the aura output + // manager. + class UserData { + public: + UserData(AuraOutputManagerV2* output_manager, + wl_resource* outout_manager_resouce); + ~UserData(); + + private: + const base::WeakPtr<AuraOutputManagerV2> output_manager_; + const raw_ptr<wl_resource> outout_manager_resouce_; + }; + + explicit AuraOutputManagerV2(ActiveOutputGetter active_output_getter); + AuraOutputManagerV2(const AuraOutputManagerV2&) = delete; + AuraOutputManagerV2& operator=(const AuraOutputManagerV2&) = delete; + virtual ~AuraOutputManagerV2(); + + // Called when the system's display configuration has changed. Returns true if + // changes were propagated to clients and a done event is necessary to + // complete the transaction. + bool OnDidProcessDisplayChanges( + const OutputConfigurationChange& configuration_change); + + // Dispatches the activated event to all bound clients for the global + // `output`. + void SendOutputActivated(const WaylandDisplayOutput& output); + + // Notifies clients of the end of the display configuration change + // transaction. + void SendDone(); + + // Called by UserData when the wrapped resource is created and destroyed + // respectively. + void Register(wl_resource* manager_resource); + void Unregister(wl_resource* manager_resource); + + base::WeakPtr<AuraOutputManagerV2> GetWeakPtr(); + + private: + // Dispatches output metrics conditional on `changed_metrics` to all bound + // clients for the global `output`. Returns true if updates were dispatched. + bool SendOutputMetrics(const WaylandDisplayOutput& output, + uint32_t changed_metrics); + + // Dispatches output metrics to a specific client bound to the output manager. + void SendOutputMetricsForClient(const WaylandDisplayOutput& output, + wl_resource* manager_resource); + + // A set of resources for clients bound to the aura output manager global. + std::unordered_set<wl_resource*> manager_resources_; + + // Gets the currently active outputs tracked by the server. + const ActiveOutputGetter active_output_getter_; + + base::WeakPtrFactory<AuraOutputManagerV2> weak_factory_{this}; +}; + +} // namespace exo::wayland + +#endif // COMPONENTS_EXO_WAYLAND_ZAURA_OUTPUT_MANAGER_V2_H_
diff --git a/components/exo/wayland/zaura_output_manager_v2_unittest.cc b/components/exo/wayland/zaura_output_manager_v2_unittest.cc new file mode 100644 index 0000000..4ba1538 --- /dev/null +++ b/components/exo/wayland/zaura_output_manager_v2_unittest.cc
@@ -0,0 +1,387 @@ +// 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/exo/wayland/zaura_output_manager_v2.h" + +#include "base/bit_cast.h" +#include "components/exo/wayland/output_controller_test_api.h" +#include "components/exo/wayland/output_metrics.h" +#include "components/exo/wayland/server_util.h" +#include "components/exo/wayland/test/test_client.h" +#include "components/exo/wayland/test/wayland_server_test.h" +#include "components/exo/wayland/wayland_display_output.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace exo::wayland { + +namespace { + +using ::testing::_; +using ::testing::ExpectationSet; +using ::testing::Mock; +using ::testing::NiceMock; +using ::testing::StrEq; + +class MockGlobalsObserver : public clients::Globals::TestObserver { + public: + MOCK_METHOD(void, + OnRegistryGlobal, + (uint32_t id, const char* interface, uint32_t version), + (override)); + MOCK_METHOD(void, OnRegistryGlobalRemove, (uint32_t id), (override)); +}; + +class MockAuraOutputManagerListener { + public: + static void OnDone(void* data, zaura_output_manager_v2* output_manager) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnDone(); + } + static void OnDisplayId(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + uint32_t display_id_hi, + uint32_t display_id_lo) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnDisplayId( + output_name, display_id_hi, display_id_lo); + } + static void OnLogicalPosition(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + int32_t x, + int32_t y) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnLogicalPosition( + output_name, x, y); + } + static void OnLogicalSize(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + int32_t width, + int32_t height) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnLogicalSize( + output_name, width, height); + } + static void OnPhysicalSize(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + int32_t width, + int32_t height) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnPhysicalSize( + output_name, width, height); + } + static void OnInsets(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + int32_t top, + int32_t left, + int32_t bottom, + int32_t right) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnInsets( + output_name, top, left, bottom, right); + } + static void OnDeviceScaleFactor(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + uint32_t scale_as_uint) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnDeviceScaleFactor( + output_name, scale_as_uint); + } + static void OnLogicalTransform(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + int32_t transform) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnLogicalTransform( + output_name, transform); + } + static void OnPanelTransform(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + int32_t transform) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnPanelTransform( + output_name, transform); + } + static void OnName(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + const char* name) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnName(output_name, + name); + } + static void OnDescription(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + const char* description) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnDescription( + output_name, description); + } + static void OnOverscanInsets(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name, + int32_t top, + int32_t left, + int32_t bottom, + int32_t right) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnOverscanInsets( + output_name, top, left, bottom, right); + } + static void OnActivated(void* data, + zaura_output_manager_v2* output_manager, + uint32_t output_name) { + static_cast<MockAuraOutputManagerListener*>(data)->MockOnActivated( + output_name); + } + + MOCK_METHOD(void, MockOnDone, ()); + MOCK_METHOD(void, + MockOnDisplayId, + (uint32_t output_name, + uint32_t display_id_hi, + uint32_t display_id_lo)); + MOCK_METHOD(void, + MockOnLogicalPosition, + (uint32_t output_name, int32_t x, int32_t y)); + MOCK_METHOD(void, + MockOnLogicalSize, + (uint32_t output_name, int32_t width, int32_t height)); + MOCK_METHOD(void, + MockOnPhysicalSize, + (uint32_t output_name, int32_t width, int32_t height)); + MOCK_METHOD(void, + MockOnInsets, + (uint32_t output_name, + int32_t top, + int32_t left, + int32_t bottom, + int32_t right)); + MOCK_METHOD(void, + MockOnDeviceScaleFactor, + (uint32_t output_name, uint32_t scale_as_uint)); + MOCK_METHOD(void, + MockOnLogicalTransform, + (uint32_t output_name, int32_t transform)); + MOCK_METHOD(void, + MockOnPanelTransform, + (uint32_t output_name, int32_t transform)); + MOCK_METHOD(void, MockOnName, (uint32_t output_name, const char* name)); + MOCK_METHOD(void, + MockOnDescription, + (uint32_t output_name, const char* description)); + MOCK_METHOD(void, + MockOnOverscanInsets, + (uint32_t output_name, + int32_t top, + int32_t left, + int32_t bottom, + int32_t right)); + MOCK_METHOD(void, MockOnActivated, (uint32_t output_name)); +}; + +// Server test asserting clients receive the events specified by the +// aura_output_manager_v2 interface in the order expected. +class AuraOutputManagerV2Test : public test::WaylandServerTest { + public: + // test::WaylandServerTest: + std::unique_ptr<test::TestClient> InitOnClientThread() override { + auto test_client = test::WaylandServerTest::InitOnClientThread(); + + test_client->globals().set_observer_for_testing(&mock_globals_observer_); + + static constexpr zaura_output_manager_v2_listener + zaura_output_manager_v2_listener = { + &MockAuraOutputManagerListener::OnDone, + &MockAuraOutputManagerListener::OnDisplayId, + &MockAuraOutputManagerListener::OnLogicalPosition, + &MockAuraOutputManagerListener::OnLogicalSize, + &MockAuraOutputManagerListener::OnPhysicalSize, + &MockAuraOutputManagerListener::OnInsets, + &MockAuraOutputManagerListener::OnDeviceScaleFactor, + &MockAuraOutputManagerListener::OnLogicalTransform, + &MockAuraOutputManagerListener::OnPanelTransform, + &MockAuraOutputManagerListener::OnName, + &MockAuraOutputManagerListener::OnDescription, + &MockAuraOutputManagerListener::OnOverscanInsets, + &MockAuraOutputManagerListener::OnActivated}; + zaura_output_manager_v2_add_listener(test_client->aura_output_manager_v2(), + &zaura_output_manager_v2_listener, + &mock_aura_output_manager_); + + return test_client; + } + + protected: + void ExpectMetrics(uint32_t output_name, + const OutputMetrics& metrics, + ExpectationSet& expectations) { + expectations += + EXPECT_CALL(mock_aura_output_manager_, + MockOnDisplayId(output_name, metrics.display_id.high, + metrics.display_id.low)); + expectations += EXPECT_CALL( + mock_aura_output_manager_, + MockOnLogicalPosition(output_name, metrics.logical_origin.x(), + metrics.logical_origin.y())); + expectations += + EXPECT_CALL(mock_aura_output_manager_, + MockOnLogicalSize(output_name, metrics.logical_size.width(), + metrics.logical_size.height())); + expectations += EXPECT_CALL( + mock_aura_output_manager_, + MockOnPhysicalSize(output_name, metrics.physical_size_px.width(), + metrics.physical_size_px.height())); + expectations += + EXPECT_CALL(mock_aura_output_manager_, + MockOnInsets(output_name, metrics.logical_insets.top(), + metrics.logical_insets.left(), + metrics.logical_insets.bottom(), + metrics.logical_insets.right())); + expectations += EXPECT_CALL( + mock_aura_output_manager_, + MockOnDeviceScaleFactor(output_name, base::bit_cast<uint32_t>( + metrics.device_scale_factor))); + expectations += EXPECT_CALL( + mock_aura_output_manager_, + MockOnLogicalTransform(output_name, metrics.logical_transform)); + expectations += + EXPECT_CALL(mock_aura_output_manager_, + MockOnPanelTransform(output_name, metrics.panel_transform)); + expectations += + EXPECT_CALL(mock_aura_output_manager_, + MockOnOverscanInsets( + output_name, metrics.physical_overscan_insets.top(), + metrics.physical_overscan_insets.left(), + metrics.physical_overscan_insets.bottom(), + metrics.physical_overscan_insets.right())); + } + + NiceMock<MockAuraOutputManagerListener> mock_aura_output_manager_; + NiceMock<MockGlobalsObserver> mock_globals_observer_; +}; + +} // namespace + +TEST_F(AuraOutputManagerV2Test, ActiveOutputMetricsUpdate) { + // Start with a single display and round-trip with client to clear the event + // queue. + UpdateDisplay("800x600"); + PostToClientAndWait([] {}); + + const auto* screen = display::Screen::GetScreen(); + ASSERT_EQ(1u, screen->GetAllDisplays().size()); + + const int64_t primary_id = screen->GetAllDisplays()[0].id(); + auto* output_controller = server_->output_controller_for_testing(); + OutputControllerTestApi output_controller_test_api(*output_controller); + const WaylandDisplayOutput* primary_output = + output_controller_test_api.GetWaylandDisplayOutput(primary_id); + const uint32_t primary_output_name = + wl_global_get_name(primary_output->global(), client_resource_.get()); + + // Update the display, expect to see updated metrics only followed by done. + OutputMetrics metrics = primary_output->metrics(); + metrics.physical_size_px.SetSize(1200, 800); + metrics.logical_size.SetSize(1200, 800); + + ExpectationSet expected_events; + expected_events += EXPECT_CALL(mock_globals_observer_, + OnRegistryGlobal(_, StrEq("wl_output"), _)) + .Times(0); + expected_events += + EXPECT_CALL(mock_globals_observer_, OnRegistryGlobalRemove(_)).Times(0); + ExpectMetrics(primary_output_name, metrics, expected_events); + EXPECT_CALL(mock_aura_output_manager_, MockOnDone()).After(expected_events); + + UpdateDisplay("1200x800"); + PostToClientAndWait([] {}); + + Mock::VerifyAndClearExpectations(&mock_aura_output_manager_); + Mock::VerifyAndClearExpectations(&mock_globals_observer_); + + // Subsequent updates should send new updates as expected. + metrics = primary_output->metrics(); + metrics.physical_size_px.SetSize(1600, 1200); + metrics.logical_size.SetSize(1600, 1200); + + ExpectationSet new_expected_events; + new_expected_events += EXPECT_CALL(mock_globals_observer_, + OnRegistryGlobal(_, StrEq("wl_output"), _)) + .Times(0); + new_expected_events += + EXPECT_CALL(mock_globals_observer_, OnRegistryGlobalRemove(_)).Times(0); + ExpectMetrics(primary_output_name, metrics, new_expected_events); + EXPECT_CALL(mock_aura_output_manager_, MockOnDone()) + .After(new_expected_events); + + UpdateDisplay("1600x1200"); + PostToClientAndWait([] {}); +} + +TEST_F(AuraOutputManagerV2Test, ActiveOutputsAdded) { + // Start with a single display and round-trip with client to clear the event + // queue. + UpdateDisplay("800x600"); + const auto* screen = display::Screen::GetScreen(); + ASSERT_EQ(1u, screen->GetAllDisplays().size()); + PostToClientAndWait([] {}); + + // Add two new displays to the configuration, events for two new outputs and + // their corresponding metrics should be propagated to clients. + ExpectationSet expected_events; + expected_events += EXPECT_CALL(mock_globals_observer_, + OnRegistryGlobal(_, StrEq("wl_output"), _)) + .Times(2); + expected_events += + EXPECT_CALL(mock_globals_observer_, OnRegistryGlobalRemove(_)).Times(0); + expected_events += + EXPECT_CALL(mock_aura_output_manager_, MockOnLogicalSize(_, 1200, 800)); + expected_events += + EXPECT_CALL(mock_aura_output_manager_, MockOnLogicalSize(_, 1600, 1200)); + EXPECT_CALL(mock_aura_output_manager_, MockOnDone()).After(expected_events); + + UpdateDisplay("800x600,1200x800,1600x1200"); + ASSERT_EQ(3u, screen->GetAllDisplays().size()); + PostToClientAndWait([] {}); +} + +TEST_F(AuraOutputManagerV2Test, ActiveOutputsRemoved) { + // Start multiple displays and round-trip with client to clear the event + // queue. + UpdateDisplay("800x600,1200x800,1600x1200"); + const auto* screen = display::Screen::GetScreen(); + ASSERT_EQ(3u, screen->GetAllDisplays().size()); + PostToClientAndWait([] {}); + + const int64_t secondary_id = screen->GetAllDisplays()[1].id(); + const int64_t tertiary_id = screen->GetAllDisplays()[2].id(); + + auto* output_controller = server_->output_controller_for_testing(); + OutputControllerTestApi output_controller_test_api(*output_controller); + const uint64_t secondary_output_name = wl_global_get_name( + output_controller_test_api.GetWaylandDisplayOutput(secondary_id) + ->global(), + client_resource_.get()); + const uint64_t tertiary_output_name = wl_global_get_name( + output_controller_test_api.GetWaylandDisplayOutput(tertiary_id)->global(), + client_resource_.get()); + + // Remove two displays from the configuration, events for the two removals + // should be propagated to clients. + ExpectationSet expected_events; + expected_events += EXPECT_CALL(mock_globals_observer_, + OnRegistryGlobal(_, StrEq("wl_output"), _)) + .Times(0); + expected_events += EXPECT_CALL(mock_globals_observer_, + OnRegistryGlobalRemove(secondary_output_name)); + expected_events += EXPECT_CALL(mock_globals_observer_, + OnRegistryGlobalRemove(tertiary_output_name)); + expected_events += + EXPECT_CALL(mock_aura_output_manager_, MockOnLogicalSize(_, _, _)) + .Times(0); + EXPECT_CALL(mock_aura_output_manager_, MockOnDone()).After(expected_events); + + UpdateDisplay("800x600"); + ASSERT_EQ(1u, screen->GetAllDisplays().size()); + PostToClientAndWait([] {}); +} + +} // namespace exo::wayland
diff --git a/components/global_media_controls/public/views/media_item_ui_list_view.cc b/components/global_media_controls/public/views/media_item_ui_list_view.cc index 83cf7ff0..c1acbac3 100644 --- a/components/global_media_controls/public/views/media_item_ui_list_view.cc +++ b/components/global_media_controls/public/views/media_item_ui_list_view.cc
@@ -49,10 +49,10 @@ ClipHeightTo(0, should_clip_height ? kMediaListMaxHeight : std::numeric_limits<int>::max()); - SetVerticalScrollBar( - std::make_unique<views::OverlayScrollBar>(/*horizontal=*/false)); - SetHorizontalScrollBar( - std::make_unique<views::OverlayScrollBar>(/*horizontal=*/true)); + SetVerticalScrollBar(std::make_unique<views::OverlayScrollBar>( + views::ScrollBar::Orientation::kVertical)); + SetHorizontalScrollBar(std::make_unique<views::OverlayScrollBar>( + views::ScrollBar::Orientation::kHorizontal)); } MediaItemUIListView::~MediaItemUIListView() = default;
diff --git a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc index 319fba9c..cb8fe81 100644 --- a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc +++ b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc
@@ -15,134 +15,25 @@ #include "base/strings/string_number_conversions.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/reporting/util/encrypted_reporting_json_keys.h" -#include "net/base/backoff_entry.h" #include "services/network/public/cpp/shared_url_loader_factory.h" namespace policy { -namespace { - -// Generate new backoff entry. -std::unique_ptr<::net::BackoffEntry> GetBackoffEntry( - ::reporting::Priority priority) { - // Retry policy for SECURITY queue. - static const ::net::BackoffEntry::Policy kSecurityUploadBackoffPolicy = { - // Number of initial errors to ignore before applying - // exponential back-off rules. - /*num_errors_to_ignore=*/0, - - // Initial delay is 10 seconds. - /*initial_delay_ms=*/10 * 1000, - - // Factor by which the waiting time will be multiplied. - /*multiply_factor=*/2, - - // Fuzzing percentage. - /*jitter_factor=*/0.1, - - // Maximum delay is 1 minute. - /*maximum_backoff_ms=*/1 * 60 * 1000, - - // It's up to the caller to reset the backoff time. - /*entry_lifetime_ms=*/-1, - - /*always_use_initial_delay=*/true, - }; - // Retry policy for all other queues, including initial key delivery. - static const ::net::BackoffEntry::Policy kDefaultUploadBackoffPolicy = { - // Number of initial errors to ignore before applying - // exponential back-off rules. - /*num_errors_to_ignore=*/0, - - // Initial delay is 10 seconds. - /*initial_delay_ms=*/10 * 1000, - - // Factor by which the waiting time will be multiplied. - /*multiply_factor=*/2, - - // Fuzzing percentage. - /*jitter_factor=*/0.1, - - // Maximum delay is 24 hours. - /*maximum_backoff_ms=*/24 * 60 * 60 * 1000, - - // It's up to the caller to reset the backoff time. - /*entry_lifetime_ms=*/-1, - - /*always_use_initial_delay=*/true, - }; - // Maximum backoff is set per priority. Current proposal is to set SECURITY - // events to be backed off only slightly: max delay is set to 1 minute. - // For all other priorities max delay is set to 24 hours. - auto backoff_entry = std::make_unique<::net::BackoffEntry>( - priority == ::reporting::SECURITY ? &kSecurityUploadBackoffPolicy - : &kDefaultUploadBackoffPolicy); - return backoff_entry; -} - -// State of single priority queue uploads. -// It is a singleton, protected implicitly by the fact that all relevant -// EncryptedReportingJobConfiguration actions are called on the sequenced task -// runner. -struct UploadState { - // Highest sequence id that has been posted for upload. - int64_t last_sequence_id; - // Generation id that has been posted for upload. - int64_t last_generation_id; - - // Time when the next request will be allowed. - // This is essentially the cache value of the backoff->GetReleaseTime(). - // When the time is reached, one request is allowed, backoff is updated as if - // the request failed, and the new release time is cached. - base::TimeTicks earliest_retry_timestamp; - - // Current backoff entry for this prioririty. - std::unique_ptr<::net::BackoffEntry> backoff_entry; -}; -// Map of all the queues states. -using UploadStateMap = base::flat_map<::reporting::Priority, UploadState>; - -UploadStateMap* state_map() { - static base::NoDestructor<UploadStateMap> map; - return map.get(); -} - -UploadState* AccessState(::reporting::Priority priority, - int64_t generation_id, - int64_t sequence_id) { - auto state_it = state_map()->find(priority); - if (state_it == state_map()->end() || - state_it->second.last_generation_id != generation_id) { - // This priority pops up for the first time or (rare case) generation has - // changed. Record new state and allow upload. - state_it = state_map() - ->insert_or_assign( - priority, - UploadState{.last_sequence_id = sequence_id, - .last_generation_id = generation_id, - .backoff_entry = GetBackoffEntry(priority)}) - .first; - state_it->second.earliest_retry_timestamp = - state_it->second.backoff_entry->GetReleaseTime(); - } - return &state_it->second; -} - -} // namespace - EncryptedReportingJobConfiguration::EncryptedReportingJobConfiguration( scoped_refptr<network::SharedURLLoaderFactory> factory, DMAuth auth_data, const std::string& server_url, base::Value::Dict merging_payload, CloudPolicyClient* cloud_policy_client, + UploadResponseCallback response_cb, UploadCompleteCallback complete_cb) : ReportingJobConfigurationBase(TYPE_UPLOAD_ENCRYPTED_REPORT, factory, std::move(auth_data), server_url, std::move(complete_cb)), - is_device_managed_(cloud_policy_client != nullptr) { + is_device_managed_(cloud_policy_client != nullptr), + response_cb_(std::move(response_cb)) { if (is_device_managed_) { // Payload for managed device InitializePayloadWithDeviceInfo(cloud_policy_client->dm_token(), @@ -153,45 +44,6 @@ } // Merge it into the base class payload. payload_.Merge(std::move(merging_payload)); - // Retrieve priorities and figure out maximum sequence id for each. - // Payload is expected to be correctly formed, any malformed piece is ignored. - // TODO(b/214040103): if batching is enabled, multiple priorities may be - // found. Before that, each payload can only have no more than one, and the - // highest sequence id comes from the last record. - // TODO(b/232455728): if test_request_payload is moved to components/ - // we would be able to use it here. - const auto* const encrypted_record_list = - payload_.FindList(reporting::json_keys::kEncryptedRecordList); - // If there are no records, assume UNDEFINED priority and seq_id = -1. - priority_ = ::reporting::UNDEFINED_PRIORITY; - generation_id_ = -1; - sequence_id_ = -1; - if (encrypted_record_list != nullptr && !encrypted_record_list->empty()) { - record_count_ = encrypted_record_list->size(); - const auto sequence_information_it = - std::prev(encrypted_record_list->cend()); - const auto* const sequence_information = - sequence_information_it->GetDict().FindDict( - reporting::json_keys::kSequenceInformation); - if (sequence_information != nullptr) { - const auto maybe_priority = - sequence_information->FindInt(reporting::json_keys::kPriority); - auto* const generation_id_ptr = - sequence_information->FindString(reporting::json_keys::kGenerationId); - auto* const sequence_id_ptr = - sequence_information->FindString(reporting::json_keys::kSequencingId); - if (maybe_priority.has_value() && - ::reporting::Priority_IsValid(maybe_priority.value())) { - priority_ = static_cast<::reporting::Priority>(maybe_priority.value()); - } - if (generation_id_ptr != nullptr) { - base::StringToInt64(*generation_id_ptr, &generation_id_); - } - if (sequence_id_ptr != nullptr) { - base::StringToInt64(*sequence_id_ptr, &sequence_id_); - } - } - } } EncryptedReportingJobConfiguration::~EncryptedReportingJobConfiguration() { @@ -221,59 +73,6 @@ context_ = std::move(context); } -base::TimeDelta EncryptedReportingJobConfiguration::WhenIsAllowedToProceed() - const { - // Now pick up the state. - const auto* const state = - AccessState(priority_, generation_id_, sequence_id_); - // If there are no records, allow upload (it will not overload the server). - if (record_count_ == 0u) { - return base::TimeDelta(); // 0 - allowed right away. - } - // Use and update previously recorded state, base upload decision on it. - if (state->last_sequence_id > sequence_id_) { - // Sequence id decreased, the upload is outdated, reject it forever. - return base::TimeDelta::Max(); - } - if (state->last_sequence_id < sequence_id_) { - // Sequence id increased, keep validating. - switch (priority_) { - case ::reporting::SECURITY: - // For SECURITY events the request is allowed. - return base::TimeDelta(); // 0 - allowed right away. - default: { - // For all other priorities we will act like in case of request’s - // last_sequence_id is == last_sequence_id above - observing the - // backoff time expiration. - } - } - } - // Allow upload only if earliest retry time has passed. - // Return delta till the allowed time - if positive, upload is going to be - // rejected. - return state->earliest_retry_timestamp - - state->backoff_entry->GetTimeTicksNow(); -} - -void EncryptedReportingJobConfiguration::CancelNotAllowedJob() { - std::move(callback_).Run( - /*job=*/nullptr, DeviceManagementStatus::DM_STATUS_REQUEST_FAILED, - /*response_code=*/DeviceManagementService::kTooManyRequests, - /*response_body=*/std::nullopt); -} - -void EncryptedReportingJobConfiguration::AccountForAllowedJob() { - auto* const state = AccessState(priority_, generation_id_, sequence_id_); - // Update state to reflect highest sequence_id_ (we never allow upload with - // lower sequence_id_). - state->last_sequence_id = sequence_id_; - // Calculate delay as exponential backoff (based on the retry_count). - // Update backoff under assumption that this request fails. - // If it is responded successfully, we will reset it. - state->backoff_entry->InformOfRequest(/*succeeded=*/false); - state->earliest_retry_timestamp = state->backoff_entry->GetReleaseTime(); -} - DeviceManagementService::Job::RetryMethod EncryptedReportingJobConfiguration::ShouldRetry( int response_code, @@ -287,26 +86,10 @@ int net_error, int response_code, const std::string& response_body) { - // Analyze the net error and update upload state for possible future retries. - auto* const state = AccessState(priority_, generation_id_, sequence_id_); - if (net_error != ::net::OK) { - // Network error - } else if (response_code >= 400 && response_code <= 499 && - response_code != 409 /* Overlapping seq_id ranges detected */) { - // Permanent error code returned by server, impose artificial 24h backoff. - state->backoff_entry->SetCustomReleaseTime( - state->backoff_entry->GetTimeTicksNow() + base::Days(1)); - } - // For all other cases keep the currently set retry time. - // In case of success, inform backoff entry about that. - if (net_error == ::net::OK && - response_code == DeviceManagementService::kSuccess) { - state->backoff_entry->InformOfRequest(/*succeeded=*/true); - } - // Cache earliest retry time based on the current backoff entry. - state->earliest_retry_timestamp = state->backoff_entry->GetReleaseTime(); - - // Then deliver response and status by making a call to the base class. + // Delegate net error and response code for further analysis that may + // affect retries and back-off. + std::move(response_cb_).Run(net_error, response_code); + // Then forward response to the base class. ReportingJobConfigurationBase::OnURLLoadComplete( job, net_error, response_code, response_body); } @@ -331,10 +114,4 @@ reporting::json_keys::kRequestId, reporting::json_keys::kSource}}; return *kTopLevelKeyAllowList; } - -// static -void EncryptedReportingJobConfiguration::ResetUploadsStateForTest() { - state_map()->clear(); -} - } // namespace policy
diff --git a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h index e5ce866..b28dde9 100644 --- a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h +++ b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h
@@ -85,12 +85,16 @@ class POLICY_EXPORT EncryptedReportingJobConfiguration : public ReportingJobConfigurationBase { public: + using UploadResponseCallback = + base::OnceCallback<void(int /*net_error*/, int /*response_code*/)>; + EncryptedReportingJobConfiguration( scoped_refptr<network::SharedURLLoaderFactory> factory, DMAuth auth_data, const std::string& server_url, base::Value::Dict merging_payload, CloudPolicyClient* cloud_policy_client, + UploadResponseCallback response_cb, UploadCompleteCallback complete_cb); ~EncryptedReportingJobConfiguration() override; @@ -101,26 +105,12 @@ // fields (check reporting::GetContext for specifics). void UpdateContext(base::Value::Dict context); - // Checks the new job against the history, determines how soon the upload will - // be allowed. Returns positive value if not allowed, and 0 or negative - // otherwise. - base::TimeDelta WhenIsAllowedToProceed() const; - - // Account for the job, that was allowed to proceed. - void AccountForAllowedJob(); - - // Cancels the job, that was not allowed to proceed. - void CancelNotAllowedJob(); - // Callback to process error codes and, in case of success, response body. void OnURLLoadComplete(DeviceManagementService::Job* job, int net_error, int response_code, const std::string& response_body) override; - // Test-only method that resets collected uploads state. - static void ResetUploadsStateForTest(); - protected: void UpdatePayloadBeforeGetInternal() override; @@ -135,11 +125,7 @@ static const base::flat_set<std::string>& GetTopLevelKeyAllowList(); const bool is_device_managed_; - // Parameters populated from the payload_. - ::reporting::Priority priority_; - int64_t generation_id_{-1}; - int64_t sequence_id_{-1}; - size_t record_count_{0u}; + UploadResponseCallback response_cb_; }; } // namespace policy
diff --git a/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc b/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc index 10caefc..b768c19 100644 --- a/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc +++ b/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc
@@ -25,6 +25,7 @@ #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/reporting/util/encrypted_reporting_json_keys.h" #include "components/version_info/version_info.h" +#include "net/http/http_status_code.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,8 +36,10 @@ using ::testing::_; using ::testing::ByRef; +using ::testing::ElementsAre; using ::testing::Eq; using ::testing::Ge; +using ::testing::IsEmpty; using ::testing::IsNull; using ::testing::MockFunction; using ::testing::NotNull; @@ -184,15 +187,17 @@ DeviceManagementStatus code, int response_code, std::optional<base::Value::Dict>)>; + using MockUploadResponseCb = + MockFunction<void(int /*net_error*/, int /*response_code*/)>; struct TestUpload { std::unique_ptr<EncryptedReportingJobConfiguration> configuration; std::unique_ptr<StrictMock<MockCompleteCb>> completion_cb; + std::unique_ptr<StrictMock<MockUploadResponseCb>> upload_response_cb; base::Value::Dict response; DeviceManagementService::Job job; }; void SetUp() override { - EncryptedReportingJobConfiguration::ResetUploadsStateForTest(); shared_url_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &url_loader_factory_); @@ -208,11 +213,16 @@ reporting::json_keys::kSequenceInformation), std::nullopt); test_upload.completion_cb = std::make_unique<StrictMock<MockCompleteCb>>(); + test_upload.upload_response_cb = + std::make_unique<StrictMock<MockUploadResponseCb>>(); test_upload.configuration = std::make_unique<EncryptedReportingJobConfiguration>( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, RequestPayloadBuilder().AddRecord(record_value).Build(), &client_, + base::BindOnce( + &MockUploadResponseCb::Call, + base::Unretained(test_upload.upload_response_cb.get())), base::BindOnce(&MockCompleteCb::Call, base::Unretained(test_upload.completion_cb.get()))); return test_upload; @@ -251,12 +261,13 @@ return context; } - void GetRecordList(EncryptedReportingJobConfiguration* configuration, - base::Value::List** record_list) { + base::Value::List* GetRecordList( + EncryptedReportingJobConfiguration* configuration) { base::Value* const payload = GetPayload(configuration); - *record_list = + auto* const record_list = payload->GetDict().FindList(reporting::json_keys::kEncryptedRecordList); - ASSERT_TRUE(*record_list); + EXPECT_THAT(record_list, NotNull()); + return record_list; } bool GetAttachEncryptionSettings( @@ -329,6 +340,7 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, RequestPayloadBuilder().Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); auto* payload = GetPayload(&configuration); const base::Value::Dict& payload_dict = payload->GetDict(); @@ -370,6 +382,7 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::NoAuth(), kServerUrl, RequestPayloadBuilder().Build(), /*cloud_policy_client=*/nullptr, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); auto* payload = GetPayload(&configuration); ASSERT_THAT(payload, NotNull()); @@ -420,16 +433,14 @@ shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, RequestPayloadBuilder().AddRecord(record_value).Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - EXPECT_EQ(record_list->size(), 1u); - EXPECT_EQ((*record_list)[0], record_value); + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, ElementsAre(Eq(ByRef(record_value)))); - std::string* encrypted_wrapped_record = - (*record_list)[0].GetDict().FindString( - reporting::json_keys::kEncryptedWrappedRecord); + auto* const encrypted_wrapped_record = (*record_list)[0].GetDict().FindString( + reporting::json_keys::kEncryptedWrappedRecord); ASSERT_THAT(encrypted_wrapped_record, NotNull()); std::string decoded_record; @@ -453,17 +464,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_EQ(record_list->size(), records.size()); - - size_t counter = 0; - for (const auto& record : records) { - EXPECT_EQ((*record_list)[counter++], record); - } + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, Eq(ByRef(records))); EXPECT_FALSE(GetAttachEncryptionSettings(&configuration)); } @@ -478,12 +483,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_TRUE(record_list->empty()); + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, IsEmpty()); EXPECT_TRUE(GetAttachEncryptionSettings(&configuration)); } @@ -504,17 +508,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_EQ(record_list->size(), records.size()); - - size_t counter = 0; - for (const auto& record : records) { - EXPECT_EQ((*record_list)[counter++], record); - } + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, Eq(ByRef(records))); EXPECT_TRUE(GetAttachEncryptionSettings(&configuration)); } @@ -528,12 +526,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_TRUE(record_list->empty()); + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, IsEmpty()); EXPECT_TRUE(VerifyConfigurationFileVersion(&configuration)); } @@ -547,12 +544,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_TRUE(record_list->empty()); + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, IsEmpty()); EXPECT_TRUE(GetAttachEncryptionSettings(&configuration)); EXPECT_TRUE(VerifyConfigurationFileVersion(&configuration)); @@ -576,17 +572,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_EQ(record_list->size(), records.size()); - - size_t counter = 0; - for (const auto& record : records) { - EXPECT_EQ((*record_list)[counter++], record); - } + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, Eq(ByRef(records))); EXPECT_TRUE(GetAttachEncryptionSettings(&configuration)); EXPECT_TRUE(VerifyConfigurationFileVersion(&configuration)); @@ -601,12 +591,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_TRUE(record_list->empty()); + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, IsEmpty()); EXPECT_TRUE(VerifySourceIsTast(&configuration)); } @@ -622,12 +611,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_TRUE(record_list->empty()); + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, IsEmpty()); EXPECT_TRUE(GetAttachEncryptionSettings(&configuration)); EXPECT_TRUE(VerifyConfigurationFileVersion(&configuration)); @@ -653,17 +641,11 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, builder.Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); - base::Value::List* record_list = nullptr; - GetRecordList(&configuration, &record_list); - - EXPECT_EQ(record_list->size(), records.size()); - - size_t counter = 0; - for (const auto& record : records) { - EXPECT_EQ((*record_list)[counter++], record); - } + auto* const record_list = GetRecordList(&configuration); + EXPECT_THAT(*record_list, Eq(ByRef(records))); EXPECT_TRUE(GetAttachEncryptionSettings(&configuration)); EXPECT_TRUE(VerifyConfigurationFileVersion(&configuration)); @@ -677,6 +659,7 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, RequestPayloadBuilder().Build(), &client_, + /*response_cb=*/base::DoNothing(), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); const std::string kTestKey = "device.name"; @@ -728,6 +711,8 @@ DeviceManagementService::kSuccess, Eq(ByRef(upload.response)))) .Times(1); + EXPECT_CALL(*upload.upload_response_cb, Call(Eq(net::OK), Eq(net::HTTP_OK))) + .Times(1); const std::string kTestString = "device.clientId"; const std::string kTestInt = "1701-A"; @@ -746,171 +731,24 @@ EXPECT_CALL(completion_cb, Call(&job, DM_STATUS_REQUEST_FAILED, _, testing::Eq(std::nullopt))) .Times(1); + StrictMock<MockUploadResponseCb> upload_response_cb; + EXPECT_CALL(upload_response_cb, Call(Eq(net::ERR_CONNECTION_RESET), _)) + .Times(1); EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, RequestPayloadBuilder().Build(), &client_, + base::BindOnce(&MockUploadResponseCb::Call, + base::Unretained(&upload_response_cb)), base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); configuration.OnURLLoadComplete(&job, net::ERR_CONNECTION_RESET, 0 /* ignored */, ""); } - -TEST_F(EncryptedReportingJobConfigurationTest, - IdenticalUploadRetriesThrottled) { - const size_t kTotalRetries = 10; - const std::string kEncryptedWrappedRecord = "TEST_INFO"; - base::Value record_value = - GenerateSingleRecord(kEncryptedWrappedRecord, kPriority); - - base::TimeDelta expected_delay_after = base::Seconds(10); - for (size_t i = 0; i < kTotalRetries; ++i) { - auto upload = CreateTestUpload(record_value); - // Expect upload to fail with a temporary error, to justify a retry. - EXPECT_CALL(*upload.completion_cb, - Call(&upload.job, DM_STATUS_TEMPORARY_UNAVAILABLE, - DeviceManagementService::kServiceUnavailable, - Eq(ByRef(upload.response)))) - .Times(1); - - auto allowed_delay = upload.configuration->WhenIsAllowedToProceed(); - if (i == 0) { - // First upload allowed immediately. - EXPECT_FALSE(allowed_delay.is_positive()); - } else { - // Further uploads allowed with delay. - EXPECT_THAT(allowed_delay, Ge(expected_delay_after)); - // Double the expectation for the next retry. - expected_delay_after *= 2; - // Move forward to allow. - task_environment_.FastForwardBy(allowed_delay - base::Seconds(1)); - EXPECT_TRUE(upload.configuration->WhenIsAllowedToProceed().is_positive()); - task_environment_.FastForwardBy(base::Seconds(1)); - } - - EXPECT_FALSE(upload.configuration->WhenIsAllowedToProceed().is_positive()); - upload.configuration->AccountForAllowedJob(); - // Process temporary error response code. - upload.configuration->OnURLLoadComplete( - &upload.job, net::OK, DeviceManagementService::kServiceUnavailable, - ResponseValueBuilder::CreateResponseString(upload.response)); - } -} - -TEST_F(EncryptedReportingJobConfigurationTest, UploadsSequenceThrottled) { - const size_t kTotalRetries = 10; - const std::string kEncryptedWrappedRecord = "TEST_INFO"; - - std::vector<TestUpload> uploads; - base::TimeDelta expected_delay_after = base::Seconds(10); - for (size_t i = 0; i < kTotalRetries; ++i) { - // Create new record with next seq id. - base::Value record_value = - GenerateSingleRecord(kEncryptedWrappedRecord, kPriority); - - uploads.emplace_back(CreateTestUpload(record_value)); - auto allowed_delay = uploads.back().configuration->WhenIsAllowedToProceed(); - if (i == 0) { - EXPECT_FALSE(allowed_delay.is_positive()); - // Next retry not before 10 sec. - } else { - EXPECT_THAT(allowed_delay, Ge(expected_delay_after)); - // Double the expectation for the next upload. - expected_delay_after *= 2; - // Move forward to allow. - task_environment_.FastForwardBy(allowed_delay - base::Seconds(1)); - EXPECT_TRUE( - uploads.back().configuration->WhenIsAllowedToProceed().is_positive()); - task_environment_.FastForwardBy(base::Seconds(1)); - } - - EXPECT_FALSE( - uploads.back().configuration->WhenIsAllowedToProceed().is_positive()); - uploads.back().configuration->AccountForAllowedJob(); - } - - // Now complete all created uploads. - for (auto& upload : uploads) { - EXPECT_CALL(*upload.completion_cb, Call(&upload.job, DM_STATUS_SUCCESS, - DeviceManagementService::kSuccess, - Eq(ByRef(upload.response)))) - .Times(1); - upload.configuration->OnURLLoadComplete( - &upload.job, net::OK, DeviceManagementService::kSuccess, - ResponseValueBuilder::CreateResponseString(upload.response)); - } -} - -TEST_F(EncryptedReportingJobConfigurationTest, - SecurityUploadsSequenceNotThrottled) { - const size_t kTotalRetries = 10; - const std::string kEncryptedWrappedRecord = "TEST_INFO"; - - std::vector<TestUpload> uploads; - for (size_t i = 0; i < kTotalRetries; ++i) { - // Create new record with next seq id. - base::Value record_value = GenerateSingleRecord( - kEncryptedWrappedRecord, ::reporting::Priority::SECURITY); - - uploads.emplace_back(CreateTestUpload(record_value)); - auto allowed_delay = uploads.back().configuration->WhenIsAllowedToProceed(); - EXPECT_FALSE(allowed_delay.is_positive()); - uploads.back().configuration->AccountForAllowedJob(); - } - - // Now complete all created uploads. - for (auto& upload : uploads) { - EXPECT_CALL(*upload.completion_cb, Call(&upload.job, DM_STATUS_SUCCESS, - DeviceManagementService::kSuccess, - Eq(ByRef(upload.response)))) - .Times(1); - upload.configuration->OnURLLoadComplete( - &upload.job, net::OK, DeviceManagementService::kSuccess, - ResponseValueBuilder::CreateResponseString(upload.response)); - } -} - -TEST_F(EncryptedReportingJobConfigurationTest, FailedUploadsSequenceThrottled) { - const size_t kTotalRetries = 10; - const std::string kEncryptedWrappedRecord = "TEST_INFO"; - - for (size_t i = 0; i < kTotalRetries; ++i) { - // Create new record with next seq id. - base::Value record_value = - GenerateSingleRecord(kEncryptedWrappedRecord, kPriority); - - auto upload = CreateTestUpload(record_value); - - EXPECT_CALL(*upload.completion_cb, - Call(&upload.job, DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID, - DeviceManagementService::kInvalidAuthCookieOrDMToken, - Eq(ByRef(upload.response)))) - .Times(1); - - auto allowed_delay = upload.configuration->WhenIsAllowedToProceed(); - if (i == 0) { - // The very first upload is allowed. - EXPECT_FALSE(allowed_delay.is_positive()); - } else { - EXPECT_THAT(allowed_delay, Ge(base::Days(1))); - // Move forward to allow. - task_environment_.FastForwardBy(allowed_delay - base::Seconds(1)); - EXPECT_TRUE(upload.configuration->WhenIsAllowedToProceed().is_positive()); - task_environment_.FastForwardBy(base::Seconds(1)); - } - - EXPECT_FALSE(upload.configuration->WhenIsAllowedToProceed().is_positive()); - upload.configuration->AccountForAllowedJob(); - upload.configuration->OnURLLoadComplete( - &upload.job, net::OK, - DeviceManagementService::kInvalidAuthCookieOrDMToken, - ResponseValueBuilder::CreateResponseString(upload.response)); - } -} - TEST_F(EncryptedReportingJobConfigurationTest, ManagedDeviceUmaName) { // Non-null cloud policy client indicates device is unmanaged. EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), - kServerUrl, RequestPayloadBuilder().Build(), &client_, base::DoNothing()); + kServerUrl, RequestPayloadBuilder().Build(), &client_, base::DoNothing(), + base::DoNothing()); EXPECT_EQ(configuration.GetUmaName(), "Browser.ERP.ManagedUploadEncryptedReport"); @@ -921,7 +759,7 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, RequestPayloadBuilder().Build(), - /*cloud_policy_client=*/nullptr, base::DoNothing()); + /*cloud_policy_client=*/nullptr, base::DoNothing(), base::DoNothing()); EXPECT_EQ(configuration.GetUmaName(), "Browser.ERP.UnmanagedUploadEncryptedReport"); @@ -942,7 +780,8 @@ EncryptedReportingJobConfiguration configuration( shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), - kServerUrl, std::move(request), &client_, base::DoNothing()); + kServerUrl, std::move(request), &client_, base::DoNothing(), + base::DoNothing()); std::optional<base::Value> payload = base::JSONReader::Read(configuration.GetPayload());
diff --git a/components/safe_browsing/content/browser/async_check_tracker.cc b/components/safe_browsing/content/browser/async_check_tracker.cc index 3073a78..6970028 100644 --- a/components/safe_browsing/content/browser/async_check_tracker.cc +++ b/components/safe_browsing/content/browser/async_check_tracker.cc
@@ -17,6 +17,16 @@ using security_interstitials::UnsafeResource; +// The threshold that will trigger a cleanup on +// `committed_navigation_timestamps_`. +constexpr int kNavigationTimestampsSizeThreshold = 10000; + +// Navigation timestamps that are older than this interval are considered +// expired and may be cleaned up. This interval must be much larger than the +// life time of UrlCheckerOnSB so that IsMainPageLoadPending returns the correct +// result when the check completes. +constexpr base::TimeDelta kNavigationTimestampExpiration = base::Seconds(180); + } // namespace WEB_CONTENTS_USER_DATA_KEY_IMPL(AsyncCheckTracker); @@ -67,7 +77,9 @@ scoped_refptr<BaseUIManager> ui_manager) : content::WebContentsUserData<AsyncCheckTracker>(*web_contents), content::WebContentsObserver(web_contents), - ui_manager_(std::move(ui_manager)) {} + ui_manager_(std::move(ui_manager)), + navigation_timestamps_size_threshold_( + kNavigationTimestampsSizeThreshold) {} AsyncCheckTracker::~AsyncCheckTracker() { DeletePendingCheckers(/*excluded_navigation_id=*/std::nullopt); @@ -145,6 +157,13 @@ // AsyncCheckTracker is created) and then a prerendered navigation starts // on the same WebContents. committed_navigation_timestamps_[navigation_id] = base::TimeTicks::Now(); + if (committed_navigation_timestamps_.size() > + navigation_timestamps_size_threshold_) { + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&AsyncCheckTracker::DeleteExpiredNavigationTimestamps, + GetWeakPtr())); + } } base::UmaHistogramCounts10000( "SafeBrowsing.AsyncCheck.CommittedNavigationIdsSize", @@ -245,10 +264,23 @@ } } +void AsyncCheckTracker::DeleteExpiredNavigationTimestamps() { + base::EraseIf(committed_navigation_timestamps_, + [&](const auto& id_timestamp_pair) { + return base::TimeTicks::Now() - id_timestamp_pair.second > + kNavigationTimestampExpiration; + }); +} + size_t AsyncCheckTracker::PendingCheckersSizeForTesting() { return pending_checkers_.size(); } +void AsyncCheckTracker::SetNavigationTimestampsSizeThresholdForTesting( + size_t threshold) { + navigation_timestamps_size_threshold_ = threshold; +} + void AsyncCheckTracker::SetOnAllCheckersCompletedForTesting( base::OnceClosure callback) { on_all_checkers_completed_callback_for_testing_ = std::move(callback);
diff --git a/components/safe_browsing/content/browser/async_check_tracker.h b/components/safe_browsing/content/browser/async_check_tracker.h index 26b1a80..382c8ef 100644 --- a/components/safe_browsing/content/browser/async_check_tracker.h +++ b/components/safe_browsing/content/browser/async_check_tracker.h
@@ -42,11 +42,17 @@ // yet committed). Note that a main frame hit may not be pending, eg. 1) // client side detection happens after the load is committed, or 2) async Safe // Browsing check is enabled. + // Caveat: This class only tracks committed navigation ids for a + // certain period, so this function may not return the correct result if the + // navigation associated with the `resource` is too old. static bool IsMainPageLoadPending( const security_interstitials::UnsafeResource& resource); // Returns the timestamp when the navigation associated with `resource` is // committed. Returns nullopt if the navigation has not committed. + // Caveat: This class only tracks committed navigation ids for a + // certain period, so this function may not return the correct result if the + // navigation associated with the `resource` is too old. static std::optional<base::TimeTicks> GetBlockedPageCommittedTimestamp( const security_interstitials::UnsafeResource& resource); @@ -76,6 +82,8 @@ size_t PendingCheckersSizeForTesting(); + void SetNavigationTimestampsSizeThresholdForTesting(size_t threshold); + base::WeakPtr<AsyncCheckTracker> GetWeakPtr(); private: @@ -95,6 +103,10 @@ // is keyed by `excluded_navigation_id`. void DeletePendingCheckers(std::optional<int64_t> excluded_navigation_id); + // Deletes expired timestamps to avoid `committed_navigation_timestamps_` + // getting too large. + void DeleteExpiredNavigationTimestamps(); + // Displays an interstitial if there is unsafe resource associated with // `redirect_chain` and `navigation_id`. void MaybeDisplayBlockingPage(const std::vector<GURL>& redirect_chain, @@ -128,6 +140,10 @@ // used for logging metrics. base::flat_map<int64_t, base::TimeTicks> committed_navigation_timestamps_; + // The threshold that will trigger a cleanup on + // `committed_navigation_timestamps_`. Overridden in tests. + size_t navigation_timestamps_size_threshold_; + // Callback that is called once all checkers are completed. Used only for // tests. base::OnceClosure on_all_checkers_completed_callback_for_testing_;
diff --git a/components/safe_browsing/content/browser/async_check_tracker_unittest.cc b/components/safe_browsing/content/browser/async_check_tracker_unittest.cc index 8aa6a1ae..32a0d67 100644 --- a/components/safe_browsing/content/browser/async_check_tracker_unittest.cc +++ b/components/safe_browsing/content/browser/async_check_tracker_unittest.cc
@@ -49,6 +49,8 @@ UnsafeResource displayed_resource_; }; +constexpr int kLocalNavigationTimestampsSizeThreshold = 5; + } // namespace class AsyncCheckTrackerTest : public content::RenderViewHostTestHarness, @@ -56,7 +58,8 @@ protected: AsyncCheckTrackerTest() : RenderViewHostTestHarness( - content::BrowserTaskEnvironment::REAL_IO_THREAD) { + content::BrowserTaskEnvironment::REAL_IO_THREAD, + base::test::TaskEnvironment::TimeSource::MOCK_TIME) { bool sb_on_ui_thread_enabled = GetParam(); if (sb_on_ui_thread_enabled) { feature_list_.InitWithFeatures( @@ -294,6 +297,80 @@ EXPECT_FALSE(AsyncCheckTracker::IsMainPageLoadPending(resource)); } +TEST_P(AsyncCheckTrackerTest, + IsMainPageLoadPending_DeleteExpiredNavigationTimestamps) { + tracker_->SetNavigationTimestampsSizeThresholdForTesting( + kLocalNavigationTimestampsSizeThreshold); + UnsafeResource resource; + resource.threat_type = SB_THREAT_TYPE_URL_PHISHING; + resource.frame_tree_node_id = main_rfh()->GetFrameTreeNodeId(); + + std::vector<int64_t> old_navigation_ids; + for (int i = 0; i < kLocalNavigationTimestampsSizeThreshold; i++) { + content::MockNavigationHandle handle(url_, main_rfh()); + old_navigation_ids.push_back(handle.GetNavigationId()); + CallDidFinishNavigation(handle, /*has_committed=*/true); + } + for (int64_t id : old_navigation_ids) { + resource.navigation_id = id; + EXPECT_FALSE(AsyncCheckTracker::IsMainPageLoadPending(resource)); + } + + task_environment()->FastForwardBy(base::Seconds(180)); + content::MockNavigationHandle recent_handle1(url_, main_rfh()); + CallDidFinishNavigation(recent_handle1, /*has_committed=*/true); + for (int64_t id : old_navigation_ids) { + resource.navigation_id = id; + EXPECT_FALSE(AsyncCheckTracker::IsMainPageLoadPending(resource)); + } + + task_environment()->FastForwardBy(base::Seconds(1)); + content::MockNavigationHandle recent_handle2(url_, main_rfh()); + CallDidFinishNavigation(recent_handle2, /*has_committed=*/true); + // The old navigation timestamps have been cleaned up, so the function returns + // true. + for (int64_t id : old_navigation_ids) { + resource.navigation_id = id; + EXPECT_TRUE(AsyncCheckTracker::IsMainPageLoadPending(resource)); + } + + // The recent timestamps should not be cleaned up. + resource.navigation_id = recent_handle1.GetNavigationId(); + EXPECT_FALSE(AsyncCheckTracker::IsMainPageLoadPending(resource)); + resource.navigation_id = recent_handle2.GetNavigationId(); + EXPECT_FALSE(AsyncCheckTracker::IsMainPageLoadPending(resource)); +} + +TEST_P( + AsyncCheckTrackerTest, + IsMainPageLoadPending_DeleteExpiredNavigationTimestamps_NotReachingThreshold) { + tracker_->SetNavigationTimestampsSizeThresholdForTesting( + kLocalNavigationTimestampsSizeThreshold); + UnsafeResource resource; + resource.threat_type = SB_THREAT_TYPE_URL_PHISHING; + resource.frame_tree_node_id = main_rfh()->GetFrameTreeNodeId(); + + content::MockNavigationHandle handle(url_, main_rfh()); + CallDidFinishNavigation(handle, /*has_committed=*/true); + resource.navigation_id = handle.GetNavigationId(); + EXPECT_FALSE(AsyncCheckTracker::IsMainPageLoadPending(resource)); + + task_environment()->FastForwardBy(base::Seconds(181)); + content::MockNavigationHandle recent_handle(url_, main_rfh()); + CallDidFinishNavigation(recent_handle, /*has_committed=*/true); + // The timestamp has expired but not cleaned up, because the size of the + // timestamps has not reached the threshold. + EXPECT_FALSE(AsyncCheckTracker::IsMainPageLoadPending(resource)); + + for (int i = 0; i < kLocalNavigationTimestampsSizeThreshold - 1; i++) { + content::MockNavigationHandle new_handle(url_, main_rfh()); + CallDidFinishNavigation(new_handle, /*has_committed=*/true); + } + // The size of the timestamps has reached the threshold, so the old timestamp + // is cleaned up. + EXPECT_TRUE(AsyncCheckTracker::IsMainPageLoadPending(resource)); +} + TEST_P(AsyncCheckTrackerTest, GetBlockedPageCommittedTimestamp) { content::MockNavigationHandle handle(web_contents()); UnsafeResource resource;
diff --git a/components/user_manager/multi_user/multi_user_sign_in_policy.h b/components/user_manager/multi_user/multi_user_sign_in_policy.h index 7113a06..e843786 100644 --- a/components/user_manager/multi_user/multi_user_sign_in_policy.h +++ b/components/user_manager/multi_user/multi_user_sign_in_policy.h
@@ -13,8 +13,14 @@ namespace user_manager { enum class MultiUserSignInPolicy { + // The user is allowed to be either a primary user or secondary user in + // multi user sign-in sessions. kUnrestricted = 0, + + // The user can be only be a primary user in multi user sign-in sessions. kPrimaryOnly = 1, + + // The user cannot be a part of multi user sign-in sessions. kNotAllowed = 2, };
diff --git a/components/variations/service/limited_entropy_synthetic_trial.cc b/components/variations/service/limited_entropy_synthetic_trial.cc index 8b0347b..e5d56be 100644 --- a/components/variations/service/limited_entropy_synthetic_trial.cc +++ b/components/variations/service/limited_entropy_synthetic_trial.cc
@@ -5,6 +5,7 @@ #include <cstdint> +#include "base/metrics/histogram_functions.h" #include "base/rand_util.h" #include "components/prefs/pref_service.h" #include "components/variations/pref_names.h" @@ -12,23 +13,43 @@ namespace variations { namespace { +#if BUILDFLAG(IS_CHROMEOS) +// A flag that is used to make sure that if seed of the trial is sync'ed from +// Ash to Lacros, the trial should only be randomized after the seed is set. +bool g_trial_is_randomized = false; +#endif + // The percentage of population that is enabled in this trial. It can be either // 100 or an integer within [0, 50]. constexpr uint64_t kEnabledPercentage = 50; +bool IsValidTrialSeed(uint64_t seed) { + return seed > 0 && seed <= 100; +} + +uint64_t GenerateTrialSeed() { + // base::RandGenerator(100) will return a number within [0, 100). Adding one + // to avoid 0 being a valid value since 0 might be a default uint64 value. + auto seed = base::RandGenerator(100) + 1; + CHECK(IsValidTrialSeed(seed)); + return seed; +} + std::string_view SelectGroup(PrefService* local_state) { static_assert((kEnabledPercentage >= 0 && kEnabledPercentage <= 50) || kEnabledPercentage == 100); +#if BUILDFLAG(IS_CHROMEOS) + g_trial_is_randomized = true; +#endif auto* seed_pref_name = prefs::kVariationsLimitedEntropySyntheticTrialSeed; if (!local_state->HasPrefPath(seed_pref_name)) { - // base::RandGenerator(100) will return a number within [0, 100). - local_state->SetUint64(seed_pref_name, base::RandGenerator(100)); + local_state->SetUint64(seed_pref_name, GenerateTrialSeed()); } auto rand_val = local_state->GetUint64(seed_pref_name); - if (rand_val < kEnabledPercentage) { + if (rand_val <= kEnabledPercentage) { return kLimitedEntropySyntheticTrialEnabled; - } else if (rand_val < 2 * kEnabledPercentage) { + } else if (rand_val <= 2 * kEnabledPercentage) { return kLimitedEntropySyntheticTrialControl; } else { return kLimitedEntropySyntheticTrialDefault; @@ -54,6 +75,41 @@ variations::prefs::kVariationsLimitedEntropySyntheticTrialSeed, 0); } +#if BUILDFLAG(IS_CHROMEOS) +// static +void LimitedEntropySyntheticTrial::SetSeedFromAsh(PrefService* local_state, + uint64_t seed) { + // This CHECK is defense in depth and is not expected to happen since this + // method will be called before the creation of + // `metrics::MetricsStateManager`, which is a dependency of + // `variations::VariationsService`. `VariationsService` will control the + // randomization of this trial through calling its constructor. + CHECK(!g_trial_is_randomized); + + // The trial seed is only expected to be invalid when there is a version skew, + // in which the Ash Chrome's version is older at a point that it is not + // sending the seed over. In this case, the mojo field will carry a zero + // value, which is an invalid seed. + bool is_valid_seed = IsValidTrialSeed(seed); + base::UmaHistogramBoolean(kIsLimitedEntropySyntheticTrialSeedValidHistogram, + is_valid_seed); + if (is_valid_seed) { + local_state->SetUint64(prefs::kVariationsLimitedEntropySyntheticTrialSeed, + seed); + } +} + +// static +uint64_t LimitedEntropySyntheticTrial::GetRandomizationSeed( + PrefService* local_state) { + // Initialize the trial to set the value of + // |kVariationsLimitedEntropySyntheticTrialSeed|. + LimitedEntropySyntheticTrial trial(local_state); + return local_state->GetUint64( + prefs::kVariationsLimitedEntropySyntheticTrialSeed); +} +#endif + bool LimitedEntropySyntheticTrial::IsEnabled() { return group_name_ == kLimitedEntropySyntheticTrialEnabled; }
diff --git a/components/variations/service/limited_entropy_synthetic_trial.h b/components/variations/service/limited_entropy_synthetic_trial.h index 2ef9878..f009c5d 100644 --- a/components/variations/service/limited_entropy_synthetic_trial.h +++ b/components/variations/service/limited_entropy_synthetic_trial.h
@@ -19,6 +19,9 @@ inline constexpr char kLimitedEntropySyntheticTrialControl[] = "Control"; inline constexpr char kLimitedEntropySyntheticTrialDefault[] = "Default"; +inline constexpr char kIsLimitedEntropySyntheticTrialSeedValidHistogram[] = + "Variations.LimitedEntropyTrial.AshSeedIsValid.OnSyncToLacros"; + class LimitedEntropySyntheticTrial { public: explicit LimitedEntropySyntheticTrial(PrefService* local_state); @@ -31,6 +34,20 @@ // Registers the prefs needed for this trial. static void RegisterPrefs(PrefRegistrySimple* registry); +#if BUILDFLAG(IS_CHROMEOS) + // Overrides the seed of this trial with the value used in Ash chrome. Note + // this method needs to be called before instantiation of the trial for the + // seed to take effect. This should only be used by the Lacros client. + static void SetSeedFromAsh(PrefService* local_state, uint64_t seed); + + // Returns the randomization seed of this trial. This should only be used by + // the Ash Chrome client when sending the seed to Lacros, or in tests. + // + // Side effect: Initializes the seed, storing the result to prefs, if the seed + // was not already initialized. + static uint64_t GetRandomizationSeed(PrefService* local_state); +#endif + // Returns whether the client is in the enabled group for this trial. bool IsEnabled();
diff --git a/components/variations/service/limited_entropy_synthetic_trial_unittest.cc b/components/variations/service/limited_entropy_synthetic_trial_unittest.cc index 7830672..769b8a4 100644 --- a/components/variations/service/limited_entropy_synthetic_trial_unittest.cc +++ b/components/variations/service/limited_entropy_synthetic_trial_unittest.cc
@@ -4,6 +4,8 @@ #include "components/variations/service/limited_entropy_synthetic_trial.h" +#include "base/test/gtest_util.h" +#include "base/test/metrics/histogram_tester.h" #include "components/prefs/testing_pref_service.h" #include "components/variations/pref_names.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,6 +20,7 @@ protected: TestingPrefServiceSimple local_state_; + base::HistogramTester histogram_tester_; }; TEST_F(LimitedEntropySyntheticTrialTest, RandomizesWithExistingSeed_Enabled) { @@ -62,4 +65,42 @@ } } +#if BUILDFLAG(IS_CHROMEOS) +TEST_F(LimitedEntropySyntheticTrialTest, TestSetSeedFromAsh) { + LimitedEntropySyntheticTrial::SetSeedFromAsh(&local_state_, 42u); + LimitedEntropySyntheticTrial trial(&local_state_); + + EXPECT_EQ(42u, trial.GetRandomizationSeed(&local_state_)); + histogram_tester_.ExpectUniqueSample( + kIsLimitedEntropySyntheticTrialSeedValidHistogram, true, 1); +} + +TEST_F(LimitedEntropySyntheticTrialTest, + TestSetSeedFromAsh_ExpectCheckIFailureIfRandomizedBeforeSyncingSeed) { + LimitedEntropySyntheticTrial trial(&local_state_); + EXPECT_CHECK_DEATH( + LimitedEntropySyntheticTrial::SetSeedFromAsh(&local_state_, 42u)); +} + +TEST_F( + LimitedEntropySyntheticTrialTest, + TestSetSeedFromAsh_ExpectCheckIFailureIfSettingSeedAgainAfterRandomization) { + LimitedEntropySyntheticTrial::SetSeedFromAsh(&local_state_, 42u); + LimitedEntropySyntheticTrial trial(&local_state_); + EXPECT_CHECK_DEATH( + LimitedEntropySyntheticTrial::SetSeedFromAsh(&local_state_, 62u)); + histogram_tester_.ExpectUniqueSample( + kIsLimitedEntropySyntheticTrialSeedValidHistogram, true, 1); +} + +TEST_F(LimitedEntropySyntheticTrialTest, + TestSetSeedFromAsh_SyncingInvalidSeed) { + LimitedEntropySyntheticTrial::SetSeedFromAsh(&local_state_, 999u); + LimitedEntropySyntheticTrial trial(&local_state_); + EXPECT_NE(999u, trial.GetRandomizationSeed(&local_state_)); + histogram_tester_.ExpectUniqueSample( + kIsLimitedEntropySyntheticTrialSeedValidHistogram, false, 1); +} + +#endif } // namespace variations
diff --git a/components/variations/service/variations_service.h b/components/variations/service/variations_service.h index 011edf6..dd2f0099 100644 --- a/components/variations/service/variations_service.h +++ b/components/variations/service/variations_service.h
@@ -321,6 +321,11 @@ FRIEND_TEST_ALL_PREFIXES(VariationsServiceTest, DoNotRetryAfterARetry); FRIEND_TEST_ALL_PREFIXES(VariationsServiceTest, DoNotRetryIfInsecureURLIsHTTPS); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // For the test to access |limited_entropy_synthetic_trial_|. + FRIEND_TEST_ALL_PREFIXES(VariationsServiceBrowserTest, + LimitedEntropySyntheticTrialSeedTransfer); +#endif void InitResourceRequestedAllowedNotifier();
diff --git a/components/viz/service/debugger/viz_debugger.h b/components/viz/service/debugger/viz_debugger.h index 2e6b5c5..8a98084 100644 --- a/components/viz/service/debugger/viz_debugger.h +++ b/components/viz/service/debugger/viz_debugger.h
@@ -285,7 +285,7 @@ __func__); \ if (dcs.IsActive()) { \ viz::VizDebugger::GetInstance()->AddLogMessage( \ - base::StringPrintf(format, __VA_ARGS__), &dcs, option); \ + base::StringPrintf(format, ##__VA_ARGS__), &dcs, option); \ } \ } \ } while (0) @@ -465,7 +465,7 @@ DBG_DRAW_TEXT_OPT(anno, DBG_OPT_BLACK, pos, text) #define DBG_LOG(anno, format, ...) \ - DBG_LOG_OPT(anno, DBG_OPT_BLACK, format, __VA_ARGS__) + DBG_LOG_OPT(anno, DBG_OPT_BLACK, format, ##__VA_ARGS__) #define DBG_DRAW_RECT_OPT_BUFF_UV(anno, option, rect, id, uv) \ DBG_DRAW_RECTANGLE_OPT_BUFF_UV( \
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc index 5949052f..a9ea0539 100644 --- a/components/viz/service/display/dc_layer_overlay.cc +++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -434,7 +434,7 @@ return !occluding_damage_rect.IsEmpty(); } -bool IsPossibleFullScreenLetterboxing(const QuadList::Iterator& it, +bool IsPossibleFullScreenLetterboxing(const QuadList::ConstIterator& it, QuadList::ConstIterator quad_list_end, const gfx::Rect& display_rect) { // Two cases are considered as possible fullscreen letterboxing: @@ -654,6 +654,99 @@ } } +// Return value of |ValidateDrawQuad|. +struct ValidateDrawQuadResult { + DCLayerResult code = DC_LAYER_FAILED_UNSUPPORTED_QUAD; + bool is_yuv_overlay = false; + gpu::Mailbox promotion_hint_mailbox; +}; + +ValidateDrawQuadResult ValidateDrawQuad( + DisplayResourceProvider* resource_provider, + const QuadList::ConstIterator& it, + const std::vector<gfx::Rect>& backdrop_filter_rects, + const bool is_page_fullscreen_mode, + const bool has_overlay_support, + const bool has_p010_video_processor_support, + const int allowed_yuv_overlay_count, + const int processed_yuv_overlay_count, + const bool allow_promotion_hinting) { + ValidateDrawQuadResult result; + switch (it->material) { + case DrawQuad::Material::kYuvVideoContent: + result.code = ValidateYUVQuad( + YUVVideoDrawQuad::MaterialCast(*it), backdrop_filter_rects, + is_page_fullscreen_mode, has_overlay_support, + has_p010_video_processor_support, allowed_yuv_overlay_count, + processed_yuv_overlay_count, resource_provider); + result.is_yuv_overlay = true; + break; + + case DrawQuad::Material::kTextureContent: { + const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(*it); + + if (tex_quad->is_stream_video) { + // Stream video quads contain Media Foundation dcomp surface which is + // always presented as overlay. + result.code = DC_LAYER_SUCCESS; + } else { + result.code = ValidateTextureQuad( + tex_quad, backdrop_filter_rects, is_page_fullscreen_mode, + has_overlay_support, has_p010_video_processor_support, + allowed_yuv_overlay_count, processed_yuv_overlay_count, + resource_provider); + } + + result.is_yuv_overlay = tex_quad->is_video_frame; + + if (allow_promotion_hinting) { + // If this quad has marked itself as wanting promotion hints then get + // the associated mailbox. + ResourceId id = tex_quad->resource_id(); + if (resource_provider->DoesResourceWantPromotionHint(id)) { + result.promotion_hint_mailbox = resource_provider->GetMailbox(id); + } + } + } break; + + default: + result.code = DC_LAYER_FAILED_UNSUPPORTED_QUAD; + break; + } + + return result; +} + +void FromDrawQuad(DisplayResourceProvider* resource_provider, + const AggregatedRenderPass* render_pass, + bool is_page_fullscreen_mode, + const QuadList::ConstIterator& it, + int& processed_yuv_overlay_count, + OverlayCandidate& dc_layer) { + dc_layer.possible_video_fullscreen_letterboxing = + is_page_fullscreen_mode + ? IsPossibleFullScreenLetterboxing(it, render_pass->quad_list.end(), + render_pass->output_rect) + : false; + switch (it->material) { + case DrawQuad::Material::kYuvVideoContent: + FromYUVQuad(YUVVideoDrawQuad::MaterialCast(*it), + render_pass->transform_to_root_target, &dc_layer); + processed_yuv_overlay_count++; + break; + case DrawQuad::Material::kTextureContent: { + const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(*it); + FromTextureQuad(tex_quad, render_pass->transform_to_root_target, + resource_provider, &dc_layer); + if (tex_quad->is_video_frame) { + processed_yuv_overlay_count++; + } + } break; + default: + NOTREACHED(); + } +} + } // namespace DCLayerOverlayProcessor::DCLayerOverlayProcessor( @@ -887,51 +980,14 @@ continue; } - gpu::Mailbox promotion_hint_mailbox; - DCLayerResult result; - bool is_yuv_overlay = false; - switch (it->material) { - case DrawQuad::Material::kYuvVideoContent: - result = ValidateYUVQuad( - YUVVideoDrawQuad::MaterialCast(*it), backdrop_filter_rects, - is_page_fullscreen_mode, has_overlay_support_, - has_p010_video_processor_support_, allowed_yuv_overlay_count_, - global_overlay_state.processed_yuv_overlay_count, - resource_provider); - is_yuv_overlay = true; - break; - case DrawQuad::Material::kTextureContent: { - const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(*it); + ValidateDrawQuadResult result = ValidateDrawQuad( + resource_provider, it, backdrop_filter_rects, is_page_fullscreen_mode, + has_overlay_support_, has_p010_video_processor_support_, + allowed_yuv_overlay_count_, + global_overlay_state.processed_yuv_overlay_count, + allow_promotion_hinting_); - if (tex_quad->is_stream_video) { - // Stream video quads contain Media Foundation dcomp surface which is - // always presented as overlay. - result = DC_LAYER_SUCCESS; - } else { - result = ValidateTextureQuad( - tex_quad, backdrop_filter_rects, is_page_fullscreen_mode, - has_overlay_support_, has_p010_video_processor_support_, - allowed_yuv_overlay_count_, - global_overlay_state.processed_yuv_overlay_count, - resource_provider); - } - - is_yuv_overlay = tex_quad->is_video_frame; - - if (allow_promotion_hinting_) { - // If this quad has marked itself as wanting promotion hints then get - // the associated mailbox. - ResourceId id = tex_quad->resource_id(); - if (resource_provider->DoesResourceWantPromotionHint(id)) { - promotion_hint_mailbox = resource_provider->GetMailbox(id); - } - } - } break; - default: - result = DC_LAYER_FAILED_UNSUPPORTED_QUAD; - } - - if (is_yuv_overlay) { + if (result.is_yuv_overlay) { global_overlay_state.yuv_quads++; if (no_undamaged_overlay_promotion_) { if (it->shared_quad_state->overlay_damage_index.has_value() && @@ -940,30 +996,31 @@ ->overlay_damage_index.value()] .IsEmpty()) { global_overlay_state.damaged_yuv_quads++; - if (result == DC_LAYER_SUCCESS) { + if (result.code == DC_LAYER_SUCCESS) { global_overlay_state.processed_yuv_overlay_count++; } } } else { - if (result == DC_LAYER_SUCCESS) { + if (result.code == DC_LAYER_SUCCESS) { global_overlay_state.processed_yuv_overlay_count++; } } } - if (!promotion_hint_mailbox.IsZero()) { + if (!result.promotion_hint_mailbox.IsZero()) { DCHECK(allow_promotion_hinting_); - bool promoted = result == DC_LAYER_SUCCESS; + bool promoted = result.code == DC_LAYER_SUCCESS; auto* overlay_state_service = OverlayStateService::GetInstance(); // The OverlayStateService should always be initialized by GpuServiceImpl // at creation - DCHECK here just to assert there aren't any corner cases // where this isn't true. DCHECK(overlay_state_service->IsInitialized()); - overlay_state_service->SetPromotionHint(promotion_hint_mailbox, promoted); + overlay_state_service->SetPromotionHint(result.promotion_hint_mailbox, + promoted); } - if (result != DC_LAYER_SUCCESS) { - RecordDCLayerResult(result, it); + if (result.code != DC_LAYER_SUCCESS) { + RecordDCLayerResult(result.code, it); continue; } @@ -1240,28 +1297,8 @@ RecordDCLayerResult(DC_LAYER_SUCCESS, it); OverlayCandidate dc_layer; - dc_layer.possible_video_fullscreen_letterboxing = - is_page_fullscreen_mode - ? IsPossibleFullScreenLetterboxing(it, render_pass->quad_list.end(), - render_pass->output_rect) - : false; - switch (it->material) { - case DrawQuad::Material::kYuvVideoContent: - FromYUVQuad(YUVVideoDrawQuad::MaterialCast(*it), - render_pass->transform_to_root_target, &dc_layer); - global_overlay_state.processed_yuv_overlay_count++; - break; - case DrawQuad::Material::kTextureContent: { - const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(*it); - FromTextureQuad(tex_quad, render_pass->transform_to_root_target, - resource_provider, &dc_layer); - if (tex_quad->is_video_frame) { - global_overlay_state.processed_yuv_overlay_count++; - } - } break; - default: - NOTREACHED(); - } + FromDrawQuad(resource_provider, render_pass, is_page_fullscreen_mode, it, + global_overlay_state.processed_yuv_overlay_count, dc_layer); // Underlays are less efficient, so attempt regular overlays first. We can // only check for occlusion within a render pass.
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index f29118d3..79acba9 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -952,6 +952,9 @@ DCHECK(!disable_image_filtering); } + DBG_LOG("renderer.ptr", "renderer = %p%s", this, + renderer_.get() == software_renderer_ ? " (software)" : ""); + draw_timer.emplace(); overlay_processor_->SetFrameSequenceNumber(frame_sequence_number_); overlay_processor_->SetIsPageFullscreen(frame.page_fullscreen_mode);
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 63e2bc32..3625794 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -22,6 +22,7 @@ #include "base/task/bind_post_task.h" #include "base/task/single_thread_task_runner.h" #include "base/trace_event/trace_event.h" +#include "base/trace_event/traced_value.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "cc/base/math_util.h" @@ -468,6 +469,64 @@ } // namespace +// A helper class to emit Viz debugger messages that has access to SkiaRenderer +// internals. +class SkiaRenderer::VizDebuggerLog { + public: + static void DebugLogDumpRenderPassBackings( + const base::flat_map<AggregatedRenderPassId, RenderPassBacking>& + render_pass_backings) { + bool enabled; + DBG_CONNECTED_OR_TRACING(enabled); + if (enabled) { + DBG_LOG("renderer.skia.render_pass_backings", + "render_pass_backings_ = ["); + for (auto& kv : render_pass_backings) { + base::trace_event::TracedValueJSON value; + base::trace_event::TracedValue::Dictionary( + { + {"size", kv.second.size.ToString()}, + {"generate_mipmap", kv.second.generate_mipmap}, + {"color_space", kv.second.color_space.ToString()}, + {"format", kv.second.format.ToString()}, + {"mailbox", kv.second.mailbox.ToDebugString()}, + {"is_root", kv.second.is_root}, + {"is_scanout", kv.second.is_scanout}, + {"scanout_dcomp_surface", kv.second.scanout_dcomp_surface}, + }) + .WriteToValue(&value); + DBG_LOG("renderer.skia.render_pass_backings", "%" PRIu64 ": %s", + kv.first.value(), value.ToFormattedJSON().c_str()); + } + DBG_LOG("renderer.skia.render_pass_backings", "]"); + } + } + + static void DebugLogNewRenderPassBacking( + const AggregatedRenderPassId& render_pass_id, + const RenderPassRequirements& requirements) { + bool enabled; + DBG_CONNECTED_OR_TRACING(enabled); + if (enabled) { + base::trace_event::TracedValueJSON value; + base::trace_event::TracedValue::Dictionary( + { + {"size", requirements.size.ToString()}, + {"generate_mipmap", requirements.generate_mipmap}, + {"format", requirements.format.ToString()}, + {"color_space", requirements.color_space.ToString()}, + {"alpha_type", static_cast<int>(requirements.alpha_type)}, + {"is_scanout", requirements.is_scanout}, + {"scanout_dcomp_surface", requirements.scanout_dcomp_surface}, + }) + .WriteToValue(&value); + DBG_LOG("renderer.skia.render_pass_backings", + "allocate backing for render_pass %" PRIu64 ", %s", + render_pass_id.value(), value.ToFormattedJSON().c_str()); + } + } +}; + // chrome style prevents this from going in skia_renderer.h, but since it // uses std::optional, the style also requires it to have a declared ctor SkiaRenderer::BatchedQuadState::BatchedQuadState() = default; @@ -1065,6 +1124,8 @@ swap_buffer_rect_ = current_frame()->root_damage_rect; + VizDebuggerLog::DebugLogDumpRenderPassBackings(render_pass_backings_); + #if BUILDFLAG(IS_OZONE) MaybeScheduleBackgroundImage(current_frame()->overlay_list); #endif // BUILDFLAG(IS_OZONE) @@ -3457,6 +3518,9 @@ auto render_pass_it = render_passes_in_frame.find(backing_id); if (render_pass_it == render_passes_in_frame.end()) { passes_to_delete.push_back(backing_id); + DBG_LOG("renderer.skia.render_pass_backings", + "render_pass %" PRIu64 " is no longer in frame", + backing_id.value()); continue; } @@ -3482,6 +3546,15 @@ !no_change_in_alpha_type || !no_change_in_color_space || !scanout_appropriate) { passes_to_delete.push_back(backing_id); + DBG_LOG("renderer.skia.render_pass_backings", + "render_pass %" PRIu64 + " allocation part not appropriate:%s%s%s%s%s%s", + backing_id.value(), !size_appropriate ? " size" : "", + !mipmap_appropriate ? " mipmap" : "", + !no_change_in_format ? " format" : "", + !no_change_in_alpha_type ? " alpha_type" : "", + !no_change_in_color_space ? " color_space" : "", + !scanout_appropriate ? " scanout" : ""); } } @@ -3572,6 +3645,9 @@ requirements.format, requirements.size, requirements.color_space, requirements.alpha_type, usage, "RenderPassBacking", gpu::kNullSurfaceHandle); + + VizDebuggerLog::DebugLogNewRenderPassBacking(render_pass_id, requirements); + render_pass_backings_.emplace( render_pass_id, RenderPassBacking({requirements.size, requirements.generate_mipmap,
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index e630f0a0..8ecbdfc 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -123,6 +123,7 @@ struct OverlayLock; class ScopedSkImageBuilder; class ScopedYUVSkImageBuilder; + class VizDebuggerLog; void ClearCanvas(SkColor4f color); void ClearFramebuffer();
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index 587b6e5..832edae 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -5,6 +5,7 @@ #include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h" #include <algorithm> +#include <cmath> #include <limits> #include <optional> #include <utility> @@ -21,6 +22,7 @@ #include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "base/tracing_buildflags.h" #include "build/build_config.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_result.h" @@ -157,6 +159,21 @@ } } +int AsPercent(float value) { + return base::saturated_cast<int>(std::nearbyint(value * 100.0f)); +} + +perfetto::Track FrameInUseTrack(const media::VideoFrameMetadata& metadata) { + return perfetto::Track(static_cast<uint64_t>( + (metadata.capture_begin_time.value() - base::TimeTicks()) + .InMicroseconds())); +} + +perfetto::Track CaptureTrack(const media::VideoFrameMetadata& metadata) { + return perfetto::Track(static_cast<uint64_t>( + (metadata.reference_time.value() - base::TimeTicks()).InMicroseconds())); +} + } // namespace // static @@ -791,19 +808,15 @@ UMA_HISTOGRAM_BOOLEAN("Viz.FrameSinkVideoCapturer.FrameResurrected", can_resurrect_content); - // Compute the current in-flight utilization and attenuate it: The utilization - // reported to the oracle is in terms of a maximum sustainable amount (not the - // absolute maximum). - const float utilization = - GetPipelineUtilization() / kTargetPipelineUtilization; + const float utilization = GetPipelineUtilization(); + const int utilization_pct = AsPercent(utilization); // Do not proceed if the pool did not provide a frame: This indicates the // pipeline is full. if (!frame) { TRACE_EVENT_INSTANT("gpu.capture", "PipelineLimited", "trigger", VideoCaptureOracle::EventAsString(event), - "atten_util_percent", - base::saturated_cast<int>(utilization * 100.0f + 0.5f)); + "utilization_pct", utilization_pct); oracle_->RecordWillNotCapture(utilization); if (next_capture_frame_number_ == 0) { // The pool was unable to provide a buffer for the very first capture, and @@ -829,17 +842,16 @@ if (utilization >= 1.0) { TRACE_EVENT_INSTANT("gpu.capture", "NearlyPipelineLimited", "trigger", VideoCaptureOracle::EventAsString(event), - "atten_util_percent", - base::saturated_cast<int>(utilization * 100.0f + 0.5f)); + "utilization_pct", utilization_pct); } // At this point, the capture is going to proceed. Populate the VideoFrame's // metadata, and notify the oracle. const int64_t capture_frame_number = next_capture_frame_number_++; + // !WARNING: now that the frame number has been incremented, returning without // adding the frame to the |delivery_queue_| or decrementing the frame number // will cause the queue to be permanently stuck. - VideoFrameMetadata& metadata = frame->metadata(); metadata.capture_begin_time = capture_begin_time; metadata.capture_counter = capture_frame_number; @@ -859,6 +871,11 @@ } metadata.top_controls_visible_height = last_top_controls_visible_height_; + // Record that the frame has been reserved for capture. + TRACE_EVENT_BEGIN("gpu.capture", "FrameInUse", FrameInUseTrack(metadata), + "frame_number", capture_frame_number, "utilization_pct", + utilization_pct); + oracle_->RecordCapture(utilization); // `content_rect` is the region of the `frame` that we would like to populate. @@ -883,9 +900,8 @@ // Note: The following is used by // chrome/browser/media/cast_mirroring_performance_browsertest.cc, in // addition to the usual runtime tracing - TRACE_EVENT_BEGIN("gpu.capture", "Capture", - perfetto::Track(oracle_frame_number), "frame_number", - capture_frame_number, "trigger", + TRACE_EVENT_BEGIN("gpu.capture", "Capture", CaptureTrack(metadata), + "frame_number", capture_frame_number, "trigger", VideoCaptureOracle::EventAsString(event)); // Determine what rectangular region has changed since the last captured @@ -1110,11 +1126,11 @@ "format=%s (%s) area:%s " "scale_from: %s " "scale_to: %s " - "frame pool utilization: %f", + "frame pool utilization: %d", format.c_str(), is_bitmap ? "bitmap" : "GPU memory buffer", request->area().ToString().c_str(), request->scale_from().ToString().c_str(), - request->scale_to().ToString().c_str(), utilization)); + request->scale_to().ToString().c_str(), utilization_pct)); } const SubtreeCaptureId subtree_id = @@ -1360,8 +1376,8 @@ // Note: The following is used by // chrome/browser/media/cast_mirroring_performance_browsertest.cc, in // addition to the usual runtime tracing - TRACE_EVENT_END("gpu.capture", perfetto::Track(oracle_frame_number)); - TRACE_EVENT_INSTANT("gpu.capture", "CaptureEnd", "success", false); + TRACE_EVENT_END("gpu.capture", CaptureTrack(frame->metadata()), "success", + false); MaybeScheduleRefreshFrame(); return; } @@ -1375,9 +1391,8 @@ // Note: The following is used by // chrome/browser/media/cast_mirroring_performance_browsertest.cc, in // addition to the usual runtime tracing - TRACE_EVENT_END("gpu.capture", perfetto::Track(oracle_frame_number), - "success", true, "time_delta", - frame->timestamp().InMicroseconds()); + TRACE_EVENT_END("gpu.capture", CaptureTrack(frame->metadata()), "success", + true, "time_delta", frame->timestamp().InMicroseconds()); // Clone a handle to the shared memory backing the populated video frame, to // send to the consumer. @@ -1412,9 +1427,15 @@ callbacks.InitWithNewPipeAndPassReceiver()); num_frames_in_flight_++; + +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + TRACE_COUNTER("gpu.capture", "NumFramesInFlight", num_frames_in_flight_); +#else + // TODO(crbug/1006541): Delete when Perfetto is the default. TRACE_COUNTER_ID1("gpu.capture", "FrameSinkVideoCapturerImpl::num_frames_in_flight_", this, num_frames_in_flight_); +#endif // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) // Send the frame to the consumer. consumer_->OnFrameCaptured(std::move(handle), std::move(info), content_rect, @@ -1480,18 +1501,17 @@ void FrameSinkVideoCapturerImpl::NotifyFrameReleased( scoped_refptr<media::VideoFrame> frame) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - num_frames_in_flight_--; - - TRACE_COUNTER_ID1("gpu.capture", - "FrameSinkVideoCapturerImpl::num_frames_in_flight_", this, - num_frames_in_flight_); + const media::VideoFrameMetadata metadata = frame->metadata(); + TRACE_EVENT_END("gpu.capture", FrameInUseTrack(metadata), "frame_number", + metadata.capture_counter, "utilization_pct", + AsPercent(GetPipelineUtilization())); } float FrameSinkVideoCapturerImpl::GetPipelineUtilization() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - return static_cast<float>(num_frames_in_flight_) / kDesignLimitMaxFrames; + return num_frames_in_flight_ / + (kDesignLimitMaxFrames * kTargetPipelineUtilization); } void FrameSinkVideoCapturerImpl::MaybeInformConsumerOfEmptyRegion() {
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h index 258e4275..8d819951 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -335,9 +335,13 @@ // been released by it. void NotifyFrameReleased(scoped_refptr<media::VideoFrame> frame); - // Returns pipeline utilization. Pipeline utilization is different from pool - // utilization, since a marked frame may be returned multiple times w/o - // increasing pool utilization, but it would increase pipeline utilization. + // Returns pipeline utilization as a fraction of kTargetPipelineUtilization. + // May be more than 1.0 if the current pool utilization is greater than + // kTargetPipelineUtilization. + // + // Pipeline utilization is different from pool utilization, since a marked + // frame may be returned multiple times w/o increasing pool utilization, but + // it would increase pipeline utilization. float GetPipelineUtilization() const; // Informs the consumer that the frame was dropped due to being cropped
diff --git a/components/webapps/browser/android/app_banner_manager_android.cc b/components/webapps/browser/android/app_banner_manager_android.cc index d019319..27364a6 100644 --- a/components/webapps/browser/android/app_banner_manager_android.cc +++ b/components/webapps/browser/android/app_banner_manager_android.cc
@@ -560,6 +560,11 @@ GetCurrentTime())) { return false; } + // If the manifest_id isn't valid, then we don't have enough information to + // show any banner for this page yet. + if (!manifest_id_.is_valid()) { + return false; + } auto a2hs_params = AppBannerManagerAndroid::CreateAddToHomescreenParams( GetCurrentInstallBannerConfig(), native_java_app_data_, install_source); return PwaBottomSheetController::MaybeShow(
diff --git a/content/OWNERS b/content/OWNERS index 9377789..a56cbbb 100644 --- a/content/OWNERS +++ b/content/OWNERS
@@ -2,12 +2,9 @@ # subdirectories that have specific owners who are the experts in reviewing that # code. Top level content/OWNERS are reviewers who are qualified to review # changes across all of content and are responsible for its architecture. They -# will defer to subdirectory owners as needed. As such we expect that a -# content/OWNER has made substantial contributions to content/ in the recent -# past, specifically both in the browser and renderer subdirectories as they -# encapsulate the main architecture, and demonstrated overall knowledge of the -# content architecture by doing code reviews for changes that affect different -# parts of content even before being a content/OWNER. +# will defer to subdirectory owners as needed. For more information about owner +# responsibilities as well as how to become a top-level owner, please see +# //content/README.md#content-owners. # # For public questions directed to OWNERS, you can send email # to content-owners@chromium.org.
diff --git a/content/README.md b/content/README.md index 5ff6fff..0675289 100644 --- a/content/README.md +++ b/content/README.md
@@ -96,6 +96,80 @@ embedders from content's inner workings, and makes it clear to people working on content which methods are used by embedders. +## Content OWNERS +Top-level `content` OWNERS are reviewers who are qualified to review changes +across all of `content` and are responsible for its architecture. In general, +`content` subdirectories will have specific owners who are the experts in +reviewing that code, and top-level owners will defer to subdirectory owners as +needed. For large architectural changes to `content`, all owners should loop in +content-owners@chromium.org to give others a chance to post suggestions. This +applies to changes large enough to warrant a design doc. + +To become a content/OWNER, candidates are expected to show substantial +contributions to `content` in recent past that demonstrate knowledge of the core +architecture and design principles, including both the browser process side and +the renderer side. To become a top-level owner, please follow the following +process: + +1. Become an owner in a few `content` subdirectories and establish yourself as + an expert reviewer in those areas. + +2. Find 1-2 current top-level owners who can become your "sponsors" for an owner + nomination. Work with them to (1) review your technical changes in `content` + to gain trust in your technical work and (2) shadow-review `content` changes + that you also review to gain trust in you as a reviewer. Once ready, your + sponsors will nominate you for ownership by sending an email to + the current top-level owners. + +A typical nomination includes: +- Projects that you worked on that involved `content`, and which concepts they + covered. +- Some representative CLs contributed and/or reviewed. This can also include + aggregate statistics, e.g. via `git shortlog -s --author=<username> + content/browser`. +- Significant improvements to documentation of the above concepts + +For reference, a top-level `content` OWNER is expected to be familiar with most +(but not necessarily all) of the following core parts of `content`: +- [Navigation](https://chromium.googlesource.com/chromium/src/+/main/docs/navigation.md) +- [Process model](https://chromium.googlesource.com/chromium/src/+/main/docs/process_model_and_site_isolation.md) +- [Session history](https://chromium.googlesource.com/chromium/src/+/main/docs/session_history.md) +- Loading, interactions with the network stack +- Manipulating pages, documents, frames, and frame trees. +- [MPArch](https://chromium.googlesource.com/chromium/src/+/main/docs/frame_trees.md) + concepts like inner FrameTrees, primary vs non-primary pages. +- How `content` interacts with compositing and input handling. +- Mojo interfaces between `content/browser` and `content/renderer` and/or + `blink/renderer`. +- Security checks (e.g., `ChildProcessSecurityPolicy`). +- [content/public APIs](public/README.md): rules for adding them, common APIs + like `WebContentsObserver`, `ContentBrowserClient`, and `NavigationThrottle`. +- Know that there are `content` embedders beyond //chrome (e.g., Android Webview). +- DEPS rules, what should and should not depend on //content. + +Correspondingly, a top-level `content` OWNER is typically familiar with most of +the following core `content` classes: +- `Render(Frame|FrameProxy|Process|Widget|View)Host` +- `Render(Frame|Widget|Thread)` +- `WebContents` and `WebContentsObserver` +- `FrameTree` and `FrameTreeNode` +- `RenderFrameHostManager` +- `NavigationHandle` and `NavigationRequest`, their ownership and lifetime +- `Page` vs `RenderFrameHost` vs blink's `Document`, + `RenderDocumentHostUserData`/`NavigationHandleUserData`, and associated + lifetime issues. +- `SiteInstance` and `BrowsingInstance`, `SiteInfo` +- `NavigationController`, `NavigationEntry` vs `FrameNavigationEntry` +- `ChildProcessSecurityPolicy` +- `BrowserContext`, `StoragePartition` +- `ContentBrowserClient` + ## Further documentation * [Bluetooth](browser/bluetooth/README.md) +* [content/browser/renderer_host](browser/renderer_host/README.md) +* [Frame trees](https://chromium.googlesource.com/chromium/src/+/main/docs/frame_trees.md) +* [Navigation](https://chromium.googlesource.com/chromium/src/+/main/docs/navigation.md) +* [Process model](https://chromium.googlesource.com/chromium/src/+/main/docs/process_model_and_site_isolation.md) +* [RenderDocument](https://chromium.googlesource.com/chromium/src/+/main/docs/render_document.md) +* [Session history](https://chromium.googlesource.com/chromium/src/+/main/docs/session_history.md)
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index 49dbd33..8c57b88 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -449,8 +449,9 @@ const std::optional<testing::Matcher<std::string>>& id, const std::optional<testing::Matcher<std::string>>& name, const std::optional<testing::Matcher<std::string>>& src, - const std::vector<testing::Matcher<std::string>>& reasons, + const std::vector<BlockingDetailsReasonsMatcher>& reasons, const std::optional<SameOriginMatcher>& same_origin_details) { + // TODO(crbug.com/1523191) Make this matcher display human-friendly messages. return testing::Pointee(testing::AllOf( id.has_value() ? testing::Field( @@ -492,6 +493,7 @@ SameOriginMatcher BackForwardCacheBrowserTest::MatchesSameOriginDetails( const testing::Matcher<std::string>& url, const std::vector<ReasonsMatcher>& children) { + // TODO(crbug.com/1523191) Make this matcher display human-friendly messages. return testing::Pointee(testing::AllOf( testing::Field( "url", &blink::mojom::SameOriginBfcacheNotRestoredDetails::url, url), @@ -501,11 +503,49 @@ testing::ElementsAreArray(children)))); } +BlockingDetailsReasonsMatcher +BackForwardCacheBrowserTest::MatchesDetailedReason( + const testing::Matcher<std::string>& name, + const std::optional<BlockingReasonLocationMatcher>& source) { + // TODO(crbug.com/1523191) Make this matcher display human-friendly + // messages. + return testing::Pointee(testing::AllOf( + testing::Field("name", &blink::mojom::BFCacheBlockingDetailedReason::name, + name), + testing::Field( + "source", &blink::mojom::BFCacheBlockingDetailedReason::source, + source.has_value() + ? source.value() + : testing::Property( + "is_null", + &blink::mojom::BlockingReasonSourceLocationPtr::is_null, + true)))); +} + +BlockingReasonLocationMatcher +BackForwardCacheBrowserTest::MatchesSourceLocation( + const testing::Matcher<std::string>& url, + const testing::Matcher<uint64_t>& line_number, + const testing::Matcher<uint64_t>& column_number) { + // TODO(crbug.com/1523191) Make this matcher display human-friendly + // messages. + return testing::Pointee(testing::AllOf( + testing::Field("url", &blink::mojom::BlockingReasonSourceLocation::url, + url), + testing::Field("line_number", + &blink::mojom::BlockingReasonSourceLocation::line_number, + line_number), + testing::Field("column_number", + &blink::mojom::BlockingReasonSourceLocation::column_number, + column_number))); +} + BlockingDetailsMatcher BackForwardCacheBrowserTest::MatchesBlockingDetails( const std::optional<testing::Matcher<std::string>>& url, const std::optional<testing::Matcher<std::string>>& function_name, const testing::Matcher<uint64_t>& line_number, const testing::Matcher<uint64_t>& column_number) { + // TODO(crbug.com/1523191) Make this matcher display human-friendly messages. return testing::Pointee(testing::AllOf( url.has_value() ? testing::Field("url", &blink::mojom::BlockingDetails::url,
diff --git a/content/browser/back_forward_cache_browsertest.h b/content/browser/back_forward_cache_browsertest.h index 4688e85..09928a5 100644 --- a/content/browser/back_forward_cache_browsertest.h +++ b/content/browser/back_forward_cache_browsertest.h
@@ -36,6 +36,10 @@ const blink::mojom::BackForwardCacheNotRestoredReasonsPtr&>; using SameOriginMatcher = testing::Matcher< const blink::mojom::SameOriginBfcacheNotRestoredDetailsPtr&>; +using BlockingDetailsReasonsMatcher = + testing::Matcher<const blink::mojom::BFCacheBlockingDetailedReasonPtr&>; +using BlockingReasonLocationMatcher = + testing::Matcher<const blink::mojom::BlockingReasonSourceLocationPtr&>; using BlockingDetailsMatcher = testing::Matcher<const blink::mojom::BlockingDetailsPtr&>; @@ -143,12 +147,26 @@ const std::optional<testing::Matcher<std::string>>& id, const std::optional<testing::Matcher<std::string>>& name, const std::optional<testing::Matcher<std::string>>& src, - const std::vector<testing::Matcher<std::string>>& reasons, + const std::vector<BlockingDetailsReasonsMatcher>& reasons, const std::optional<SameOriginMatcher>& same_origin_details); + SameOriginMatcher MatchesSameOriginDetails( const testing::Matcher<std::string>& url, const std::vector<ReasonsMatcher>& children); + // Used in tests that ensure source location is sent to the renderer side from + // the browser one + BlockingDetailsReasonsMatcher MatchesDetailedReason( + const testing::Matcher<std::string>& name, + const std::optional<BlockingReasonLocationMatcher>& source); + + BlockingReasonLocationMatcher MatchesSourceLocation( + const testing::Matcher<std::string>& url, + const testing::Matcher<uint64_t>& line_number, + const testing::Matcher<uint64_t>& column_number); + + // Used in tests that ensure source location is sent to the browser side from + // the renderer one. BlockingDetailsMatcher MatchesBlockingDetails( const std::optional<testing::Matcher<std::string>>& url, const std::optional<testing::Matcher<std::string>>& function_name,
diff --git a/content/browser/back_forward_cache_no_store_browsertest.cc b/content/browser/back_forward_cache_no_store_browsertest.cc index 58cca5e..1cf689a1 100644 --- a/content/browser/back_forward_cache_no_store_browsertest.cc +++ b/content/browser/back_forward_cache_no_store_browsertest.cc
@@ -959,8 +959,11 @@ auto subframe_result = MatchesNotRestoredReasons( /*id=*/"", /*name=*/"", /*src=*/url_a_no_store.spec(), /*reasons=*/ - {"JsNetworkRequestReceivedCacheControlNoStoreResource", - "MainResourceHasCacheControlNoStore"}, + {MatchesDetailedReason( + "JsNetworkRequestReceivedCacheControlNoStoreResource", + /*source=*/std::nullopt), + MatchesDetailedReason("MainResourceHasCacheControlNoStore", + /*source=*/std::nullopt)}, MatchesSameOriginDetails( /*url=*/url_a_no_store.spec(), /*children=*/{})); @@ -968,7 +971,9 @@ current_frame_host()->NotRestoredReasonsForTesting(), MatchesNotRestoredReasons( /*id=*/std::nullopt, /*name=*/std::nullopt, /*src=*/std::nullopt, - /*reasons=*/{"MainResourceHasCacheControlNoStore"}, + /*reasons=*/ + {MatchesDetailedReason("MainResourceHasCacheControlNoStore", + /*source=*/std::nullopt)}, MatchesSameOriginDetails( /*url=*/url_a_no_store.spec(), /*children=*/
diff --git a/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc b/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc index c09ca5c..8da89b5b2 100644 --- a/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc +++ b/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc
@@ -4,6 +4,8 @@ #include "content/browser/back_forward_cache_browsertest.h" +#include <optional> + #include "content/browser/back_forward_cache_test_util.h" #include "content/browser/renderer_host/navigation_request.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -74,7 +76,8 @@ // Expect that NotRestoredReasons are reported. auto rfh_a_result = MatchesNotRestoredReasons( /*id=*/std::nullopt, - /*name=*/std::nullopt, /*src=*/std::nullopt, /*reasons=*/{"Dummy"}, + /*name=*/std::nullopt, /*src=*/std::nullopt, /*reasons=*/ + {MatchesDetailedReason("Dummy", /*source=*/std::nullopt)}, MatchesSameOriginDetails( /*url=*/rfh_a_url, /*children=*/{})); EXPECT_THAT(current_frame_host()->NotRestoredReasonsForTesting(), @@ -134,7 +137,9 @@ // Note that |rfh_a_3| is masked because it's a child of |rfh_b|. auto rfh_b_result = MatchesNotRestoredReasons( /*id=*/"rfh_b_id", /*name=*/"rfh_b_name", - /*src=*/rfh_b_url, /*reasons=*/{"masked"}, std::nullopt); + /*src=*/rfh_b_url, /*reasons=*/ + {MatchesDetailedReason("masked", /*source=*/std::nullopt)}, + /*same_origin_details=*/std::nullopt); auto rfh_a_2_result = MatchesNotRestoredReasons( /*id=*/"rfh_a_2_id", /*name=*/"rfh_a_2_name", @@ -192,18 +197,22 @@ // of null. EXPECT_EQ(true, EvalJs(current_frame_host(), "document.getElementById('child-0').name == ''")); - auto rfh_a_2_result = MatchesNotRestoredReasons(/*id=*/"child-0", /*name=*/"", - /*src=*/rfh_a_2_url, - /*reasons=*/{"Dummy"}, - MatchesSameOriginDetails( - /*url=*/rfh_a_2_url, - /*children=*/{})); - auto rfh_a_4_result = MatchesNotRestoredReasons(/*id=*/"child-0", /*name=*/"", - /*src=*/rfh_a_4_url, - /*reasons=*/{"Dummy"}, - MatchesSameOriginDetails( - /*url=*/rfh_a_4_url, - /*children=*/{})); + auto rfh_a_2_result = MatchesNotRestoredReasons( + /*id=*/"child-0", /*name=*/"", + /*src=*/rfh_a_2_url, + /*reasons=*/ + {MatchesDetailedReason("Dummy", /*source=*/std::nullopt)}, + MatchesSameOriginDetails( + /*url=*/rfh_a_2_url, + /*children=*/{})); + auto rfh_a_4_result = MatchesNotRestoredReasons( + /*id=*/"child-0", /*name=*/"", + /*src=*/rfh_a_4_url, + /*reasons=*/ + {MatchesDetailedReason("Dummy", /*source=*/std::nullopt)}, + MatchesSameOriginDetails( + /*url=*/rfh_a_4_url, + /*children=*/{})); EXPECT_EQ(true, EvalJs(current_frame_host(), "document.getElementById('child-1').name == ''")); auto rfh_a_3_result = MatchesNotRestoredReasons( @@ -217,7 +226,8 @@ auto rfh_a_1_result = MatchesNotRestoredReasons( /*id=*/std::nullopt, /*name=*/std::nullopt, /*src=*/std::nullopt, - /*reasons=*/{"Dummy"}, + /*reasons=*/ + {MatchesDetailedReason("Dummy", /*source=*/std::nullopt)}, MatchesSameOriginDetails( /*url=*/rfh_a_1_url, /*children=*/{rfh_a_2_result, rfh_a_3_result})); @@ -322,7 +332,10 @@ auto rfh_a_result = MatchesNotRestoredReasons( /*id=*/std::nullopt, /*name=*/std::nullopt, /*src=*/std::nullopt, - /*reasons=*/{"Related active contents", "internal-error"}, + /*reasons=*/ + {MatchesDetailedReason("Related active contents", + /*source=*/std::nullopt), + MatchesDetailedReason("internal-error", /*source=*/std::nullopt)}, MatchesSameOriginDetails( /*url=*/rfh_a_url, /*children=*/{})); @@ -370,13 +383,14 @@ auto reasons = navigation_request->commit_params().not_restored_reasons.Clone(); // The reasons have not been reset yet. - auto rfh_a_result = - MatchesNotRestoredReasons(/*id=*/std::nullopt, /*name=*/std::nullopt, - /*src=*/std::nullopt, - /*reasons=*/{"JavaScript execution"}, - MatchesSameOriginDetails( - /*url=*/url_a_redirect.spec(), - /*children=*/{})); + auto rfh_a_result = MatchesNotRestoredReasons( + /*id=*/std::nullopt, /*name=*/std::nullopt, + /*src=*/std::nullopt, + /*reasons=*/ + {MatchesDetailedReason("JavaScript execution", /*source=*/std::nullopt)}, + MatchesSameOriginDetails( + /*url=*/url_a_redirect.spec(), + /*children=*/{})); EXPECT_THAT(reasons, rfh_a_result); @@ -427,14 +441,16 @@ // Blocking reasons should be recorded. ExpectNotRestored({NotRestoredReason::kBlocklistedFeatures}, {kBlockingReasonEnum}, {}, {}, {}, FROM_HERE); - // Expect that NotRestoredReasons are reported. - auto rfh_a_result = - MatchesNotRestoredReasons(/*id=*/std::nullopt, /*name=*/std::nullopt, - /*src=*/std::nullopt, - /*reasons=*/{kBlockingReasonString}, - MatchesSameOriginDetails( - /*url=*/url_a.spec(), - /*children=*/{})); + // Expect that NotRestoredReasons and the blocking feature's source location + // are reported. + auto rfh_a_result = MatchesNotRestoredReasons( + /*id=*/std::nullopt, /*name=*/std::nullopt, + /*src=*/std::nullopt, + /*reasons=*/ + {MatchesDetailedReason(kBlockingReasonString, /*source=*/std::nullopt)}, + MatchesSameOriginDetails( + /*url=*/url_a.spec(), + /*children=*/{})); EXPECT_THAT(current_frame_host()->NotRestoredReasonsForTesting(), rfh_a_result); @@ -503,7 +519,8 @@ /*same_origin_details=*/std::nullopt); auto rfh_a_result = MatchesNotRestoredReasons( /*id=*/std::nullopt, - /*name=*/std::nullopt, /*src=*/std::nullopt, /*reasons=*/{"masked"}, + /*name=*/std::nullopt, /*src=*/std::nullopt, /*reasons=*/ + {MatchesDetailedReason("masked", /*source=*/std::nullopt)}, MatchesSameOriginDetails( /*url=*/rfh_a_url, /*children=*/{rfh_a_1_result, rfh_a_2_result}));
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index 9499be2f..a1a576d 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -51,6 +51,7 @@ #include "services/metrics/public/cpp/ukm_source_id.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h" +#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom.h" #include "third_party/blink/public/mojom/frame/sudden_termination_disabler_type.mojom-shared.h" #if BUILDFLAG(IS_ANDROID) #include "content/public/browser/android/child_process_importance.h" @@ -1786,18 +1787,31 @@ blink::mojom::SameOriginBfcacheNotRestoredDetails::New(); not_restored_reasons->same_origin_details->url = url_.spec(); // Populate the reasons for same-origin frames. - not_restored_reasons->reasons = GetDocumentResult().GetStringReasons(); + for (auto& name : GetDocumentResult().GetStringReasons()) { + blink::mojom::BFCacheBlockingDetailedReasonPtr reason = + blink::mojom::BFCacheBlockingDetailedReason::New(); + reason->name = name; + not_restored_reasons->reasons.push_back(std::move(reason)); + } if (is_root_outermost_main_frame_) { int index_copy = exposed_cross_origin_iframe_index; + bool no_masked_reason = + std::find_if( + not_restored_reasons->reasons.begin(), + not_restored_reasons->reasons.end(), + [](const blink::mojom::BFCacheBlockingDetailedReasonPtr& reason) { + return reason->name == "masked"; + }) == not_restored_reasons->reasons.end(); if (HasUnexposedCrossOriginBlockingIframe(index_copy) && - std::find(not_restored_reasons->reasons.begin(), - not_restored_reasons->reasons.end(), - "masked") == not_restored_reasons->reasons.end()) { + no_masked_reason) { // If any cross-origin iframe is blocking and does not have "masked" in // its own reasons, we need to add "masked" to the outermost main // frame's reasons. Note that we need to add "masked" only when the // reasons do not have it yet. - not_restored_reasons->reasons.push_back("masked"); + blink::mojom::BFCacheBlockingDetailedReasonPtr masked_reason = + blink::mojom::BFCacheBlockingDetailedReason::New(); + masked_reason->name = "masked"; + not_restored_reasons->reasons.push_back(std::move(masked_reason)); } } for (const auto& subtree : GetChildren()) { @@ -1815,7 +1829,10 @@ // Note that we need to flatten the tree in order to check the eligibility // of the cross-origin subtree. Add "masked" to this frame to signal that // this is the blocking frame. - not_restored_reasons->reasons.push_back("masked"); + blink::mojom::BFCacheBlockingDetailedReasonPtr masked_reason = + blink::mojom::BFCacheBlockingDetailedReason::New(); + masked_reason->name = "masked"; + not_restored_reasons->reasons.push_back(std::move(masked_reason)); } // Decrease the index now that we saw a cross-origin iframe. exposed_cross_origin_iframe_index--;
diff --git a/content/browser/renderer_host/back_forward_cache_impl_unittest.cc b/content/browser/renderer_host/back_forward_cache_impl_unittest.cc index fc913c43..44fa1e1 100644 --- a/content/browser/renderer_host/back_forward_cache_impl_unittest.cc +++ b/content/browser/renderer_host/back_forward_cache_impl_unittest.cc
@@ -82,7 +82,8 @@ auto result = tree_root->GetWebExposedNotRestoredReasonsInternal(index); // Main frame has "masked" as a reason. EXPECT_EQ(static_cast<int>(result->reasons.size()), 1); - EXPECT_EQ(result->reasons[0], "masked"); + EXPECT_EQ(result->reasons[0]->name, "masked"); + EXPECT_FALSE(result->reasons[0]->source); // b-1 is masked. EXPECT_TRUE(result->same_origin_details->children[0]->reasons.empty()); @@ -115,7 +116,8 @@ auto result = tree_root->GetWebExposedNotRestoredReasonsInternal(index); // Main frame has "masked" as a reason. EXPECT_EQ(static_cast<int>(result->reasons.size()), 1); - EXPECT_EQ(result->reasons[0], "masked"); + EXPECT_EQ(result->reasons[0]->name, "masked"); + EXPECT_FALSE(result->reasons[0]->source); // b-1 is unmasked, but reasons are empty because it does not have any // blocking reasons. EXPECT_TRUE(result->same_origin_details->children[0]->reasons.empty()); @@ -134,7 +136,8 @@ auto result = tree_root->GetWebExposedNotRestoredReasonsInternal(index); // Main frame has "masked" as a reason. EXPECT_EQ(static_cast<int>(result->reasons.size()), 1); - EXPECT_EQ(result->reasons[0], "masked"); + EXPECT_EQ(result->reasons[0]->name, "masked"); + EXPECT_FALSE(result->reasons[0]->source); // b-1 is masked. EXPECT_TRUE(result->same_origin_details->children[0]->reasons.empty()); @@ -143,10 +146,11 @@ ->same_origin_details->children[0] ->reasons.size()), 1); - EXPECT_EQ(result->same_origin_details->children[1] - ->same_origin_details->children[0] - ->reasons[0], - "masked"); + auto& reason = result->same_origin_details->children[1] + ->same_origin_details->children[0] + ->reasons[0]; + EXPECT_EQ(reason->name, "masked"); + EXPECT_FALSE(result->reasons[0]->source); // b-4 is masked. EXPECT_TRUE(result->same_origin_details->children[2]->reasons.empty()); }
diff --git a/content/common/service_worker/race_network_request_url_loader_client.cc b/content/common/service_worker/race_network_request_url_loader_client.cc index 1d7d2e0..35efb9bd 100644 --- a/content/common/service_worker/race_network_request_url_loader_client.cc +++ b/content/common/service_worker/race_network_request_url_loader_client.cc
@@ -18,6 +18,7 @@ #include "mojo/public/c/system/data_pipe.h" #include "net/http/http_status_code.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/header_util.h" #include "services/network/public/cpp/record_ontransfersizeupdate_utils.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" @@ -256,14 +257,14 @@ case FetchResponseFrom::kSubresourceLoaderIsHandlingRedirect: // If the fetch handler result is a fallback, commit the // RaceNetworkRequest response. If the result is not a fallback and the - // response is not 200, use the other response from the fetch handler - // instead because it may have a response from the cache. + // response is not ok status, use the other response from the fetch + // handler instead because it may have a response from the cache. // TODO(crbug.com/1420517): More comprehensive error handling may be // needed, especially the case when HTTP cache hit or redirect happened. // // When the AutoPreload is enabled, RaceNetworkRequest works just for the // dedupe purpose. The fetch handler should always commit the response. - if (head_->headers->response_code() != net::HttpStatusCode::HTTP_OK) { + if (!network::IsSuccessfulStatus(head_->headers->response_code())) { owner_->SetCommitResponsibility(FetchResponseFrom::kServiceWorker); } else { owner_->SetCommitResponsibility( @@ -658,8 +659,14 @@ uint32_t buffer_num_bytes = 0; base::span<const char> read_buffer; MojoResult result = body_->BeginReadData(&buffer, &buffer_num_bytes, - MOJO_READ_DATA_FLAG_NONE); + MOJO_BEGIN_READ_DATA_FLAG_NONE); if (result == MOJO_RESULT_OK) { + SCOPED_CRASH_KEY_NUMBER("SWRace", "num_bytes_read_buffer", + buffer_num_bytes); + volatile const char* buffer_v = static_cast<volatile const char*>(buffer); + for (size_t i = 0; i < buffer_num_bytes; ++i) { + buffer_v[i]; + } read_buffer = base::make_span(static_cast<const char*>(buffer), buffer_num_bytes); }
diff --git a/content/renderer/media/renderer_web_media_player_delegate.cc b/content/renderer/media/renderer_web_media_player_delegate.cc index 7339726..19dcac3 100644 --- a/content/renderer/media/renderer_web_media_player_delegate.cc +++ b/content/renderer/media/renderer_web_media_player_delegate.cc
@@ -258,7 +258,7 @@ if (!pending_update_task_) { base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(&RendererWebMediaPlayerDelegate::UpdateTask, - AsWeakPtr())); + weak_ptr_factory_.GetWeakPtr())); pending_update_task_ = true; } }
diff --git a/content/renderer/media/renderer_web_media_player_delegate.h b/content/renderer/media/renderer_web_media_player_delegate.h index 2d5b403..b9e86944 100644 --- a/content/renderer/media/renderer_web_media_player_delegate.h +++ b/content/renderer/media/renderer_web_media_player_delegate.h
@@ -32,11 +32,10 @@ // Standard implementation of WebMediaPlayerDelegate; communicates state to // the MediaPlayerDelegateHost. -class CONTENT_EXPORT RendererWebMediaPlayerDelegate +class CONTENT_EXPORT RendererWebMediaPlayerDelegate final : public content::RenderFrameObserver, public blink::WebViewObserver, - public blink::WebMediaPlayerDelegate, - public base::SupportsWeakPtr<RendererWebMediaPlayerDelegate> { + public blink::WebMediaPlayerDelegate { public: explicit RendererWebMediaPlayerDelegate(content::RenderFrame* render_frame); @@ -152,6 +151,8 @@ // Last page shown/hidden state sent to the player. Unset if we have not sent // any message. Used to elide duplicates. std::optional<bool> is_shown_; + + base::WeakPtrFactory<RendererWebMediaPlayerDelegate> weak_ptr_factory_{this}; }; } // namespace media
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test.py b/content/test/gpu/gpu_tests/gpu_integration_test.py index 390db90..d882dd9 100644 --- a/content/test/gpu/gpu_tests/gpu_integration_test.py +++ b/content/test/gpu/gpu_tests/gpu_integration_test.py
@@ -126,6 +126,10 @@ # workaround. See crbug.com/1079244. _first_run_test: Optional[str] = None + # Keeps track of whether this is the first browser start on a shard for a + # flakiness workaround. See crbug.com/323927831. + _is_first_browser_start = True + tab: Optional[ct.Tab] = None def __init__(self, *args, **kwargs): @@ -540,15 +544,11 @@ if os_name == 'android': cls.browser.platform.android_action_runner.TurnScreenOn() + # pylint: disable=no-self-use def _ShouldForceRetryOnFailureFirstTest(self) -> bool: - # TODO(crbug.com/323927831): Remove this once the flaky crashes on certain - # Mac machines go away. - try: - retry_on_ventura = 'ventura' in self.GetPlatformTags(self.browser) - except Exception: # pylint: disable=broad-except - logging.warning('Failed to determine if running on Ventura, assuming no') - retry_on_ventura = False - return retry_on_ventura + return False + + # pylint: enable=no-self-use def _DetermineFirstTestRetryWorkaround(self, test_name: str) -> bool: """Potentially allows retries for the first test run on a shard. @@ -574,6 +574,21 @@ return False # pylint: disable=no-self-use + def _DetermineFirstBrowserStartWorkaround(self) -> bool: + """Potentially allows retries for the first browser start on a shard. + + This is a temporary workaround for crbug.com/323927831 and should be + removed once the root cause is fixed. + """ + # The browser is assumed to be dead at this point, so we can't rely on + # GetPlatformTags() to restrict this to the flaking Mac configs. + if not GpuIntegrationTest._is_first_browser_start: + return False + return sys.platform == 'darwin' + + # pylint: enable=no-self-use + + # pylint: disable=no-self-use def _DetermineRetryWorkaround(self, exception: Exception) -> bool: """Potentially allows retries depending on the exception type. @@ -1013,7 +1028,17 @@ return cls._original_finder_options def setUp(self) -> None: - self._EnsureTabIsAvailable() + # TODO(crbug.com/323927831): Remove this try/except logic once the root + # cause of flakes on Macs is resolved. + try: + self._EnsureTabIsAvailable() + except Exception: # pylint: disable=broad-except + if self._DetermineFirstBrowserStartWorkaround(): + self._EnsureTabIsAvailable() + else: + raise + finally: + GpuIntegrationTest._is_first_browser_start = False # Append overlay support for extra Intel GPUs when the extra device id is # current active GPU's device id
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index c232cdb..f59da7b 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -317,6 +317,9 @@ # Causes the render process to hang crbug.com/1280692 [ fuchsia web-engine-shell ] conformance/context/context-creation-and-destruction.html [ Skip ] +# Crashes on fuchsia-fyi-sherlock-qemu +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 passthrough ] WebglExtension_EXT_texture_mirror_clamp_to_edge [ Skip ] + # Linux Intel # Can occasionally kill machines. Appears to be tied to kernel version, so can # be removed once upgraded to kernel 5.4.0-77 or later. @@ -456,6 +459,30 @@ # Anti-aliasing disabled on Fuchsia [ fuchsia ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ] +# Failures on fuchsia-fyi-sherlock-qemu +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/extensions/oes-texture-float-linear.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/extensions/oes-texture-float-with-canvas.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/glsl/samplers/glsl-function-texture2dproj.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/glsl/samplers/glsl-function-texture2dprojlod.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/tex-video-using-tex-unit-non-zero.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/texparameter-test.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/texture-npot.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/gl-teximage.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/texture-active-bind-2.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/texture-active-bind.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/canvas/tex-2d-alpha-alpha-unsigned_byte.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/canvas-teximage-after-multiple-drawimages.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/texture-srgb-upload.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/rendering/line-loop-tri-fan.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/rendering/line-rendering-quality.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/extensions/webgl-polygon-mode.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/rendering/more-than-65536-indices.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ Failure ] +crbug.com/1490427 [ fuchsia fuchsia-board-qemu-x64 ] conformance/textures/misc/texture-video-transparent.html [ Failure ] + #################### # Win failures # ####################
diff --git a/docs/website b/docs/website index ac76949..7854b9d 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit ac769493150a27e6a4dc32da747c9613496a9e87 +Subproject commit 7854b9d90b9fb1e57c50e6f039bc44fa587a9eca
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index b6afb48..f5362e9 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn
@@ -316,9 +316,8 @@ if (!is_android) { sources += [ + "abstract_texture.cc", "abstract_texture.h", - "passthrough_abstract_texture_impl.cc", - "passthrough_abstract_texture_impl.h", ] } else { sources += [
diff --git a/gpu/command_buffer/service/passthrough_abstract_texture_impl.cc b/gpu/command_buffer/service/abstract_texture.cc similarity index 74% rename from gpu/command_buffer/service/passthrough_abstract_texture_impl.cc rename to gpu/command_buffer/service/abstract_texture.cc index 65806587..f25b3bb 100644 --- a/gpu/command_buffer/service/passthrough_abstract_texture_impl.cc +++ b/gpu/command_buffer/service/abstract_texture.cc
@@ -8,23 +8,23 @@ #include "gpu/command_buffer/service/abstract_texture.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/error_state.h" -#include "gpu/command_buffer/service/passthrough_abstract_texture_impl.h" #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_context.h" #include "ui/gl/scoped_binders.h" #include "ui/gl/scoped_make_current.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h" namespace gpu { namespace gles2 { -PassthroughAbstractTextureImpl::PassthroughAbstractTextureImpl( +AbstractTexture::AbstractTexture( scoped_refptr<TexturePassthrough> texture_passthrough, GLES2DecoderPassthroughImpl* decoder) : texture_passthrough_(std::move(texture_passthrough)), gl_api_(decoder->api()), decoder_(decoder) {} -PassthroughAbstractTextureImpl::~PassthroughAbstractTextureImpl() { +AbstractTexture::~AbstractTexture() { if (cleanup_cb_) { DCHECK(texture_passthrough_); std::move(cleanup_cb_).Run(this); @@ -35,11 +35,11 @@ DCHECK(!texture_passthrough_); } -TextureBase* PassthroughAbstractTextureImpl::GetTextureBase() const { +TextureBase* AbstractTexture::GetTextureBase() const { return texture_passthrough_.get(); } -void PassthroughAbstractTextureImpl::SetParameteri(GLenum pname, GLint param) { +void AbstractTexture::SetParameteri(GLenum pname, GLint param) { if (!texture_passthrough_) return; @@ -47,20 +47,20 @@ gl_api_->glTexParameteriFn(texture_passthrough_->target(), pname, param); } -void PassthroughAbstractTextureImpl::SetCleared() { +void AbstractTexture::SetCleared() { // The passthrough decoder has no notion of 'cleared', so do nothing. } -void PassthroughAbstractTextureImpl::SetCleanupCallback(CleanupCallback cb) { +void AbstractTexture::SetCleanupCallback(CleanupCallback cb) { cleanup_cb_ = std::move(cb); } -void PassthroughAbstractTextureImpl::NotifyOnContextLost() { +void AbstractTexture::NotifyOnContextLost() { NOTIMPLEMENTED(); } scoped_refptr<TexturePassthrough> -PassthroughAbstractTextureImpl::OnDecoderWillDestroy() { +AbstractTexture::OnDecoderWillDestroy() { // Make sure that destruction_cb_ does nothing when destroyed, since // the DecoderContext is invalid. Also null out invalid pointer. DCHECK(texture_passthrough_);
diff --git a/gpu/command_buffer/service/abstract_texture.h b/gpu/command_buffer/service/abstract_texture.h index 0888b488..39c07a8 100644 --- a/gpu/command_buffer/service/abstract_texture.h +++ b/gpu/command_buffer/service/abstract_texture.h
@@ -6,8 +6,11 @@ #define GPU_COMMAND_BUFFER_SERVICE_ABSTRACT_TEXTURE_H_ #include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" #include "build/build_config.h" #include "gpu/command_buffer/service/texture_base.h" +#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/gpu_gles2_export.h" // Forwardly declare a few GL types to avoid including GL header files. @@ -20,6 +23,8 @@ namespace gles2 { +class GLES2DecoderPassthroughImpl; + // An AbstractTexture enables access to GL textures from the GPU process, for // things that set up textures using some client's decoder. Creating an // AbstractTexture is similar to "glGenTexture", and deleting it is similar to @@ -41,21 +46,24 @@ public: using CleanupCallback = base::OnceCallback<void(AbstractTexture*)>; + AbstractTexture(scoped_refptr<TexturePassthrough> texture_passthrough, + GLES2DecoderPassthroughImpl* decoder); + // The texture is guaranteed to be around while |this| exists, as long as // the decoder isn't destroyed / context isn't lost. - virtual ~AbstractTexture() = default; + ~AbstractTexture(); // Return our TextureBase, useful mostly for creating a mailbox. This may // return null if the texture has been destroyed. - virtual TextureBase* GetTextureBase() const = 0; + TextureBase* GetTextureBase() const; // Set a texture parameter. The GL context must be current. - virtual void SetParameteri(GLenum pname, GLint param) = 0; + void SetParameteri(GLenum pname, GLint param); // Marks the texture as cleared, to help prevent sending an uninitialized // texture to the (untrusted) renderer. One should call this only when one // has actually initialized the texture. - virtual void SetCleared() = 0; + void SetCleared(); // Set a callback that will be called when the AbstractTexture is going to // drop its reference to the underlying TextureBase. We can't guarantee that @@ -64,12 +72,21 @@ // AbstractTexture is destroyed, or when our stub is destroyed. Do not change // the current context during this callback. Also, do not assume that one // has a current context. - virtual void SetCleanupCallback(CleanupCallback cleanup_callback) = 0; + void SetCleanupCallback(CleanupCallback cleanup_callback); // Used to notify the AbstractTexture if the context is lost. - virtual void NotifyOnContextLost() = 0; + void NotifyOnContextLost(); unsigned int service_id() const { return GetTextureBase()->service_id(); } + + // Called when our decoder is going away, so that we can try to clean up. + scoped_refptr<TexturePassthrough> OnDecoderWillDestroy(); + + private: + scoped_refptr<TexturePassthrough> texture_passthrough_; + raw_ptr<gl::GLApi> gl_api_; + raw_ptr<GLES2DecoderPassthroughImpl> decoder_; + CleanupCallback cleanup_cb_; }; } // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index dc6a6f1..23d249bd 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -14,6 +14,7 @@ #include "base/ranges/algorithm.h" #include "base/strings/string_split.h" #include "build/build_config.h" +#include "gpu/command_buffer/service/abstract_texture.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/decoder_client.h" #include "gpu/command_buffer/service/feature_info.h" @@ -1104,7 +1105,7 @@ #if !BUILDFLAG(IS_ANDROID) if (resources_) { // Initialize may not have been called yet. - for (PassthroughAbstractTextureImpl* iter : abstract_textures_) { + for (AbstractTexture* iter : abstract_textures_) { resources_->textures_pending_destruction.insert( iter->OnDecoderWillDestroy()); } @@ -1648,15 +1649,15 @@ new TexturePassthrough(service_id, target)); // Unretained is safe, because of the destruction cb. - std::unique_ptr<PassthroughAbstractTextureImpl> abstract_texture = - std::make_unique<PassthroughAbstractTextureImpl>(texture, this); + std::unique_ptr<AbstractTexture> abstract_texture = + std::make_unique<AbstractTexture>(texture, this); abstract_textures_.insert(abstract_texture.get()); return abstract_texture; } void GLES2DecoderPassthroughImpl::OnAbstractTextureDestroyed( - PassthroughAbstractTextureImpl* abstract_texture, + AbstractTexture* abstract_texture, scoped_refptr<TexturePassthrough> texture) { DCHECK(texture); abstract_textures_.erase(abstract_texture);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index 51a3214..ecf5445 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -38,10 +38,6 @@ #include "ui/gl/gl_surface.h" #include "ui/gl/gpu_switching_observer.h" -#if !BUILDFLAG(IS_ANDROID) -#include "gpu/command_buffer/service/passthrough_abstract_texture_impl.h" -#endif - namespace gl { class GLFence; class ProgressReporter; @@ -54,7 +50,7 @@ class ContextGroup; class GPUTracer; -class PassthroughAbstractTextureImpl; +class AbstractTexture; class MultiDrawManager; class GLES2DecoderPassthroughImpl; class GLES2ExternalFramebuffer; @@ -404,7 +400,7 @@ CopyTexImageResourceManager* copy_tex_image_blit) override; #if !BUILDFLAG(IS_ANDROID) - void OnAbstractTextureDestroyed(PassthroughAbstractTextureImpl*, + void OnAbstractTextureDestroyed(AbstractTexture*, scoped_refptr<TexturePassthrough>); #endif @@ -524,9 +520,9 @@ bool OnlyHasPendingProgramCompletionQueries(); #if !BUILDFLAG(IS_ANDROID) - // A set of raw pointers to currently living PassthroughAbstractTextures + // A set of raw pointers to currently living AbstractTextures // which allow us to properly signal to them when we are destroyed. - base::flat_set<PassthroughAbstractTextureImpl*> abstract_textures_; + base::flat_set<AbstractTexture*> abstract_textures_; #endif int commands_to_process_;
diff --git a/gpu/command_buffer/service/passthrough_abstract_texture_impl.h b/gpu/command_buffer/service/passthrough_abstract_texture_impl.h deleted file mode 100644 index 4fe2777..0000000 --- a/gpu/command_buffer/service/passthrough_abstract_texture_impl.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_PASSTHROUGH_ABSTRACT_TEXTURE_IMPL_H_ -#define GPU_COMMAND_BUFFER_SERVICE_PASSTHROUGH_ABSTRACT_TEXTURE_IMPL_H_ - -#include "base/memory/raw_ptr.h" -#include "build/build_config.h" -#include "gpu/command_buffer/service/abstract_texture.h" -#include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h" - -#include "base/functional/callback.h" -#include "base/memory/scoped_refptr.h" -#include "gpu/command_buffer/service/texture_manager.h" - -namespace gpu { -namespace gles2 { - -class TexturePassthrough; -class GLES2DecoderPassthroughImpl; - -// Implementation of AbstractTexture used by the passthrough command decoder. -class GPU_GLES2_EXPORT PassthroughAbstractTextureImpl : public AbstractTexture { - public: - PassthroughAbstractTextureImpl( - scoped_refptr<TexturePassthrough> texture_passthrough, - GLES2DecoderPassthroughImpl* decoder); - ~PassthroughAbstractTextureImpl() override; - - // AbstractTexture - TextureBase* GetTextureBase() const override; - void SetParameteri(GLenum pname, GLint param) override; - - void SetCleared() override; - void SetCleanupCallback(CleanupCallback cb) override; - void NotifyOnContextLost() override; - - // Called when our decoder is going away, so that we can try to clean up. - scoped_refptr<TexturePassthrough> OnDecoderWillDestroy(); - - private: - scoped_refptr<TexturePassthrough> texture_passthrough_; - raw_ptr<gl::GLApi> gl_api_; - raw_ptr<GLES2DecoderPassthroughImpl> decoder_; - CleanupCallback cleanup_cb_; -}; - -} // namespace gles2 -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_PASSTHROUGH_ABSTRACT_TEXTURE_IMPL_H_
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/gpu/command_buffer/service/raster_decoder_unittest_base.cc index 6723ae82..de4ed2a 100644 --- a/gpu/command_buffer/service/raster_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -111,6 +111,9 @@ // in turn initialize FeatureInfo, which needs a context to determine // extension support. context_ = new StrictMock<GLContextMock>(); + // The stub ctx needs to be initialized so that the gl::GLContext can + // store the offscreen stub |surface|. + context_->Initialize(surface_.get(), {}); context_->SetExtensionsString(all_extensions.c_str()); context_->SetGLVersionString(init.gl_version.c_str());
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc index d8b78ad49..a03fd2f4 100644 --- a/gpu/command_buffer/service/shared_context_state.cc +++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -220,7 +220,6 @@ share_group_(std::move(share_group)), context_(context), real_context_(std::move(context)), - surface_(std::move(surface)), sk_surface_cache_(MaxNumSkSurface()) { if (gr_context_type_ == GrContextType::kVulkan) { if (vk_context_provider_) { @@ -231,6 +230,11 @@ } } + DCHECK(context_ && surface && context_->default_surface()); + // |this| no longer stores the |surface| as that one must be stored by the + // context. Do a sanity check that it is true. + DCHECK(context_->default_surface() == surface); + if (base::SingleThreadTaskRunner::HasCurrentDefault()) { base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( this, "SharedContextState", @@ -274,15 +278,7 @@ // current, or the GrContext was already abandoned if the GLContext was lost. owned_gr_context_.reset(); - // |surface_| needs to be destroyed while there is a current GL context if - // using GL, as some implementations make calls to the GL bindings. Any such - // implementations will themselves ensure that the context is current in their - // destructor (we cannot blindly make the context current here, as there are - // other implementations that crash if the context is made current at this - // point :\). However, we drop our reference to |surface_| before releasing - // the context below so that the release has the intended effect. last_current_surface_ = nullptr; - surface_.reset(); if (context_->IsCurrent(nullptr)) context_->ReleaseCurrent(nullptr); @@ -567,7 +563,7 @@ auto virtual_context = base::MakeRefCounted<GLContextVirtual>( share_group_.get(), real_context_.get(), weak_ptr_factory_.GetWeakPtr()); - if (!virtual_context->Initialize(surface_.get(), gl::GLContextAttribs())) { + if (!virtual_context->Initialize(surface(), gl::GLContextAttribs())) { LOG(ERROR) << "SharedContextState::InitializeGL failure Initialize " "virtual context failed"; feature_info_ = nullptr; @@ -646,8 +642,9 @@ const bool using_gl = GrContextIsGL() || needs_gl; if (using_gl) { - gl::GLSurface* dont_care_surface = - last_current_surface_ ? last_current_surface_.get() : surface_.get(); + gl::GLSurface* dont_care_surface = last_current_surface_ + ? last_current_surface_.get() + : context_->default_surface(); surface = surface ? surface : dont_care_surface; if (!context_->MakeCurrent(surface)) { @@ -831,8 +828,14 @@ } } +gl::GLSurface* SharedContextState::surface() const { + return context_->default_surface(); +} + gl::GLDisplay* SharedContextState::display() { - return surface_.get()->GetGLDisplay(); + auto* gl_surface = surface(); + DCHECK(gl_surface); + return gl_surface->GetGLDisplay(); } bool SharedContextState::initialized() const {
diff --git a/gpu/command_buffer/service/shared_context_state.h b/gpu/command_buffer/service/shared_context_state.h index e57deab..a885986 100644 --- a/gpu/command_buffer/service/shared_context_state.h +++ b/gpu/command_buffer/service/shared_context_state.h
@@ -146,7 +146,7 @@ gl::GLShareGroup* share_group() const { return share_group_.get(); } gl::GLContext* context() const { return context_.get(); } gl::GLContext* real_context() const { return real_context_.get(); } - gl::GLSurface* surface() const { return surface_.get(); } + gl::GLSurface* surface() const; gl::GLDisplay* display(); // non const since it calls GLSurface::GetGLDisplay viz::VulkanContextProvider* vk_context_provider() const { return vk_context_provider_; @@ -378,7 +378,6 @@ scoped_refptr<gl::GLShareGroup> share_group_; scoped_refptr<gl::GLContext> context_; scoped_refptr<gl::GLContext> real_context_; - scoped_refptr<gl::GLSurface> surface_; // Most recent surface that this ShareContextState was made current with. // Avoids a call to MakeCurrent with a different surface, if we don't
diff --git a/gpu/command_buffer/service/shared_context_state_unittest.cc b/gpu/command_buffer/service/shared_context_state_unittest.cc index e3782e34..dd4bd29 100644 --- a/gpu/command_buffer/service/shared_context_state_unittest.cc +++ b/gpu/command_buffer/service/shared_context_state_unittest.cc
@@ -58,6 +58,9 @@ context->SetGLVersionString(gl_version); const char gl_extensions[] = "GL_KHR_robustness"; context->SetExtensionsString(gl_extensions); + // The stub ctx needs to be initialized so that the gl::GLContext can + // store the offscreen stub |surface|. + context->Initialize(surface.get(), {}); context->MakeCurrent(surface.get());
diff --git a/infra/config/generated/builders/try/linux_chromium_asan_siso_rel_ng-compilator/properties.json b/infra/config/generated/builders/try/linux_chromium_asan_siso_rel_ng-compilator/properties.json index 640ab37..16d87763 100644 --- a/infra/config/generated/builders/try/linux_chromium_asan_siso_rel_ng-compilator/properties.json +++ b/infra/config/generated/builders/try/linux_chromium_asan_siso_rel_ng-compilator/properties.json
@@ -92,7 +92,8 @@ }, "$build/siso": { "configs": [ - "builder" + "builder", + "remote-library-link" ], "enable_cloud_profiler": true, "enable_cloud_trace": true,
diff --git a/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json b/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json index 9fe19e5d..c972589a 100644 --- a/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json +++ b/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json
@@ -90,7 +90,8 @@ }, "$build/siso": { "configs": [ - "builder" + "builder", + "remote-library-link" ], "enable_cloud_profiler": true, "enable_cloud_trace": true,
diff --git a/infra/config/generated/builders/try/linux_chromium_tsan_siso_rel_ng-compilator/properties.json b/infra/config/generated/builders/try/linux_chromium_tsan_siso_rel_ng-compilator/properties.json index b527551..95ad3eb 100644 --- a/infra/config/generated/builders/try/linux_chromium_tsan_siso_rel_ng-compilator/properties.json +++ b/infra/config/generated/builders/try/linux_chromium_tsan_siso_rel_ng-compilator/properties.json
@@ -90,7 +90,8 @@ }, "$build/siso": { "configs": [ - "builder" + "builder", + "remote-library-link" ], "enable_cloud_profiler": true, "enable_cloud_trace": true,
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index fcb45b7d..b2b0664f 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -602,7 +602,8 @@ ' },' ' "$build/siso": {' ' "configs": [' - ' "builder"' + ' "builder",' + ' "remote-library-link"' ' ],' ' "enable_cloud_profiler": true,' ' "enable_cloud_trace": true,' @@ -1119,7 +1120,9 @@ ' "scandeps_server": true' ' },' ' "$build/siso": {' - ' "configs": [],' + ' "configs": [' + ' "remote-library-link"' + ' ],' ' "enable_cloud_profiler": true,' ' "enable_cloud_trace": true,' ' "experiments": [],' @@ -1379,7 +1382,8 @@ ' },' ' "$build/siso": {' ' "configs": [' - ' "builder"' + ' "builder",' + ' "remote-library-link"' ' ],' ' "enable_cloud_profiler": true,' ' "enable_cloud_trace": true,' @@ -74932,7 +74936,8 @@ ' },' ' "$build/siso": {' ' "configs": [' - ' "builder"' + ' "builder",' + ' "remote-library-link"' ' ],' ' "enable_cloud_profiler": true,' ' "enable_cloud_trace": true,'
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index fab1872..f4ef9ab9 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -307,32 +307,32 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 123.0.6287.0', + 'description': 'Run with ash-chrome version 123.0.6288.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6287.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.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.6287.0', - 'revision': 'version:123.0.6287.0', + 'location': 'lacros_version_skew_tests_v123.0.6288.0', + 'revision': 'version:123.0.6288.0', }, ], }, }, 'LACROS_VERSION_SKEW_DEV': { 'identifier': 'Lacros version skew testing ash dev', - 'description': 'Run with ash-chrome version 122.0.6241.0', + 'description': 'Run with ash-chrome version 123.0.6276.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6241.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v122.0.6241.0', - 'revision': 'version:122.0.6241.0', + 'location': 'lacros_version_skew_tests_v123.0.6276.0', + 'revision': 'version:123.0.6276.0', }, ], },
diff --git a/infra/config/subprojects/build/build.star b/infra/config/subprojects/build/build.star index f48c8bd..cb9f7df 100644 --- a/infra/config/subprojects/build/build.star +++ b/infra/config/subprojects/build/build.star
@@ -71,13 +71,14 @@ def cq_build_perf_builder(description_html, **kwargs): # Use CQ reclient instance and high reclient jobs/cores to simulate CQ builds. + if not kwargs.get("siso_configs"): + kwargs["siso_configs"] = ["builder"] return ci.builder( description_html = description_html + "<br>Build stats is show in http://shortn/_gaAdI3x6o6.", reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, reclient_instance = reclient.instance.DEFAULT_UNTRUSTED, siso_project = siso.project.DEFAULT_UNTRUSTED, use_clang_coverage = True, - siso_configs = ["builder"], **kwargs ) @@ -213,6 +214,7 @@ category = "linux", short_name = "siso", ), + siso_configs = ["builder", "remote-library-link"], ) cq_build_perf_builder( @@ -337,6 +339,7 @@ category = "cros", short_name = "siso", ), + siso_configs = ["builder", "remote-library-link"], ) cq_build_perf_builder( @@ -486,6 +489,7 @@ short_name = "dev", ), reclient_jobs = 5120, + siso_configs = ["remote-library-link"], ) developer_build_perf_builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star index 239f461..c317c4b 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
@@ -108,6 +108,7 @@ ], }, }, + siso_configs = ["builder", "remote-library-link"], siso_enabled = True, tryjob = try_.job( experiment_percentage = 10,
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star index 9b10010..35bbfd7 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -610,6 +610,7 @@ try_.compilator_builder( name = "linux_chromium_asan_siso_rel_ng-compilator", main_list_view = "try", + siso_configs = ["builder", "remote-library-link"], siso_enabled = True, ) @@ -747,6 +748,7 @@ contact_team_email = "chrome-build-team@google.com", main_list_view = "try", reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, + siso_configs = ["builder", "remote-library-link"], siso_enabled = True, tryjob = try_.job( experiment_percentage = 10, @@ -880,6 +882,7 @@ try_.compilator_builder( name = "linux_chromium_tsan_siso_rel_ng-compilator", main_list_view = "try", + siso_configs = ["builder", "remote-library-link"], siso_enabled = True, )
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index be0093d..9dcd8d4 100644 --- a/infra/config/targets/lacros-version-skew-variants.json +++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,32 +1,32 @@ { "LACROS_VERSION_SKEW_CANARY": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.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.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ] } }, "LACROS_VERSION_SKEW_DEV": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "identifier": "Lacros version skew testing ash dev", "swarming": { "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ] }
diff --git a/internal b/internal index c0441ac..7dad41b4 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit c0441ac66681bb025fe45ca06acbd21a72b8f39e +Subproject commit 7dad41b491ac6ef10b238af85d0cfe5a91124393
diff --git a/ios/chrome/browser/docking_promo/ui/docking_promo_view_controller.mm b/ios/chrome/browser/docking_promo/ui/docking_promo_view_controller.mm index cf06815f..c035f03 100644 --- a/ios/chrome/browser/docking_promo/ui/docking_promo_view_controller.mm +++ b/ios/chrome/browser/docking_promo/ui/docking_promo_view_controller.mm
@@ -48,7 +48,7 @@ - (void)viewDidLoad { [super viewDidLoad]; self.view.accessibilityIdentifier = kDockingPromoAccessibilityId; - self.view.backgroundColor = [UIColor colorNamed:kGrey100Color]; + self.view.backgroundColor = [UIColor colorNamed:kBackgroundColor]; if (self.animationViewWrapper) { [self configureAndLayoutAnimationView]; } @@ -56,6 +56,22 @@ [self layoutAlertScreen]; } +// Called when the device is rotated or dark mode is enabled/disabled. (Un)Hide +// the animations accordingly. +- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + BOOL darkModeEnabled = + (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark); + BOOL hidden = ![self shouldShowAnimation]; + + self.animationViewWrapper.animationView.hidden = hidden || darkModeEnabled; + self.animationViewWrapperDarkMode.animationView.hidden = + hidden || !darkModeEnabled; + + [self updateAnimationsPlaying]; + [self updateAlertScreenTopAnchorConstraint]; +} + #pragma mark - DockingPromoConsumer - (void)setTitleString:(NSString*)titleString @@ -122,8 +138,7 @@ ]; UIView* instructionView = - [[InstructionView alloc] initWithList:dockingPromoSteps - style:InstructionViewStyleBold]; + [[InstructionView alloc] initWithList:dockingPromoSteps]; instructionView.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/chrome/browser/shared/ui/elements/instruction_view.h b/ios/chrome/browser/shared/ui/elements/instruction_view.h index 21dc73f..a11d842 100644 --- a/ios/chrome/browser/shared/ui/elements/instruction_view.h +++ b/ios/chrome/browser/shared/ui/elements/instruction_view.h
@@ -10,8 +10,7 @@ // Enum defining different styles for the instruction view. typedef NS_ENUM(NSInteger, InstructionViewStyle) { InstructionViewStyleDefault = 0, - InstructionViewStyleGrayscale, - InstructionViewStyleBold, + InstructionViewStyleGrayscale }; // View containing an instruction list with their step number.
diff --git a/ios/chrome/browser/shared/ui/elements/instruction_view.mm b/ios/chrome/browser/shared/ui/elements/instruction_view.mm index 9180fa0..e48a3ada 100644 --- a/ios/chrome/browser/shared/ui/elements/instruction_view.mm +++ b/ios/chrome/browser/shared/ui/elements/instruction_view.mm
@@ -93,7 +93,6 @@ self.backgroundColor = [UIColor colorNamed:kGroupedSecondaryBackgroundColor]; break; - case InstructionViewStyleBold: case InstructionViewStyleDefault: self.backgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor]; break; @@ -284,11 +283,6 @@ // initialization and when entering or exiting dark mode. - (void)updateColorForStepNumberLabel:(UILabel*)stepNumberLabel { switch (self.style) { - case InstructionViewStyleBold: - stepNumberLabel.textColor = [UIColor colorNamed:kBlue600Color]; - stepNumberLabel.layer.backgroundColor = - [UIColor colorNamed:kBlueHaloColor].CGColor; - break; case InstructionViewStyleGrayscale: stepNumberLabel.textColor = [UIColor colorNamed:kGrey600Color]; stepNumberLabel.layer.backgroundColor =
diff --git a/media/capture/content/video_capture_oracle.cc b/media/capture/content/video_capture_oracle.cc index 1be76d3..5f5ed1a7 100644 --- a/media/capture/content/video_capture_oracle.cc +++ b/media/capture/content/video_capture_oracle.cc
@@ -230,8 +230,8 @@ return true; } -void VideoCaptureOracle::RecordCapture(double pool_utilization) { - DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0); +void VideoCaptureOracle::RecordCapture(float pool_utilization) { + DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0f); smoothing_sampler_.RecordSample(); const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_); @@ -246,12 +246,12 @@ next_frame_number_++; } -void VideoCaptureOracle::RecordWillNotCapture(double pool_utilization) { +void VideoCaptureOracle::RecordWillNotCapture(float pool_utilization) { VLOG(1) << "Client rejects proposal to capture frame (at #" << next_frame_number_ << ")."; if (capture_size_throttling_mode_ == kThrottlingActive) { - DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0); + DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0f); const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_); buffer_pool_utilization_.Update(pool_utilization, timestamp); AnalyzeAndAdjust(timestamp);
diff --git a/media/capture/content/video_capture_oracle.h b/media/capture/content/video_capture_oracle.h index ecd42fc1..593a56b 100644 --- a/media/capture/content/video_capture_oracle.h +++ b/media/capture/content/video_capture_oracle.h
@@ -92,8 +92,8 @@ // the current buffer pool utilization relative to a sustainable maximum (not // the absolute maximum). This method should only be called if the last call // to ObserveEventAndDecideCapture() returned true. - void RecordCapture(double pool_utilization); - void RecordWillNotCapture(double pool_utilization); + void RecordCapture(float pool_utilization); + void RecordWillNotCapture(float pool_utilization); // Notify of the completion of a capture, and whether it was successful. // Returns true iff the captured frame should be delivered. |frame_timestamp|
diff --git a/net/third_party/quiche/src b/net/third_party/quiche/src index 9c463fd..bccc7cc 160000 --- a/net/third_party/quiche/src +++ b/net/third_party/quiche/src
@@ -1 +1 @@ -Subproject commit 9c463fdd34e5975521f6211c5609d1f3945f3c15 +Subproject commit bccc7cc648236d93d8cd4f07c82d7a15a6218bf6
diff --git a/services/webnn/coreml/context_impl.mm b/services/webnn/coreml/context_impl.mm index 9c7b945..889f3a0b 100644 --- a/services/webnn/coreml/context_impl.mm +++ b/services/webnn/coreml/context_impl.mm
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import <CoreML/CoreML.h> - #include "services/webnn/coreml/context_impl.h" -#import "base/strings/sys_string_conversions.h" +#import <CoreML/CoreML.h> + #include "services/webnn/coreml/graph_impl.h" #include "services/webnn/webnn_context_provider_impl.h"
diff --git a/services/webnn/coreml/graph_impl.mm b/services/webnn/coreml/graph_impl.mm index f89a52c0..82ad582 100644 --- a/services/webnn/coreml/graph_impl.mm +++ b/services/webnn/coreml/graph_impl.mm
@@ -26,7 +26,7 @@ @implementation WebNNMLFeatureProvider - (MLFeatureValue*)featureValueForName:(NSString*)featureName { - return [_featureValues objectForKey:featureName]; + return _featureValues[featureName]; } - (instancetype)initWithFeatures:(NSSet<NSString*>*)feature_names featureValues:(NSDictionary*)feature_values { @@ -138,8 +138,7 @@ // TODO(https://crbug.com/1522278): Add metrics to measure compilation time. [MLModel - compileModelAtURL:[NSURL URLWithString:base::apple::FilePathToNSString( - model_file_path)] + compileModelAtURL:base::apple::FilePathToNSURL(model_file_path) completionHandler:^(NSURL* compiled_model_url, NSError* error) { // compiled_model_url refers to a directory placed directly inside // NSTemporaryDirectory(), it is not inside model_file_dir. @@ -262,11 +261,11 @@ } uint32_t current_stride = expected_size.ValueOrDie(); for (uint32_t dimension : operand_info->dimensions) { - [shape addObject:[NSNumber numberWithUnsignedInt:dimension]]; + [shape addObject:@(dimension)]; // since expected_size was computed by multiplying all dimensions together // current_stride has to be perfectly divisible by dimension. current_stride = current_stride / dimension; - [stride addObject:[NSNumber numberWithUnsignedInt:current_stride]]; + [stride addObject:@(current_stride)]; } return GraphImpl::CoreMLFeatureInfo(data_type, shape, stride); } @@ -300,7 +299,7 @@ mojom::Error::Code::kUnknownError, "Input initialization error"))); return; } - [feature_values setObject:feature_value forKey:feature_name]; + feature_values[feature_name] = feature_value; } // Run the MLModel
diff --git a/services/webnn/dml/adapter.cc b/services/webnn/dml/adapter.cc index a9af33a..c489bd8 100644 --- a/services/webnn/dml/adapter.cc +++ b/services/webnn/dml/adapter.cc
@@ -115,10 +115,26 @@ hr = dml_create_device_proc(d3d12_device.Get(), flags, IID_PPV_ARGS(&dml_device)); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to create DirectML device: " + - logging::SystemErrorCodeToString(hr); - return base::unexpected(CreateError(mojom::Error::Code::kUnknownError, - "Failed to create DirectML device.")); + if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING) { + // DirectML debug layer can fail to load even when it has been installed + // on the system. Try again without the debug flag and see if we're + // successful. + flags = flags & ~DML_CREATE_DEVICE_FLAG_DEBUG; + hr = dml_create_device_proc(d3d12_device.Get(), flags, + IID_PPV_ARGS(&dml_device)); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to create DirectML device without debug flag: " + + logging::SystemErrorCodeToString(hr); + return base::unexpected( + CreateError(mojom::Error::Code::kUnknownError, + "Failed to create DirectML device.")); + } + } else { + DLOG(ERROR) << "Failed to create DirectML device: " + + logging::SystemErrorCodeToString(hr); + return base::unexpected(CreateError(mojom::Error::Code::kUnknownError, + "Failed to create DirectML device.")); + } }; const DML_FEATURE_LEVEL max_feature_level_supported =
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 72eefddf..b34e3b66 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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.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.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -5341,9 +5341,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5353,8 +5353,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.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.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -5497,9 +5497,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5509,8 +5509,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index e9b6218f..40b112c 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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.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.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -20493,9 +20493,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20505,8 +20505,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.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.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -20643,9 +20643,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20655,8 +20655,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 3e99092..75956db 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -41458,9 +41458,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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41469,8 +41469,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -41487,9 +41487,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41498,8 +41498,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ], "dimensions": { @@ -41608,9 +41608,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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41619,8 +41619,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -41637,9 +41637,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41648,8 +41648,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ], "dimensions": { @@ -42940,9 +42940,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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -42951,8 +42951,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -42969,9 +42969,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -42980,8 +42980,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ], "dimensions": { @@ -43090,9 +43090,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.6287.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6287.0", + "description": "Run with ash-chrome version 123.0.6288.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -43101,8 +43101,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -43119,9 +43119,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_v122.0.6241.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -43130,8 +43130,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 521bf51..f1ee887 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.6287.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.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.6287.0", + "description": "Run with ash-chrome version 123.0.6288.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.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -16540,12 +16540,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_v122.0.6241.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16555,8 +16555,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.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.6287.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.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.6287.0", + "description": "Run with ash-chrome version 123.0.6288.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.6287.0", - "revision": "version:123.0.6287.0" + "location": "lacros_version_skew_tests_v123.0.6288.0", + "revision": "version:123.0.6288.0" } ], "dimensions": { @@ -16716,12 +16716,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_v122.0.6241.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 122.0.6241.0", + "description": "Run with ash-chrome version 123.0.6276.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16731,8 +16731,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v122.0.6241.0", - "revision": "version:122.0.6241.0" + "location": "lacros_version_skew_tests_v123.0.6276.0", + "revision": "version:123.0.6276.0" } ], "dimensions": {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index c4fdd272..f4e3f30 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -21,7 +21,7 @@ # "ios_chrome_ui_eg2tests_module_iPhone 6s 14.0" # The goal is to drive the number of exceptions to zero, to make all -# the bots behave similarly. +# the bots behave similarly. whitespace { 'accessibility_unittests': { 'modifications': {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index fab1872..f4ef9ab9 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -307,32 +307,32 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 123.0.6287.0', + 'description': 'Run with ash-chrome version 123.0.6288.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6287.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.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.6287.0', - 'revision': 'version:123.0.6287.0', + 'location': 'lacros_version_skew_tests_v123.0.6288.0', + 'revision': 'version:123.0.6288.0', }, ], }, }, 'LACROS_VERSION_SKEW_DEV': { 'identifier': 'Lacros version skew testing ash dev', - 'description': 'Run with ash-chrome version 122.0.6241.0', + 'description': 'Run with ash-chrome version 123.0.6276.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v122.0.6241.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6276.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v122.0.6241.0', - 'revision': 'version:122.0.6241.0', + 'location': 'lacros_version_skew_tests_v123.0.6276.0', + 'revision': 'version:123.0.6276.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 1198221..7083b5b 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2394,8 +2394,10 @@ "platforms": [ "android", "android_webview", + "chromeos", "chromeos_lacros", "fuchsia", + "ios", "linux", "mac", "windows" @@ -3654,6 +3656,21 @@ ] } ], + "ChromeOSDocumentScanAsyncDiscovery": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AsynchronousScannerDiscovery" + ] + } + ] + } + ], "ChromeOSGlanceablesTimeManagementTasksView": [ { "platforms": [ @@ -4781,6 +4798,24 @@ ] } ], + "CrOSFederatedAutocorrectPhh": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "launch_stage": "prod" + }, + "enable_features": [ + "AutocorrectFederatedPhh" + ] + } + ] + } + ], "CrOSFederatedLauncherQueryPhhVersion1": [ { "platforms": [ @@ -4799,6 +4834,24 @@ ] } ], + "CrOSFederatedLauncherQueryPhhVersion2": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "launch_stage": "prod" + }, + "enable_features": [ + "FederatedLauncherQueryAnalyticsVersion2Task" + ] + } + ] + } + ], "CrOSFederatedTimezoneCodePhh": [ { "platforms": [ @@ -18239,6 +18292,38 @@ ], "experiments": [ { + "name": "UploadCadence20ReadCadence5", + "params": { + "external_metrics_collection_interval_in_seconds": "300", + "upload_time_in_seconds": "1200" + }, + "enable_features": [ + "EnableStructuredMetrics", + "EnableStructuredMetricsService" + ] + }, + { + "name": "UploadCadence10ReadCadence3", + "params": { + "external_metrics_collection_interval_in_seconds": "180", + "upload_time_in_seconds": "600" + }, + "enable_features": [ + "EnableStructuredMetrics", + "EnableStructuredMetricsService" + ] + }, + { + "name": "UploadCadence20", + "params": { + "upload_time_in_seconds": "1200" + }, + "enable_features": [ + "EnableStructuredMetrics", + "EnableStructuredMetricsService" + ] + }, + { "name": "StructuredMetricsExternalMetrics_100_20231027", "params": { "file_limit": "100"
diff --git a/third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom b/third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom index 5e510ec4..330f32be 100644 --- a/third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom +++ b/third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom
@@ -12,11 +12,37 @@ struct SameOriginBfcacheNotRestoredDetails { // URL when the frame navigated away. This could be cut down if the // reported value was longer than a limit. + // TODO(crbug.com/324031239): Use url.mojom.Url (in url/mojom/url.mojom) + // instead of string. string url; // List of children frames' information. array<BackForwardCacheNotRestoredReasons> children; }; +// JavaScript source location of a BFCache blocking reason. +struct BlockingReasonSourceLocation { + // The absolute URL (e.g. https://...) of the file where the reason was found. + // This should be empty string if the reason doesn't have URL. + // TODO(crbug.com/324031239): Use url.mojom.Url (in url/mojom/url.mojom) + // instead of string. + string url; + // The line number of the reason. + uint64 line_number; + // The column number of the reason. + uint64 column_number; +}; + +// Detailed information for why the frame in question was blocked +// from BFCache. +struct BFCacheBlockingDetailedReason { + // The name of the reason. + // TODO(crbug.com/1519483): Define enums of reasons and use them instead of strings. + string name; + // The JavaScript source location of the reason. This should be null if the reason + // doesn't have a source location. + BlockingReasonSourceLocation? source; +}; + // Struct for NotRestoredReasons API to report from browser to renderer. This // contains the information that is common to both same-origin and cross-origin iframes. struct BackForwardCacheNotRestoredReasons { @@ -29,7 +55,7 @@ string? name; // List of reasons that blocked back/forward cache if any. // TODO(crbug.com/1519483): Define enums of reasons and use them instead of strings. - array<string> reasons; + array<BFCacheBlockingDetailedReason> reasons; // This will be absl::nullopt when this document is cross-origin from the main // document. SameOriginBfcacheNotRestoredDetails? same_origin_details;
diff --git a/third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom b/third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom index 9f561f5a..714d21e 100644 --- a/third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom +++ b/third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom
@@ -17,9 +17,10 @@ // TODO(crbug.com/1522767): Use enum instead of uint32 or have validation to // really avoid unintended messages. uint32? feature; - // The URL of the JavaScript file where the feature is used or where JavaScript executed. - // This will be empty when when a flag is disabled to send this information, and will be - // null when a feature is used from C++ in tests. + // The absolute URL of the JavaScript file where the feature is used or where JavaScript + // executed. This will be empty when when a flag is disabled to send this information, and + // will be null when a feature is used from C++ in tests. + // TODO(crbug.com/324031239): Use the struct url.mojom.Url instead of string. string? url; // The function in the JavaScript file where the feature is used or where JavaScript executed. // This will be empty when a flag is disabled to send this information, and will be null when @@ -28,6 +29,8 @@ // The line number in JavaScript file where the feature is used or where JavaScript executed. // This will be zero when a flag is disabled to send this information, and when a feature is // used from C++ in tests. + // TODO(crbug.com/1523193): Make `line_number` and `column_number` nullable, so the types here + // will correspond to blink::mojom::BFCacheBlockingDetailedReason. uint64 line_number; // The column number in JavaScript file where the feature is used or where JavaScript executed. // This will be zero when a flag is disabled to send this information, and when a feature is
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index e01031af..ce29d02 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -2908,7 +2908,7 @@ overflow_style->OverscrollBehaviorY()))); } - if (overflow_style->HasCustomScrollbarStyle()) { + if (overflow_style->HasCustomScrollbarStyle(GetDocument())) { update_scrollbar_style = true; } }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index a5e2d4c..d763485 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -3189,8 +3189,19 @@ if (reasons_to_copy->src) { not_restored_reasons->src = reasons_to_copy->src.value().c_str(); } - for (const auto& reason : reasons_to_copy->reasons) { - not_restored_reasons->reasons.push_back(reason.c_str()); + for (const auto& reason_to_copy : reasons_to_copy->reasons) { + mojom::blink::BFCacheBlockingDetailedReasonPtr reason = + mojom::blink::BFCacheBlockingDetailedReason::New(); + reason->name = WTF::String(reason_to_copy->name); + if (reason_to_copy->source) { + mojom::blink::BlockingReasonSourceLocationPtr source_location = + mojom::blink::BlockingReasonSourceLocation::New(); + source_location->url = WTF::String(reason_to_copy->source->url); + source_location->line_number = reason_to_copy->source->line_number; + source_location->column_number = reason_to_copy->source->column_number; + reason->source = std::move(source_location); + } + not_restored_reasons->reasons.push_back(std::move(reason)); } if (reasons_to_copy->same_origin_details) { auto details = mojom::blink::SameOriginBfcacheNotRestoredDetails::New();
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index f69eb607..ed86caa 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -1032,8 +1032,9 @@ bool LayoutBox::UsesOverlayScrollbars() const { NOT_DESTROYED(); - if (StyleRef().HasCustomScrollbarStyle()) + if (StyleRef().HasCustomScrollbarStyle(GetDocument())) { return false; + } if (GetFrame()->GetPage()->GetScrollbarTheme().UsesOverlayScrollbars()) return true; return false;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 3f15131..8d9a46d 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -1490,13 +1490,15 @@ // can scroll. Element* body = doc.body(); if (body && body->GetLayoutObject() && body->GetLayoutObject()->IsBox() && - body->GetLayoutObject()->StyleRef().HasCustomScrollbarStyle()) + body->GetLayoutObject()->StyleRef().HasCustomScrollbarStyle(doc)) { return *body->GetLayoutObject(); + } // If the <body> didn't have a custom style, then the root element might. Element* doc_element = doc.documentElement(); if (doc_element && doc_element->GetLayoutObject() && - doc_element->GetLayoutObject()->StyleRef().HasCustomScrollbarStyle() && + doc_element->GetLayoutObject()->StyleRef().HasCustomScrollbarStyle( + doc) && !layout_box.StyleRef().UsesStandardScrollbarStyle()) { return *doc_element->GetLayoutObject(); } @@ -1543,7 +1545,8 @@ return scrollbar->ScrollbarThickness(); const LayoutObject& style_source = ScrollbarStyleSource(*GetLayoutBox()); - if (style_source.StyleRef().HasCustomScrollbarStyle()) { + if (style_source.StyleRef().HasCustomScrollbarStyle( + style_source.GetDocument())) { return CustomScrollbar::HypotheticalScrollbarThickness(this, orientation, &style_source); } @@ -1561,7 +1564,8 @@ const LayoutObject& style_source = ScrollbarStyleSource(*GetLayoutBox()); bool needs_custom = - style_source.IsBox() && style_source.StyleRef().HasCustomScrollbarStyle(); + style_source.IsBox() && style_source.StyleRef().HasCustomScrollbarStyle( + style_source.GetDocument()); Scrollbar* scrollbars[] = {HorizontalScrollbar(), VerticalScrollbar()}; @@ -1646,9 +1650,10 @@ // only appear when scrolling, we don't create them if there isn't overflow // to scroll. Thus, overlay scrollbars can't be "always on". i.e. // |overlay:scroll| behaves like |overlay:auto|. + Document& document = GetLayoutBox()->GetDocument(); bool has_custom_scrollbar_style = ScrollbarStyleSource(*GetLayoutBox()) .StyleRef() - .HasCustomScrollbarStyle(); + .HasCustomScrollbarStyle(document); bool will_be_overlay = GetPageScrollbarTheme().UsesOverlayScrollbars() && !has_custom_scrollbar_style; if (will_be_overlay) { @@ -2646,7 +2651,8 @@ Scrollbar* scrollbar = nullptr; const LayoutObject& style_source = ScrollbarStyleSource(*ScrollableArea()->GetLayoutBox()); - if (style_source.StyleRef().HasCustomScrollbarStyle()) { + if (style_source.StyleRef().HasCustomScrollbarStyle( + style_source.GetDocument())) { DCHECK(style_source.GetNode() && style_source.GetNode()->IsElementNode()); scrollbar = MakeGarbageCollected<CustomScrollbar>( ScrollableArea(), orientation, &style_source);
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.cc b/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.cc index 95734f5..fedfbbf 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.cc +++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.cc
@@ -128,6 +128,13 @@ return style_.fade_out_duration; } +ScrollbarPart ScrollbarThemeFluent::PartsToInvalidateOnThumbPositionChange( + const Scrollbar& scrollbar, + float old_position, + float new_position) const { + return ScrollbarPart::kNoPart; +} + int ScrollbarThemeFluent::ThumbThickness( const float scale_from_dip, const EScrollbarWidth scrollbar_width) const {
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.h b/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.h index 712562fc..ec9b10c 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.h +++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent.h
@@ -51,6 +51,11 @@ base::TimeDelta OverlayScrollbarFadeOutDelay() const override; base::TimeDelta OverlayScrollbarFadeOutDuration() const override; + ScrollbarPart PartsToInvalidateOnThumbPositionChange( + const Scrollbar&, + float old_position, + float new_position) const override; + private: friend class ScrollbarThemeFluentMock;
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent_unittest.cc b/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent_unittest.cc index 076fb07e..15447def 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent_unittest.cc +++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_fluent_unittest.cc
@@ -19,7 +19,7 @@ namespace blink { -using ::testing::NiceMock; +using ::testing::Return; namespace { @@ -62,7 +62,8 @@ void SetUp() override { feature_list_.InitAndEnableFeature(::features::kFluentScrollbar); ScrollbarThemeSettings::SetFluentScrollbarsEnabled(true); - mock_scrollable_area_ = MakeGarbageCollected<MockScrollableArea>(); + mock_scrollable_area_ = MakeGarbageCollected<MockScrollableArea>( + /*maximum_scroll_offset=*/ScrollOffset(0, 1000)); mock_scrollable_area_->SetScaleFromDIP(GetParam()); // ScrollbarThemeFluent Needs to be instantiated after feature flag and // scrollbar settings have been set. @@ -179,6 +180,39 @@ scrollbar_thickness)); } +// The test verifies that the track/buttons paint is not invalidated when +// the thumb position changes. Aura scrollbars change arrow buttons color +// when the scroll offset changes from and to the min/max scroll offset. +// Fluent scrollbars do not change the arrow buttons color in this case. +TEST_P(ScrollbarThemeFluentTest, ScrollbarTrackPartInvalidationTest) { + Scrollbar* scrollbar = Scrollbar::CreateForTesting( + mock_scrollable_area(), kVerticalScrollbar, &(theme_->GetInstance())); + ON_CALL(*mock_scrollable_area(), VerticalScrollbar()) + .WillByDefault(Return(scrollbar)); + + scrollbar->SetFrameRect( + gfx::Rect(0, 0, ScrollbarThickness(), kScrollbarLength)); + scrollbar->ClearTrackNeedsRepaint(); + + // Verifies that when the thumb position changes from min offset, the track + // invalidation is not triggered. + mock_scrollable_area()->SetScrollOffset( + ScrollOffset(0, 10), mojom::blink::ScrollType::kCompositor); + EXPECT_FALSE(scrollbar->TrackNeedsRepaint()); + + // Verifies that when the thumb position changes from a non-zero offset, + // the track invalidation is not triggered. + mock_scrollable_area()->SetScrollOffset( + ScrollOffset(0, 20), mojom::blink::ScrollType::kCompositor); + EXPECT_FALSE(scrollbar->TrackNeedsRepaint()); + + // Verifies that when the thumb position changes back to 0 (min) offset, + // the track invalidation is not triggered. + mock_scrollable_area()->SetScrollOffset( + ScrollOffset(0, 0), mojom::blink::ScrollType::kCompositor); + EXPECT_FALSE(scrollbar->TrackNeedsRepaint()); +} + // Test that Scrollbar objects are correctly sized with Overlay Fluent theme // parts. TEST_P(OverlayScrollbarThemeFluentTest, OverlaySetsCorrectTrackAndInsetSize) {
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 0c56948..b96f7071 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -48,6 +48,7 @@ #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/html_body_element.h" #include "third_party/blink/renderer/core/html/html_html_element.h" #include "third_party/blink/renderer/core/html/html_progress_element.h" @@ -2280,6 +2281,24 @@ return blink::GetVariableValue(*this, name, is_inherited_property); } +bool ComputedStyle::HasCustomScrollbarStyle(const Document& document) const { + + // Ignore ::-webkit-scrollbar when the web setting to prefer default scrollbar + // styling is true. This web setting ignores both ::-webkit-scrollbar styling + // and standard properties. + if (RuntimeEnabledFeatures::PreferDefaultScrollbarStylesEnabled()) { + const Settings* settings = document.GetSettings(); + if (settings && settings->GetPrefersDefaultScrollbarStyles()) { + return false; + } + } + + // Ignore non-standard ::-webkit-scrollbar when standard properties are in + // use. + return HasPseudoElementStyle(kPseudoIdScrollbar) && + !UsesStandardScrollbarStyle(); +} + Length ComputedStyle::LineHeight() const { const Length& lh = LineHeightInternal(); // Unlike getFontDescription().computedSize() and hence fontSize(), this is
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 37839e9..153ebb5 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -712,12 +712,7 @@ ScrollbarColor().has_value(); } - // Ignore non-standard ::-webkit-scrollbar when standard properties are in - // use. - bool HasCustomScrollbarStyle() const { - return HasPseudoElementStyle(kPseudoIdScrollbar) && - !UsesStandardScrollbarStyle(); - } + bool HasCustomScrollbarStyle(const Document& document) const; // shape-outside (aka -webkit-shape-outside) ShapeValue* ShapeOutside() const { return ShapeOutsideInternal().Get(); }
diff --git a/third_party/blink/renderer/core/timing/performance_navigation_timing.cc b/third_party/blink/renderer/core/timing/performance_navigation_timing.cc index 7841453..0524cd8 100644 --- a/third_party/blink/renderer/core/timing/performance_navigation_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
@@ -327,7 +327,7 @@ HeapVector<Member<NotRestoredReasons>> children; for (const auto& reason : nrr->reasons) { NotRestoredReasonDetails* detail = - MakeGarbageCollected<NotRestoredReasonDetails>(reason); + MakeGarbageCollected<NotRestoredReasonDetails>(reason->name); reasons.push_back(detail); } if (nrr->same_origin_details) {
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc index 03e73ba6..b20190e 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -3098,8 +3098,14 @@ canvas->GetDocument().UpdateStyleAndLayoutTreeForElement( canvas, DocumentUpdateReason::kCanvas); } + const Font& font = AccessFont(canvas); + if (HostAsOffscreenCanvas() && font.GetFontSelector() && + !font.GetFontSelector()->GetExecutionContext()) { + return MakeGarbageCollected<TextMetrics>(); + } + const CanvasRenderingContext2DState& state = GetState(); TextDirection direction = ToTextDirection(state.GetDirection(), canvas);
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d_test.cc index f20e9f6..5c389387 100644 --- a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d_test.cc +++ b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d_test.cc
@@ -273,5 +273,17 @@ host->transferToImageBitmap(scope.GetScriptState(), no_exception); } +// Regression test for https://crbug.com/1509382. +TEST(OffscreenCanvasRenderingContext2DTest, NoCrashOnDocumentShutdown) { + test::TaskEnvironment task_environment; + V8TestingScope scope; + auto* host = OffscreenCanvas::Create(scope.GetScriptState(), /*width=*/10, + /*height=*/10); + OffscreenCanvasRenderingContext2D* context = GetContext(scope, host); + context->setFont("12px Ahem"); + scope.GetDocument().Shutdown(); + context->measureText("hello world"); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_object.cc b/third_party/blink/renderer/modules/webgpu/dawn_object.cc index 67b8e615..ded2839 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_object.cc +++ b/third_party/blink/renderer/modules/webgpu/dawn_object.cc
@@ -4,11 +4,31 @@ #include "third_party/blink/renderer/modules/webgpu/dawn_object.h" +#include "base/numerics/checked_math.h" #include "gpu/command_buffer/client/webgpu_interface.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device.h" namespace blink { +// ExternalMemoryTracker + +ExternalMemoryTracker::~ExternalMemoryTracker() { + SetCurrentSize(0); +} + +void ExternalMemoryTracker::SetCurrentSize(size_t newSizeUnchecked) { + base::CheckedNumeric<int64_t> newSize = newSizeUnchecked; + base::CheckedNumeric<int64_t> deltaChecked = newSize - size_; + + int64_t delta = deltaChecked.ValueOrDie(); + if (delta != 0) { + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(delta); + size_ = newSize.ValueOrDie(); + } +} + +// DawnObjectBase + DawnObjectBase::DawnObjectBase( scoped_refptr<DawnControlClientHolder> dawn_control_client) : dawn_control_client_(std::move(dawn_control_client)) {} @@ -31,6 +51,8 @@ dawn_control_client_->Flush(); } +// DawnObjectImpl + DawnObjectImpl::DawnObjectImpl(GPUDevice* device) : DawnObjectBase(device->GetDawnControlClient()), device_(device) {}
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_object.h b/third_party/blink/renderer/modules/webgpu/dawn_object.h index 9bd305c..09ffb7fb 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_object.h +++ b/third_party/blink/renderer/modules/webgpu/dawn_object.h
@@ -68,6 +68,31 @@ class GPUDevice; +// RAII tracker for known memory allocations outside of V8, informing V8 using +// AdjustAmountOfExternalAllocatedMemory. This causes V8 to collect garbage +// more often when it knows the footprint of V8-managed objects is large. +// +// - It is OK for the tracked size to be an estimate. +// - It is OK to update the tracked size dynamically/asynchronously. +// - It is OK to use this for CPU memory allocated in another process. +// - It is NOT OK to use this for VRAM allocations. This may cause GC to +// trigger too often: GC is trying to manage CPU memory pressure, but freeing +// VRAM allocations may or may not reduce CPU memory pressure. +class ExternalMemoryTracker final { + public: + // Non-copyable/non-movable + ExternalMemoryTracker(const ExternalMemoryTracker&) = delete; + ExternalMemoryTracker& operator=(const ExternalMemoryTracker&) = delete; + + ExternalMemoryTracker() = default; + ~ExternalMemoryTracker(); + + void SetCurrentSize(size_t newSize); + + private: + int64_t size_ = 0; +}; + // This class allows objects to hold onto a DawnControlClientHolder. // The DawnControlClientHolder is used to hold the WebGPUInterface and keep // track of whether or not the client has been destroyed. If the client is
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc b/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc index 8076240..1c2721ab 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc
@@ -7,6 +7,7 @@ #include <dawn/webgpu.h> #include "base/command_line.h" +#include "base/numerics/clamped_math.h" #include "gpu/command_buffer/client/webgpu_interface.h" #include "gpu/config/gpu_switches.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" @@ -41,7 +42,7 @@ bool has_null_character = false; switch (wgsl_or_spirv->GetContentType()) { case V8UnionUSVStringOrUint32Array::ContentType::kUSVString: { - WTF::String wtf_wgsl_code(wgsl_or_spirv->GetAsUSVString()); + const WTF::String& wtf_wgsl_code = wgsl_or_spirv->GetAsUSVString(); wgsl_code = wtf_wgsl_code.Utf8(); wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; wgsl_desc.code = wgsl_code.c_str(); @@ -91,10 +92,25 @@ shader_module = device->GetProcs().deviceCreateShaderModule( device->GetHandle(), &dawn_desc); } + GPUShaderModule* shader = MakeGarbageCollected<GPUShaderModule>(device, shader_module); if (webgpu_desc->hasLabel()) shader->setLabel(webgpu_desc->label()); + + // Very roughly approximate how much memory Tint might need for this shader. + // Pessimizes if Tint actually holds less memory than this (including if the + // shader module ends up being invalid). + // + // The actual estimate (100x code size) is chosen by profiling: large enough + // to show some improvement in peak GPU process memory usage, small enough to + // not slow down shader conformance tests (which are much, much heavier on + // shader creation than normal workloads) more than a few percent. + // + // TODO(crbug.com/dawn/2367): Get a real memory estimate from Tint. + base::ClampedNumeric<int32_t> input_code_size = wgsl_code.size(); + shader->tint_memory_estimate_.SetCurrentSize(input_code_size * 100); + return shader; }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_shader_module.h b/third_party/blink/renderer/modules/webgpu/gpu_shader_module.h index e1c5dda..e7e40ab 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_shader_module.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_shader_module.h
@@ -27,6 +27,7 @@ GPUShaderModule(const GPUShaderModule&) = delete; GPUShaderModule& operator=(const GPUShaderModule&) = delete; + ~GPUShaderModule() override = default; ScriptPromise getCompilationInfo(ScriptState* script_state); @@ -39,6 +40,9 @@ std::string utf8_label = value.Utf8(); GetProcs().shaderModuleSetLabel(GetHandle(), utf8_label.c_str()); } + + // Holds an estimate of the memory used by Tint for this shader module. + ExternalMemoryTracker tint_memory_estimate_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index a29e8c3..cf6cbf0 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -17,12 +17,10 @@ #include "components/viz/common/resources/transferable_resource.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/client_shared_image.h" -#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/client/webgpu_interface.h" #include "gpu/command_buffer/common/capabilities.h" -#include "gpu/command_buffer/common/gpu_memory_buffer_support.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/shared_image_trace_utils.h" #include "gpu/command_buffer/common/shared_image_usage.h" @@ -61,10 +59,6 @@ "AddSharedImageRasterUsageWithNonOOPR", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kAlwaysUseMappableSIForSoftwareCanvas, - "AlwaysUseMappableSIForSoftwareCanvas", - base::FEATURE_ENABLED_BY_DEFAULT); - } // namespace CanvasResource::CanvasResource(base::WeakPtr<CanvasResourceProvider> provider, @@ -444,27 +438,6 @@ context_provider_wrapper_->ContextProvider() ->GetCapabilities() .gpu_rasterization) { - auto* gpu_memory_buffer_manager = - SharedGpuContext::GetGpuMemoryBufferManager(); - - // Note that we create |gpu_memory_buffer_| only when MappableSI is not used - // and disabled. - if (!is_accelerated_ && - !base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas)) { - DCHECK(gpu_memory_buffer_manager); - DCHECK(shared_image_usage_flags & gpu::SHARED_IMAGE_USAGE_DISPLAY_READ); - - gpu_memory_buffer_ = gpu_memory_buffer_manager->CreateGpuMemoryBuffer( - Size(), GetBufferFormat(), gfx::BufferUsage::SCANOUT_CPU_READ_WRITE, - gpu::kNullSurfaceHandle, nullptr); - if (!gpu_memory_buffer_) - return; - -#if BUILDFLAG(IS_MAC) - gpu_memory_buffer_->SetColorSpace(GetColorSpace()); -#endif - } - auto* shared_image_interface = context_provider_wrapper_->ContextProvider()->SharedImageInterface(); DCHECK(shared_image_interface); @@ -510,12 +483,9 @@ SkAlphaType surface_alpha_type = GetSkColorInfo().alphaType(); scoped_refptr<gpu::ClientSharedImage> client_shared_image; - if (!is_accelerated_ && - base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas)) { - CHECK(!gpu_memory_buffer_); - // Using the new SII to create CPU mappable mailbox when this feature is - // enabled. Ideally we should add SHARED_IMAGE_USAGE_CPU_WRITE to the - // shared image usage flag here since mailbox will be used for CPU writes + if (!is_accelerated_) { + // Ideally we should add SHARED_IMAGE_USAGE_CPU_WRITE to the shared image + // usage flag here since mailbox will be used for CPU writes // by the client. But doing that stops us from using CompoundImagebacking as // many backings do not support SHARED_IMAGE_USAGE_CPU_WRITE. // TODO(crbug.com/1478238): Add that usage flag back here once the issue is @@ -528,12 +498,6 @@ if (!client_shared_image) { return; } - } else if (gpu_memory_buffer_) { - client_shared_image = shared_image_interface->CreateSharedImage( - GetSharedImageFormat(), Size(), GetColorSpace(), surface_origin, - surface_alpha_type, shared_image_usage_flags, "CanvasResourceRasterGmb", - gpu_memory_buffer_->CloneHandle()); - CHECK(client_shared_image); } else { client_shared_image = shared_image_interface->CreateSharedImage( GetSharedImageFormat(), Size(), GetColorSpace(), surface_origin, @@ -723,29 +687,18 @@ std::unique_ptr<gpu::ClientSharedImage::ScopedMapping> mapping; void* memory = nullptr; size_t stride = 0; - if (base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas)) { - mapping = client_shared_image()->Map(); - if (!mapping) { - LOG(ERROR) << "MapSharedImage Failed."; - return nullptr; - } - memory = mapping->Memory(0); - stride = mapping->Stride(0); - } else { - if (!gpu_memory_buffer_->Map()) { - LOG(ERROR) << "Unable to map gpu_memory_buffer_"; - return nullptr; - } - memory = gpu_memory_buffer_->memory(0); - stride = gpu_memory_buffer_->stride(0); + mapping = client_shared_image()->Map(); + if (!mapping) { + LOG(ERROR) << "MapSharedImage Failed."; + return nullptr; } + memory = mapping->Memory(0); + stride = mapping->Stride(0); SkPixmap pixmap(CreateSkImageInfo(), memory, stride); auto sk_image = SkImages::RasterFromPixmapCopy(pixmap); // Unmap the underlying buffer. - base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas) - ? mapping.reset() - : gpu_memory_buffer_->Unmap(); + mapping.reset(); return sk_image ? UnacceleratedStaticBitmapImage::Create(sk_image) : nullptr; } @@ -811,22 +764,13 @@ std::unique_ptr<gpu::ClientSharedImage::ScopedMapping> mapping; void* memory = nullptr; size_t stride = 0; - if (base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas)) { - mapping = client_shared_image()->Map(); - if (!mapping) { - LOG(ERROR) << "MapSharedImage failed."; - return; - } - memory = mapping->Memory(0); - stride = mapping->Stride(0); - } else { - if (!gpu_memory_buffer_->Map()) { - LOG(ERROR) << "Unable to map gpu_memory_buffer_."; - return; - } - memory = gpu_memory_buffer_->memory(0); - stride = gpu_memory_buffer_->stride(0); + mapping = client_shared_image()->Map(); + if (!mapping) { + LOG(ERROR) << "MapSharedImage failed."; + return; } + memory = mapping->Memory(0); + stride = mapping->Stride(0); auto surface = SkSurfaces::WrapPixels(CreateSkImageInfo(), memory, stride); SkPixmap pixmap; @@ -834,9 +778,7 @@ surface->writePixels(pixmap, 0, 0); // Unmap the underlying buffer. - base::FeatureList::IsEnabled(kAlwaysUseMappableSIForSoftwareCanvas) - ? mapping.reset() - : gpu_memory_buffer_->Unmap(); + mapping.reset(); sii->UpdateSharedImage(gpu::SyncToken(), client_shared_image()->mailbox()); owning_thread_data().sync_token = sii->GenUnverifiedSyncToken(); }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h index 08adfbe..2499528 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -37,7 +37,6 @@ namespace gfx { class ColorSpace; -class GpuMemoryBuffer; } // namespace gfx @@ -459,10 +458,6 @@ // active readers or not. bool is_origin_clean_ = true; - // GMB based software raster path. The resource is written to on the CPU but - // passed using the mailbox to the display compositor for use as an overlay. - std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; - // Accessed on any thread. const gfx::Size size_; const bool is_origin_top_left_;
diff --git a/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py b/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py index 685ee0db..2181e86 100644 --- a/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py +++ b/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py
@@ -38,7 +38,7 @@ path_finder.bootstrap_wpt_imports() from tools.manifest.manifest import Manifest -from wptrunner import manifestexpected, testloader, wpttest +from wptrunner import manifestexpected, testloader, testrunner, wpttest from wptrunner.wptmanifest import node as wptnode from wptrunner.wptmanifest.backends import static @@ -169,10 +169,52 @@ @classmethod def install(cls, port: Port, expectations: TestExpectations): + """Patch overrides into the wptrunner API (may be unstable).""" testloader.TestLoader = functools.partial(cls, port, expectations=expectations) + # Ideally, we would patch `executorchrome.*.convert_result`, but changes + # to the executor classes here in the main process don't persist to + # worker processes, which reload the module from source. Therefore, + # patch `TestRunnerManager`, which runs in the main process. + test_ended = testrunner.TestRunnerManager.test_ended + + @functools.wraps(test_ended) + def wrapper(self, test, results): + return test_ended(self, test, + allow_any_subtests_on_timeout(test, results)) + + testrunner.TestRunnerManager.test_ended = wrapper + + +Results = Tuple[wpttest.Result, List[wpttest.SubtestResult]] + + +def allow_any_subtests_on_timeout(test: wpttest.Test, + results: Results) -> Results: + """On timeout, suppress all subtest mismatches with added expectations. + + When a test times out in `run_web_tests.py`, text mismatches don't affect + pass/fail status or trigger retries. This prevents the test from being + susceptible to flakiness due to variation in which subtest times out and + lets build gardeners suppress failures with just a `[ Timeout ]` line in + TestExpectations. + + This converter injects extra expectations to mimic the `run_web_tests.py` + behavior. Note that, if the test expected to time out runs to completion, + the subtest results are then checked as usual. + + See Also: + https://github.com/web-platform-tests/wpt/pull/44134 + """ + harness_result, subtest_results = results + if harness_result.status == 'TIMEOUT': + for result in subtest_results: + result.expected, result.known_intermittent = result.status, [] + result.message = test.expected_fail_message(result.name) + return harness_result, subtest_results + def _build_expectation_ast(name: str, statuses: Container[str], @@ -237,20 +279,7 @@ expr_data={}, data_cls_getter=lambda x, y: manifestexpected.SubtestNode, test_path=self.parent.test_path)) - subtest = super().get_subtest(name) - # When a test times out in `run_web_tests.py`, the text output is still - # diffed but mismatches don't affect pass/fail status or retries. For - # wptrunner to mimic this behavior with variations in timing (i.e., - # which subtest times out can differ between runs), any subtest is - # allowed to time out or not run if the overall test is expected to - # time out. - if subtest and 'TIMEOUT' in {self.expected, *self.known_intermittent}: - expected = [subtest.expected, *subtest.known_intermittent] - for status in ['TIMEOUT', 'NOTRUN']: - if status not in expected: - expected.append(status) - subtest.set('expected', expected) - return subtest + return super().get_subtest(name) def _test_basename(test_id: str) -> str:
diff --git a/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py b/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py index 9f768ed..9f0b895 100644 --- a/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py +++ b/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py
@@ -5,13 +5,18 @@ import json import textwrap import unittest +from unittest import mock from blinkpy.common import path_finder from blinkpy.common.host_mock import MockHost -from blinkpy.wpt_tests.test_loader import TestLoader, wpt_url_to_blink_test +from blinkpy.wpt_tests.test_loader import ( + allow_any_subtests_on_timeout, + TestLoader, + wpt_url_to_blink_test, +) path_finder.bootstrap_wpt_imports() -from wptrunner import wptlogging +from wptrunner import wptlogging, wpttest from tools.manifest.manifest import load_and_update @@ -263,14 +268,51 @@ subtest = test.get_subtest('subtest1') self.assertEqual(subtest.expected, 'FAIL') - self.assertEqual(subtest.known_intermittent, ['TIMEOUT', 'NOTRUN']) + self.assertEqual(subtest.known_intermittent, []) subtest = test.get_subtest('subtest2') self.assertEqual(subtest.expected, 'PASS') - self.assertEqual(subtest.known_intermittent, ['TIMEOUT', 'NOTRUN']) + self.assertEqual(subtest.known_intermittent, []) def test_wpt_url_to_exp_test(self): self.assertEqual(wpt_url_to_blink_test('/css/test.html?a'), 'external/wpt/css/test.html?a') self.assertEqual(wpt_url_to_blink_test('/wpt_internal/test.html'), 'wpt_internal/test.html') + + def test_allow_any_subtests_on_timeout(self): + test = mock.Mock() + test.expected_fail_message.return_value = 'expect this message' + test_result = wpttest.TestharnessResult('TIMEOUT', + message=None, + expected='TIMEOUT') + subtest_result = wpttest.TestharnessSubtestResult('subtest', + 'TIMEOUT', + message=None, + expected='FAIL') + + test_result, (subtest_result, ) = allow_any_subtests_on_timeout( + test, (test_result, [subtest_result])) + self.assertEqual(subtest_result.expected, 'TIMEOUT') + self.assertEqual(subtest_result.known_intermittent, []) + self.assertEqual(subtest_result.message, 'expect this message') + test.expected_fail_message.assert_called_once_with('subtest') + + def test_do_not_allow_any_subtests_on_completion(self): + test = mock.Mock() + test.expected_fail_message.return_value = ( + 'should not expect this message') + test_result = wpttest.TestharnessResult('OK', + message=None, + expected='TIMEOUT') + subtest_result = wpttest.TestharnessSubtestResult('subtest', + 'FAIL', + message=None, + expected='TIMEOUT') + + test_result, (subtest_result, ) = allow_any_subtests_on_timeout( + test, (test_result, [subtest_result])) + self.assertEqual(subtest_result.expected, 'TIMEOUT') + self.assertEqual(subtest_result.known_intermittent, []) + self.assertIsNone(subtest_result.message) + test.expected_fail_message.assert_not_called()
diff --git a/third_party/blink/web_tests/ChromeTestExpectations b/third_party/blink/web_tests/ChromeTestExpectations index 0a42599..d40b321 100644 --- a/third_party/blink/web_tests/ChromeTestExpectations +++ b/third_party/blink/web_tests/ChromeTestExpectations
@@ -55,24 +55,25 @@ crbug.com/1512119 external/wpt/webdriver/tests/classic/perform_actions/pointer_touch.py [ Failure ] # Those tests (flaky) fail when DCHECK enabled +crbug.com/1499775 external/wpt/svg/styling/use-element-transitions.html [ Failure Pass ] crbug.com/1499775 external/wpt/media-capabilities/encodingInfo.any.worker.html [ Crash ] crbug.com/1499775 external/wpt/navigation-api/navigate-event/navigate-history-back-bfcache.html [ Failure ] crbug.com/1499775 external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.html [ Failure Timeout ] crbug.com/1499775 external/wpt/url/failure.html [ Pass Timeout ] -crbug.com/1499775 external/wpt/credential-management/fedcm-endpoint-redirects.https.html [ Crash Timeout ] +crbug.com/1499775 external/wpt/credential-management/fedcm-endpoint-redirects.https.html [ Crash Failure Timeout ] crbug.com/1499775 external/wpt/credential-management/fedcm-no-login-url.https.html [ Crash Timeout ] -crbug.com/1499775 wpt_internal/credential-management/fedcm-reauth-with-signin-status.https.html [ Crash Timeout ] +crbug.com/1499775 wpt_internal/credential-management/fedcm-reauth-with-signin-status.https.html [ Crash Failure Timeout ] crbug.com/1499775 external/wpt/css/css-properties-values-api/animation/custom-property-animation-used-in-shorthand.html [ Failure Pass ] crbug.com/1499775 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-seeking.html [ Failure Pass ] crbug.com/1499775 external/wpt/screen-capture/getdisplaymedia.https.html [ Crash Failure Pass ] crbug.com/1499775 external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html [ Failure Pass ] crbug.com/1499775 external/wpt/cookies/attributes/attributes-ctl.sub.html [ Failure Pass ] -crbug.com/1499775 external/wpt/credential-management/fedcm-auto-selected-flag.https.html [ Crash Pass Timeout ] -crbug.com/1499775 external/wpt/credential-management/fedcm-auto-reauthn-without-approved-clients.https.html [ Crash Pass Timeout ] -crbug.com/1499775 external/wpt/credential-management/fedcm-returning-account-auto-reauthn.https.html [ Crash Pass Timeout ] +crbug.com/1499775 external/wpt/credential-management/fedcm-auto-selected-flag.https.html [ Crash Failure Timeout ] +crbug.com/1499775 external/wpt/credential-management/fedcm-auto-reauthn-without-approved-clients.https.html [ Crash Failure Timeout ] +crbug.com/1499775 external/wpt/credential-management/fedcm-returning-account-auto-reauthn.https.html [ Crash Failure Timeout ] crbug.com/1499775 external/wpt/credential-management/fedcm-pending-disconnect.https.html [ Crash Pass Timeout ] crbug.com/1499775 external/wpt/credential-management/fedcm-too-many-disconnect-calls.https.html [ Crash Pass Timeout ] -crbug.com/1499775 external/wpt/credential-management/fedcm-pending-userinfo.https.html [ Crash Pass Timeout ] +crbug.com/1499775 external/wpt/credential-management/fedcm-pending-userinfo.https.html [ Crash Failure Timeout ] crbug.com/1499775 wpt_internal/credential-management/fedcm-mismatch-dialog.tentative.https.html [ Crash Pass Timeout ] crbug.com/1499775 external/wpt/css/css-grid/alignment/grid-item-aspect-ratio-stretch-4.html [ Failure Pass ] crbug.com/1499775 external/wpt/css/css-images/object-view-box-fit-fill-video.html [ Failure Pass ] @@ -385,6 +386,7 @@ crbug.com/1499775 external/wpt/html/semantics/popovers/popover-open-overflow-display.tentative.html [ Failure ] # Reftest image failure crbug.com/1499775 external/wpt/html/semantics/popovers/popover-top-layer-combinations.html [ Timeout ] crbug.com/1499775 external/wpt/html/semantics/popovers/popover-top-layer-interactions.html [ Timeout ] +crbug.com/1499775 external/wpt/html/semantics/popovers/popover-focus-2.html [ Failure ] # Flaky output crbug.com/1499775 external/wpt/html/user-activation/activation-trigger-keyboard-enter.html [ Timeout ] crbug.com/1499775 external/wpt/html/user-activation/activation-trigger-mouse-left.html [ Timeout ] crbug.com/1499775 external/wpt/html/user-activation/activation-trigger-mouse-right.html [ Timeout ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 430ebc6..3d52308 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -50,6 +50,7 @@ external/wpt/infrastructure/expected-fail/timeout.html [ Timeout ] external/wpt/infrastructure/reftest/reftest_ref_timeout.html [ Timeout ] external/wpt/infrastructure/reftest/reftest_timeout.html [ Timeout ] +wpt_internal/infrastructure/fail-before-timeout.html [ Timeout ] # We don't support extracting fuzzy information from .ini files, which these # WPT infrastructure tests rely on. @@ -6732,8 +6733,6 @@ crbug.com/1519178 [ Mac12 ] virtual/fenced-frame-mparch/http/tests/inspector-protocol/fenced-frame/automatic-beacon.https.js [ Failure Pass ] crbug.com/1521090 [ Mac12 ] virtual/static-routing-api/http/tests/inspector-protocol/service-worker/tentative/static-router/receive-router-rules-on-update.js [ Failure Pass ] -crbug.com/1522196 http/tests/devtools/resource-har-conversion.js [ Failure Pass ] - ### sheriff 2023-01-24 crbug.com/1521311 http/tests/devtools/service-workers/sw-navigate-useragent.js [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index f651d2fe..266014a 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -2672,5 +2672,15 @@ "bases": [ "external/wpt/custom-elements/state" ] + }, + { + "prefix": "prefers-default-scrollbar-styles", + "platforms": ["Linux"], + "exclusive_tests": "ALL", + "bases": ["scrollbars/prefers-default-scrollbar-styles"], + "args": ["--enable-blink-features=PreferDefaultScrollbarStyles", + "--blink-settings=prefersDefaultScrollbarStyles=true"], + "expires": "Feb 1, 2025", + "owners": ["evelynn.kaplan@microsoft.com", "almaher@microsoft.com"] } ]
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/resources/direct.py b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/resources/direct.py index c2bcfce..d30d41b 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/resources/direct.py +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/resources/direct.py
@@ -4,4 +4,8 @@ def main(request, response): if 'server_slow' in request.url_parts.query: time.sleep(0.2) + if 'server_no_content' in request.url_parts.query: + return 204, [(b'Content-Type', b'text/plain')], u'Network with %s request' % request.method + if 'server_not_found' in request.url_parts.query: + return 404, [(b'Content-Type', b'text/plain')], u'Not Found' return 200, [(b'Content-Type', b'text/plain')], u'Network with %s request' % request.method
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/static-router-race-network-and-fetch-handler.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/static-router-race-network-and-fetch-handler.https.html index de31f6c..0dad64ad9 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/static-router-race-network-and-fetch-handler.https.html +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/tentative/static-router/static-router-race-network-and-fetch-handler.https.html
@@ -61,5 +61,31 @@ const {requests} = await get_info_from_worker(worker); assert_equals(requests.length, 2); }, 'Subresource load matched the rule with race-network-and-fetch-handler source, and the server reseponse is faster than the fetch handler'); + +promise_test(async t => { + const rnd = randomString(); + const worker = await registerAndActivate(t, ROUTER_KEY, SW_SRC); + const iframe = await createIframe(t, FRAME_SRC); + // Expect the response from the network request. + const response = await iframe.contentWindow.fetch(`?nonce=${rnd}&sw_slow&server_no_content`); + assert_equals(response.status, 204); + // Ensure the fetch handler is also executed. + const {requests} = await get_info_from_worker(worker); + assert_equals(requests.length, 2); +}, 'Subresource load matched the rule with race-network-and-fetch-handler source, and the server reseponse with 204 response is faster than the fetch handler'); + + +promise_test(async t => { + const rnd = randomString(); + const worker = await registerAndActivate(t, ROUTER_KEY, SW_SRC); + const iframe = await createIframe(t, FRAME_SRC); + const response = await iframe.contentWindow.fetch(`?nonce=${rnd}&sw_slow&server_not_found`); + // Expect the response from the network request was faster, but the result was 404. + // So, the fetch handler result will be used instead. + assert_equals(response.status, 200); + assert_equals(await response.text(), rnd); + const {requests} = await get_info_from_worker(worker); + assert_equals(requests.length, 2); +}, 'Subresource load matched the rule with race-network-and-fetch-handler source, and the server reseponse is faster than the fetch handler, but not found'); </script> </body>
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-har-conversion-expected.txt b/third_party/blink/web_tests/http/tests/devtools/resource-har-conversion-expected.txt index e7337727..1591381 100644 --- a/third_party/blink/web_tests/http/tests/devtools/resource-har-conversion-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/resource-har-conversion-expected.txt
@@ -1,6 +1,8 @@ Tests conversion of Inspector's resource representation into HAR format. Page reloaded. +error: Failed getting cookie attribute: Discard +error: Failed getting cookie attribute: Version { creator : { name : "WebInspector"
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/interaction/focus/document-level-focus-apis/document-has-system-focus-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/interaction/focus/document-level-focus-apis/document-has-system-focus-expected.txt new file mode 100644 index 0000000..5214859 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/interaction/focus/document-level-focus-apis/document-has-system-focus-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +[FAIL] Top-level document receives blur/focus events and loses system focus during opening/closing of a popup + assert_true: Document received blur event when popup opened expected true got false +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-focus-2-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-focus-2-expected.txt deleted file mode 100644 index 5b37deb..0000000 --- a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-focus-2-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. -Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-orientation/onchange-event-subframe-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-orientation/onchange-event-subframe-expected.txt new file mode 100644 index 0000000..fa4e62a3c --- /dev/null +++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-orientation/onchange-event-subframe-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +[FAIL] Test subframes receive orientation change events + promise_test: Unhandled rejection with value: object "NotSupportedError: screen.orientation.lock() is not available on this device." +[FAIL] Check directly that events are fired in right order (from top to bottom) + promise_test: Unhandled rejection with value: object "NotSupportedError: screen.orientation.lock() is not available on this device." +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-pause-resume.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-pause-resume.tentative-expected.txt new file mode 100644 index 0000000..73b0b7e --- /dev/null +++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-pause-resume.tentative-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +[FAIL] speechSynthesis.pause() and resume() state and events + assert_unreached: error event Reached unreachable code +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/scrollbars/prefers-default-scrollbar-styles/webkit-scrollbar-styles-disabled.html b/third_party/blink/web_tests/scrollbars/prefers-default-scrollbar-styles/webkit-scrollbar-styles-disabled.html new file mode 100644 index 0000000..6759627 --- /dev/null +++ b/third_party/blink/web_tests/scrollbars/prefers-default-scrollbar-styles/webkit-scrollbar-styles-disabled.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<title> + Tests that the scrollbar styling using ::webkit-scrollbar pseudos is + disabled when there is a preference for default scrollbar styles. +</title> +<style> + p { + font-size: 100px; + } + + ::-webkit-scrollbar { + width: 100px; + height: 40px; + } + + ::-webkit-scrollbar-button + { + background-color: red; + } + + ::-webkit-scrollbar-corner { + background-color: orange; + } + + ::-webkit-scrollbar-thumb { + background-color: green; + } + + ::-webkit-scrollbar-track { + background-color: purple; + } + + ::-webkit-scrollbar-track-piece { + background-color: blue; + } +</style> +<body> + <p>testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest</p> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> +</body>
diff --git a/third_party/blink/web_tests/virtual/prefers-default-scrollbar-styles/README.md b/third_party/blink/web_tests/virtual/prefers-default-scrollbar-styles/README.md new file mode 100644 index 0000000..fd836a1 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefers-default-scrollbar-styles/README.md
@@ -0,0 +1,2 @@ +These tests run with the runtime feature PreferDefaultScrollbarStyles enabled +and the blink web setting prefersDefaultScrollbarStyles set to true. \ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/prefers-default-scrollbar-styles/scrollbars/prefers-default-scrollbar-styles/webkit-scrollbar-styles-disabled-expected.html b/third_party/blink/web_tests/virtual/prefers-default-scrollbar-styles/scrollbars/prefers-default-scrollbar-styles/webkit-scrollbar-styles-disabled-expected.html new file mode 100644 index 0000000..3e180d9 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefers-default-scrollbar-styles/scrollbars/prefers-default-scrollbar-styles/webkit-scrollbar-styles-disabled-expected.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<title> + Tests that the scrollbar styling using ::webkit-scrollbar pseudos is + disabled when there is a preference for default scrollbar styles. +</title> +<style> + p { + font-size: 100px; + } +</style> +<body> + <p>testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest</p> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> + <br><br><br><br><br> +</body>
diff --git a/third_party/blink/web_tests/wpt_internal/infrastructure/fail-before-timeout.html b/third_party/blink/web_tests/wpt_internal/infrastructure/fail-before-timeout.html new file mode 100644 index 0000000..108345d --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/infrastructure/fail-before-timeout.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<title>`run_wpt_tests.py` should ignore unexpected FAIL before expected TIMEOUT</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + test(() => { + assert_equals(1, 2); + }, 'Fail unexpectedly'); + + promise_test(async (t) => + new Promise((resolve) => t.step_timeout(resolve, 120000)), 'Timeout expectedly'); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/delay_get_texture.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/delay_get_texture.https.html new file mode 100644 index 0000000..8dce6d0b --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/delay_get_texture.https.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html class="reftest-wait"> + <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/" /> + <title>WebGPU delay getCurrentTexture</title> + <meta charset="utf-8" /> + <link rel="help" href="https://gpuweb.github.io/gpuweb/" /> + <meta name="assert" content="WebGPU delay calling getCurrentTexture should be presented correctly" /> + <link rel="match" href="./ref/delay_get_texture-ref.html" /> + <canvas id="cvs0" width="20" height="20" style="width: 20px; height: 20px;"></canvas> + <script type="module" src="delay_get_texture.html.js"></script> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/ref/delay_get_texture-ref.html b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/ref/delay_get_texture-ref.html new file mode 100644 index 0000000..624dadf9 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/webgpu/web_platform/reftests/ref/delay_get_texture-ref.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> + <base href="/gen/third_party/webgpu-cts/src/webgpu/web_platform/reftests/ref/" /> + <title>WebGPU delay getCurrentTexture (ref)</title> + <meta charset="utf-8" /> + <link rel="help" href="https://gpuweb.github.io/gpuweb/" /> + <canvas id="cvs0" width="20" height="20" style="width: 20px; height: 20px;"></canvas> + <script> + function draw(canvas) { + var c = document.getElementById(canvas); + var ctx = c.getContext('2d'); + ctx.fillStyle = '#00FF00'; + ctx.fillRect(0, 0, c.width, c.height); + } + + draw('cvs0'); + </script> +</html>
diff --git a/third_party/cardboard/proguard-rules.pro b/third_party/cardboard/proguard-rules.pro index a698b2365..b5ca79e 100644 --- a/third_party/cardboard/proguard-rules.pro +++ b/third_party/cardboard/proguard-rules.pro
@@ -20,3 +20,7 @@ getDistortionCoefficientsCount(); getLeftEyeFieldOfViewAngles(int); } +# Prevent native methods which are used from being obfuscated. +-keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class com.google.cardboard.sdk.** { + native <methods>; +}
diff --git a/third_party/catapult b/third_party/catapult index 27e029f..ca502d3 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit 27e029f52955bf8ac9e35a1dacf4f56bb39d3eb8 +Subproject commit ca502d307f30e7ac2de76211d8d590ff31e5080f
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index 94fec55..8460157 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit 94fec55cb64a630ad0790e1833dd195181ce6688 +Subproject commit 8460157bc5ad13094b0e93276c7387b47932195d
diff --git a/third_party/depot_tools b/third_party/depot_tools index 784db7a..74a6ca9 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 784db7a5f04f5093941b6c2228e40b9a10d553b2 +Subproject commit 74a6ca92bba677fc87328637bf573deb5944ac91
diff --git a/third_party/libc++/src b/third_party/libc++/src index 9d119c1..c51c9efb 160000 --- a/third_party/libc++/src +++ b/third_party/libc++/src
@@ -1 +1 @@ -Subproject commit 9d119c1f4a097b7d27210874f4eba3fc91a83a4e +Subproject commit c51c9efb6c5a83e0e25c1e30864449d2beadd7a8
diff --git a/third_party/libunwind/src b/third_party/libunwind/src index fc50574..8bad7bd 160000 --- a/third_party/libunwind/src +++ b/third_party/libunwind/src
@@ -1 +1 @@ -Subproject commit fc505746f02c927d792bdeb328307e0e87500342 +Subproject commit 8bad7bd6ec30f94bce82f7cb5b58ecbd6ce02996
diff --git a/third_party/openscreen/src b/third_party/openscreen/src index 739dc8a..03c85f7 160000 --- a/third_party/openscreen/src +++ b/third_party/openscreen/src
@@ -1 +1 @@ -Subproject commit 739dc8a257547a54c71ecf73bba66bef0726825a +Subproject commit 03c85f7fe80efa241092f258e33452f47b2ace4e
diff --git a/third_party/perfetto b/third_party/perfetto index 74cdba3..6821c955 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 74cdba3b28c2a48bb3c5b5cae32812eb6c76a8da +Subproject commit 6821c955bdf682556ec4828a174a9cd916d0a02a
diff --git a/third_party/skia b/third_party/skia index 9b103a4..fe4aa8a3 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 9b103a4148e291537909a1c0765b43a5125676d2 +Subproject commit fe4aa8a3ea5380f02ba16568299b2d11a2c0a41e
diff --git a/third_party/webgpu-cts/resource_files.txt b/third_party/webgpu-cts/resource_files.txt index f0e84564..2866cba 100644 --- a/third_party/webgpu-cts/resource_files.txt +++ b/third_party/webgpu-cts/resource_files.txt
@@ -1,14 +1,17 @@ README.md cache +four-colors-h264-bt601-hflip.mp4 four-colors-h264-bt601-rotate-180.mp4 four-colors-h264-bt601-rotate-270.mp4 four-colors-h264-bt601-rotate-90.mp4 +four-colors-h264-bt601-vflip.mp4 four-colors-h264-bt601.mp4 -four-colors-theora-bt601.ogv four-colors-vp8-bt601.webm +four-colors-vp9-bt601-hflip.mp4 four-colors-vp9-bt601-rotate-180.mp4 four-colors-vp9-bt601-rotate-270.mp4 four-colors-vp9-bt601-rotate-90.mp4 +four-colors-vp9-bt601-vflip.mp4 four-colors-vp9-bt601.mp4 four-colors-vp9-bt601.webm four-colors-vp9-bt709.webm
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src index e082b08..6493b87 160000 --- a/third_party/webgpu-cts/src +++ b/third_party/webgpu-cts/src
@@ -1 +1 @@ -Subproject commit e082b08475761a2ba6a3349dfea72f704c8b68d4 +Subproject commit 6493b876ade082dc4e4d883691e8900d5b42f01c
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt index 6b552a86..320c2cf 100644 --- a/third_party/webgpu-cts/ts_sources.txt +++ b/third_party/webgpu-cts/ts_sources.txt
@@ -179,6 +179,7 @@ src/webgpu/api/operation/memory_sync/buffer/buffer_sync_test.ts src/webgpu/api/operation/memory_sync/buffer/multiple_buffers.spec.ts src/webgpu/api/operation/memory_sync/buffer/single_buffer.spec.ts +src/webgpu/api/operation/memory_sync/texture/readonly_depth_stencil.spec.ts src/webgpu/api/operation/memory_sync/texture/texture_sync_test.ts src/webgpu/api/operation/memory_sync/texture/same_subresource.spec.ts src/webgpu/api/operation/pipeline/default_layout.spec.ts @@ -205,6 +206,7 @@ src/webgpu/api/operation/rendering/stencil.spec.ts src/webgpu/api/operation/resource_init/buffer.spec.ts src/webgpu/util/texture/subresource.ts +src/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.ts src/webgpu/api/operation/resource_init/check_texture/by_copy.ts src/webgpu/api/operation/resource_init/check_texture/by_ds_test.ts src/webgpu/api/operation/resource_init/check_texture/by_sampling.ts @@ -243,6 +245,7 @@ src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts src/webgpu/api/validation/capability_checks/limits/limit_utils.ts src/webgpu/api/validation/capability_checks/limits/maxBindGroups.spec.ts +src/webgpu/api/validation/capability_checks/limits/maxBindGroupsPlusVertexBuffers.spec.ts src/webgpu/api/validation/capability_checks/limits/maxBindingsPerBindGroup.spec.ts src/webgpu/api/validation/capability_checks/limits/maxBufferSize.spec.ts src/webgpu/api/validation/capability_checks/limits/maxColorAttachmentBytesPerSample.spec.ts @@ -359,10 +362,12 @@ src/webgpu/shader/types.ts src/webgpu/shader/values.ts src/webgpu/shader/execution/float_parse.spec.ts +src/webgpu/shader/execution/memory_layout.spec.ts src/webgpu/shader/execution/padding.spec.ts src/webgpu/shader/execution/robust_access.spec.ts src/webgpu/shader/execution/robust_access_vertex.spec.ts src/webgpu/shader/execution/shadow.spec.ts +src/webgpu/shader/execution/stage.spec.ts src/webgpu/shader/execution/zero_init.spec.ts src/webgpu/shader/execution/expression/expression.ts src/webgpu/shader/execution/expression/binary/af_addition.cache.ts @@ -480,6 +485,8 @@ src/webgpu/shader/execution/expression/call/builtin/distance.spec.ts src/webgpu/shader/execution/expression/call/builtin/dot.cache.ts src/webgpu/shader/execution/expression/call/builtin/dot.spec.ts +src/webgpu/shader/execution/expression/call/builtin/dot4I8Packed.spec.ts +src/webgpu/shader/execution/expression/call/builtin/dot4U8Packed.spec.ts src/webgpu/shader/execution/expression/call/builtin/dpdx.spec.ts src/webgpu/shader/execution/expression/call/builtin/dpdxCoarse.spec.ts src/webgpu/shader/execution/expression/call/builtin/dpdxFine.spec.ts @@ -533,6 +540,10 @@ src/webgpu/shader/execution/expression/call/builtin/pack2x16unorm.spec.ts src/webgpu/shader/execution/expression/call/builtin/pack4x8snorm.spec.ts src/webgpu/shader/execution/expression/call/builtin/pack4x8unorm.spec.ts +src/webgpu/shader/execution/expression/call/builtin/pack4xI8.spec.ts +src/webgpu/shader/execution/expression/call/builtin/pack4xI8Clamp.spec.ts +src/webgpu/shader/execution/expression/call/builtin/pack4xU8.spec.ts +src/webgpu/shader/execution/expression/call/builtin/pack4xU8Clamp.spec.ts src/webgpu/shader/execution/expression/call/builtin/pow.cache.ts src/webgpu/shader/execution/expression/call/builtin/pow.spec.ts src/webgpu/shader/execution/expression/call/builtin/quantizeToF16.cache.ts @@ -595,6 +606,8 @@ src/webgpu/shader/execution/expression/call/builtin/unpack4x8snorm.spec.ts src/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.cache.ts src/webgpu/shader/execution/expression/call/builtin/unpack4x8unorm.spec.ts +src/webgpu/shader/execution/expression/call/builtin/unpack4xI8.spec.ts +src/webgpu/shader/execution/expression/call/builtin/unpack4xU8.spec.ts src/webgpu/shader/execution/expression/call/builtin/workgroupBarrier.spec.ts src/webgpu/shader/execution/expression/call/builtin/atomics/harness.ts src/webgpu/shader/execution/expression/call/builtin/atomics/atomicAdd.spec.ts @@ -614,6 +627,8 @@ src/webgpu/shader/execution/expression/unary/af_arithmetic.spec.ts src/webgpu/shader/execution/expression/unary/af_assignment.cache.ts src/webgpu/shader/execution/expression/unary/af_assignment.spec.ts +src/webgpu/shader/execution/expression/unary/ai_assignment.cache.ts +src/webgpu/shader/execution/expression/unary/ai_assignment.spec.ts src/webgpu/shader/execution/expression/unary/bool_conversion.cache.ts src/webgpu/shader/execution/expression/unary/bool_conversion.spec.ts src/webgpu/shader/execution/expression/unary/bool_logical.spec.ts @@ -631,6 +646,7 @@ src/webgpu/shader/execution/expression/unary/i32_complement.spec.ts src/webgpu/shader/execution/expression/unary/i32_conversion.cache.ts src/webgpu/shader/execution/expression/unary/i32_conversion.spec.ts +src/webgpu/shader/execution/expression/unary/indirection.spec.ts src/webgpu/shader/execution/expression/unary/u32_complement.cache.ts src/webgpu/shader/execution/expression/unary/u32_complement.spec.ts src/webgpu/shader/execution/expression/unary/u32_conversion.cache.ts @@ -655,13 +671,17 @@ src/webgpu/shader/execution/shader_io/compute_builtins.spec.ts src/webgpu/shader/execution/shader_io/fragment_builtins.spec.ts src/webgpu/shader/execution/shader_io/shared_structs.spec.ts +src/webgpu/shader/execution/shader_io/workgroup_size.spec.ts +src/webgpu/shader/execution/statement/compound.spec.ts src/webgpu/shader/execution/statement/increment_decrement.spec.ts src/webgpu/shader/validation/shader_validation_test.ts src/webgpu/shader/validation/const_assert/const_assert.spec.ts +src/webgpu/shader/validation/decl/compound_statement.spec.ts src/webgpu/shader/validation/decl/const.spec.ts src/webgpu/shader/validation/decl/override.spec.ts src/webgpu/shader/validation/decl/util.ts src/webgpu/shader/validation/decl/ptr_spelling.spec.ts +src/webgpu/shader/validation/decl/var.spec.ts src/webgpu/shader/validation/decl/var_access_mode.spec.ts src/webgpu/shader/validation/expression/access/vector.spec.ts src/webgpu/shader/validation/expression/binary/bitwise_shift.spec.ts @@ -669,12 +689,14 @@ src/webgpu/shader/validation/expression/call/builtin/abs.spec.ts src/webgpu/shader/validation/expression/call/builtin/acos.spec.ts src/webgpu/shader/validation/expression/call/builtin/acosh.spec.ts +src/webgpu/shader/validation/expression/call/builtin/arrayLength.spec.ts src/webgpu/shader/validation/expression/call/builtin/asin.spec.ts src/webgpu/shader/validation/expression/call/builtin/asinh.spec.ts src/webgpu/shader/validation/expression/call/builtin/atan.spec.ts src/webgpu/shader/validation/expression/call/builtin/atan2.spec.ts src/webgpu/shader/validation/expression/call/builtin/atanh.spec.ts src/webgpu/shader/validation/expression/call/builtin/atomics.spec.ts +src/webgpu/shader/validation/expression/call/builtin/barriers.spec.ts src/webgpu/shader/validation/expression/call/builtin/bitcast.spec.ts src/webgpu/shader/validation/expression/call/builtin/ceil.spec.ts src/webgpu/shader/validation/expression/call/builtin/clamp.spec.ts @@ -685,6 +707,7 @@ src/webgpu/shader/validation/expression/call/builtin/dot4U8Packed.spec.ts src/webgpu/shader/validation/expression/call/builtin/exp.spec.ts src/webgpu/shader/validation/expression/call/builtin/exp2.spec.ts +src/webgpu/shader/validation/expression/call/builtin/floor.spec.ts src/webgpu/shader/validation/expression/call/builtin/inverseSqrt.spec.ts src/webgpu/shader/validation/expression/call/builtin/length.spec.ts src/webgpu/shader/validation/expression/call/builtin/log.spec.ts @@ -704,6 +727,7 @@ src/webgpu/shader/validation/expression/call/builtin/tan.spec.ts src/webgpu/shader/validation/expression/call/builtin/unpack4xI8.spec.ts src/webgpu/shader/validation/expression/call/builtin/unpack4xU8.spec.ts +src/webgpu/shader/validation/extension/pointer_composite_access.spec.ts src/webgpu/shader/validation/functions/alias_analysis.spec.ts src/webgpu/shader/validation/functions/restrictions.spec.ts src/webgpu/shader/validation/parse/align.spec.ts @@ -711,10 +735,13 @@ src/webgpu/shader/validation/parse/binary_ops.spec.ts src/webgpu/shader/validation/parse/blankspace.spec.ts src/webgpu/shader/validation/parse/break.spec.ts +src/webgpu/shader/validation/parse/break_if.spec.ts src/webgpu/shader/validation/parse/builtin.spec.ts src/webgpu/shader/validation/parse/comments.spec.ts +src/webgpu/shader/validation/parse/compound.spec.ts src/webgpu/shader/validation/parse/const.spec.ts src/webgpu/shader/validation/parse/const_assert.spec.ts +src/webgpu/shader/validation/parse/continuing.spec.ts src/webgpu/shader/validation/parse/diagnostic.spec.ts src/webgpu/shader/validation/parse/discard.spec.ts src/webgpu/shader/validation/parse/enable.spec.ts @@ -722,6 +749,7 @@ src/webgpu/shader/validation/parse/literal.spec.ts src/webgpu/shader/validation/parse/must_use.spec.ts src/webgpu/shader/validation/parse/pipeline_stage.spec.ts +src/webgpu/shader/validation/parse/requires.spec.ts src/webgpu/shader/validation/parse/semicolon.spec.ts src/webgpu/shader/validation/parse/source.spec.ts src/webgpu/shader/validation/parse/unary_ops.spec.ts @@ -743,6 +771,7 @@ src/webgpu/shader/validation/types/vector.spec.ts src/webgpu/shader/validation/uniformity/uniformity.spec.ts src/webgpu/util/copy_to_texture.ts +src/webgpu/util/texture/color_space_conversions.spec.ts src/webgpu/util/texture/texel_data.spec.ts src/webgpu/util/texture/texture_ok.spec.ts src/webgpu/web_platform/canvas/configure.spec.ts @@ -764,6 +793,7 @@ src/webgpu/web_platform/reftests/canvas_composite_alpha.html.ts src/webgpu/web_platform/reftests/canvas_image_rendering.html.ts src/webgpu/web_platform/reftests/create-pattern-data-url.ts +src/webgpu/web_platform/reftests/delay_get_texture.html.ts src/webgpu/web_platform/reftests/resize_observer.html.ts src/webgpu/web_platform/reftests/ref/canvas_colorspace-ref.html.ts src/webgpu/web_platform/worker/worker.spec.ts
diff --git a/third_party/webrtc b/third_party/webrtc index aaa123d..fe6178e 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit aaa123debbd106669fc849425b92607edbd5d26f +Subproject commit fe6178ef7d7f4f25ce93253bdda0b7daae0769a6
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 74bd19f..5ef5b54 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -20817,6 +20817,7 @@ <int value="56900498" label="OmniboxOneClickUnelide:enabled"/> <int value="57255632" label="site-isolation-for-password-sites:disabled"/> <int value="57639188" label="SoundContentSetting:disabled"/> + <int value="57730593" label="FileSystemProviderCloudFileSystem:enabled"/> <int value="57791920" label="MemoryCoordinator:enabled"/> <int value="57874550" label="AutofillOfferToSaveCardWithSameLastFour:disabled"/> @@ -24409,6 +24410,7 @@ <int value="1717987538" label="NTPTilesLowerResolutionFavicons:enabled"/> <int value="1718341860" label="NTPButton:enabled"/> <int value="1718421370" label="SharingHubLinkToggle:enabled"/> + <int value="1719019077" label="FileSystemProviderCloudFileSystem:disabled"/> <int value="1719189460" label="EnablePasswordSelection:disabled"/> <int value="1719958026" label="QueryTiles:enabled"/> <int value="1720399117" label="SkiaGraphite:enabled"/>
diff --git a/tools/metrics/histograms/metadata/cros_ml/enums.xml b/tools/metrics/histograms/metadata/cros_ml/enums.xml index fc496f7..644f356 100644 --- a/tools/metrics/histograms/metadata/cros_ml/enums.xml +++ b/tools/metrics/histograms/metadata/cros_ml/enums.xml
@@ -74,6 +74,12 @@ <int value="0" label="OK"/> <int value="1" label="MODEL_INTERPRETATION_ERROR"/> <int value="2" label="MEMORY_ALLOCATION_ERROR"/> + <int value="3" label="NNAPI_UNAVAILABLE"/> + <int value="4" label="NNAPI_USE_ERROR"/> + <int value="5" label="GPU_UNAVAILABLE"/> + <int value="6" label="GPU_USE_ERROR"/> + <int value="7" label="DELEGATE_CONFIG_ERROR"/> + <int value="8" label="NOT_FULLY_DELEGABLE"/> </enum> <enum name="MachineLearningServiceDocumentScannerResultEvent"> @@ -121,6 +127,8 @@ <int value="0" label="OK"/> <int value="1" label="MODEL_SPEC_ERROR"/> <int value="2" label="LOAD_MODEL_ERROR"/> + <int value="3" label="FEATURE_NOT_SUPPORTED_ERROR"/> + <int value="4" label="LANGUAGE_NOT_SUPPORTED_ERROR"/> </enum> <enum name="MachineLearningServiceMojoConnectionEvent">
diff --git a/tools/metrics/histograms/metadata/cros_ml/histograms.xml b/tools/metrics/histograms/metadata/cros_ml/histograms.xml index 44aaaae..cbc2b18 100644 --- a/tools/metrics/histograms/metadata/cros_ml/histograms.xml +++ b/tools/metrics/histograms/metadata/cros_ml/histograms.xml
@@ -559,6 +559,9 @@ <variant name="DocumentScanner.LoadModelResult"/> <variant name="HandwritingModel.LoadModelResult"/> <variant name="HandwritingModel.Recognize"/> + <variant name="ImageAnnotator.AnnotateEncodedImage"/> + <variant name="ImageAnnotator.AnnotateRawImage"/> + <variant name="ImageAnnotator.LoadModelResult"/> <variant name="SmartDimModel.CreateGraphExecutorResult"/> <variant name="SmartDimModel.ExecuteResult"/> <variant name="SmartDimModel.LoadModelResult"/> @@ -620,6 +623,7 @@ </summary> <token key="RequestName"> <variant name="DocumentScanner"/> + <variant name="ImageAnnotator"/> <variant name="SmartDimModel"/> <variant name="TestModel"/> <variant name="TextClassifier"/> @@ -639,6 +643,9 @@ <variant name="DocumentScanner.LoadModelResult"/> <variant name="HandwritingModel.LoadModelResult"/> <variant name="HandwritingModel.Recognize"/> + <variant name="ImageAnnotator.AnnotateEncodedImage"/> + <variant name="ImageAnnotator.AnnotateRawImage"/> + <variant name="ImageAnnotator.LoadModelResult"/> <variant name="SmartDimModel.CreateGraphExecutorResult"/> <variant name="SmartDimModel.ExecuteResult"/> <variant name="SmartDimModel.LoadModelResult"/>
diff --git a/tools/metrics/histograms/metadata/file/enums.xml b/tools/metrics/histograms/metadata/file/enums.xml index 7816590a..958f37f 100644 --- a/tools/metrics/histograms/metadata/file/enums.xml +++ b/tools/metrics/histograms/metadata/file/enums.xml
@@ -455,6 +455,8 @@ <int value="11" label="Metered connection"/> <int value="12" label="Empty alternate URL"/> <int value="13" label="Local file waiting for upload"/> + <int value="14" label="Disable Drive preference set"/> + <int value="15" label="Drive disabled for account type"/> </enum> <enum name="OfficeFileHandler">
diff --git a/tools/metrics/histograms/metadata/input/enums.xml b/tools/metrics/histograms/metadata/input/enums.xml index b522625..15c458ff 100644 --- a/tools/metrics/histograms/metadata/input/enums.xml +++ b/tools/metrics/histograms/metadata/input/enums.xml
@@ -227,6 +227,8 @@ <int value="39" label="PROMO_CARD_IMPRESSION"/> <int value="40" label="PROMO_CARD_EXPLICIT_DISMISSAL"/> <int value="41" label="CONSENT_SCREEN_IMPRESSION"/> + <int value="42" label="TEXT_INSERTION_REQUESTED"/> + <int value="43" label="TEXT_QUEUED_FOR_INSERTION"/> </enum> <enum name="IMEGrammarActions">
diff --git a/tools/metrics/histograms/metadata/profile/enums.xml b/tools/metrics/histograms/metadata/profile/enums.xml index df0b151..4c2fa163 100644 --- a/tools/metrics/histograms/metadata/profile/enums.xml +++ b/tools/metrics/histograms/metadata/profile/enums.xml
@@ -397,6 +397,7 @@ <int value="36" label="kWebAppUninstall"/> <int value="37" label="kOsIntegrationForceUnregistration"/> <int value="38" label="kRemoteDebugging"/> + <int value="39" label="kHeadlessCommand"/> </enum> <enum name="ProfileMenuActionableItem">
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml index fa71b789..cd99207 100644 --- a/tools/metrics/histograms/metadata/variations/histograms.xml +++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -289,6 +289,17 @@ </summary> </histogram> +<histogram name="Variations.LimitedEntropyTrial.AshSeedIsValid.OnSyncToLacros" + enum="BooleanValid" expires_after="2025-01-07"> + <owner>yulunz@chromium.org</owner> + <owner>src/base/metrics/OWNERS</owner> + <summary> + Whether the seed value to randomize the limited entropy synthetic trial is + valid. This is only emitted from LaCrOS clients when reading the seed value + from the Ash Chrome client. + </summary> +</histogram> + <histogram name="Variations.Limits.VariationKeySize.{Size}" units="KiB" expires_after="2024-11-01"> <owner>dalerogerson@google.com</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 75c15de..4ed0202 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "perfetto-luci-artifacts/v42.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "59e4abe43023a57a761547b00f0fe42414594049", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/9c3cfdb0dacc59243527a5cef0989a3db5c30c69/trace_processor_shell.exe" + "hash": "db063bbed4ddda62cdf181242abeb02fa44ce049", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/6821c955bdf682556ec4828a174a9cd916d0a02a/trace_processor_shell.exe" }, "linux_arm": { "hash": "46739eeb4b8f2a65a8a0aac57743767e6407f7bb", "full_remote_path": "perfetto-luci-artifacts/v42.0/linux-arm/trace_processor_shell" }, "mac": { - "hash": "d5f9f140e7d3ae096bba9b9008cb9589bd5912b6", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/74cdba3b28c2a48bb3c5b5cae32812eb6c76a8da/trace_processor_shell" + "hash": "4c06710a5566077117ad084bcf92bb8955c2931e", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/6821c955bdf682556ec4828a174a9cd916d0a02a/trace_processor_shell" }, "mac_arm64": { "hash": "789f24a091d50faafdd5d7c5096bb923d073f138", "full_remote_path": "perfetto-luci-artifacts/v42.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "e483814f76f9b7eec355f7b8a0ef6a2d191c25bd", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/74cdba3b28c2a48bb3c5b5cae32812eb6c76a8da/trace_processor_shell" + "hash": "c17caab00d94d8c803df62c76920f29c529de4d4", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6821c955bdf682556ec4828a174a9cd916d0a02a/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/file_manager/file_manager/common/js/filtered_volume_manager.ts b/ui/file_manager/file_manager/common/js/filtered_volume_manager.ts index bf01e623..862aca2 100644 --- a/ui/file_manager/file_manager/common/js/filtered_volume_manager.ts +++ b/ui/file_manager/file_manager/common/js/filtered_volume_manager.ts
@@ -267,9 +267,7 @@ // runtime "The event is already being dispatched." error. switch (event.type) { case 'drive-connection-changed': - if (this.isAllowedVolumeType_(VolumeType.DRIVE)) { - this.dispatchEvent(new CustomEvent('drive-connection-changed')); - } + this.dispatchEvent(new CustomEvent('drive-connection-changed')); break; case 'externally-unmounted': if (this.isAllowedVolume(event.detail)) { @@ -337,7 +335,7 @@ */ override getDriveConnectionState(): chrome.fileManagerPrivate.DriveConnectionState { - if (!this.isAllowedVolumeType_(VolumeType.DRIVE) || !this.volumeManager_) { + if (!this.volumeManager_) { return { type: chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE, reason: chrome.fileManagerPrivate.DriveOfflineReason.NO_SERVICE,
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.ts b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.ts index c163b63a..4b73d252 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.ts +++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {ImageLoaderClient} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js'; -import {LoadImageRequest, type LoadImageResponse, LoadImageResponseStatus} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; +import {createForUrl, type LoadImageResponse, LoadImageResponseStatus} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; import {getContentMetadata, getContentMimeType} from '../../../common/js/api.js'; @@ -168,7 +168,7 @@ (entry as FileEntry) .file( file => { - const request = LoadImageRequest.createForUrl(entry.toURL()); + const request = createForUrl(entry.toURL()); request.maxWidth = THUMBNAIL_MAX_WIDTH; request.maxHeight = THUMBNAIL_MAX_HEIGHT; request.timestamp = file.lastModified;
diff --git a/ui/file_manager/file_manager/foreground/js/quick_view_controller.ts b/ui/file_manager/file_manager/foreground/js/quick_view_controller.ts index afb18b2..40dec9d 100644 --- a/ui/file_manager/file_manager/foreground/js/quick_view_controller.ts +++ b/ui/file_manager/file_manager/foreground/js/quick_view_controller.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {ImageLoaderClient} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js'; -import {LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; +import {createForUrl, LoadImageResponse, LoadImageResponseStatus} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; import {assert} from 'chrome://resources/js/assert.js'; import type {VolumeManager} from '../../background/js/volume_manager.js'; @@ -635,7 +635,7 @@ private async loadThumbnailFromDrive_(url: string, modificationTime?: Date): Promise<LoadImageResponse> { const client = ImageLoaderClient.getInstance(); - const request = LoadImageRequest.createForUrl(url); + const request = createForUrl(url); request.cache = true; request.timestamp = modificationTime ? modificationTime.valueOf() : undefined; @@ -652,7 +652,7 @@ Promise<LoadImageResponse> { return new Promise((resolve, reject) => { entry.file((file) => { - const request = LoadImageRequest.createForUrl(entry.toURL()); + const request = createForUrl(entry.toURL()); request.maxWidth = THUMBNAIL_MAX_WIDTH; request.maxHeight = THUMBNAIL_MAX_HEIGHT; request.timestamp = file.lastModified;
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader.ts b/ui/file_manager/file_manager/foreground/js/thumbnail_loader.ts index 103e5deb..af11994 100644 --- a/ui/file_manager/file_manager/foreground/js/thumbnail_loader.ts +++ b/ui/file_manager/file_manager/foreground/js/thumbnail_loader.ts
@@ -4,7 +4,7 @@ import {ImageLoaderClient} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js'; import type {ImageTransformParam} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_orientation.js'; -import {LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; +import {createRequest, LoadImageResponse, LoadImageResponseStatus} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; import {getMediaType, isImage, isPDF, isRaw, isVideo} from '../../common/js/file_type.js'; @@ -28,7 +28,7 @@ /** * The image transform from metadata. */ - private transform_: ImageTransformParam|null = null; + private transform_?: ImageTransformParam = undefined; private loadTarget_: LoadTarget|null = null; private thumbnailUrl_: string|null; private fallbackUrl_: string|null = null; @@ -79,7 +79,7 @@ this.thumbnailUrl_ = this.metadata_.thumbnail.url; this.transform_ = (this.metadata_.thumbnail && this.metadata_.thumbnail.transform) ?? - null; + undefined; this.loadTarget_ = LoadTarget.CONTENT_METADATA; } break; @@ -100,7 +100,7 @@ this.thumbnailUrl_ = this.entry_.toURL(); this.transform_ = (this.metadata_.media && this.metadata_.media.imageTransform) ?? - null; + undefined; this.loadTarget_ = LoadTarget.FILE_ENTRY; } break; @@ -177,7 +177,7 @@ this.metadata_.filesystem.modificationTime && this.metadata_.filesystem.modificationTime.getTime(); this.taskId_ = ImageLoaderClient.loadToImage( - LoadImageRequest.createRequest({ + createRequest({ url: this.thumbnailUrl_, maxWidth: THUMBNAIL_MAX_WIDTH, maxHeight: THUMBNAIL_MAX_HEIGHT, @@ -226,7 +226,7 @@ this.metadata_.filesystem.modificationTime.getTime(); // Load using ImageLoaderClient. - const request = LoadImageRequest.createRequest({ + const request = createRequest({ url: requestUrl, maxWidth: THUMBNAIL_MAX_WIDTH, maxHeight: THUMBNAIL_MAX_HEIGHT,
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.ts b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.ts index a66bd7a..8b66c90 100644 --- a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.ts +++ b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.ts
@@ -4,7 +4,7 @@ import {ImageLoaderClient} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js'; import type {ImageOrientation, ImageTransformParam} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_orientation.js'; -import {LoadImageRequest, LoadImageResponse} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; +import {type LoadImageRequest, LoadImageResponse} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; import {MockEntry, MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_names.gni b/ui/file_manager/file_names.gni index adac2dac..60ba336 100644 --- a/ui/file_manager/file_names.gni +++ b/ui/file_manager/file_names.gni
@@ -2,7 +2,6 @@ image_loader_static_js_files = [ "image_loader/image_loader_util.js", "image_loader/image_request_task.js", - "image_loader/load_image_request.js", ] image_loader_ts = [ @@ -17,7 +16,7 @@ # "image_loader/image_request_task.ts", - # "image_loader/load_image_request.ts", + "image_loader/load_image_request.ts", "image_loader/piex_loader.ts",
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn index 4201e056..9914352 100644 --- a/ui/file_manager/image_loader/BUILD.gn +++ b/ui/file_manager/image_loader/BUILD.gn
@@ -39,7 +39,7 @@ "image_loader_util.js", "image_orientation.ts", "image_request_task.js", - "load_image_request.js", + "load_image_request.ts", "piex_loader.ts", "scheduler.ts", ]
diff --git a/ui/file_manager/image_loader/cache_unittest.ts b/ui/file_manager/image_loader/cache_unittest.ts index a506bec..bf4f656 100644 --- a/ui/file_manager/image_loader/cache_unittest.ts +++ b/ui/file_manager/image_loader/cache_unittest.ts
@@ -4,18 +4,18 @@ import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; -import {LoadImageRequest} from './load_image_request.js'; +import {cacheKey} from './load_image_request.js'; export function testCreateCacheKey() { - const key = LoadImageRequest.cacheKey({url: 'http://example.com/image.jpg'}); + const key = cacheKey({url: 'http://example.com/image.jpg'}); assertTrue(!!key); } export function testNotCreateCacheKey() { - let key = LoadImageRequest.cacheKey({url: 'data:xxx'}); + let key = cacheKey({url: 'data:xxx'}); assertFalse(!!key); - key = LoadImageRequest.cacheKey({url: 'DaTa:xxx'}); + key = cacheKey({url: 'DaTa:xxx'}); assertFalse(!!key); }
diff --git a/ui/file_manager/image_loader/image_loader.ts b/ui/file_manager/image_loader/image_loader.ts index 9a4ce4d..1aadb6b 100644 --- a/ui/file_manager/image_loader/image_loader.ts +++ b/ui/file_manager/image_loader/image_loader.ts
@@ -5,10 +5,10 @@ import {assert} from 'chrome://resources/js/assert.js'; import {ImageCache} from './cache.js'; -import {ImageOrientation} from './image_orientation.js'; import type {ImageTransformParam} from './image_orientation.js'; +import {ImageOrientation} from './image_orientation.js'; import {ImageRequestTask} from './image_request_task.js'; -import {LoadImageRequest, LoadImageResponse} from './load_image_request.js'; +import {type LoadImageRequest, LoadImageResponse} from './load_image_request.js'; import {Scheduler} from './scheduler.js'; let instance: ImageLoader|null = null;
diff --git a/ui/file_manager/image_loader/image_loader_client.ts b/ui/file_manager/image_loader/image_loader_client.ts index dfdca8f..b5ddf937 100644 --- a/ui/file_manager/image_loader/image_loader_client.ts +++ b/ui/file_manager/image_loader/image_loader_client.ts
@@ -4,17 +4,7 @@ import {LruCache} from 'chrome://file-manager/common/js/lru_cache.js'; -import {LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js'; - -// TODO(b/319188711): Share this definition with load_image_request.js when it's -// converted to TS. -interface CacheValue { - timestamp: number|null; - width: number; - height: number; - ifd: string|null; - data: string; -} +import {cacheKey, type CacheValue, createCancel, type LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js'; let instance: ImageLoaderClient|null = null; @@ -68,16 +58,16 @@ request.url = request.url.replace(CLIENT_SWA_REGEX, IMAGE_LOADER_URL); // Try to load from cache, if available. - const cacheKey = LoadImageRequest.cacheKey(request); - if (cacheKey) { + const key = cacheKey(request); + if (key) { if (request.cache) { // Load from cache. - let cachedValue: CacheValue|null = this.cache_.get(cacheKey); + let cachedValue: CacheValue|null = this.cache_.get(key); // Check if the image in cache is up to date. If not, then remove it. // It relies on comparing `null` equals to `undefined`. // eslint-disable-next-line eqeqeq if (cachedValue && cachedValue.timestamp != request.timestamp) { - this.cache_.remove(cacheKey); + this.cache_.remove(key); cachedValue = null; } if (cachedValue && cachedValue.data && cachedValue.width && @@ -93,7 +83,7 @@ } } else { // Remove from cache. - this.cache_.remove(cacheKey); + this.cache_.remove(key); } } @@ -110,11 +100,11 @@ } const result = resultData; // Save to cache. - if (cacheKey && request.cache) { + if (key && request.cache) { const value: CacheValue|null = LoadImageResponse.cacheValue(result, request.timestamp); if (value) { - this.cache_.put(cacheKey, value, value.data.length); + this.cache_.put(key, value, value.data.length); } } callback(result); @@ -128,8 +118,7 @@ * @param taskId Task id returned by ImageLoaderClient.load(). */ cancel(taskId: number) { - ImageLoaderClient.sendMessage_( - LoadImageRequest.createCancel(taskId), (_result) => {}); + ImageLoaderClient.sendMessage_(createCancel(taskId), (_result) => {}); } // Helper functions.
diff --git a/ui/file_manager/image_loader/image_loader_client_unittest.ts b/ui/file_manager/image_loader/image_loader_client_unittest.ts index bcbabe7..6f617f5 100644 --- a/ui/file_manager/image_loader/image_loader_client_unittest.ts +++ b/ui/file_manager/image_loader/image_loader_client_unittest.ts
@@ -5,7 +5,7 @@ import {assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; import {ImageLoaderClient} from './image_loader_client.js'; -import {LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js'; +import {createForUrl, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js'; /** * Lets the client to load URL and returns the local cache (not caches in the @@ -26,7 +26,7 @@ {width: 100, height: 100, ifd: null, data: 'ImageData'})); }; - const request = LoadImageRequest.createForUrl(url); + const request = createForUrl(url); request.cache = cache; return new Promise((fulfill) => {
diff --git a/ui/file_manager/image_loader/image_loader_unittest.js b/ui/file_manager/image_loader/image_loader_unittest.js index b127c3e2..7010c96 100644 --- a/ui/file_manager/image_loader/image_loader_unittest.js +++ b/ui/file_manager/image_loader/image_loader_unittest.js
@@ -6,7 +6,6 @@ import {ImageLoaderUtil} from './image_loader_util.js'; import {ImageOrientation} from './image_orientation.js'; -import {LoadImageRequest} from './load_image_request.js'; /** @@ -17,8 +16,7 @@ * @return {!ImageLoaderUtil.CopyParameters} Calculated copy parameters. */ function calculateCopyParametersFromOptions(source, options) { - return ImageLoaderUtil.calculateCopyParameters( - source, /** @type{!LoadImageRequest} */ (options)); + return ImageLoaderUtil.calculateCopyParameters(source, options); } /**
diff --git a/ui/file_manager/image_loader/image_loader_util.js b/ui/file_manager/image_loader/image_loader_util.js index 9904b6185..b3b9d12 100644 --- a/ui/file_manager/image_loader/image_loader_util.js +++ b/ui/file_manager/image_loader/image_loader_util.js
@@ -4,8 +4,6 @@ import {assert} from 'chrome://resources/ash/common/assert.js'; -import {LoadImageRequest} from './load_image_request.js'; - export function ImageLoaderUtil() {} /** @@ -13,7 +11,8 @@ * * @param {number} width Source width. * @param {number} height Source height. - * @param {!LoadImageRequest} request The request, containing resizing options. + * @param {!import('./load_image_request.js').LoadImageRequest} request The + * request, containing resizing options. * @return {boolean} True if yes, false if not. */ ImageLoaderUtil.shouldProcess = function(width, height, request) { @@ -45,7 +44,8 @@ * * @param {number} width Source width. * @param {number} height Source height. - * @param {!LoadImageRequest} request The request, containing resizing options. + * @param {!import('./load_image_request.js').LoadImageRequest} request The + * request, containing resizing options. * @return {!{width: number, height:number}} Dimensions. */ ImageLoaderUtil.resizeDimensions = function(width, height, request) { @@ -88,7 +88,8 @@ * * @param {HTMLCanvasElement|HTMLImageElement} source Source image or canvas. * @param {HTMLCanvasElement} target Target canvas. - * @param {!LoadImageRequest} request The request, containing resizing options. + * @param {!import('./load_image_request.js').LoadImageRequest} request The + * request, containing resizing options. */ ImageLoaderUtil.resizeAndCrop = function(source, target, request) { // Calculates copy parameters. @@ -131,7 +132,8 @@ * Calculates copy parameters. * * @param {HTMLCanvasElement|HTMLImageElement} source Source image or canvas. - * @param {!LoadImageRequest} request The request, containing resizing options. + * @param {!import('./load_image_request.js').LoadImageRequest} request The + * request, containing resizing options. * @return {!ImageLoaderUtil.CopyParameters} Calculated copy parameters. */ ImageLoaderUtil.calculateCopyParameters = function(source, request) {
diff --git a/ui/file_manager/image_loader/image_orientation.ts b/ui/file_manager/image_loader/image_orientation.ts index 88cfe03c..351aade 100644 --- a/ui/file_manager/image_loader/image_orientation.ts +++ b/ui/file_manager/image_loader/image_orientation.ts
@@ -12,7 +12,6 @@ /** * Class representing image orientation. - * @final */ export class ImageOrientation { /**
diff --git a/ui/file_manager/image_loader/image_request_task.js b/ui/file_manager/image_loader/image_request_task.js index 2c21e34..1283073 100644 --- a/ui/file_manager/image_loader/image_request_task.js +++ b/ui/file_manager/image_loader/image_request_task.js
@@ -8,7 +8,7 @@ import {ImageCache} from './cache.js'; import {ImageLoaderUtil} from './image_loader_util.js'; import {ImageOrientation} from './image_orientation.js'; -import {LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js'; +import {cacheKey, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js'; import {PiexLoader} from './piex_loader.js'; /** @@ -19,7 +19,8 @@ /** * @param {string} id Request ID. * @param {ImageCache} cache Cache object. - * @param {LoadImageRequest} request Request message as a hash array. + * @param {import('./load_image_request.js').LoadImageRequest} request Request + * message as a hash array. * @param {(a: LoadImageResponse)=> void} callback Response handler. */ constructor(id, cache, request, callback) { @@ -37,7 +38,7 @@ this.cache_ = cache; /** - * @type {!LoadImageRequest} + * @type {!import('./load_image_request.js').LoadImageRequest} * @private */ this.request_ = request; @@ -193,9 +194,9 @@ * @private */ loadFromCache_(onSuccess, onFailure) { - const cacheKey = LoadImageRequest.cacheKey(this.request_); + const key = cacheKey(this.request_); - if (!cacheKey) { + if (!key) { // Cache key is not provided for the request. onFailure(); return; @@ -204,7 +205,7 @@ if (!this.request_.cache) { // Cache is disabled for this request; therefore, remove it from cache // if existed. - this.cache_.removeImage(cacheKey); + this.cache_.removeImage(key); onFailure(); return; } @@ -220,7 +221,7 @@ // string | null, d: string) => void' is not assignable to parameter of type // '(width: number, height: number, ifd?: string | undefined, data?: string // | undefined) => void'. - this.cache_.loadImage(cacheKey, timestamp, onSuccess, onFailure); + this.cache_.loadImage(key, timestamp, onSuccess, onFailure); } /** @@ -239,15 +240,15 @@ return; } - const cacheKey = LoadImageRequest.cacheKey(this.request_); - if (!cacheKey) { + const key = cacheKey(this.request_); + if (!key) { // Cache key is not provided for the request. return; } // @ts-ignore: error TS2345: Argument of type 'string | null' is not // assignable to parameter of type 'string | undefined'. - this.cache_.saveImage(cacheKey, timestamp, width, height, this.ifd_, data); + this.cache_.saveImage(key, timestamp, width, height, this.ifd_, data); } /**
diff --git a/ui/file_manager/image_loader/load_image_request.js b/ui/file_manager/image_loader/load_image_request.js deleted file mode 100644 index ec4b563c..0000000 --- a/ui/file_manager/image_loader/load_image_request.js +++ /dev/null
@@ -1,227 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {assert} from 'chrome://resources/ash/common/assert.js'; - - -/** - * Response status. - * - * @enum {string} - */ -export const LoadImageResponseStatus = { - SUCCESS: 'success', - ERROR: 'error', -}; - -/** - * Structure of the response object passed to the LoadImageRequest callback. - * All methods must be static since this is passed between isolated contexts. - * - * @struct - */ -export class LoadImageResponse { - /** - * @param {!LoadImageResponseStatus} status - * @param {?number} taskId or null if fulfilled by the client-side cache. - * @param {{width:number, height:number, ifd:?string, data:string}=} - * opt_result - */ - constructor(status, taskId, opt_result) { - /** @type {!LoadImageResponseStatus} */ - this.status = status; - /** @type {?number} */ - this.taskId = taskId; - - if (status === LoadImageResponseStatus.ERROR) { - return; - } - - // Response result defined only when status === SUCCESS. - assert(opt_result); - - /** @type {number|undefined} */ - // @ts-ignore: error TS18048: 'opt_result' is possibly 'undefined'. - this.width = opt_result.width; - /** @type {number|undefined} */ - // @ts-ignore: error TS18048: 'opt_result' is possibly 'undefined'. - this.height = opt_result.height; - /** @type {?string} */ - // @ts-ignore: error TS18048: 'opt_result' is possibly 'undefined'. - this.ifd = opt_result.ifd; - - /** - * The (compressed) image data as a data URL. - * @type {string|undefined} - */ - // @ts-ignore: error TS18048: 'opt_result' is possibly 'undefined'. - this.data = opt_result.data; - } - - /** - * Returns the cacheable result value for |response|, or null for an error. - * - * @param {!LoadImageResponse} response Response data from the ImageLoader. - * @param {number|undefined} timestamp The request timestamp. If undefined, - * then null is used. Currently this disables any caching in the - * ImageLoader, but disables only *expiration* in the client unless a - * timestamp is presented on a later request. - * @return {?{ - * timestamp: ?number, - * width: number, - * height: number, - * ifd: ?string, - * data: string - * }} - */ - static cacheValue(response, timestamp) { - if (!response || response.status === LoadImageResponseStatus.ERROR) { - return null; - } - - // Response result defined only when status === SUCCESS. - assert(response.width); - assert(response.height); - assert(response.data); - - return { - timestamp: timestamp || null, - // @ts-ignore: error TS2322: Type 'number | undefined' is not assignable - // to type 'number'. - width: response.width, - // @ts-ignore: error TS2322: Type 'number | undefined' is not assignable - // to type 'number'. - height: response.height, - ifd: response.ifd, - // @ts-ignore: error TS2322: Type 'string | undefined' is not assignable - // to type 'string'. - data: response.data, - }; - } -} - -/** - * Encapsulates a request to load an image. - * All methods must be static since this is passed between isolated contexts. - * - * @struct - */ -export class LoadImageRequest { - constructor() { - // Parts that uniquely identify the request. - - /** - * Url of the requested image. Undefined only for cancellations. - * @type {string|undefined} - */ - this.url; - - /** - * @type{import('./image_orientation.js').ImageOrientation|import('./image_orientation.js').ImageTransformParam|undefined} - */ - this.orientation; - /** @type {number|undefined} */ - this.scale; - /** @type {number|undefined} */ - this.width; - /** @type {number|undefined} */ - this.height; - /** @type {number|undefined} */ - this.maxWidth; - /** @type {number|undefined} */ - this.maxHeight; - - // Parts that control the request flow. - - /** @type {number|undefined} */ - this.taskId; - /** @type {boolean|undefined} */ - this.cancel; - /** @type {boolean|undefined} */ - this.crop; - /** @type {number|undefined} */ - this.timestamp; - /** @type {boolean|undefined} */ - this.cache; - /** @type {number|undefined} */ - this.priority; - } - - /** - * Creates a cache key. - * - * @return {?string} Cache key. It may be null if the cache does not support - * the request. e.g. Data URI. - */ - // @ts-ignore: error TS7006: Parameter 'request' implicitly has an 'any' type. - static cacheKey(request) { - if (/^data:/i.test(request.url)) { - return null; - } - return JSON.stringify({ - url: request.url, - orientation: request.orientation, - scale: request.scale, - width: request.width, - height: request.height, - maxWidth: request.maxWidth, - maxHeight: request.maxHeight, - }); - } - - /** - * Creates a cancel request. - * - * @param{number} taskId The task to cancel. - * @return {!LoadImageRequest} - */ - static createCancel(taskId) { - return /** @type {!LoadImageRequest} */ ({taskId: taskId, cancel: true}); - } - - /** - * Creates a load request from an option map. - * Only the timestamp may be undefined. - * - * @param {{ - * url: !string, - * maxWidth: number, - * maxHeight: number, - * cache: boolean, - * priority: number, - * timestamp: (number|undefined), - * orientation: ?import('./image_orientation.js').ImageTransformParam, - * }} params Request parameters. - * @return {!LoadImageRequest} - */ - static createRequest(params) { - return /** @type {!LoadImageRequest} */ (params); - } - - /** - * Creates a request to load a full-sized image. - * Only the timestamp may be undefined. - * - * @param {{ - * url: !string, - * cache: boolean, - * priority: number, - * timestamp: (?number|undefined), - * }} params Request parameters. - * @return {!LoadImageRequest} - */ - static createFullImageRequest(params) { - return /** @type {!LoadImageRequest} */ (params); - } - - /** - * Creates a load request from a url string. All options are undefined. - * - * @param {string} url - * @return {!LoadImageRequest} - */ - static createForUrl(url) { - return /** @type {!LoadImageRequest} */ ({url: url}); - } -}
diff --git a/ui/file_manager/image_loader/load_image_request.ts b/ui/file_manager/image_loader/load_image_request.ts new file mode 100644 index 0000000..7ddc3d5 --- /dev/null +++ b/ui/file_manager/image_loader/load_image_request.ts
@@ -0,0 +1,180 @@ +// Copyright 2018 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert} from 'chrome://resources/js/assert.js'; + +import type {ImageOrientation, ImageTransformParam} from './image_orientation.js'; + +export interface CacheValue { + timestamp: number|null; + width: number; + height: number; + ifd: string|null; + data: string; +} + +/** + * Response status. + */ +export enum LoadImageResponseStatus { + SUCCESS = 'success', + ERROR = 'error', +} + +/** + * Structure of the response object passed to the LoadImageRequest callback. + * All methods must be static since this is passed between isolated contexts. + */ +export class LoadImageResponse { + status: LoadImageResponseStatus; + taskId: number|null; + width?: number; + height?: number; + ifd: string|null = null; + /** The (compressed) image data as a data URL. */ + data?: string; + + /** @param taskId or null if fulfilled by the client-side cache. */ + constructor( + status: LoadImageResponseStatus, taskId: number|null, + result?: + {width: number, height: number, ifd: string|null, data: string}) { + this.status = status; + this.taskId = taskId; + + if (status === LoadImageResponseStatus.ERROR) { + return; + } + + // Response result defined only when status === SUCCESS. + assert(result); + + this.width = result.width; + this.height = result.height; + this.ifd = result.ifd; + + this.data = result.data; + } + + /** + * Returns the cacheable result value for |response|, or null for an error. + * + * @param response Response data from the ImageLoader. + * @param timestamp The request timestamp. If undefined, then null is used. + * Currently this disables any caching in the ImageLoader, but disables + * only *expiration* in the client unless a timestamp is presented on a + * later request. + */ + static cacheValue(response: LoadImageResponse, timestamp: number|undefined): + CacheValue|null { + if (!response || response.status === LoadImageResponseStatus.ERROR) { + return null; + } + + // Response result defined only when status === SUCCESS. + assert(response.width); + assert(response.height); + assert(response.data); + + return { + timestamp: timestamp || null, + width: response.width, + height: response.height, + ifd: response.ifd, + data: response.data, + }; + } +} + +/** + * Encapsulates a request to load an image. + * All methods must be static since this is passed between isolated contexts. + */ +export interface LoadImageRequest { + // Parts that uniquely identify the request. + /** Url of the requested image. Undefined only for cancellations. */ + url?: string; + orientation?: ImageOrientation|ImageTransformParam; + scale?: number; + width?: number; + height?: number; + maxWidth?: number; + maxHeight?: number; + + // Parts that control the request flow. + taskId?: number; + cancel?: boolean; + crop?: boolean; + timestamp?: number; + cache?: boolean; + priority?: number; +} + +/** + * Creates a cache key. + * + * @return Cache key. It may be null if the cache does not support the request. + * e.g. Data URI. + */ +export function cacheKey(request: LoadImageRequest): string|null { + if (/^data:/i.test(request.url ?? '')) { + return null; + } + return JSON.stringify({ + url: request.url, + orientation: request.orientation, + scale: request.scale, + width: request.width, + height: request.height, + maxWidth: request.maxWidth, + maxHeight: request.maxHeight, + }); +} + +/** + * Creates a cancel request. + * + * @param taskId The task to cancel. + */ +export function createCancel(taskId: number): LoadImageRequest { + return {taskId: taskId, cancel: true}; +} + +/** + * Creates a load request from an option map. + * Only the timestamp may be undefined. + * + * @param params Request parameters. + */ +export function createRequest(params: { + url: string, + maxWidth: number, + maxHeight: number, + cache: boolean, + priority: number, + timestamp?: number, + orientation?: ImageTransformParam, +}): LoadImageRequest { + return params; +} + +/** + * Creates a request to load a full-sized image. + * Only the timestamp may be undefined. + * + * @param params Request parameters. + */ +export function createFullImageRequest(params: { + url: string, + cache: boolean, + priority: number, + timestamp?: number, +}): LoadImageRequest { + return params; +} + +/** Creates a load request from a url string. All options are undefined. */ +export function createForUrl(url: string): LoadImageRequest { + return {url: url}; +}
diff --git a/ui/gfx/linux/fontconfig_util.cc b/ui/gfx/linux/fontconfig_util.cc index 8aed8ede..cd3589c2 100644 --- a/ui/gfx/linux/fontconfig_util.cc +++ b/ui/gfx/linux/fontconfig_util.cc
@@ -30,6 +30,13 @@ FILE_PATH_LITERAL("/usr/share/fonts/google-sans/static"); #endif +#if BUILDFLAG(IS_CHROMEOS_ASH) +// This should match `imageloader::kImageloaderMountBase` from +// //third_party/cros_system_api/constants/imageloader.h. +constexpr base::FilePath::CharType kImageloaderMountBase[] = + FILE_PATH_LITERAL("/run/imageloader/"); +#endif + // A singleton class to wrap a global font-config configuration. The // configuration reference counter is incremented to avoid the deletion of the // structure while being used. This class is single-threaded and should only be @@ -274,4 +281,28 @@ } } +#if BUILDFLAG(IS_CHROMEOS_ASH) +bool AddAppFontDir(base::FilePath dir) { + if (dir.ReferencesParent()) { + // Possible path traversal. + return false; + } + if (!base::FilePath(kImageloaderMountBase).IsParent(dir)) { + // Not a DLC path. + return false; + } + + FcConfig* config = GetGlobalFontConfig(); + + // Points to memory owned by `dir`. + const FcChar8* dir_fcstring = + reinterpret_cast<const FcChar8*>(dir.value().c_str()); + + // Adds the folder to the available fonts in the application. Returns + // false only when fonts cannot be added due to "allocation failure". + // https://www.freedesktop.org/software/fontconfig/fontconfig-devel/fcconfigappfontadddir.html + return FcConfigAppFontAddDir(config, dir_fcstring); +} +#endif + } // namespace gfx
diff --git a/ui/gfx/linux/fontconfig_util.h b/ui/gfx/linux/fontconfig_util.h index e17acaa..2caf517 100644 --- a/ui/gfx/linux/fontconfig_util.h +++ b/ui/gfx/linux/fontconfig_util.h
@@ -47,6 +47,13 @@ GFX_EXPORT void GetFontRenderParamsFromFcPattern(FcPattern* pattern, FontRenderParams* param_out); +#if BUILDFLAG(IS_CHROMEOS_ASH) +// Adds a given directory to the available fonts in the application. +// Directory must start with `/run/imageloader/` (guaranteed by DLC). +// Returns whether the fonts were added or not. +GFX_EXPORT bool AddAppFontDir(base::FilePath dir); +#endif + } // namespace gfx #endif // UI_GFX_LINUX_FONTCONFIG_UTIL_H_
diff --git a/ui/gl/gl_surface_stub.cc b/ui/gl/gl_surface_stub.cc index 9d2b7dd58..d68f172 100644 --- a/ui/gl/gl_surface_stub.cc +++ b/ui/gl/gl_surface_stub.cc
@@ -23,7 +23,7 @@ } bool GLSurfaceStub::IsOffscreen() { - return false; + return true; } gfx::SwapResult GLSurfaceStub::SwapBuffers(PresentationCallback callback,
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index 28dd264c..239ff372 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -250,7 +250,7 @@ // Default to using ANGLE's Metal backend. BASE_FEATURE(kDefaultANGLEMetal, "DefaultANGLEMetal", -#if BUILDFLAG(IS_IOS) || (BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM64)) +#if BUILDFLAG(IS_IOS) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/ui/gl/init/gl_factory_android.cc b/ui/gl/init/gl_factory_android.cc index 28b4dd1..b12f931f 100644 --- a/ui/gl/init/gl_factory_android.cc +++ b/ui/gl/init/gl_factory_android.cc
@@ -95,11 +95,15 @@ TRACE_EVENT0("gpu", "gl::init::CreateGLContext"); switch (GetGLImplementation()) { case kGLImplementationMockGL: - return scoped_refptr<GLContext>(new GLContextStub(share_group)); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - new GLContextStub(share_group); - stub_context->SetUseStubApi(true); + MakeRefCounted<GLContextStub>(share_group); + if (GetGLImplementation() == kGLImplementationStubGL) { + stub_context->SetUseStubApi(true); + } + // The stub ctx needs to be initialized so that the gl::GLContext can + // store the |compatible_surface|. + stub_context->Initialize(compatible_surface, attribs); return stub_context; } case kGLImplementationDisabled:
diff --git a/ui/gl/init/gl_factory_mac.cc b/ui/gl/init/gl_factory_mac.cc index 64aee97..2726747 100644 --- a/ui/gl/init/gl_factory_mac.cc +++ b/ui/gl/init/gl_factory_mac.cc
@@ -45,11 +45,15 @@ return InitializeGLContext(new GLContextEGL(share_group), compatible_surface, attribs); case kGLImplementationMockGL: - return new GLContextStub(share_group); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - new GLContextStub(share_group); - stub_context->SetUseStubApi(true); + base::MakeRefCounted<GLContextStub>(share_group); + if (GetGLImplementation() == kGLImplementationStubGL) { + stub_context->SetUseStubApi(true); + } + // The stub ctx needs to be initialized so that the gl::GLContext can + // store the |compatible_surface|. + stub_context->Initialize(compatible_surface, attribs); return stub_context; } default:
diff --git a/ui/gl/init/gl_factory_ozone.cc b/ui/gl/init/gl_factory_ozone.cc index 2c02251b..2d10c7c 100644 --- a/ui/gl/init/gl_factory_ozone.cc +++ b/ui/gl/init/gl_factory_ozone.cc
@@ -42,17 +42,22 @@ attribs); } + scoped_refptr<GLContextStub> context; switch (GetGLImplementation()) { case kGLImplementationMockGL: - return scoped_refptr<GLContext>(new GLContextStub(share_group)); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - new GLContextStub(share_group); - stub_context->SetUseStubApi(true); + base::MakeRefCounted<GLContextStub>(share_group); + if (GetGLImplementation() == kGLImplementationStubGL) { + stub_context->SetUseStubApi(true); + } + // The stub ctx needs to be initialized so that the gl::GLContext can + // store the |compatible_surface|. + stub_context->Initialize(compatible_surface, attribs); return stub_context; } case kGLImplementationDisabled: - return nullptr; + break; default: NOTREACHED() << "Expected Mock or Stub, actual:" << GetGLImplementation(); }
diff --git a/ui/gl/init/gl_factory_win.cc b/ui/gl/init/gl_factory_win.cc index 3398765..2d6ba9d 100644 --- a/ui/gl/init/gl_factory_win.cc +++ b/ui/gl/init/gl_factory_win.cc
@@ -46,11 +46,15 @@ return InitializeGLContext(new GLContextEGL(share_group), compatible_surface, attribs); case kGLImplementationMockGL: - return new GLContextStub(share_group); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - new GLContextStub(share_group); - stub_context->SetUseStubApi(true); + base::MakeRefCounted<GLContextStub>(share_group); + if (GetGLImplementation() == kGLImplementationStubGL) { + stub_context->SetUseStubApi(true); + } + // The stub ctx needs to be initialized so that the gl::GLContext can + // store the |compatible_surface|. + stub_context->Initialize(compatible_surface, attribs); return stub_context; } case kGLImplementationDisabled:
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index 1aad752..593009c1 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -1321,6 +1321,7 @@ wl::EnableAuraShellProtocol::kEnabled}, wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true})); + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1})); } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_output_unittest.cc b/ui/ozone/platform/wayland/host/wayland_output_unittest.cc index 0448397..4aeee57 100644 --- a/ui/ozone/platform/wayland/host/wayland_output_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_output_unittest.cc
@@ -144,7 +144,8 @@ WaylandOutputWithAuraOutputManagerTest() : WaylandTestSimple(wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true}) {} + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1}) {} WaylandOutputManager* wayland_output_manager() { auto* wayland_output_manager = connection_->wayland_output_manager();
diff --git a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc index 3b4b9bb9..1c06317 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
@@ -1421,7 +1421,8 @@ wl::EnableAuraShellProtocol::kEnabled}, wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true})); + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1})); INSTANTIATE_TEST_SUITE_P( XdgVersionStableTest, @@ -1430,7 +1431,8 @@ wl::EnableAuraShellProtocol::kEnabled}, wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true})); + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1})); #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc b/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc index d2f197c..df8f8b32 100644 --- a/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc
@@ -59,7 +59,8 @@ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled}, wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true})); + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1})); } // namespace } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc index 1d4a1daf..3964d3f 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -1888,6 +1888,7 @@ WaylandWindowDragControllerTest, Values(wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true})); + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1})); } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc index f89eb1d..f3458e2 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -5238,7 +5238,8 @@ wl::EnableAuraShellProtocol::kEnabled}, wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true})); + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1})); #endif INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, @@ -5253,7 +5254,8 @@ wl::EnableAuraShellProtocol::kEnabled}, wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true})); + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1})); #endif } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_unittest.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_unittest.cc index 98ef0ead..af5f7bded 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output_manager_unittest.cc
@@ -50,7 +50,8 @@ WaylandZAuraOutputManagerTest() : WaylandTestSimple(wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, - .use_aura_output_manager = true}) {} + .aura_output_manager_protocol = + wl::AuraOutputManagerProtocol::kEnabledV1}) {} protected: // Sends sample metrics to the primary output configured for this fixture. @@ -273,14 +274,14 @@ // Activate the secondary output. PostToServerAndWait([&](wl::TestWaylandServerThread* server) { - server->zaura_output_manager()->SendActivated(secondary_output->resource()); + server->zaura_output_manager()->SendActivated(secondary_output); }); EXPECT_EQ(secondary_id, display::Screen::GetScreen()->GetDisplayForNewWindows().id()); // Activate the primary output. PostToServerAndWait([&](wl::TestWaylandServerThread* server) { - server->zaura_output_manager()->SendActivated(primary_output->resource()); + server->zaura_output_manager()->SendActivated(primary_output); }); EXPECT_EQ(primary_id, display::Screen::GetScreen()->GetDisplayForNewWindows().id());
diff --git a/ui/ozone/platform/wayland/test/test_output.cc b/ui/ozone/platform/wayland/test/test_output.cc index 743ee11c..e26271f 100644 --- a/ui/ozone/platform/wayland/test/test_output.cc +++ b/ui/ozone/platform/wayland/test/test_output.cc
@@ -94,7 +94,7 @@ } void TestOutput::Flush() { - flush_metrics_callback_.Run(resource(), metrics_); + flush_metrics_callback_.Run(this, metrics_); constexpr char kUnknownMake[] = "unknown_make"; constexpr char kUnknownModel[] = "unknown_model";
diff --git a/ui/ozone/platform/wayland/test/test_output.h b/ui/ozone/platform/wayland/test/test_output.h index 8dfada2..879eb405 100644 --- a/ui/ozone/platform/wayland/test/test_output.h +++ b/ui/ozone/platform/wayland/test/test_output.h
@@ -29,10 +29,9 @@ public: // A callback that allows clients to respond to a Flush() of a given // TestOutput's metrics_. This is called immediately before Flush() sends - // metrics events to clients. The output_resource is the wl_resource - // associated with this output. + // metrics events to clients. using FlushMetricsCallback = - base::RepeatingCallback<void(wl_resource* output_resource, + base::RepeatingCallback<void(TestOutput* TestOutput, const TestOutputMetrics& metrics)>; explicit TestOutput(FlushMetricsCallback flush_metrics_callback);
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc index f8e4dfc5..c94f23d 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
@@ -110,7 +110,8 @@ return false; if (config_.enable_aura_shell == EnableAuraShellProtocol::kEnabled) { - if (config_.use_aura_output_manager) { + if (config_.aura_output_manager_protocol == + AuraOutputManagerProtocol::kEnabledV1) { // zaura_output_manager should be initialized before any wl_output // globals. if (!zaura_output_manager_.Initialize(display_.get())) { @@ -234,10 +235,10 @@ } void TestWaylandServerThread::OnTestOutputMetricsFlush( - wl_resource* output_resource, + TestOutput* test_output, const TestOutputMetrics& metrics) { if (zaura_output_manager_.resource()) { - zaura_output_manager_.SendOutputMetrics(output_resource, metrics); + zaura_output_manager_.SendOutputMetrics(test_output, metrics); } }
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h index ece72a3..00846d7 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
@@ -55,6 +55,7 @@ enum class PrimarySelectionProtocol { kNone, kGtk, kZwp }; enum class ShouldUseExplicitSynchronizationProtocol { kNone, kUse }; enum class EnableAuraShellProtocol { kEnabled, kDisabled }; +enum class AuraOutputManagerProtocol { kDisabled, kEnabledV1 }; struct ServerConfig { TestZcrTextInputExtensionV1::Version text_input_extension_version = @@ -68,7 +69,8 @@ EnableAuraShellProtocol::kDisabled; bool surface_submission_in_pixel_coordinates = true; bool supports_viewporter_surface_scaling = false; - bool use_aura_output_manager = false; + AuraOutputManagerProtocol aura_output_manager_protocol = + AuraOutputManagerProtocol::kDisabled; }; class TestWaylandServerThread; @@ -138,10 +140,10 @@ return output_ptr; } - // Called when the Flush() is called for a TestOutput associated with - // `output_resource`. When called sends the corresponding events for the - // `metrics` to clients of the zaura_output_manager. - void OnTestOutputMetricsFlush(wl_resource* output_resource, + // Called when the Flush() is called for a `test_output`. When called sends + // the corresponding events for the `metrics` to clients of the + // aura output manager. + void OnTestOutputMetricsFlush(TestOutput* test_output, const TestOutputMetrics& metrics); TestDataDeviceManager* data_device_manager() { return &data_device_manager_; }
diff --git a/ui/ozone/platform/wayland/test/test_zaura_output_manager.cc b/ui/ozone/platform/wayland/test/test_zaura_output_manager.cc index 944268c..e5faeec6 100644 --- a/ui/ozone/platform/wayland/test/test_zaura_output_manager.cc +++ b/ui/ozone/platform/wayland/test/test_zaura_output_manager.cc
@@ -8,6 +8,7 @@ #include "base/bit_cast.h" #include "ui/base/wayland/wayland_display_util.h" +#include "ui/ozone/platform/wayland/test/test_output.h" #include "ui/ozone/platform/wayland/test/test_output_metrics.h" namespace wl { @@ -25,8 +26,10 @@ TestZAuraOutputManager::~TestZAuraOutputManager() = default; void TestZAuraOutputManager::SendOutputMetrics( - wl_resource* output_resource, + TestOutput* test_output, const TestOutputMetrics& metrics) { + wl_resource* output_resource = test_output->resource(); + const auto& physical_size = metrics.wl_physical_size; zaura_output_manager_send_physical_size(resource(), output_resource, physical_size.width(), @@ -63,7 +66,8 @@ zaura_output_manager_send_done(resource(), output_resource); } -void TestZAuraOutputManager::SendActivated(wl_resource* output_resource) { +void TestZAuraOutputManager::SendActivated(TestOutput* test_output) { + wl_resource* output_resource = test_output->resource(); zaura_output_manager_send_activated(resource(), output_resource); }
diff --git a/ui/ozone/platform/wayland/test/test_zaura_output_manager.h b/ui/ozone/platform/wayland/test/test_zaura_output_manager.h index 800fa8d2..95e7a1a 100644 --- a/ui/ozone/platform/wayland/test/test_zaura_output_manager.h +++ b/ui/ozone/platform/wayland/test/test_zaura_output_manager.h
@@ -7,9 +7,9 @@ #include "ui/ozone/platform/wayland/test/global_object.h" -struct wl_resource; - namespace wl { + +class TestOutput; struct TestOutputMetrics; class TestZAuraOutputManager : public GlobalObject { @@ -20,11 +20,11 @@ ~TestZAuraOutputManager() override; // Propagates events for metrics to bound clients for the output. - void SendOutputMetrics(wl_resource* output_resource, + void SendOutputMetrics(TestOutput* test_output, const TestOutputMetrics& metrics); // Sends the activated event for the given output. - void SendActivated(wl_resource* output_resource); + void SendActivated(TestOutput* test_output); }; } // namespace wl
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc index c479b90..a4aa2a0 100644 --- a/ui/views/controls/scroll_view.cc +++ b/ui/views/controls/scroll_view.cc
@@ -285,8 +285,10 @@ : ScrollWithLayers::kDisabled) {} ScrollView::ScrollView(ScrollWithLayers scroll_with_layers) - : horiz_sb_(AddChildView(PlatformStyle::CreateScrollBar(true))), - vert_sb_(AddChildView(PlatformStyle::CreateScrollBar(false))), + : horiz_sb_(AddChildView( + PlatformStyle::CreateScrollBar(ScrollBar::Orientation::kHorizontal))), + vert_sb_(AddChildView( + PlatformStyle::CreateScrollBar(ScrollBar::Orientation::kVertical))), corner_view_(std::make_unique<ScrollCornerView>()), scroll_with_layers_enabled_(scroll_with_layers == ScrollWithLayers::kEnabled) { @@ -1029,7 +1031,8 @@ int ScrollView::GetScrollIncrement(ScrollBar* source, bool is_page, bool is_positive) { - bool is_horizontal = source->IsHorizontal(); + bool is_horizontal = + source->GetOrientation() == ScrollBar::Orientation::kHorizontal; if (is_page) { return is_horizontal ? contents_viewport_->width() : contents_viewport_->height();
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc index ae38875..26112f2 100644 --- a/ui/views/controls/scroll_view_unittest.cc +++ b/ui/views/controls/scroll_view_unittest.cc
@@ -251,8 +251,8 @@ METADATA_HEADER(TestScrollBar, ScrollBar) public: - TestScrollBar(bool horizontal, bool overlaps_content, int thickness) - : ScrollBar(horizontal), + TestScrollBar(Orientation orientation, bool overlaps_content, int thickness) + : ScrollBar(orientation), overlaps_content_(overlaps_content), thickness_(thickness) { SetThumb(new TestScrollBarThumb(this)); @@ -2137,11 +2137,13 @@ constexpr int kThickness = 1; // Assume horizontal scroll bar is the default and is overlapping. - scroll_view_->SetHorizontalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/true, /*overlaps_content=*/true, kThickness)); + scroll_view_->SetHorizontalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kHorizontal, + /*overlaps_content=*/true, kThickness)); // Assume vertical scroll bar is custom and it we want it to not overlap. - scroll_view_->SetVerticalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/false, /*overlaps_content=*/false, kThickness)); + scroll_view_->SetVerticalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kVertical, + /*overlaps_content=*/false, kThickness)); // Also, let's turn off horizontal scroll bar. scroll_view_->SetHorizontalScrollBarMode( @@ -2163,11 +2165,13 @@ constexpr int kThickness = 1; // Assume horizontal scroll bar is the default and is overlapping. - scroll_view_->SetHorizontalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/true, /*overlaps_content=*/true, kThickness)); + scroll_view_->SetHorizontalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kHorizontal, + /*overlaps_content=*/true, kThickness)); // Assume vertical scroll bar is custom and it we want it to not overlap. - scroll_view_->SetVerticalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/false, /*overlaps_content=*/false, kThickness)); + scroll_view_->SetVerticalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kVertical, + /*overlaps_content=*/false, kThickness)); // Also, let's turn off horizontal scroll bar. scroll_view_->SetHorizontalScrollBarMode( @@ -2189,11 +2193,13 @@ constexpr int kThickness = 1; // Assume horizontal scroll bar is custom and it we want it to not overlap. - scroll_view_->SetHorizontalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/true, /*overlaps_content=*/false, kThickness)); + scroll_view_->SetHorizontalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kHorizontal, + /*overlaps_content=*/false, kThickness)); // Assume vertical scroll bar is the default and is overlapping. - scroll_view_->SetVerticalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/false, /*overlaps_content=*/true, kThickness)); + scroll_view_->SetVerticalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kVertical, + /*overlaps_content=*/true, kThickness)); // Also, let's turn off horizontal scroll bar. scroll_view_->SetVerticalScrollBarMode(ScrollView::ScrollBarMode::kDisabled); @@ -2214,11 +2220,13 @@ constexpr int kThickness = 1; // Assume horizontal scroll bar is custom and it we want it to not overlap. - scroll_view_->SetHorizontalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/true, /*overlaps_content=*/false, kThickness)); + scroll_view_->SetHorizontalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kHorizontal, + /*overlaps_content=*/false, kThickness)); // Assume vertical scroll bar is the default and is overlapping. - scroll_view_->SetVerticalScrollBar(std::make_unique<TestScrollBar>( - /*horizontal=*/false, /*overlaps_content=*/true, kThickness)); + scroll_view_->SetVerticalScrollBar( + std::make_unique<TestScrollBar>(ScrollBar::Orientation::kVertical, + /*overlaps_content=*/true, kThickness)); // Also, let's turn off horizontal scroll bar. scroll_view_->SetVerticalScrollBarMode(
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc b/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc index 2e6749d..5aa83dc 100644 --- a/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc +++ b/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
@@ -136,7 +136,7 @@ } bool BaseScrollBarThumb::IsHorizontal() const { - return scroll_bar_->IsHorizontal(); + return scroll_bar_->GetOrientation() == ScrollBar::Orientation::kHorizontal; } BEGIN_METADATA(BaseScrollBarThumb)
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/ui/views/controls/scrollbar/cocoa_scroll_bar.h index c264ff8..0481be8d 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.h +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -24,7 +24,7 @@ METADATA_HEADER(CocoaScrollBar, ScrollBar) public: - explicit CocoaScrollBar(bool horizontal); + explicit CocoaScrollBar(ScrollBar::Orientation orientation); CocoaScrollBar(const CocoaScrollBar&) = delete; CocoaScrollBar& operator=(const CocoaScrollBar&) = delete;
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm index c07b45f..99fb29c0 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -144,8 +144,8 @@ ////////////////////////////////////////////////////////////////// // CocoaScrollBar class -CocoaScrollBar::CocoaScrollBar(bool horizontal) - : ScrollBar(horizontal), +CocoaScrollBar::CocoaScrollBar(ScrollBar::Orientation orientation) + : ScrollBar(orientation), hide_scrollbar_timer_(FROM_HERE, base::Milliseconds(500), base::BindRepeating(&CocoaScrollBar::HideScrollbar, @@ -192,7 +192,7 @@ // The length of the thumb is set by ScrollBar::Update(). gfx::Rect thumb_bounds(GetThumb()->bounds()); gfx::Rect track_bounds(GetTrackBounds()); - if (IsHorizontal()) { + if (GetOrientation() == Orientation::kHorizontal) { GetThumb()->SetBounds(thumb_bounds.x(), track_bounds.y(), thumb_bounds.width(), @@ -327,8 +327,10 @@ // hide timer check because Update() is called asynchronously, after event // processing. So when |event| is the first event in a particular direction // the hide timer will not have started. - if ((IsHorizontal() ? event.x_offset() : event.y_offset()) != 0) + if ((GetOrientation() == Orientation::kHorizontal ? event.x_offset() + : event.y_offset()) != 0) { return; + } // Otherwise, scrolling has started, but not in this scroller direction. If // already faded out, don't start another fade animation since that would @@ -415,7 +417,7 @@ ui::NativeTheme::ExtraParams CocoaScrollBar::GetPainterParams() const { ui::NativeTheme::ScrollbarExtraParams scrollbar; - if (IsHorizontal()) { + if (GetOrientation() == Orientation::kHorizontal) { scrollbar.orientation = ui::NativeTheme::ScrollbarOrientation::kHorizontal; } else if (base::i18n::IsRTL()) { scrollbar.orientation = @@ -479,10 +481,11 @@ void CocoaScrollBar::UpdateScrollbarThickness() { int thickness = ScrollbarThickness(); - if (IsHorizontal()) + if (GetOrientation() == Orientation::kHorizontal) { SetBounds(x(), bounds().bottom() - thickness, width(), thickness); - else + } else { SetBounds(bounds().right() - thickness, y(), thickness, height()); + } } void CocoaScrollBar::ResetOverlayScrollbar() {
diff --git a/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/ui/views/controls/scrollbar/overlay_scroll_bar.cc index 37dee14..909b643 100644 --- a/ui/views/controls/scrollbar/overlay_scroll_bar.cc +++ b/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -136,7 +136,8 @@ BEGIN_METADATA(OverlayScrollBar, Thumb, BaseScrollBarThumb) END_METADATA -OverlayScrollBar::OverlayScrollBar(bool horizontal) : ScrollBar(horizontal) { +OverlayScrollBar::OverlayScrollBar(Orientation orientation) + : ScrollBar(orientation) { SetNotifyEnterExitOnChild(true); SetPaintToLayer(); layer()->SetMasksToBounds(true); @@ -154,8 +155,9 @@ OverlayScrollBar::~OverlayScrollBar() = default; gfx::Insets OverlayScrollBar::GetInsets() const { - return IsHorizontal() ? gfx::Insets::TLBR(-kThumbHoverOffset, 0, 0, 0) - : gfx::Insets::TLBR(0, -kThumbHoverOffset, 0, 0); + return GetOrientation() == Orientation::kHorizontal + ? gfx::Insets::TLBR(-kThumbHoverOffset, 0, 0, 0) + : gfx::Insets::TLBR(0, -kThumbHoverOffset, 0, 0); } void OverlayScrollBar::OnMouseEntered(const ui::MouseEvent& event) {
diff --git a/ui/views/controls/scrollbar/overlay_scroll_bar.h b/ui/views/controls/scrollbar/overlay_scroll_bar.h index 893a182..474ed7f 100644 --- a/ui/views/controls/scrollbar/overlay_scroll_bar.h +++ b/ui/views/controls/scrollbar/overlay_scroll_bar.h
@@ -17,7 +17,7 @@ METADATA_HEADER(OverlayScrollBar, ScrollBar) public: - explicit OverlayScrollBar(bool horizontal); + explicit OverlayScrollBar(Orientation orientation); OverlayScrollBar(const OverlayScrollBar&) = delete; OverlayScrollBar& operator=(const OverlayScrollBar&) = delete;
diff --git a/ui/views/controls/scrollbar/scroll_bar.cc b/ui/views/controls/scrollbar/scroll_bar.cc index 9ecb2515..00ec24c 100644 --- a/ui/views/controls/scrollbar/scroll_bar.cc +++ b/ui/views/controls/scrollbar/scroll_bar.cc
@@ -34,8 +34,8 @@ ScrollBar::~ScrollBar() = default; -bool ScrollBar::IsHorizontal() const { - return is_horiz_; +ScrollBar::Orientation ScrollBar::GetOrientation() const { + return orientation_; } void ScrollBar::SetThumb(BaseScrollBarThumb* thumb) { @@ -170,7 +170,7 @@ float scroll_amount_f; int scroll_amount; - if (IsHorizontal()) { + if (GetOrientation() == Orientation::kHorizontal) { scroll_amount_f = event->details().scroll_x() - roundoff_error_.x(); scroll_amount = base::ClampRound(scroll_amount_f); roundoff_error_.set_x(scroll_amount - scroll_amount_f); @@ -187,8 +187,12 @@ if (event->type() == ui::ET_SCROLL_FLING_START) { scroll_status_ = ScrollStatus::kScrollInEnding; GetOrCreateScrollAnimator()->Start( - IsHorizontal() ? event->details().velocity_x() : 0.f, - IsHorizontal() ? 0.f : event->details().velocity_y()); + GetOrientation() == Orientation::kHorizontal + ? event->details().velocity_x() + : 0.f, + GetOrientation() == Orientation::kHorizontal + ? 0.f + : event->details().velocity_y()); event->SetHandled(); } } @@ -197,8 +201,8 @@ // ScrollBar, ScrollDelegate implementation: bool ScrollBar::OnScroll(float dx, float dy) { - return IsHorizontal() ? ScrollByContentsOffset(dx) - : ScrollByContentsOffset(dy); + return ScrollByContentsOffset( + GetOrientation() == Orientation::kHorizontal ? dx : dy); } void ScrollBar::OnFlingScrollEnded() { @@ -226,7 +230,8 @@ gfx::Rect widget_bounds = widget->GetWindowBoundsInScreen(); gfx::Point temp_pt(p.x() - widget_bounds.x(), p.y() - widget_bounds.y()); View::ConvertPointFromWidget(this, &temp_pt); - context_menu_mouse_position_ = IsHorizontal() ? temp_pt.x() : temp_pt.y(); + context_menu_mouse_position_ = + GetOrientation() == Orientation::kHorizontal ? temp_pt.x() : temp_pt.y(); if (!menu_model_) { menu_model_ = std::make_unique<ui::SimpleMenuModel>(this); @@ -235,26 +240,30 @@ menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); menu_model_->AddItemWithStringId( ScrollBarContextMenuCommand_ScrollStart, - IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFTEDGE - : IDS_APP_SCROLLBAR_CXMENU_SCROLLHOME); + GetOrientation() == Orientation::kHorizontal + ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFTEDGE + : IDS_APP_SCROLLBAR_CXMENU_SCROLLHOME); menu_model_->AddItemWithStringId( ScrollBarContextMenuCommand_ScrollEnd, - IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHTEDGE - : IDS_APP_SCROLLBAR_CXMENU_SCROLLEND); + GetOrientation() == Orientation::kHorizontal + ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHTEDGE + : IDS_APP_SCROLLBAR_CXMENU_SCROLLEND); menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); menu_model_->AddItemWithStringId(ScrollBarContextMenuCommand_ScrollPageUp, IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEUP); menu_model_->AddItemWithStringId(ScrollBarContextMenuCommand_ScrollPageDown, IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEDOWN); menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); - menu_model_->AddItemWithStringId(ScrollBarContextMenuCommand_ScrollPrev, - IsHorizontal() - ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFT - : IDS_APP_SCROLLBAR_CXMENU_SCROLLUP); - menu_model_->AddItemWithStringId(ScrollBarContextMenuCommand_ScrollNext, - IsHorizontal() - ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHT - : IDS_APP_SCROLLBAR_CXMENU_SCROLLDOWN); + menu_model_->AddItemWithStringId( + ScrollBarContextMenuCommand_ScrollPrev, + GetOrientation() == Orientation::kHorizontal + ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFT + : IDS_APP_SCROLLBAR_CXMENU_SCROLLUP); + menu_model_->AddItemWithStringId( + ScrollBarContextMenuCommand_ScrollNext, + GetOrientation() == Orientation::kHorizontal + ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHT + : IDS_APP_SCROLLBAR_CXMENU_SCROLLDOWN); } menu_runner_ = std::make_unique<MenuRunner>( menu_model_.get(), @@ -270,7 +279,7 @@ switch (id) { case ScrollBarContextMenuCommand_ScrollPageUp: case ScrollBarContextMenuCommand_ScrollPageDown: - return !IsHorizontal(); + return GetOrientation() == Orientation::kVertical; } return true; } @@ -390,8 +399,8 @@ GetOrCreateScrollAnimator()->set_velocity_multiplier(fling_multiplier_); } -ScrollBar::ScrollBar(bool is_horiz) - : is_horiz_(is_horiz), +ScrollBar::ScrollBar(Orientation orientation) + : orientation_(orientation), repeater_(base::BindRepeating(&ScrollBar::TrackClicked, base::Unretained(this))) { set_context_menu_controller(this); @@ -415,7 +424,7 @@ void ScrollBar::ProcessPressEvent(const ui::LocatedEvent& event) { gfx::Rect thumb_bounds = thumb_->bounds(); - if (IsHorizontal()) { + if (GetOrientation() == Orientation::kHorizontal) { if (GetMirroredXInView(event.x()) < thumb_bounds.x()) { last_scroll_amount_ = ScrollAmount::kPrevPage; } else if (GetMirroredXInView(event.x()) > thumb_bounds.right()) { @@ -443,7 +452,8 @@ int ScrollBar::GetTrackSize() const { gfx::Rect track_bounds = GetTrackBounds(); - return IsHorizontal() ? track_bounds.width() : track_bounds.height(); + return GetOrientation() == Orientation::kHorizontal ? track_bounds.width() + : track_bounds.height(); } int ScrollBar::CalculateThumbPosition(int contents_scroll_offset) const { @@ -484,9 +494,11 @@ ScrollBar::ScrollAmount ScrollBar::DetermineScrollAmountByKeyCode( const ui::KeyboardCode& keycode) const { // Reject arrows that don't match the scrollbar orientation. - if (IsHorizontal() ? (keycode == ui::VKEY_UP || keycode == ui::VKEY_DOWN) - : (keycode == ui::VKEY_LEFT || keycode == ui::VKEY_RIGHT)) + if (GetOrientation() == Orientation::kHorizontal + ? (keycode == ui::VKEY_UP || keycode == ui::VKEY_DOWN) + : (keycode == ui::VKEY_LEFT || keycode == ui::VKEY_RIGHT)) { return ScrollAmount::kNone; + } static const base::NoDestructor< base::flat_map<ui::KeyboardCode, ScrollAmount>>
diff --git a/ui/views/controls/scrollbar/scroll_bar.h b/ui/views/controls/scrollbar/scroll_bar.h index c9a3f0d..9a53a5e 100644 --- a/ui/views/controls/scrollbar/scroll_bar.h +++ b/ui/views/controls/scrollbar/scroll_bar.h
@@ -93,13 +93,18 @@ kNextPage, }; + // Whether the scrollbar is horizontal or vertical. + enum class Orientation : bool { + kHorizontal, + kVertical, + }; + ScrollBar(const ScrollBar&) = delete; ScrollBar& operator=(const ScrollBar&) = delete; ~ScrollBar() override; - // Returns whether this scrollbar is horizontal. - bool IsHorizontal() const; + Orientation GetOrientation() const; void set_controller(ScrollBarController* controller) { controller_ = controller; @@ -187,7 +192,7 @@ // Create new scrollbar, either horizontal or vertical. These are protected // since you need to be creating either a NativeScrollBar or a // ImageScrollBar. - explicit ScrollBar(bool is_horiz); + explicit ScrollBar(Orientation orientation); BaseScrollBarThumb* GetThumb() const; @@ -264,7 +269,7 @@ // was invoked. int context_menu_mouse_position_ = 0; - const bool is_horiz_; + const Orientation orientation_; raw_ptr<BaseScrollBarThumb> thumb_ = nullptr;
diff --git a/ui/views/controls/scrollbar/scroll_bar_views.cc b/ui/views/controls/scrollbar/scroll_bar_views.cc index f7dee9d8..d2eaad3 100644 --- a/ui/views/controls/scrollbar/scroll_bar_views.cc +++ b/ui/views/controls/scrollbar/scroll_bar_views.cc
@@ -69,8 +69,9 @@ GetNativeThemePart(), theme_state, local_bounds, extra_params); const ui::NativeTheme::Part gripper_part = - scroll_bar_->IsHorizontal() ? ui::NativeTheme::kScrollbarHorizontalGripper - : ui::NativeTheme::kScrollbarVerticalGripper; + scroll_bar_->GetOrientation() == ScrollBar::Orientation::kHorizontal + ? ui::NativeTheme::kScrollbarHorizontalGripper + : ui::NativeTheme::kScrollbarVerticalGripper; GetNativeTheme()->Paint(canvas->sk_canvas(), GetColorProvider(), gripper_part, theme_state, local_bounds, extra_params); } @@ -88,8 +89,9 @@ } ui::NativeTheme::Part ScrollBarThumb::GetNativeThemePart() const { - if (scroll_bar_->IsHorizontal()) + if (scroll_bar_->GetOrientation() == ScrollBar::Orientation::kHorizontal) { return ui::NativeTheme::kScrollbarHorizontalThumb; + } return ui::NativeTheme::kScrollbarVerticalThumb; } @@ -113,13 +115,15 @@ } // namespace -ScrollBarViews::ScrollBarViews(bool horizontal) : ScrollBar(horizontal) { +ScrollBarViews::ScrollBarViews(Orientation orientation) + : ScrollBar(orientation) { SetFlipCanvasOnPaintForRTLUI(true); state_ = ui::NativeTheme::kNormal; auto* layout = SetLayoutManager(std::make_unique<views::FlexLayout>()); - if (!horizontal) + if (orientation == ScrollBar::Orientation::kVertical) { layout->SetOrientation(views::LayoutOrientation::kVertical); + } const auto scroll_func = [](ScrollBarViews* scrollbar, ScrollAmount amount) { scrollbar->ScrollByAmount(amount); @@ -128,7 +132,8 @@ prev_button_ = AddChildView(std::make_unique<ScrollBarButton>( base::BindRepeating(scroll_func, base::Unretained(this), ScrollAmount::kPrevLine), - horizontal ? Type::kLeft : Type::kUp)); + orientation == ScrollBar::Orientation::kHorizontal ? Type::kLeft + : Type::kUp)); prev_button_->set_context_menu_controller(this); SetThumb(new ScrollBarThumb(this)); @@ -143,10 +148,12 @@ next_button_ = AddChildView(std::make_unique<ScrollBarButton>( base::BindRepeating(scroll_func, base::Unretained(this), ScrollBar::ScrollAmount::kNextLine), - horizontal ? Type::kRight : Type::kDown)); + orientation == ScrollBar::Orientation::kHorizontal ? Type::kRight + : Type::kDown)); next_button_->set_context_menu_controller(this); - part_ = horizontal ? ui::NativeTheme::kScrollbarHorizontalTrack - : ui::NativeTheme::kScrollbarVerticalTrack; + part_ = orientation == ScrollBar::Orientation::kHorizontal + ? ui::NativeTheme::kScrollbarHorizontalTrack + : ui::NativeTheme::kScrollbarVerticalTrack; } ScrollBarViews::~ScrollBarViews() = default; @@ -184,22 +191,24 @@ scrollbar_track.is_upper = true; ui::NativeTheme::ExtraParams params(scrollbar_track); gfx::Rect upper_bounds = bounds; - if (IsHorizontal()) + if (GetOrientation() == ScrollBar::Orientation::kHorizontal) { upper_bounds.set_width(thumb->x() - upper_bounds.x()); - else + } else { upper_bounds.set_height(thumb->y() - upper_bounds.y()); + } if (!upper_bounds.IsEmpty()) { GetNativeTheme()->Paint(canvas->sk_canvas(), GetColorProvider(), part_, state_, upper_bounds, params); } scrollbar_track.is_upper = false; - if (IsHorizontal()) + if (GetOrientation() == ScrollBar::Orientation::kHorizontal) { bounds.Inset( gfx::Insets::TLBR(0, thumb->bounds().right() - bounds.x(), 0, 0)); - else + } else { bounds.Inset( gfx::Insets::TLBR(thumb->bounds().bottom() - bounds.y(), 0, 0, 0)); + } if (!bounds.IsEmpty()) { GetNativeTheme()->Paint(canvas->sk_canvas(), GetColorProvider(), part_, state_, bounds, params); @@ -208,7 +217,8 @@ int ScrollBarViews::GetThickness() const { const gfx::Size size = GetPreferredSize(); - return IsHorizontal() ? size.height() : size.width(); + return GetOrientation() == ScrollBar::Orientation::kHorizontal ? size.height() + : size.width(); } gfx::Rect ScrollBarViews::GetTrackBounds() const { @@ -216,7 +226,7 @@ gfx::Size size = prev_button_->GetPreferredSize(); BaseScrollBarThumb* thumb = GetThumb(); - if (IsHorizontal()) { + if (GetOrientation() == ScrollBar::Orientation::kHorizontal) { bounds.set_x(bounds.x() + size.width()); bounds.set_width(std::max(0, bounds.width() - 2 * size.width())); bounds.set_height(thumb->GetPreferredSize().height());
diff --git a/ui/views/controls/scrollbar/scroll_bar_views.h b/ui/views/controls/scrollbar/scroll_bar_views.h index 954309e..06bc7d4 100644 --- a/ui/views/controls/scrollbar/scroll_bar_views.h +++ b/ui/views/controls/scrollbar/scroll_bar_views.h
@@ -23,7 +23,7 @@ public: // Creates new scrollbar, either horizontal or vertical. - explicit ScrollBarViews(bool horizontal = true); + explicit ScrollBarViews(Orientation orientation = Orientation::kHorizontal); ScrollBarViews(const ScrollBarViews&) = delete; ScrollBarViews& operator=(const ScrollBarViews&) = delete;
diff --git a/ui/views/style/platform_style.cc b/ui/views/style/platform_style.cc index f6bc21e..39a14eb 100644 --- a/ui/views/style/platform_style.cc +++ b/ui/views/style/platform_style.cc
@@ -57,11 +57,12 @@ #endif // static -std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) { +std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar( + ScrollBar::Orientation orientation) { #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) - return std::make_unique<OverlayScrollBar>(is_horizontal); + return std::make_unique<OverlayScrollBar>(orientation); #else - return std::make_unique<ScrollBarViews>(is_horizontal); + return std::make_unique<ScrollBarViews>(orientation); #endif }
diff --git a/ui/views/style/platform_style.h b/ui/views/style/platform_style.h index d3d97c3..b1d16005 100644 --- a/ui/views/style/platform_style.h +++ b/ui/views/style/platform_style.h
@@ -8,6 +8,7 @@ #include <memory> #include "ui/views/controls/button/button.h" +#include "ui/views/controls/scrollbar/scroll_bar.h" #include "ui/views/view.h" #include "ui/views/views_export.h" @@ -17,8 +18,6 @@ namespace views { -class ScrollBar; - // Cross-platform API for providing platform-specific styling for toolkit-views. class VIEWS_EXPORT PlatformStyle { public: @@ -77,7 +76,8 @@ static const View::FocusBehavior kDefaultFocusBehavior; // Creates the default scrollbar for the given orientation. - static std::unique_ptr<ScrollBar> CreateScrollBar(bool is_horizontal); + static std::unique_ptr<ScrollBar> CreateScrollBar( + ScrollBar::Orientation orientation); // Called whenever a textfield edit fails. Gives visual/audio feedback about // the failed edit if platform-appropriate.
diff --git a/ui/views/style/platform_style_mac.mm b/ui/views/style/platform_style_mac.mm index fd780b3..ace1e3b 100644 --- a/ui/views/style/platform_style_mac.mm +++ b/ui/views/style/platform_style_mac.mm
@@ -55,8 +55,9 @@ const bool PlatformStyle::kReturnClicksFocusedControl = false; // static -std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) { - return std::make_unique<CocoaScrollBar>(is_horizontal); +std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar( + ScrollBar::Orientation orientation) { + return std::make_unique<CocoaScrollBar>(orientation); } // static
diff --git a/v8 b/v8 index 93c5bbc..4892aa3 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 93c5bbc582e38f3a543ae0e5a28e593f2e7cc6dd +Subproject commit 4892aa3e774cdd84597e696d57b4468a6ae3d77f