diff --git a/DEPS b/DEPS index a5f222d..ef77d071 100644 --- a/DEPS +++ b/DEPS
@@ -304,15 +304,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': '60b76f3502c88409b8190bc66362666ffe6dce81', + 'src_internal_revision': '1ec6eaf1463ef817385ef7fd9014c5e74ce4b91b', # 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': '3d3d12b3fed33cf7d43f69204c3b91656f2f59d9', + 'skia_revision': '62f369c759947272dfdd2d8f060afadbcc361e79', # 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': '2a06d4e3534debe1294744c208e85d8c4f06d579', + 'v8_revision': 'dbccf5638033c2f65fa8726313050ddecadda427', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -383,7 +383,7 @@ # 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': '9e9b01285b3b1febec28c95040e7ed89e3b86bc8', + 'chromium_variations_revision': '9485c21d7b149d1fd9a663762182a7838095913e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -399,7 +399,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'c1d688bcb2e1d1ebcebbe07e48ddcfa90228b138', + 'devtools_frontend_revision': 'ecbae84d39c9a39365dfbcb791c6b78d4df6e373', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -423,7 +423,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '7ffb6e9573216af00374a8dd474598ce94f2d97a', + 'dawn_revision': '538f02eecf1a80738f1ece234bbf6c947d127add', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1004,7 +1004,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - 'abd3ccee94ac82bc22053398886ba2dfb5a518fa', + 'aa6befe0ff74c3a26e310d3e119191e064b6b197', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1163,7 +1163,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'JZ72YZlEwPXylEAvSLZX9OglfCwT4XpDJscRG8nioCkC', + 'version': 'vAfIh85uzcaBMYEt3ZZIgV2Byl0NtbeE8DNHORAF1r0C', }, ], 'condition': 'checkout_android', @@ -1425,7 +1425,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8a31c4e2f3416b669a31b6e6b8be77bf4ec12532', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8199e2bbaef867e258148454b1ee7a472fe3a638', 'condition': 'checkout_chromeos', }, @@ -1460,13 +1460,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd32e1cb5717853a1837347884abc85149813c398', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0dd502813398cb44477df2c246ed4495c4a0c46d', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '701f4784e9e7d73927dcf4d60bc0f0db552b79b7', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '454bc68b84610f49e617ab997e056e7cb2429ad5', 'condition': 'checkout_src_internal', }, @@ -1802,7 +1802,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '611d9ba0a55df154ff5cb7a97d41a41103265f5e', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '5b4cfe88e45a42fbdf22f7210ed253faec9c0fe6', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da', @@ -1930,7 +1930,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '09a4f3ec842a8932341b195c5b01e141c8a16eb7', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '17661211decceb52c9597a8bed5c5bdfcc44a2a2', + Var('chromium_git') + '/openscreen' + '@' + 'd77735d9e5ef30477139b0fc1ca3db6706ec8651', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '95fe35ffb383710a6e0567e958ead9a3b66e930c', @@ -1993,7 +1993,7 @@ }, 'src/third_party/re2/src': - Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'a67d6c1d5308b0950a91fed8e03e5c048d22d5cd', + Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'a771d3fbe7c432dc4db68360c6c0004fdde5646b', 'src/third_party/r8': { 'packages': [ @@ -2173,7 +2173,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '007e1015875a0a91794edbc14feb3ad5fe60f90b', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'f317f7106a7a15a04da7cd30c2e2ddb1b3025bc6', + Var('webrtc_git') + '/src.git' + '@' + 'fa4128eedbe427eecd28988f2585753645514296', # 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. @@ -2307,7 +2307,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'kKc697kATRyvYNkrIemhsZB-hPhYXqiliFMKPeBuYqkC', + 'version': '1SgwxREi0QXR9Sbc-MWrlCbZ98Byk7dZ09tHDL9j_N0C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc index e95e2a9..a31adce 100644 --- a/android_webview/browser/cookie_manager.cc +++ b/android_webview/browser/cookie_manager.cc
@@ -178,10 +178,6 @@ // Are cookies allowed for file:// URLs by default? const bool kDefaultFileSchemeAllowed = false; -BASE_FEATURE(kWebViewCookieManagerUseThreadPool, - "WebViewCookieManagerUseThreadPool", - base::FEATURE_DISABLED_BY_DEFAULT); - } // namespace // static @@ -212,13 +208,9 @@ cookie_store_client_thread_("CookieMonsterClient"), cookie_store_backend_thread_("CookieMonsterBackend"), setting_new_mojo_cookie_manager_(false) { - if (base::FeatureList::IsEnabled(kWebViewCookieManagerUseThreadPool)) { - cookie_store_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner({}); - } else { - cookie_store_client_thread_.Start(); - cookie_store_backend_thread_.Start(); - cookie_store_task_runner_ = cookie_store_client_thread_.task_runner(); - } + cookie_store_client_thread_.Start(); + cookie_store_backend_thread_.Start(); + cookie_store_task_runner_ = cookie_store_client_thread_.task_runner(); cookie_store_path_ = GetContextPath().Append(FILE_PATH_LITERAL("Cookies")); if (!parent_context_) { // Default profile @@ -336,13 +328,8 @@ cookie_store_path_, /* restore_old_session_cookies= */ true, /* persist_session_cookies= */ true); cookie_config.client_task_runner = cookie_store_task_runner_; - - // If `background_task_runner` is not set it will be created from the thread - // pool internally. - if (!base::FeatureList::IsEnabled(kWebViewCookieManagerUseThreadPool)) { - cookie_config.background_task_runner = - cookie_store_backend_thread_.task_runner(); - } + cookie_config.background_task_runner = + cookie_store_backend_thread_.task_runner(); { base::AutoLock lock(allow_file_scheme_cookies_lock_);
diff --git a/android_webview/browser/cookie_manager.h b/android_webview/browser/cookie_manager.h index 74db4b8d..89ea066 100644 --- a/android_webview/browser/cookie_manager.h +++ b/android_webview/browser/cookie_manager.h
@@ -22,6 +22,10 @@ class GURL; +namespace base { +class SingleThreadTaskRunner; +} + namespace net { class CookieStore; class CanonicalCookie; @@ -288,7 +292,7 @@ base::Thread cookie_store_client_thread_; base::Thread cookie_store_backend_thread_; - scoped_refptr<base::SequencedTaskRunner> cookie_store_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> cookie_store_task_runner_; std::unique_ptr<net::CookieStore> cookie_store_; // Tracks if we're in the middle of a call to SetMojoCookieManager(). See the
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index c53df92..c4d00088 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -1001,7 +1001,6 @@ Flag.baseFeature( BlinkFeatures.CONCURRENT_VIEW_TRANSITIONS_SPA, "Allows concurrent transitions in local frames rendered in the same process"), - Flag.baseFeature("WebViewCookieManagerUseThreadPool"), Flag.baseFeature("WebViewVizUseThreadPool"), // Add new commandline switches and features above. The final entry should have a // trailing comma for cleaner diffs.
diff --git a/ash/accelerators/keyboard_code_util.cc b/ash/accelerators/keyboard_code_util.cc index d984c83..1e8d2107 100644 --- a/ash/accelerators/keyboard_code_util.cc +++ b/ash/accelerators/keyboard_code_util.cc
@@ -84,7 +84,7 @@ if (key_label) return key_label.value(); - return ash::KeycodeToKeyString(key_code, remap_positional_key); + return ash::GetKeyDisplay(key_code, remap_positional_key); } const gfx::VectorIcon* GetVectorIconForKeyboardCode(ui::KeyboardCode key_code) {
diff --git a/ash/accelerators/shortcut_input_handler.cc b/ash/accelerators/shortcut_input_handler.cc index 8182649a7..cd89dee2d 100644 --- a/ash/accelerators/shortcut_input_handler.cc +++ b/ash/accelerators/shortcut_input_handler.cc
@@ -23,7 +23,7 @@ constexpr int kKeyboardModifierFlags = ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN | - ui::EF_ALT_DOWN; + ui::EF_ALT_DOWN | ui::EF_FUNCTION_DOWN; ui::KeyboardCode RetrieveKeyCode(const ui::KeyEvent& event) { // Remap positional keys in the current layout to the corresponding US layout
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index c869e65..e66712a7e 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -7937,44 +7937,29 @@ <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_NUDGE_TITLE" translateable="false" desc="Title of the pop up nudge to remind using fn key."> Use your fn Key </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus top row key."> - Press fn + the action key + <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_TOP_ROW_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus top row key."> + To access F keys, hold Fn key and press corresponding top row key </message> <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_CAPS_LOCK_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus top row key."> - Press fn + right alt for CAPS LOCK + Looking for Caps Lock? Try </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_UP_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus up arrow key."> - Press fn + up for page up + <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_PAGE_UP_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus up arrow key."> + Looking for Page Up? Try </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_DOWN_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus down arrow key."> - Press fn + down for page down + <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_PAGE_DOWN_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus down arrow key."> + Looking for Page Down? Try </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_LEFT_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus left arrow key."> - Press fn + left for home + <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_HOME_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus left arrow key."> + Looking for Home? Try </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_RIGHT_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus right arrow key."> - Press fn + right for end + <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_END_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus right arrow key."> + Looking for End? Try </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_BACKSPACE_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus backspace key."> - Press fn + backspace for delete + <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_DELETE_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus backspace key."> + Looking for Delete? Try </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_SHIFT_BACKSPACE_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus shift backspace key."> - Press Fn + shift + backspace in stead of search + shift + backspace key - </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_UP_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses alt plus up arrow key."> - Press fn + up for page up - </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_DOWN_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses alt plus down arrow key."> - Press fn + down for page down - </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_LEFT_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses alt plus left arrow key."> - Press fn + left for home - </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_RIGHT_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses alt plus right arrow key."> - Press fn + right for end - </message> - <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_BACKSPACE_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses alt plus backspace key."> - Press fn + backspace for delete + <message name="IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_INSERT_NUDGE_DESCRIPTION" translateable="false" desc="Description of the pop up nudge to remind using fn key when user presses search plus shift backspace key."> + Looking for Insert? Try </message> <!-- Modifier key names --> <message name="IDS_ASH_SETTINGS_SHORTCUT_MODIFIER_LAUNCHER" desc="Name of the [Launcher] key. This key has a different name and keyboard glyph/icon depending on the device. This is the string for when it is called Launcher and has a circle/launcher icon.">
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 3035e1c..9bccb77d 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -1138,11 +1138,6 @@ "kFileNotificationRevamp", base::FEATURE_ENABLED_BY_DEFAULT); -// Enables experimental UI features in Files app. -BASE_FEATURE(kFilesAppExperimental, - "FilesAppExperimental", - base::FEATURE_DISABLED_BY_DEFAULT); - // Enables the files transfer conflict dialog in Files app. BASE_FEATURE(kFilesConflictDialog, "FilesConflictDialog",
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 80fa4a14..0b282187 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -354,7 +354,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFederatedLauncherQueryAnalyticsVersion2Task); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFileNotificationRevamp); -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFilesAppExperimental); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFilesConflictDialog); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFilesLocalImageSearch); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFilesMaterializedViews);
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h index 54a0c87..cb012dc 100644 --- a/ash/constants/ash_pref_names.h +++ b/ash/constants/ash_pref_names.h
@@ -176,6 +176,9 @@ inline constexpr char kEduCoexistenceToSAcceptedVersion[] = "family_link_user.edu_coexistence_tos_accepted_version"; +// A string pref that stores the PIN used to unlock parental app controls. +inline constexpr char kOnDeviceAppControlsPin[] = "on_device_app_controls.pin"; + // A boolean pref indicating if a PIN has been set up for on-device apps // parental controls. inline constexpr char kOnDeviceAppControlsSetupCompleted[] =
diff --git a/ash/login/ui/lock_screen_media_controls_view_unittest.cc b/ash/login/ui/lock_screen_media_controls_view_unittest.cc index bf70731..983d972c 100644 --- a/ash/login/ui/lock_screen_media_controls_view_unittest.cc +++ b/ash/login/ui/lock_screen_media_controls_view_unittest.cc
@@ -23,7 +23,6 @@ #include "services/media_session/public/cpp/test/test_media_controller.h" #include "services/media_session/public/mojom/media_session.mojom.h" #include "ui/accessibility/ax_enums.mojom.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_observer.h" @@ -662,11 +661,8 @@ EXPECT_EQ(1, media_controller()->seek_forward_count()); } -TEST_F(LockScreenMediaControlsViewTest, UpdateAppIcon) { - // TODO (crbug/1520620): Remove the skip code once test is fixed. - if (::features::IsChromeRefresh2023()) { - GTEST_SKIP(); - } +// TODO (crbug/1520620): Test fails post-ChromeRefresh2023. Fix and reenable. +TEST_F(LockScreenMediaControlsViewTest, DISABLED_UpdateAppIcon) { SimulateMediaSessionChanged( media_session::mojom::MediaPlaybackState::kPlaying);
diff --git a/ash/system/input_device_settings/input_device_settings_notification_controller.cc b/ash/system/input_device_settings/input_device_settings_notification_controller.cc index 7f46292..83ccc7d 100644 --- a/ash/system/input_device_settings/input_device_settings_notification_controller.cc +++ b/ash/system/input_device_settings/input_device_settings_notification_controller.cc
@@ -307,50 +307,59 @@ } } -std::u16string GetSixPackShortcutUpdatedString( - ui::KeyboardCode key_code, - SixPackShortcutModifier blocked_modifier) { - CHECK(blocked_modifier != SixPackShortcutModifier::kNone); - std::u16string input_key_string; +std::u16string GetSixPackShortcutUpdatedString(ui::KeyboardCode key_code) { switch (key_code) { case ui::VKEY_PRIOR: - return blocked_modifier == SixPackShortcutModifier::kSearch - ? l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_UP_NUDGE_DESCRIPTION) - : l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_UP_NUDGE_DESCRIPTION); + return l10n_util::GetStringUTF16( + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_PAGE_UP_NUDGE_DESCRIPTION); case ui::VKEY_NEXT: - return blocked_modifier == SixPackShortcutModifier::kSearch - ? l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_DOWN_NUDGE_DESCRIPTION) - : l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_DOWN_NUDGE_DESCRIPTION); + return l10n_util::GetStringUTF16( + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_PAGE_DOWN_NUDGE_DESCRIPTION); case ui::VKEY_HOME: - return blocked_modifier == SixPackShortcutModifier::kSearch - ? l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_LEFT_NUDGE_DESCRIPTION) - : l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_LEFT_NUDGE_DESCRIPTION); + return l10n_util::GetStringUTF16( + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_HOME_NUDGE_DESCRIPTION); case ui::VKEY_END: - return blocked_modifier == SixPackShortcutModifier::kSearch - ? l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_RIGHT_NUDGE_DESCRIPTION) - : l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_RIGHT_NUDGE_DESCRIPTION); + return l10n_util::GetStringUTF16( + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_END_NUDGE_DESCRIPTION); case ui::VKEY_DELETE: - return blocked_modifier == SixPackShortcutModifier::kSearch - ? l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_BACKSPACE_NUDGE_DESCRIPTION) - : l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_BACKSPACE_NUDGE_DESCRIPTION); + return l10n_util::GetStringUTF16( + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_DELETE_NUDGE_DESCRIPTION); case ui::VKEY_INSERT: return l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_SHIFT_BACKSPACE_NUDGE_DESCRIPTION); + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_INSERT_NUDGE_DESCRIPTION); default: NOTREACHED_NORETURN(); } } +void InsertSixPackShortcutKeyboardCodes( + ui::KeyboardCode key_code, + std::vector<ui::KeyboardCode>& keyboard_codes) { + switch (key_code) { + case ui::VKEY_PRIOR: + keyboard_codes.push_back(ui::VKEY_UP); + break; + case ui::VKEY_NEXT: + keyboard_codes.push_back(ui::VKEY_DOWN); + break; + case ui::VKEY_HOME: + keyboard_codes.push_back(ui::VKEY_LEFT); + break; + case ui::VKEY_END: + keyboard_codes.push_back(ui::VKEY_RIGHT); + break; + case ui::VKEY_DELETE: + keyboard_codes.push_back(ui::VKEY_BACK); + break; + case ui::VKEY_INSERT: + keyboard_codes.push_back(ui::VKEY_SHIFT); + keyboard_codes.push_back(ui::VKEY_BACK); + break; + default: + NOTREACHED(); + } +} + std::u16string GetSixPackShortcut(ui::KeyboardCode key_code, SixPackShortcutModifier modifier) { CHECK(modifier != SixPackShortcutModifier::kNone); @@ -1065,7 +1074,7 @@ AnchoredNudgeData nudge_data( kTopRowKeyNoMatchNudgeId, NudgeCatalogName::kSearchTopRowKeyPressed, l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_NUDGE_DESCRIPTION)); + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_TOP_ROW_NUDGE_DESCRIPTION)); nudge_data.title_text = l10n_util::GetStringUTF16( IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_NUDGE_TITLE); @@ -1131,11 +1140,14 @@ prefs->SetInteger(shown_count_pref_name, shown_count + 1); prefs->SetTime(last_shown_time_pref_name, now); - AnchoredNudgeData nudge_data( - kSixPackKeyNoMatchNudgeId, NudgeCatalogName::kSixPackRemappingPressed, - GetSixPackShortcutUpdatedString(key_code, old_matched_modifier)); + AnchoredNudgeData nudge_data(kSixPackKeyNoMatchNudgeId, + NudgeCatalogName::kSixPackRemappingPressed, + GetSixPackShortcutUpdatedString(key_code)); nudge_data.title_text = l10n_util::GetStringUTF16( IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_NUDGE_TITLE); + std::vector<ui::KeyboardCode> keyboard_codes = {ui::VKEY_FUNCTION}; + InsertSixPackShortcutKeyboardCodes(key_code, keyboard_codes); + nudge_data.keyboard_codes = std::move(keyboard_codes); AnchoredNudgeManager::Get()->Show(nudge_data); } @@ -1170,6 +1182,7 @@ IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_CAPS_LOCK_NUDGE_DESCRIPTION)); nudge_data.title_text = l10n_util::GetStringUTF16( IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_NUDGE_TITLE); + nudge_data.keyboard_codes = {ui::VKEY_FUNCTION, ui::VKEY_RIGHT_ALT}; AnchoredNudgeManager::Get()->Show(nudge_data); }
diff --git a/ash/system/input_device_settings/input_device_settings_notification_controller_unittest.cc b/ash/system/input_device_settings/input_device_settings_notification_controller_unittest.cc index 06ac2be..9ce7b566 100644 --- a/ash/system/input_device_settings/input_device_settings_notification_controller_unittest.cc +++ b/ash/system/input_device_settings/input_device_settings_notification_controller_unittest.cc
@@ -636,7 +636,7 @@ EXPECT_EQ( nudge_manager->GetNudgeBodyTextForTest(kSixPackKeyNoMatchNudgeId), l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_SHIFT_BACKSPACE_NUDGE_DESCRIPTION)); + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_INSERT_NUDGE_DESCRIPTION)); CancelNudge(kSixPackKeyNoMatchNudgeId); EXPECT_FALSE(nudge_manager->GetNudgeIfShown(kSixPackKeyNoMatchNudgeId)); @@ -651,7 +651,7 @@ EXPECT_EQ( nudge_manager->GetNudgeBodyTextForTest(kSixPackKeyNoMatchNudgeId), l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_BACKSPACE_NUDGE_DESCRIPTION)); + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_DELETE_NUDGE_DESCRIPTION)); CancelNudge(kSixPackKeyNoMatchNudgeId); EXPECT_FALSE(nudge_manager->GetNudgeIfShown(kSixPackKeyNoMatchNudgeId)); @@ -662,7 +662,7 @@ EXPECT_EQ( nudge_manager->GetNudgeBodyTextForTest(kSixPackKeyNoMatchNudgeId), l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_LEFT_NUDGE_DESCRIPTION)); + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_HOME_NUDGE_DESCRIPTION)); CancelNudge(kSixPackKeyNoMatchNudgeId); EXPECT_FALSE(nudge_manager->GetNudgeIfShown(kSixPackKeyNoMatchNudgeId)); @@ -673,7 +673,7 @@ EXPECT_EQ( nudge_manager->GetNudgeBodyTextForTest(kSixPackKeyNoMatchNudgeId), l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_SEARCH_PLUS_RIGHT_NUDGE_DESCRIPTION)); + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_END_NUDGE_DESCRIPTION)); CancelNudge(kSixPackKeyNoMatchNudgeId); EXPECT_FALSE(nudge_manager->GetNudgeIfShown(kSixPackKeyNoMatchNudgeId)); @@ -684,7 +684,7 @@ EXPECT_EQ( nudge_manager->GetNudgeBodyTextForTest(kSixPackKeyNoMatchNudgeId), l10n_util::GetStringUTF16( - IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_ALT_PLUS_UP_NUDGE_DESCRIPTION)); + IDS_ASH_SETTINGS_KEYBOARD_USE_FN_KEY_FOR_PAGE_UP_NUDGE_DESCRIPTION)); CancelNudge(kSixPackKeyNoMatchNudgeId); EXPECT_FALSE(nudge_manager->GetNudgeIfShown(kSixPackKeyNoMatchNudgeId));
diff --git a/ash/webui/common/mojom/sea_pen.mojom b/ash/webui/common/mojom/sea_pen.mojom index e1cb6c9d..27f6871 100644 --- a/ash/webui/common/mojom/sea_pen.mojom +++ b/ash/webui/common/mojom/sea_pen.mojom
@@ -32,7 +32,7 @@ string template_title; }; -// The information needed to query template wallpapers. The possible `id` and +// The information needed to send a template query. The possible `id` and // `options` values are defined in cs/ChromeOsWallpaperQueryProcessor.kt. They // are not controlled by the renderer. The browser is responsible for validating // the values. @@ -88,10 +88,10 @@ RecentSeaPenImageInfo? image_info; }; -// Maximum allowable search text length, in bytes. +// Maximum allowable query text length, in bytes. // When validating length in Javascript, be careful of the difference between // UTF-16 (Javascript) length and UTF-8 length. -const uint32 kMaximumSearchWallpaperTextBytes = 3000; +const uint32 kMaximumGetSeaPenThumbnailsTextBytes = 3000; // Should match the associated enum in components/manta/manta_status.h enum MantaStatusCode { @@ -110,43 +110,45 @@ kMax = kPerUserQuotaExceeded, }; -// Provides APIs to perform wallpaper searches. Uses APIs in -// `manta.proto` to send search requests to a server. +// Provides APIs to get thumbnails and full size images. Uses APIs in +// `manta.proto` to send requests to a google owned server. // Implemented in the browser process, and called by the ChromeOS // Personalization App (chrome://personalization) in a renderer process. interface SeaPenProvider { - // Given a user text input, return a set of matching images. - // `images` will be null in case of an unrecoverable error, such as network - // failure. - // `images` will be empty array when the request succeeded, but no matching - // images were returned. - // `text` must be smaller than `kMaximumSearchWallpaperTextBytes` bytes. - SearchWallpaper(SeaPenQuery query) => - (array<SeaPenThumbnail>? images, MantaStatusCode statusCode); + // Given a user text input, return a set of matching thumbnails. + // `thumbnails` will be null in case of an unrecoverable error, such as + // network failure. + // `thumbnails` will be empty array when the request succeeded, but no + // matching thumbnails were returned. + // If `query` is of type string, it must be smaller than + // `kMaximumGetSeaPenThumbnailsTextBytes` bytes. + GetSeaPenThumbnails(SeaPenQuery query) => + (array<SeaPenThumbnail>? thumbnails, MantaStatusCode statusCode); - // Select a thumbnail and set as the system wallpaper for the current user. - // `id` must be a valid id from a previous call to `SearchWallpaper`. + // Select a thumbnail for the current user. + // `id` must be a valid id from a previous call to `GetSeaPenThumbnails`. SelectSeaPenThumbnail(uint32 id) => (bool success); - // Gets the available previously selected SeaPen wallpapers. `ids` will be + // Gets the available previously selected SeaPen images. `ids` will be // empty if no thumbnails have been previously selected, or in case of disk // or other failure. - GetRecentSeaPenImages() => (array<uint32> ids); + GetRecentSeaPenImageIds() => (array<uint32> ids); // Sets the given SeaPen image id as the user's background. Must be a valid - // id from a previous call to `GetRecentSeaPenImages`. + // id from a previous call to `GetRecentSeaPenImageIds`. SelectRecentSeaPenImage(uint32 id) => (bool success); // Fetches the thumbnail data for the given recent Sea Pen image `id`. - // `id` must be a valid id from a previous call to `GetRecentSeaPenImages`. + // `id` must be a valid id from a previous call to + // `GetRecentSeaPenImageIds`. // `thumbnail_data` is null if the `id` is invalid or the image fails to // decode. GetRecentSeaPenImageThumbnail(uint32 id) => (RecentSeaPenThumbnailData? thumbnail_data); // Deletes the selected SeaPen image from SeaPen directory. `id` must be a - // valid id from a previous call to `GetRecentSeaPenImages`. + // valid id from a previous call to `GetRecentSeaPenImageIds`. DeleteRecentSeaPenImage(uint32 id) => (bool success); // Pops up a feedback dialog when user clicks feedback buttons.
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_actions.ts b/ash/webui/common/resources/sea_pen/sea_pen_actions.ts index 0f39045..9b18c005 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_actions.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_actions.ts
@@ -76,7 +76,7 @@ export interface SetSeaPenThumbnailsAction extends Action { name: SeaPenActionName.SET_SEA_PEN_THUMBNAILS; query: SeaPenQuery; - images: SeaPenThumbnail[]|null; + thumbnails: SeaPenThumbnail[]|null; } /** @@ -84,8 +84,8 @@ */ export function setSeaPenThumbnailsAction( query: SeaPenQuery, - images: SeaPenThumbnail[]|null): SetSeaPenThumbnailsAction { - return {name: SeaPenActionName.SET_SEA_PEN_THUMBNAILS, query, images}; + thumbnails: SeaPenThumbnail[]|null): SetSeaPenThumbnailsAction { + return {name: SeaPenActionName.SET_SEA_PEN_THUMBNAILS, query, thumbnails}; } export interface BeginLoadRecentSeaPenImagesAction extends Action {
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_controller.ts b/ash/webui/common/resources/sea_pen/sea_pen_controller.ts index 95b49ad..099f235 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_controller.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_controller.ts
@@ -14,8 +14,8 @@ id: SeaPenImageId, provider: SeaPenProviderInterface, store: SeaPenStoreInterface): Promise<void> { const originalCurrentSelected = store.data.currentSelected; - // Returns if the selected image is the current wallpaper. if (id === originalCurrentSelected) { + // Return if the just selected image is already the current image. return; } // Batch these changes together to reduce polymer churn as multiple state @@ -30,7 +30,7 @@ store.beginBatchUpdate(); store.dispatch(seaPenAction.endSelectRecentSeaPenImageAction(id, success)); if (!success) { - console.warn('Error setting wallpaper'); + console.warn('Error setting image'); } if (store.data.loading.setImage === 0) { // Mark the image as applied or revert back to the old one. @@ -44,14 +44,14 @@ } } -export async function searchSeaPenThumbnails( +export async function getSeaPenThumbnails( query: SeaPenQuery, provider: SeaPenProviderInterface, store: SeaPenStoreInterface): Promise<void> { store.dispatch(seaPenAction.beginSearchSeaPenThumbnailsAction(query)); store.dispatch(seaPenAction.setCurrentSeaPenQueryAction(query)); - const {images, statusCode} = - await withMinimumDelay(provider.searchWallpaper(query)); - if (!isNonEmptyArray(images) || statusCode !== MantaStatusCode.kOk) { + const {thumbnails, statusCode} = + await withMinimumDelay(provider.getSeaPenThumbnails(query)); + if (!isNonEmptyArray(thumbnails) || statusCode !== MantaStatusCode.kOk) { console.warn('Error generating thumbnails. Status code: ', statusCode); } @@ -69,11 +69,11 @@ (templateIdParam === 'Query' && !!query.textQuery)) { store.dispatch( seaPenAction.setThumbnailResponseStatusCodeAction(statusCode)); - store.dispatch(seaPenAction.setSeaPenThumbnailsAction(query, images)); + store.dispatch(seaPenAction.setSeaPenThumbnailsAction(query, thumbnails)); } } -export async function selectSeaPenWallpaper( +export async function selectSeaPenThumbnail( thumbnail: SeaPenThumbnail, provider: SeaPenProviderInterface, store: SeaPenStoreInterface): Promise<void> { const originalCurrentSelected = store.data.currentSelected; @@ -104,7 +104,7 @@ success ? thumbnail.id : originalCurrentSelected)); } store.endBatchUpdate(); - // Re-fetches the recent Sea Pen image if setting sea pen wallpaper + // Re-fetches the recent SeaPen image if setting SeaPen thumbnail // successfully, which means the file has been downloaded successfully. if (success) { logSeaPenImageSet(/*source=*/ 'Create'); @@ -135,12 +135,12 @@ } } -export async function getRecentSeaPenImages( +export async function getRecentSeaPenImageIds( provider: SeaPenProviderInterface, store: SeaPenStoreInterface): Promise<void> { store.dispatch(seaPenAction.beginLoadRecentSeaPenImagesAction()); - const {ids} = await provider.getRecentSeaPenImages(); + const {ids} = await provider.getRecentSeaPenImageIds(); if (ids == null) { console.warn('Failed to fetch recent sea pen images'); } @@ -157,7 +157,7 @@ store: SeaPenStoreInterface): Promise<void> { // Do not restart loading local image list if a load is already in progress. if (!store.data.loading.recentImages) { - await getRecentSeaPenImages(provider, store); + await getRecentSeaPenImageIds(provider, store); } await getMissingRecentSeaPenImageData(provider, store); }
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_images_element.ts b/ash/webui/common/resources/sea_pen/sea_pen_images_element.ts index 67cea39..aee9fc9b 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_images_element.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_images_element.ts
@@ -24,7 +24,7 @@ import {Query, SeaPenImageId} from './constants.js'; import {isLacrosEnabled} from './load_time_booleans.js'; import {MantaStatusCode, SeaPenThumbnail} from './sea_pen.mojom-webui.js'; -import {clearSeaPenThumbnails, openFeedbackDialog, selectSeaPenWallpaper} from './sea_pen_controller.js'; +import {clearSeaPenThumbnails, openFeedbackDialog, selectSeaPenThumbnail} from './sea_pen_controller.js'; import {SeaPenTemplateId} from './sea_pen_generated.mojom-webui.js'; import {getTemplate} from './sea_pen_images_element.html.js'; import {getSeaPenProvider} from './sea_pen_interface_provider.js'; @@ -283,7 +283,7 @@ logSeaPenThumbnailClicked(this.templateId as SeaPenTemplateId); } - selectSeaPenWallpaper( + selectSeaPenThumbnail( event.model.item, getSeaPenProvider(), this.getStore()); }
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_input_query_element.ts b/ash/webui/common/resources/sea_pen/sea_pen_input_query_element.ts index 3065fe7..26fdfd0 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_input_query_element.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_input_query_element.ts
@@ -22,8 +22,8 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {isSeaPenTextInputEnabled} from './load_time_booleans.js'; -import {MAXIMUM_SEARCH_WALLPAPER_TEXT_BYTES, SeaPenQuery, SeaPenThumbnail} from './sea_pen.mojom-webui.js'; -import {searchSeaPenThumbnails} from './sea_pen_controller.js'; +import {MAXIMUM_GET_SEA_PEN_THUMBNAILS_TEXT_BYTES, SeaPenQuery, SeaPenThumbnail} from './sea_pen.mojom-webui.js'; +import {getSeaPenThumbnails} from './sea_pen_controller.js'; import {getTemplate} from './sea_pen_input_query_element.html.js'; import {getSeaPenProvider} from './sea_pen_interface_provider.js'; import {WithSeaPenStore} from './sea_pen_store.js'; @@ -67,7 +67,7 @@ maxTextLength_: { type: Number, - value: Math.floor(MAXIMUM_SEARCH_WALLPAPER_TEXT_BYTES / 3), + value: Math.floor(MAXIMUM_GET_SEA_PEN_THUMBNAILS_TEXT_BYTES / 3), }, }; } @@ -95,7 +95,7 @@ const query: SeaPenQuery = { textQuery: this.textValue_, }; - searchSeaPenThumbnails(query, getSeaPenProvider(), this.getStore()); + getSeaPenThumbnails(query, getSeaPenProvider(), this.getStore()); // Stop the event propagation, otherwise, the event will be passed to parent // element, this.onClick_ will be triggered improperly. event.preventDefault();
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_recent_wallpapers_element.ts b/ash/webui/common/resources/sea_pen/sea_pen_recent_wallpapers_element.ts index b5fcfef..e5a6510 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_recent_wallpapers_element.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_recent_wallpapers_element.ts
@@ -24,7 +24,7 @@ import {SeaPenImageId} from './constants.js'; import {isSeaPenUINextEnabled} from './load_time_booleans.js'; import {RecentSeaPenThumbnailData, SeaPenThumbnail} from './sea_pen.mojom-webui.js'; -import {deleteRecentSeaPenImage, fetchRecentSeaPenData, searchSeaPenThumbnails, selectRecentSeaPenImage} from './sea_pen_controller.js'; +import {deleteRecentSeaPenImage, fetchRecentSeaPenData, getSeaPenThumbnails, selectRecentSeaPenImage} from './sea_pen_controller.js'; import {getSeaPenProvider} from './sea_pen_interface_provider.js'; import {logRecentImageActionMenuItemClick, RecentImageActionMenuItem} from './sea_pen_metrics_logger.js'; import {getTemplate} from './sea_pen_recent_wallpapers_element.html.js'; @@ -333,7 +333,7 @@ seaPenQuery.textQuery ? 'Query' : seaPenQuery.templateQuery?.id; // Route to the results page and search thumbnails for the Sea Pen query. SeaPenRouterElement.instance().selectSeaPenTemplate(templateId); - searchSeaPenThumbnails(seaPenQuery, getSeaPenProvider(), this.getStore()); + getSeaPenThumbnails(seaPenQuery, getSeaPenProvider(), this.getStore()); } private async onClickDeleteWallpaper_(event: Event&{
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts b/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts index a9b08ea..d659de2 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_reducer.ts
@@ -205,7 +205,7 @@ switch (action.name) { case SeaPenActionName.SET_SEA_PEN_THUMBNAILS: assert(!!action.query, 'input text is empty.'); - return action.images; + return action.thumbnails; case SeaPenActionName.CLEAR_SEA_PEN_THUMBNAILS: return null; default:
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_template_query_element.ts b/ash/webui/common/resources/sea_pen/sea_pen_template_query_element.ts index d5aa2f7..a2b140d 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_template_query_element.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_template_query_element.ts
@@ -22,7 +22,7 @@ import {getSeaPenTemplates, SeaPenOption, SeaPenTemplate} from './constants.js'; import {SeaPenQuery, SeaPenThumbnail, SeaPenUserVisibleQuery} from './sea_pen.mojom-webui.js'; -import {searchSeaPenThumbnails} from './sea_pen_controller.js'; +import {getSeaPenThumbnails} from './sea_pen_controller.js'; import {SeaPenTemplateChip, SeaPenTemplateId, SeaPenTemplateOption} from './sea_pen_generated.mojom-webui.js'; import {getSeaPenProvider} from './sea_pen_interface_provider.js'; import {logGenerateSeaPenWallpaper} from './sea_pen_metrics_logger.js'; @@ -364,7 +364,7 @@ private onClickSearchButton_(event: Event) { this.clearSelectedChipState_(); - searchSeaPenThumbnails( + getSeaPenThumbnails( this.getTemplateRequest_(), getSeaPenProvider(), this.getStore()); logGenerateSeaPenWallpaper(this.getSeaPenTemplateId_());
diff --git a/ash/webui/common/resources/shortcut_input_ui/shortcut_input.html b/ash/webui/common/resources/shortcut_input_ui/shortcut_input.html index fa44ec6..70ba833b 100644 --- a/ash/webui/common/resources/shortcut_input_ui/shortcut_input.html +++ b/ash/webui/common/resources/shortcut_input_ui/shortcut_input.html
@@ -69,6 +69,14 @@ pendingPrerewrittenKeyEvent.*)]]" has-launcher-button="[[hasLauncherButton]]"> </shortcut-input-key> + <template is="dom-if" if="[[hasFunctionKey]]"> + <shortcut-input-key id="functionKey" + key="function" + key-state="[[getFunctionState(pendingKeyEvent.*, + pendingPrerewrittenKeyEvent.*)]]" + has-launcher-button="[[hasLauncherButton]]"> + </shortcut-input-key> + </template> <div id="keySeparator"> + </div> <shortcut-input-key id="pendingKey" key="[[getKey(pendingKeyEvent.*, pendingPrerewrittenKeyEvent.*)]]"
diff --git a/ash/webui/common/resources/shortcut_input_ui/shortcut_input.ts b/ash/webui/common/resources/shortcut_input_ui/shortcut_input.ts index 241a826..f5de57b 100644 --- a/ash/webui/common/resources/shortcut_input_ui/shortcut_input.ts +++ b/ash/webui/common/resources/shortcut_input_ui/shortcut_input.ts
@@ -82,10 +82,16 @@ shouldIgnoreKeyRelease: { type: Boolean, }, + + hasFunctionKey: { + type: Boolean, + }, + }; } hasLauncherButton: boolean = true; + hasFunctionKey: boolean = false; shortcutInputProvider: ShortcutInputProviderInterface|null = null; pendingKeyEvent: KeyEvent|null = null; pendingPrerewrittenKeyEvent: KeyEvent|null = null; @@ -348,6 +354,13 @@ /** * Returns the specified CSS state of the modifier key element. */ + protected getFunctionState(): string { + return this.getModifierState(Modifier.FN_KEY); + } + + /** + * Returns the specified CSS state of the modifier key element. + */ private getModifierState(modifier: Modifier): KeyInputState { const keyEvent = this.getPendingKeyEvent(); if (keyEvent && keyEvent?.modifiers & modifier) { @@ -367,6 +380,8 @@ return 'alt'; case Modifier.COMMAND: return 'meta'; + case Modifier.FN_KEY: + return 'fn'; } return assertNotReached(); }
diff --git a/ash/webui/common/resources/shortcut_input_ui/shortcut_utils.ts b/ash/webui/common/resources/shortcut_input_ui/shortcut_utils.ts index 2c9dde4..855c856 100644 --- a/ash/webui/common/resources/shortcut_input_ui/shortcut_utils.ts +++ b/ash/webui/common/resources/shortcut_input_ui/shortcut_utils.ts
@@ -26,6 +26,7 @@ CONTROL = 1 << 2, ALT = 1 << 3, COMMAND = 1 << 4, + FN_KEY = 1 << 5, } export const Modifiers: Modifier[] = [ @@ -33,6 +34,7 @@ Modifier.CONTROL, Modifier.ALT, Modifier.COMMAND, + Modifier.FN_KEY, ]; export enum AllowedModifierKeyCodes { @@ -41,6 +43,7 @@ ALT = 18, META_LEFT = 91, META_RIGHT = 92, + FN_KEY = 255, } export const ModifierKeyCodes: AllowedModifierKeyCodes[] = [ @@ -49,10 +52,11 @@ AllowedModifierKeyCodes.CTRL, AllowedModifierKeyCodes.META_LEFT, AllowedModifierKeyCodes.META_RIGHT, + AllowedModifierKeyCodes.FN_KEY, ]; export const getSortedModifiers = (modifierStrings: string[]): string[] => { - const sortOrder = ['meta', 'ctrl', 'alt', 'shift']; + const sortOrder = ['meta', 'ctrl', 'alt', 'shift', 'fn']; if (modifierStrings.length <= 1) { return modifierStrings; }
diff --git a/ash/webui/personalization_app/resources/js/personalization_app.ts b/ash/webui/personalization_app/resources/js/personalization_app.ts index c9ca1eb..96c48ed 100644 --- a/ash/webui/personalization_app/resources/js/personalization_app.ts +++ b/ash/webui/personalization_app/resources/js/personalization_app.ts
@@ -119,7 +119,7 @@ export {DEFAULT_COLOR_SCHEME} from './theme/utils.js'; export {LocalImagesElement} from './wallpaper/local_images_element.js'; export * from 'chrome://resources/ash/common/sea_pen/sea_pen_actions.js'; -export {getRecentSeaPenImages, selectRecentSeaPenImage, searchSeaPenThumbnails, selectSeaPenWallpaper} from 'chrome://resources/ash/common/sea_pen/sea_pen_controller.js'; +export {getRecentSeaPenImageIds, selectRecentSeaPenImage, getSeaPenThumbnails, selectSeaPenThumbnail} from 'chrome://resources/ash/common/sea_pen/sea_pen_controller.js'; export {SeaPenFeedbackElement} from 'chrome://resources/ash/common/sea_pen/sea_pen_feedback_element.js'; export {SeaPenImageLoadingElement} from 'chrome://resources/ash/common/sea_pen/sea_pen_image_loading_element.js'; export {SeaPenImagesElement} from 'chrome://resources/ash/common/sea_pen/sea_pen_images_element.js';
diff --git a/ash/webui/personalization_app/test/personalization_app_mojom_banned_mocha_test_base.cc b/ash/webui/personalization_app/test/personalization_app_mojom_banned_mocha_test_base.cc index 8425395..7bf2321 100644 --- a/ash/webui/personalization_app/test/personalization_app_mojom_banned_mocha_test_base.cc +++ b/ash/webui/personalization_app/test/personalization_app_mojom_banned_mocha_test_base.cc
@@ -116,8 +116,9 @@ bool IsEligibleForSeaPen() override { return true; } // ::ash::personalization_app::mojom::SeaPenProvider: MOCK_METHOD(void, - SearchWallpaper, - (const mojom::SeaPenQueryPtr, SearchWallpaperCallback callback), + GetSeaPenThumbnails, + (const mojom::SeaPenQueryPtr, + GetSeaPenThumbnailsCallback callback), (override)); MOCK_METHOD(void, SelectSeaPenThumbnail, @@ -128,8 +129,8 @@ (uint32_t id, SelectRecentSeaPenImageCallback), (override)); MOCK_METHOD(void, - GetRecentSeaPenImages, - (GetRecentSeaPenImagesCallback), + GetRecentSeaPenImageIds, + (GetRecentSeaPenImageIdsCallback), (override)); MOCK_METHOD(void, GetRecentSeaPenImageThumbnail,
diff --git a/ash/webui/sanitize_ui/BUILD.gn b/ash/webui/sanitize_ui/BUILD.gn new file mode 100644 index 0000000..e4df07d --- /dev/null +++ b/ash/webui/sanitize_ui/BUILD.gn
@@ -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. + +import("//build/config/chromeos/ui_mode.gni") +import("//testing/test.gni") + +assert(is_chromeos_ash, "Sanitize App is ash-chrome only") + +static_library("sanitize_ui") { + sources = [ + "sanitize_ui.cc", + "sanitize_ui.h", + "url_constants.cc", + "url_constants.h", + ] + + public_deps = [ ":url_constants" ] + + deps = [ + "//ash/webui/common:chrome_os_webui_config", + "//ash/webui/common:trusted_types_util", + "//ash/webui/sanitize_ui/resources:resources", + "//chromeos/strings:strings_grit", + "//content/public/browser:browser", + "//ui/base", + "//ui/resources", + "//ui/web_dialogs", + "//ui/webui", + ] +} + +# Url constants pulled out to enable depending on production url constants in +# browser tests. +source_set("url_constants") { + sources = [ + "url_constants.cc", + "url_constants.h", + ] +}
diff --git a/ash/webui/sanitize_ui/DEPS b/ash/webui/sanitize_ui/DEPS new file mode 100644 index 0000000..52d69fec --- /dev/null +++ b/ash/webui/sanitize_ui/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ui/webui", +]
diff --git a/ash/webui/sanitize_ui/resources/BUILD.gn b/ash/webui/sanitize_ui/resources/BUILD.gn new file mode 100644 index 0000000..62e052a --- /dev/null +++ b/ash/webui/sanitize_ui/resources/BUILD.gn
@@ -0,0 +1,24 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chromeos/ui_mode.gni") +import("//ui/webui/resources/tools/build_webui.gni") + +assert(is_chromeos_ash, "Non-ChromeOS builds cannot depend on //ash") + +build_webui("build") { + static_files = [ "index.html" ] + + web_component_files = [ "sanitize_done.ts" ] + + ts_composite = true + ts_deps = [ + "//third_party/polymer/v3_0:library", + "//ui/webui/resources/js:build_ts", + ] + + webui_context_type = "trusted" + grd_prefix = "ash_sanitize_app" + grit_output_dir = "$root_gen_dir/ash/webui" +}
diff --git a/ash/webui/sanitize_ui/resources/index.html b/ash/webui/sanitize_ui/resources/index.html new file mode 100644 index 0000000..04b7d83 --- /dev/null +++ b/ash/webui/sanitize_ui/resources/index.html
@@ -0,0 +1,15 @@ +<!-- Copyright 2024 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<!DOCTYPE html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> + <head> + <title></title> + <meta charset="utf-8"> + </head> + <body> + <sanitize-done></sanitize-done> + <script type="module" src="sanitize_done.js"></script> + </body> +</html> +
diff --git a/ash/webui/sanitize_ui/resources/sanitize_done.html b/ash/webui/sanitize_ui/resources/sanitize_done.html new file mode 100644 index 0000000..743263b --- /dev/null +++ b/ash/webui/sanitize_ui/resources/sanitize_done.html
@@ -0,0 +1 @@ +<div id="header"></div>
diff --git a/ash/webui/sanitize_ui/resources/sanitize_done.ts b/ash/webui/sanitize_ui/resources/sanitize_done.ts new file mode 100644 index 0000000..6e99321 --- /dev/null +++ b/ash/webui/sanitize_ui/resources/sanitize_done.ts
@@ -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. + +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './sanitize_done.html.js'; + +export interface SanitizeDoneElement { + $: { + header: HTMLDivElement, + }; +} + +/** + * @fileoverview + * 'sanitize-done' is a dialog shown after reverting to safe settings + * (aka sanitize). + */ +export class SanitizeDoneElement extends PolymerElement { + static get is() { + return 'sanitize-done' as const; + } + + static get template() { + return getTemplate(); + } + + override ready() { + super.ready(); + this.$.header.textContent = 'Sanitize Done'; + } +} + +declare global { + interface HTMLElementTagNameMap { + [SanitizeDoneElement.is]: SanitizeDoneElement; + } +} +customElements.define(SanitizeDoneElement.is, SanitizeDoneElement);
diff --git a/ash/webui/sanitize_ui/sanitize_ui.cc b/ash/webui/sanitize_ui/sanitize_ui.cc new file mode 100644 index 0000000..ce36754 --- /dev/null +++ b/ash/webui/sanitize_ui/sanitize_ui.cc
@@ -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. + +#include "ash/webui/sanitize_ui/sanitize_ui.h" + +#include "ash/webui/common/trusted_types_util.h" +#include "ash/webui/grit/ash_sanitize_app_resources.h" +#include "ash/webui/grit/ash_sanitize_app_resources_map.h" +#include "ash/webui/sanitize_ui/url_constants.h" +#include "chromeos/strings/grit/chromeos_strings.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/resources/grit/webui_resources.h" + +namespace ash { + +SanitizeDialogUI::SanitizeDialogUI(content::WebUI* web_ui) + : ui::MojoWebDialogUI(web_ui) { + content::WebUIDataSource* html_source = + content::WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUISanitizeAppHost); + html_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, + "script-src chrome://resources chrome://webui-test 'self';"); + ash::EnableTrustedTypesCSP(html_source); + html_source->EnableReplaceI18nInJS(); + + const auto resources = + base::make_span(kAshSanitizeAppResources, kAshSanitizeAppResourcesSize); + html_source->AddResourcePaths(resources); + html_source->AddResourcePath("", IDR_ASH_SANITIZE_APP_INDEX_HTML); + html_source->AddResourcePath("test_loader.html", IDR_WEBUI_TEST_LOADER_HTML); + html_source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER_JS); + html_source->AddResourcePath("test_loader_util.js", + IDR_WEBUI_JS_TEST_LOADER_UTIL_JS); +} + +SanitizeDialogUI::~SanitizeDialogUI() {} + +WEB_UI_CONTROLLER_TYPE_IMPL(SanitizeDialogUI) + +} // namespace ash
diff --git a/ash/webui/sanitize_ui/sanitize_ui.h b/ash/webui/sanitize_ui/sanitize_ui.h new file mode 100644 index 0000000..dec1f0e --- /dev/null +++ b/ash/webui/sanitize_ui/sanitize_ui.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 ASH_WEBUI_SANITIZE_UI_SANITIZE_UI_H_ +#define ASH_WEBUI_SANITIZE_UI_SANITIZE_UI_H_ + +#include "ash/webui/common/chrome_os_webui_config.h" +#include "ash/webui/sanitize_ui/url_constants.h" +#include "ui/web_dialogs/web_dialog_ui.h" + +namespace ash { +class SanitizeDialogUI; + +// The WebDialogUIConfig for chrome://sanitize +class SanitizeDialogUIConfig : public ChromeOSWebUIConfig<SanitizeDialogUI> { + public: + explicit SanitizeDialogUIConfig( + CreateWebUIControllerFunc create_controller_func) + : ChromeOSWebUIConfig(content::kChromeUIScheme, + ash::kChromeUISanitizeAppHost, + create_controller_func) {} +}; + +// The WebDialogUI for chrome://sanitize +class SanitizeDialogUI : public ui::MojoWebDialogUI { + public: + explicit SanitizeDialogUI(content::WebUI* web_ui); + ~SanitizeDialogUI() override; + + SanitizeDialogUI(const SanitizeDialogUI&) = delete; + SanitizeDialogUI& operator=(const SanitizeDialogUI&) = delete; + + private: + WEB_UI_CONTROLLER_TYPE_DECL(); +}; + +} // namespace ash + +#endif // ASH_WEBUI_SANITIZE_UI_SANITIZE_UI_H_
diff --git a/ash/webui/sanitize_ui/url_constants.cc b/ash/webui/sanitize_ui/url_constants.cc new file mode 100644 index 0000000..660df2e --- /dev/null +++ b/ash/webui/sanitize_ui/url_constants.cc
@@ -0,0 +1,12 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/webui/sanitize_ui/url_constants.h" + +namespace ash { + +const char kChromeUISanitizeAppHost[] = "sanitize"; +const char kChromeUISanitizeAppUrl[] = "chrome://sanitize"; + +} // namespace ash
diff --git a/ash/webui/sanitize_ui/url_constants.h b/ash/webui/sanitize_ui/url_constants.h new file mode 100644 index 0000000..b6edc5861 --- /dev/null +++ b/ash/webui/sanitize_ui/url_constants.h
@@ -0,0 +1,10 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef ASH_WEBUI_SANITIZE_UI_URL_CONSTANTS_H_ +#define ASH_WEBUI_SANITIZE_UI_URL_CONSTANTS_H_ +namespace ash { +extern const char kChromeUISanitizeAppHost[]; +extern const char kChromeUISanitizeAppUrl[]; +} // namespace ash +#endif // ASH_WEBUI_SANITIZE_UI_URL_CONSTANTS_H_
diff --git a/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.html b/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.html index 9d17258..c6ce8984 100644 --- a/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.html +++ b/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.html
@@ -70,6 +70,7 @@ should-ignore-key-release="[[hasError]]" update-on-key-press display-prerewritten-key-events + has-function-key="[[hasFunctionKey]]" ignore-blur> </shortcut-input> </template>
diff --git a/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts b/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts index 4e0c697f..e7447d1 100644 --- a/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts +++ b/ash/webui/shortcut_customization_ui/resources/js/accelerator_view.ts
@@ -6,13 +6,14 @@ import 'chrome://resources/ash/common/shortcut_input_ui/shortcut_input_key.js'; import 'chrome://resources/ash/common/shortcut_input_ui/shortcut_input.js'; +import {getInstance as getAnnouncerInstance} from 'chrome://resources/ash/common/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; +import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {KeyEvent} from 'chrome://resources/ash/common/shortcut_input_ui/input_device_settings.mojom-webui.js'; import {ShortcutInputElement} from 'chrome://resources/ash/common/shortcut_input_ui/shortcut_input.js'; import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; -import {getInstance as getAnnouncerInstance} from 'chrome://resources/ash/common/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; -import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {mojoString16ToString} from 'chrome://resources/js/mojo_type_util.js'; import {String16} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js'; import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js'; @@ -150,6 +151,11 @@ /** Whether to show a launcher icon or search icon for meta key. */ hasLauncherButton: Boolean, + + hasFunctionKey: { + type: Boolean, + value: loadTimeData.getBoolean('hasFunctionKey'), + }, }; } @@ -170,6 +176,7 @@ pendingKeyEvent: KeyEvent|null = null; shortcutInput: ShortcutInputElement|null; defaultAccelerators: Accelerator[]; + hasFunctionKey: boolean; protected isCapturing: boolean; protected lastAccelerator: Accelerator; protected lastResult: AcceleratorConfigResult;
diff --git a/ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.cc b/ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.cc index 8575dda..b020c0bb 100644 --- a/ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.cc +++ b/ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.cc
@@ -247,6 +247,9 @@ ash::features::IsJellyEnabledForShortcutCustomization()); html_source->AddBoolean("isInputDeviceSettingsSplitEnabled", features::IsInputDeviceSettingsSplitEnabled()); + html_source->AddBoolean( + "hasFunctionKey", + Shell::Get()->keyboard_capability()->HasFunctionKeyOnAnyKeyboard()); } } // namespace
diff --git a/ash/wm/desks/templates/saved_desk_item_view.cc b/ash/wm/desks/templates/saved_desk_item_view.cc index 7aae1dbb..ab0ad0ee 100644 --- a/ash/wm/desks/templates/saved_desk_item_view.cc +++ b/ash/wm/desks/templates/saved_desk_item_view.cc
@@ -303,6 +303,8 @@ hover_container_->layer()->SetOpacity(0.0f); icon_container_view_->layer()->SetOpacity(1.0f); + + AddAccelerator(ui::Accelerator(ui::VKEY_W, ui::EF_CONTROL_DOWN)); } SavedDeskItemView::~SavedDeskItemView() { @@ -564,6 +566,18 @@ return Button::GetKeyClickActionForEvent(event); } +bool SavedDeskItemView::AcceleratorPressed(const ui::Accelerator& accelerator) { + if (accelerator.IsCtrlDown() && accelerator.key_code() == ui::VKEY_W) { + OnDeleteButtonPressed(); + return true; + } + return views::Button::AcceleratorPressed(accelerator); +} + +bool SavedDeskItemView::CanHandleAccelerators() const { + return HasFocus() && views::Button::CanHandleAccelerators(); +} + void SavedDeskItemView::UpdateSavedDeskName() { saved_desk_->set_template_name(name_view_->GetText()); OnSavedDeskNameChanged(saved_desk_->template_name());
diff --git a/ash/wm/desks/templates/saved_desk_item_view.h b/ash/wm/desks/templates/saved_desk_item_view.h index 3454e05c..32e922e 100644 --- a/ash/wm/desks/templates/saved_desk_item_view.h +++ b/ash/wm/desks/templates/saved_desk_item_view.h
@@ -120,6 +120,8 @@ void OnFocus() override; void OnBlur() override; KeyClickAction GetKeyClickActionForEvent(const ui::KeyEvent& event) override; + bool AcceleratorPressed(const ui::Accelerator& accelerator) override; + bool CanHandleAccelerators() const override; // views::TextfieldController: void ContentsChanged(views::Textfield* sender,
diff --git a/ash/wm/desks/templates/saved_desk_save_desk_button.cc b/ash/wm/desks/templates/saved_desk_save_desk_button.cc index 7fdb2be6..24273b5 100644 --- a/ash/wm/desks/templates/saved_desk_save_desk_button.cc +++ b/ash/wm/desks/templates/saved_desk_save_desk_button.cc
@@ -4,6 +4,7 @@ #include "ash/wm/desks/templates/saved_desk_save_desk_button.h" +#include "ash/constants/ash_features.h" #include "ash/style/style_util.h" #include "ash/wm/desks/templates/saved_desk_constants.h" #include "ash/wm/overview/overview_utils.h" @@ -29,12 +30,14 @@ button_type_(button_type) { auto* focus_ring = views::FocusRing::Get(this); focus_ring->SetOutsetFocusRingDisabled(true); - focus_ring->SetHasFocusPredicate( - base::BindRepeating([](const views::View* view) { - const auto* v = views::AsViewClass<SavedDeskSaveDeskButton>(view); - CHECK(v); - return v->is_focused(); - })); + if (!features::IsOverviewNewFocusEnabled()) { + focus_ring->SetHasFocusPredicate( + base::BindRepeating([](const views::View* view) { + const auto* v = views::AsViewClass<SavedDeskSaveDeskButton>(view); + CHECK(v); + return v->is_focused(); + })); + } SetBorder(std::make_unique<views::HighlightBorder>( kSaveDeskCornerRadius,
diff --git a/ash/wm/desks/templates/saved_desk_unittest.cc b/ash/wm/desks/templates/saved_desk_unittest.cc index e23cc11..b6b83d4 100644 --- a/ash/wm/desks/templates/saved_desk_unittest.cc +++ b/ash/wm/desks/templates/saved_desk_unittest.cc
@@ -1969,11 +1969,14 @@ } TEST_F(SavedDeskTest, OverviewTabbing) { + const base::Time saved_desk_creation_time = + base::Time::FromSecondsSinceUnixEpoch(10); + auto test_window = CreateAppWindow(); - AddEntry(base::Uuid::GenerateRandomV4(), "template1", base::Time::Now(), - DeskTemplateType::kTemplate); - AddEntry(base::Uuid::GenerateRandomV4(), "template2", base::Time::Now(), - DeskTemplateType::kTemplate); + AddEntry(base::Uuid::GenerateRandomV4(), "template1", + saved_desk_creation_time, DeskTemplateType::kTemplate); + AddEntry(base::Uuid::GenerateRandomV4(), "template2", + saved_desk_creation_time, DeskTemplateType::kTemplate); OpenOverviewAndShowSavedDeskGrid(); SavedDeskItemView* first_item = GetItemViewFromSavedDeskGrid(0); @@ -1993,6 +1996,14 @@ // Testing that we traverse to the `name_view` of the second item. PressAndReleaseKey(ui::VKEY_TAB); EXPECT_EQ(second_item->name_view(), GetFocusedView()); + + // Traversing name views should not update the template if there was no + // editing. + std::vector<raw_ptr<const DeskTemplate, VectorExperimental>> entries = + GetAllEntries(); + ASSERT_EQ(2u, entries.size()); + EXPECT_EQ(saved_desk_creation_time, entries[0]->GetLastUpdatedTime()); + EXPECT_EQ(saved_desk_creation_time, entries[1]->GetLastUpdatedTime()); } // Tests that if the templates button is invisible, it is not part of the
diff --git a/ash/wm/overview/overview_focus_cycler.cc b/ash/wm/overview/overview_focus_cycler.cc index ca407485..3a06cfd 100644 --- a/ash/wm/overview/overview_focus_cycler.cc +++ b/ash/wm/overview/overview_focus_cycler.cc
@@ -111,7 +111,8 @@ } // Skip this widget if it has no focusable views. (i.e. Saved desks library - // with all saved desks deleted.) + // with all saved desks deleted or saved desk button container with all + // buttons disabled.) if (!widget->GetFocusManager()->GetNextFocusableView( /*starting_view=*/nullptr, widget, /*reverse=*/false, /*dont_loop=*/false)) { @@ -125,6 +126,7 @@ OverviewGrid* primary_grid = overview_session_->GetGridWithRootWindow(Shell::GetPrimaryRootWindow()); maybe_add_widget(primary_grid->pine_widget()); + maybe_add_widget(primary_grid->save_desk_button_container_widget()); maybe_add_widget(primary_grid->feedback_widget()); maybe_add_widget(primary_grid->birch_bar_widget()); maybe_add_widget(primary_grid->saved_desk_library_widget());
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 838fe79..f7560ae 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -325,7 +325,7 @@ Shell::Get()->accessibility_controller()->spoken_feedback().enabled(); params.activatable = (spoken_feedback_enabled || features::IsOverviewNewFocusEnabled()) - ? views::Widget::InitParams::Activatable::kDefault + ? views::Widget::InitParams::Activatable::kYes : views::Widget::InitParams::Activatable::kNo; params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
diff --git a/ash/wm/overview/overview_grid_unittest.cc b/ash/wm/overview/overview_grid_unittest.cc index ae188b2..5bdb9ee 100644 --- a/ash/wm/overview/overview_grid_unittest.cc +++ b/ash/wm/overview/overview_grid_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/overview/overview_item.h" +#include "ash/wm/overview/overview_test_base.h" #include "ash/wm/overview/overview_test_util.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" @@ -33,7 +34,7 @@ scoped_feature_list_.InitWithFeatures( /*enabled_features=*/{features::kFasterSplitScreenSetup, features::kOsSettingsRevampWayfinding}, - /*disabled_features=*/{}); + /*disabled_features=*/{features::kForestFeature}); } OverviewGridTest(const OverviewGridTest&) = delete; @@ -320,4 +321,289 @@ EXPECT_FALSE(item3->should_animate_when_entering()); } +class OverviewGridForestTest : public OverviewTestBase { + public: + OverviewGridForestTest() { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{features::kFasterSplitScreenSetup, + features::kOsSettingsRevampWayfinding, + features::kForestFeature}, + /*disabled_features=*/{}); + } + OverviewGridForestTest(const OverviewGridForestTest&) = delete; + OverviewGridForestTest& operator=(const OverviewGridForestTest&) = delete; + ~OverviewGridForestTest() override = default; + + // Calculates `OverviewItemBase::should_animate_when_exiting_`. The reason we + // do it like this is because this is normally called during shutdown, and + // then the grid and items objects are destroyed. Note that this function + // assumes one root window. + void CalculateShouldAnimateWhenExiting( + OverviewItemBase* selected_item = nullptr) { + ASSERT_EQ(1u, Shell::GetAllRootWindows().size()); + + OverviewGrid* grid = GetOverviewGridForRoot(Shell::GetPrimaryRootWindow()); + ASSERT_TRUE(grid); + grid->CalculateWindowListAnimationStates(selected_item, + OverviewTransition::kExit, + /*target_bounds=*/{}); + } + + // Checks expected against actual enter and exit animation values. Note that + // this function assumes one root window. + void VerifyAnimationStates( + const std::vector<bool>& expected_enter_animations, + const std::vector<bool>& expected_exit_animations) { + ASSERT_EQ(1u, Shell::GetAllRootWindows().size()); + + OverviewGrid* grid = GetOverviewGridForRoot(Shell::GetPrimaryRootWindow()); + ASSERT_TRUE(grid); + + const std::vector<std::unique_ptr<OverviewItemBase>>& overview_items = + grid->window_list(); + if (!expected_enter_animations.empty()) { + ASSERT_EQ(overview_items.size(), expected_enter_animations.size()); + for (size_t i = 0; i < overview_items.size(); ++i) { + EXPECT_EQ(expected_enter_animations[i], + overview_items[i]->should_animate_when_entering()); + } + } + if (!expected_exit_animations.empty()) { + ASSERT_EQ(overview_items.size(), expected_exit_animations.size()); + for (size_t i = 0; i < overview_items.size(); ++i) { + EXPECT_EQ(expected_exit_animations[i], + overview_items[i]->should_animate_when_exiting()); + } + } + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// Tests that with only one window, we always animate. +TEST_F(OverviewGridForestTest, AnimateWithSingleWindow) { + auto window = CreateAppWindow(gfx::Rect(100, 100)); + ToggleOverview(); + VerifyAnimationStates({true}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true}); +} + +// Tests that are animations if the destination bounds are shown. +TEST_F(OverviewGridForestTest, SourceHiddenDestinationShown) { + auto window1 = CreateAppWindow(gfx::Rect(100, 100)); + auto window2 = CreateAppWindow(gfx::Rect(200, 200)); + + ToggleOverview(); + VerifyAnimationStates({true, true}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true, true}); +} + +// Tests that are animations if the source bounds are shown. +TEST_F(OverviewGridForestTest, SourceShownDestinationHidden) { + auto window1 = CreateAppWindow(gfx::Rect(100, 100)); + WindowState::Get(window1.get())->Maximize(); + + auto window2 = CreateAppWindow(gfx::Rect(400, 400)); + + ToggleOverview(); + VerifyAnimationStates({true, true}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true, true}); +} + +// Tests that a window that is in the union of two other windows, but is still +// shown will be animated. +TEST_F(OverviewGridForestTest, SourceShownButInTheUnionOfTwoOtherWindows) { + // Create three windows, the union of the first two windows will be + // gfx::Rect(0, 0, 200, 200). Window 3 will be in that union, but should still + // animate since its not fully occluded. + auto window3 = CreateAppWindow(gfx::Rect(50, 200)); + auto window2 = CreateAppWindow(gfx::Rect(50, 50, 150, 150)); + auto window1 = CreateAppWindow(gfx::Rect(100, 100)); + + ToggleOverview(); + VerifyAnimationStates({true, true, true}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true, true, true}); +} + +// Tests that an always on top window will still be animated even if its source +// and destination bounds are covered. +TEST_F(OverviewGridForestTest, AlwaysOnTopWindow) { + UpdateDisplay("800x600"); + + // Create two windows, even if `window1` is maximized, `window2` will still + // animate since it is always on top. + auto window2 = CreateAppWindow(gfx::Rect(100, 100)); + window2->SetProperty(aura::client::kZOrderingKey, + ui::ZOrderLevel::kFloatingWindow); + auto window1 = CreateAppWindow(gfx::Rect(100, 100)); + WindowState::Get(window1.get())->Maximize(); + + ToggleOverview(); + VerifyAnimationStates({true, true}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true, true}); +} + +// Tests that windows that are minimized are animated as expected. +TEST_F(OverviewGridForestTest, MinimizedWindows) { + UpdateDisplay("800x600"); + + auto window3 = CreateAppWindow(gfx::Rect(800, 600)); + WindowState::Get(window3.get())->Minimize(); + auto window2 = CreateAppWindow(gfx::Rect(800, 600)); + WindowState::Get(window2.get())->Minimize(); + auto window1 = CreateAppWindow(gfx::Rect(10, 10, 780, 580)); + + // The minimized windows do not animate since their source is hidden, and + // their destination is blocked by the near maximized window. + ToggleOverview(); + VerifyAnimationStates({true, false, false}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true, false, false}); +} + +TEST_F(OverviewGridForestTest, SelectedWindow) { + // Create 3 windows with the third window being maximized. All windows are + // visible on entering, so they should all be animated. On exit we select the + // third window which is maximized, so the other two windows should not + // animate. + auto window3 = CreateAppWindow(gfx::Rect(400, 400)); + WindowState::Get(window3.get())->Maximize(); + auto window2 = CreateAppWindow(gfx::Rect(400, 400)); + auto window1 = CreateAppWindow(gfx::Rect(100, 100)); + + ToggleOverview(); + VerifyAnimationStates({true, true, true}, {}); + + OverviewItemBase* selected_item = GetOverviewItemForWindow(window3.get()); + CalculateShouldAnimateWhenExiting(selected_item); + VerifyAnimationStates({}, {false, false, true}); +} + +TEST_F(OverviewGridForestTest, WindowWithBackdrop) { + // Create one non resizable window and one normal window and verify that the + // backdrop shows over the non resizable window, and that normal window + // becomes maximized upon entering tablet mode. + auto window1 = CreateTestWindow(gfx::Rect(100, 100)); + auto window2 = CreateTestWindow(gfx::Rect(400, 400)); + window1->SetProperty(aura::client::kResizeBehaviorKey, + aura::client::kResizeBehaviorNone); + wm::ActivateWindow(window1.get()); + + Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); + BackdropController* backdrop_controller = + GetWorkspaceControllerForContext(window1.get()) + ->layout_manager() + ->backdrop_controller(); + EXPECT_EQ(window1.get(), backdrop_controller->GetTopmostWindowWithBackdrop()); + EXPECT_TRUE(backdrop_controller->backdrop_window()); + EXPECT_TRUE(WindowState::Get(window2.get())->IsMaximized()); + + // Tests that the second window despite being larger than the first window + // does not animate as it is hidden behind the backdrop. On exit, it still + // animates as the backdrop is not visible yet. + ToggleOverview(); + VerifyAnimationStates({true, false}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true, true}); +} + +TEST_F(OverviewGridForestTest, SourcePartiallyOffscreenWindow) { + UpdateDisplay("500x400"); + + // Create `window2` to be partially offscreen. + auto window2 = CreateAppWindow(gfx::Rect(450, 100, 100, 100)); + auto window1 = CreateAppWindow(gfx::Rect(100, 100)); + + // Tests that it still animates because the onscreen portion is not occluded + // by `window1`. + ToggleOverview(); + VerifyAnimationStates({true, true}, {}); + + CalculateShouldAnimateWhenExiting(); + VerifyAnimationStates({}, {true, true}); + ToggleOverview(); + + // Maximize `window1`. `window2` should no longer animate since the parts of + // it that are onscreen are fully occluded. + WindowState::Get(window1.get())->Maximize(); + ToggleOverview(); + VerifyAnimationStates({true, false}, {}); +} + +// Tests that windows whose destination is partially or fully offscreen never +// animate. +TEST_F(OverviewGridForestTest, PartialAndFullOffscreenWindow) { + UpdateDisplay("800x600"); + + Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); + + // With this display size, the 9th and 10th windows will be partially + // offscreen and the 11th and 12th windows will be fully offscreen once we + // enter overview. Since the earlier created windows are lower on the MRU + // order, this equals the 3rd and 4th windows and the 1st and 2nd window + // respectively. + std::vector<std::unique_ptr<aura::Window>> windows; + for (int i = 0; i < 12; ++i) { + windows.push_back(CreateAppWindow(gfx::Rect(100, 100))); + } + + // Enter overview and assert that we have one partially offscreen overview + // item and one fully offscreen overview item. + ToggleOverview(); + OverviewItemBase* partially_offscreen_item = + GetOverviewItemForWindow(windows[2].get()); + OverviewItemBase* fully_offscreen_item = + GetOverviewItemForWindow(windows[0].get()); + ASSERT_FALSE(gfx::RectF(800.f, 600.f) + .Contains(partially_offscreen_item->target_bounds())); + ASSERT_TRUE(gfx::RectF(800.f, 600.f) + .Intersects(partially_offscreen_item->target_bounds())); + ASSERT_FALSE( + gfx::RectF(800.f, 600.f).Contains(fully_offscreen_item->target_bounds())); + ASSERT_FALSE(gfx::RectF(800.f, 600.f) + .Intersects(fully_offscreen_item->target_bounds())); + EXPECT_FALSE(partially_offscreen_item->should_animate_when_entering()); + EXPECT_FALSE(fully_offscreen_item->should_animate_when_entering()); + + CalculateShouldAnimateWhenExiting(); + EXPECT_FALSE(partially_offscreen_item->should_animate_when_exiting()); + EXPECT_FALSE(fully_offscreen_item->should_animate_when_exiting()); +} + +// Tests that only one window animates when entering overview from splitview +// double snapped. +TEST_F(OverviewGridForestTest, SnappedWindow) { + auto window3 = CreateAppWindow(gfx::Rect(100, 100)); + auto window2 = CreateAppWindow(gfx::Rect(100, 100)); + auto window1 = CreateAppWindow(gfx::Rect(100, 100)); + + Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); + auto* split_view_controller = + SplitViewController::Get(Shell::GetPrimaryRootWindow()); + split_view_controller->SnapWindow(window1.get(), SnapPosition::kPrimary); + + // Snap `window2` and check that `window3` is maximized. + split_view_controller->SnapWindow(window2.get(), SnapPosition::kSecondary); + EXPECT_TRUE(WindowState::Get(window3.get())->IsMaximized()); + + // Tests that `window3` is not animated even though its bounds are larger than + // `window2` because it is fully occluded by `window1` + `window2` and the + // split view divider. + ToggleOverview(); + VerifyAnimationStates({true, false}, {}); +} + } // namespace ash
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc index 33df687b..235ba4c8 100644 --- a/ash/wm/overview/overview_session.cc +++ b/ash/wm/overview/overview_session.cc
@@ -1527,6 +1527,10 @@ break; } case ui::VKEY_RETURN: { + if (!focus_cycler_old_) { + return; + } + if (focus_cycler_old_ && !focus_cycler_old_->MaybeActivateFocusedView()) { return; }
diff --git a/build/fuchsia/test/test_server.py b/build/fuchsia/test/test_server.py index e3af0c5..8166e08cf 100644 --- a/build/fuchsia/test/test_server.py +++ b/build/fuchsia/test/test_server.py
@@ -10,7 +10,7 @@ from typing import List, Optional, Tuple -from common import DIR_SRC_ROOT, run_ffx_command +from common import DIR_SRC_ROOT, get_ssh_address from compatible_utils import get_ssh_prefix sys.path.append(os.path.join(DIR_SRC_ROOT, 'build', 'util', 'lib', 'common')) @@ -19,11 +19,14 @@ # pylint: enable=import-error,wrong-import-position -def port_forward(host_port_pair: str, host_port: int) -> int: - """Establishes a port forwarding SSH task to a localhost TCP endpoint - hosted at port |local_port|. Blocks until port forwarding is established. +def ports_forward(host_port_pair: str, + ports: List[Tuple[int, int]]) -> subprocess.CompletedProcess: + """Establishes a port forwarding SSH task to forward ports from fuchsia to + the local endpoints specified by tuples of port numbers. Blocks until port + forwarding is established. - Returns the remote port number.""" + Returns the CompletedProcess of the SSH task.""" + assert len(ports) > 0 ssh_prefix = get_ssh_prefix(host_port_pair) @@ -33,11 +36,11 @@ forward_cmd = [ '-O', 'forward', # Send SSH mux control signal. - '-R', - '0:localhost:%d' % host_port, '-v', # Get forwarded port info from stderr. '-NT' # Don't execute command; don't allocate terminal. ] + for port in ports: + forward_cmd.extend(['-R', f'{port[0]}:localhost:{port[1]}']) forward_proc = subprocess.run(ssh_prefix + forward_cmd, capture_output=True, check=False, @@ -46,9 +49,17 @@ raise Exception( 'Got an error code when requesting port forwarding: %d' % forward_proc.returncode) + return forward_proc - output = forward_proc.stdout - parsed_port = int(output.splitlines()[0].strip()) + +def port_forward(host_port_pair: str, host_port: int) -> int: + """Establishes a port forwarding SSH task to a localhost TCP endpoint + hosted at port |local_port|. Blocks until port forwarding is established. + + Returns the remote port number.""" + + forward_proc = ports_forward(host_port_pair, [(0, host_port)]) + parsed_port = int(forward_proc.stdout.splitlines()[0].strip()) logging.debug('Port forwarding established (local=%d, device=%d)', host_port, parsed_port) return parsed_port @@ -110,9 +121,7 @@ logging.debug('Starting test server.') - host_port_pair = run_ffx_command(cmd=('target', 'get-ssh-address'), - target_id=target_id, - capture_output=True).stdout.strip() + host_port_pair = get_ssh_address(target_id) # The TestLauncher can launch more jobs than the limit specified with # --test-launcher-jobs so the max number of spawned test servers is set to
diff --git a/build/fuchsia/test/test_server_unittests.py b/build/fuchsia/test/test_server_unittests.py index f601884..209d452 100755 --- a/build/fuchsia/test/test_server_unittests.py +++ b/build/fuchsia/test/test_server_unittests.py
@@ -75,7 +75,7 @@ server = test_server.chrome_test_server_spawner.SpawningServer server.Start = mock.Mock() server_mock.return_value = server - with mock.patch('test_server.run_ffx_command'): + with mock.patch('test_server.get_ssh_address'): _, url = test_server.setup_test_server(_HOST_PORT_PAIR, 4) self.assertTrue(str(_HOST_PORT) in url)
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 84abe3a..ec32776 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -6253,6 +6253,9 @@ <message name="IDS_SETTINGS_APP_PARENTAL_CONTROLS_FORGOT_PIN_LINK_NAME" desc="The name of the link which sends the user to an article with instructions to follow in the case of a forgotten App Parental Controls PIN."> Forgot PIN? </message> + <message name="IDS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_MISMATCH_ERROR_TEXT" desc="The text displayed under the PIN input section that notifies the user that the re-entered PIN does not match the first PIN entered."> + PINs do not match + </message> <message name="IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION" desc="The text description of the Do Not Disturb toggle within help icon tooltip."> Notifications won't pop up on the screen. You can still see notifications by clicking the Do Not Disturb icon on the bottom right of your screen. </message> @@ -6379,8 +6382,8 @@ <message name="IDS_SETTINGS_STORAGE_ITEM_AVAILABLE" desc="In Device Settings > Storage, label for the available storage size of ChromeOS internal storage."> Available </message> - <message name="IDS_SETTINGS_STORAGE_ITEM_MY_FILES" desc="In Device Settings > Storage, label for the size of local files in 'This Chromebook' folder."> - Files on this Chromebook + <message name="IDS_SETTINGS_STORAGE_ITEM_MY_FILES" desc="In Device Settings > Storage, label for the size of My files root."> + My files </message> <message name="IDS_SETTINGS_STORAGE_ITEM_BROWSING_DATA" desc="In Device Settings > Storage, label for the size of browsing data."> Browsing data
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_MISMATCH_ERROR_TEXT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_MISMATCH_ERROR_TEXT.png.sha1 new file mode 100644 index 0000000..d11b3db --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_MISMATCH_ERROR_TEXT.png.sha1
@@ -0,0 +1 @@ +f1cc16414f6d099dfdf67863e5469911eb679bd3 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_STORAGE_ITEM_MY_FILES.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_STORAGE_ITEM_MY_FILES.png.sha1 index dc28733..0945ced 100644 --- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_STORAGE_ITEM_MY_FILES.png.sha1 +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_STORAGE_ITEM_MY_FILES.png.sha1
@@ -1 +1 @@ -7ad8fc251b0b85d04d29a7cc5967e6383a01d508 \ No newline at end of file +cae980b2c029aca2cb46b6f36dd6c3df40fb7e13 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 8a26cd3..fce727b 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -5373,6 +5373,7 @@ "//ash/webui/projector_app", "//ash/webui/projector_app/mojom:annotator_mojo_bindings", "//ash/webui/projector_app/mojom:projector_mojo_bindings", + "//ash/webui/sanitize_ui", "//ash/webui/scanning", "//ash/webui/scanning/mojom", "//ash/webui/shimless_rma",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 9d434a1..831d3b0e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3991,6 +3991,10 @@ {"stop-app-indexing-report", flag_descriptions::kStopAppIndexingReportName, flag_descriptions::kStopAppIndexingReportDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kStopAppIndexingReport)}, + {"omnibox-rich-autocompletion-android", + flag_descriptions::kRichAutocompletionAndroidName, + flag_descriptions::kRichAutocompletionAndroidDescription, kOsAndroid, + FEATURE_VALUE_TYPE(omnibox::kRichAutocompletion)}, #endif // BUILDFLAG(IS_ANDROID) {"show-autofill-type-predictions", flag_descriptions::kShowAutofillTypePredictionsName, @@ -5846,9 +5850,6 @@ flag_descriptions::kFileTransferEnterpriseConnectorUIName, flag_descriptions::kFileTransferEnterpriseConnectorUIDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kFileTransferEnterpriseConnectorUI)}, - {"files-app-experimental", flag_descriptions::kFilesAppExperimentalName, - flag_descriptions::kFilesAppExperimentalDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kFilesAppExperimental)}, {"files-conflict-dialog", flag_descriptions::kFilesConflictDialogName, flag_descriptions::kFilesConflictDialogDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kFilesConflictDialog)},
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 24b54da..f089f23 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -856,6 +856,10 @@ "child_accounts/on_device_controls/app_controls_service_factory.h", "child_accounts/on_device_controls/blocked_app_registry.cc", "child_accounts/on_device_controls/blocked_app_registry.h", + "child_accounts/on_device_controls/blocked_app_store.cc", + "child_accounts/on_device_controls/blocked_app_store.h", + "child_accounts/on_device_controls/blocked_app_types.cc", + "child_accounts/on_device_controls/blocked_app_types.h", "child_accounts/on_device_controls/on_device_utils.cc", "child_accounts/on_device_controls/on_device_utils.h", "child_accounts/parent_access_code/authenticator.cc", @@ -2219,6 +2223,9 @@ "login/users/avatar/user_image_file_selector.h", "login/users/avatar/user_image_loader.cc", "login/users/avatar/user_image_loader.h", + "login/users/avatar/user_image_loader_delegate.h", + "login/users/avatar/user_image_loader_delegate_impl.cc", + "login/users/avatar/user_image_loader_delegate_impl.h", "login/users/avatar/user_image_manager_impl.cc", "login/users/avatar/user_image_manager_impl.h", "login/users/avatar/user_image_manager_registry.cc", @@ -5616,6 +5623,8 @@ "child_accounts/on_device_controls/app_controls_test_base.cc", "child_accounts/on_device_controls/app_controls_test_base.h", "child_accounts/on_device_controls/blocked_app_registry_unittest.cc", + "child_accounts/on_device_controls/blocked_app_store_unittest.cc", + "child_accounts/on_device_controls/blocked_app_types_unittest.cc", "child_accounts/on_device_controls/on_device_utils_unittest.cc", "child_accounts/parent_access_code/authenticator_unittest.cc", "child_accounts/time_limit_notifier_unittest.cc", @@ -5936,6 +5945,7 @@ "login/ui/oobe_dialog_size_utils_unittest.cc", "login/user_online_signin_notifier_unittest.cc", "login/users/avatar/user_image_loader_unittest.cc", + "login/users/avatar/user_image_manager_impl_unittest.cc", "login/users/default_user_image/default_user_images_unittest.cc", "login/users/multi_user_sign_in_policy_controller_unittest.cc", "login/users/user_manager_unittest.cc", @@ -6572,6 +6582,7 @@ "//chromeos/ash/components/trash_service/public/cpp", "//chromeos/ash/components/trash_service/public/mojom", "//chromeos/ash/components/wifi_p2p", + "//chromeos/ash/resources", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/ash/services/cros_healthd/public/cpp:test_support", "//chromeos/ash/services/cros_healthd/public/mojom",
diff --git a/chrome/browser/ash/accessibility/accessibility_manager.cc b/chrome/browser/ash/accessibility/accessibility_manager.cc index eb74fae..428c56a 100644 --- a/chrome/browser/ash/accessibility/accessibility_manager.cc +++ b/chrome/browser/ash/accessibility/accessibility_manager.cc
@@ -1859,6 +1859,10 @@ base::UmaHistogramBoolean( "Accessibility.CrosSpokenFeedback.BrailleDisplayConnected", IsBrailleDisplayConnected()); + if (::features::IsAccessibilityFaceGazeEnabled()) { + base::UmaHistogramBoolean("Accessibility.CrosFaceGaze", + IsFaceGazeEnabled()); + } } void AccessibilityManager::PlayVolumeAdjustSound() {
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service.cc b/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service.cc index 342c713..42a7616 100644 --- a/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service.cc +++ b/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ash/child_accounts/on_device_controls/app_controls_service.h" +#include <string> + #include "ash/constants/ash_pref_names.h" #include "components/prefs/pref_registry_simple.h" @@ -11,6 +13,7 @@ // static void AppControlsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterStringPref(prefs::kOnDeviceAppControlsPin, std::string()); registry->RegisterBooleanPref(prefs::kOnDeviceAppControlsSetupCompleted, false); }
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service_factory.cc b/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service_factory.cc index bc9d255..4518f6ac 100644 --- a/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service_factory.cc +++ b/chrome/browser/ash/child_accounts/on_device_controls/app_controls_service_factory.cc
@@ -9,6 +9,7 @@ #include "ash/constants/ash_features.h" #include "base/no_destructor.h" #include "chrome/browser/ash/child_accounts/on_device_controls/app_controls_service.h" +#include "chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.h" #include "chrome/browser/ash/child_accounts/on_device_controls/on_device_utils.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/profiles/profile.h" @@ -67,6 +68,7 @@ void AppControlsServiceFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { AppControlsService::RegisterProfilePrefs(registry); + BlockedAppStore::RegisterProfilePrefs(registry); } } // namespace ash::on_device_controls
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.cc b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.cc index 98a4042c..2149c26 100644 --- a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.cc +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.cc
@@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/time/time.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" -#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/app_update.h" @@ -24,26 +23,17 @@ } // namespace -BlockedAppRegistry::AppDetails::AppDetails() - : AppDetails(base::TimeTicks::Now()) {} - -BlockedAppRegistry::AppDetails::AppDetails(base::TimeTicks block_timestamp) - : block_timestamp(block_timestamp) {} - -BlockedAppRegistry::AppDetails::~AppDetails() = default; - -// static -void BlockedAppRegistry::RegisterProfilePrefs(PrefRegistrySimple* registry) { - registry->RegisterListPref(prefs::kOnDeviceAppControlsBlockedApps); -} - BlockedAppRegistry::BlockedAppRegistry(apps::AppServiceProxy* app_service, PrefService* pref_service) - : app_service_(app_service), pref_service_(pref_service) { + : store_(pref_service), app_service_(app_service) { CHECK(app_service_); - CHECK(pref_service_); + registry_ = store_.GetFromPref(); app_registry_cache_observer_.Observe(&GetAppCache()); + + VLOG(1) << "app-controls: calling block apps to initialize the state in app " + "service"; + app_service_->BlockApps(GetBlockedApps()); } BlockedAppRegistry::~BlockedAppRegistry() = default; @@ -55,11 +45,13 @@ LOG(WARNING) << app_id << " already in blocked app registry"; return; } - registry_[app_id] = AppDetails(); + registry_[app_id] = BlockedAppDetails(); + VLOG(1) << "app-controls: calling block app: " << app_id; app_service_->BlockApps({app_id}); - // TODO(b/338247185): Update pref state. + // TODO(b/338247185): Only update value that changed. + store_.SaveToPref(registry_); } void BlockedAppRegistry::RemoveApp(const std::string& app_id) { @@ -71,9 +63,11 @@ } registry_.erase(app_id); + VLOG(1) << "app-controls: calling unblock app: " << app_id; app_service_->UnblockApps({app_id}); - // TODO(b/338247185): Update pref state. + // TODO(b/338247185): Only update value that changed. + store_.SaveToPref(registry_); } std::set<std::string> BlockedAppRegistry::GetBlockedApps() { @@ -89,7 +83,7 @@ return LocalAppState::kAvailable; } - if (registry_.at(app_id).uninstall_timestamp.has_value()) { + if (!registry_.at(app_id).IsInstalled()) { return LocalAppState::kBlockedUninstalled; } @@ -120,6 +114,8 @@ } void BlockedAppRegistry::OnAppRegistryCacheWillBeDestroyed( apps::AppRegistryCache* cache) { + VLOG(1) << "app-controls: persisting apps before app service cache destroyed"; + store_.SaveToPref(registry_); app_registry_cache_observer_.Reset(); } @@ -129,31 +125,32 @@ void BlockedAppRegistry::OnAppReady(const std::string& app_id) { VLOG(1) << "app-controls: app ready " << app_id; - if (GetAppState(app_id) == LocalAppState::kAvailable) { return; } if (GetAppState(app_id) == LocalAppState::kBlockedUninstalled) { // Clear the uninstall timestamp, but keep the initial blocked timestamp. - registry_[app_id].uninstall_timestamp.reset(); + registry_[app_id].MarkInstalled(); + + // TODO(b/338247185): Only update value that changed. + store_.SaveToPref(registry_); } + VLOG(1) << "app-controls: calling block app: " << app_id; app_service_->BlockApps({app_id}); - - // TODO(b/338247185): Update pref state. } void BlockedAppRegistry::OnAppUninstalled(const std::string& app_id) { VLOG(1) << "app-controls: app uninstalled " << app_id; - if (GetAppState(app_id) == LocalAppState::kAvailable) { return; } - registry_[app_id].uninstall_timestamp = base::TimeTicks::Now(); + registry_[app_id].SetUninstallTimestamp(base::Time::Now()); - // TODO(b/338247185): Update pref state. + // TODO(b/338247185): Only update value that changed. + store_.SaveToPref(registry_); } } // namespace ash::on_device_controls
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.h b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.h index 46ed457..4886e20 100644 --- a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.h +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_registry.h
@@ -6,39 +6,25 @@ #define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_ON_DEVICE_CONTROLS_BLOCKED_APP_REGISTRY_H_ #include <map> -#include <optional> #include <set> #include <string> #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" -#include "base/time/time.h" #include "chrome/browser/apps/app_service/app_service_proxy_forward.h" +#include "chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.h" +#include "chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" -class PrefRegistrySimple; class PrefService; namespace ash::on_device_controls { -// State of the app -enum class LocalAppState { - // App is not blocked by on device controls. - kAvailable = 0, - // App installed and blocked by on device controls. - kBlocked = 1, - // App uninstalled and blocked by on device controls. - // Used to block the app upon reinstallation. - kBlockedUninstalled = 2, -}; - // Keeps track of blocked apps and persists blocked apps on the disk. // TODO(b/338246850): Handle app uninstall/reinstall. // TODO(b/338247185): Persist blocked apps in a pref. class BlockedAppRegistry : public apps::AppRegistryCache::Observer { public: - static void RegisterProfilePrefs(PrefRegistrySimple* registry); - BlockedAppRegistry(apps::AppServiceProxy* app_service, PrefService* pref_service); BlockedAppRegistry(const BlockedAppRegistry&) = delete; @@ -60,19 +46,6 @@ LocalAppState GetAppState(const std::string& app_id) const; private: - struct AppDetails { - AppDetails(); - explicit AppDetails(base::TimeTicks block_timestamp); - ~AppDetails(); - - // The timestamp when the app was uninstalled.. - // If not populated app is currently installed. - std::optional<base::TimeTicks> uninstall_timestamp; - - // The timestamp when the app was blocked. - base::TimeTicks block_timestamp; - }; - // apps::AppRegistryCache::Observer: void OnAppUpdate(const apps::AppUpdate& update) override; void OnAppRegistryCacheWillBeDestroyed( @@ -89,12 +62,13 @@ // The in-memory registry of the locked apps. // Maps blocked app id to blocked ap metadata. - std::map<std::string, AppDetails> registry_; + BlockedAppMap registry_; + + // Manages persisting and restoring blocked apps. + BlockedAppStore store_; const raw_ptr<apps::AppServiceProxy> app_service_; - const raw_ptr<PrefService> pref_service_; - base::ScopedObservation<apps::AppRegistryCache, apps::AppRegistryCache::Observer> app_registry_cache_observer_{this};
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.cc b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.cc new file mode 100644 index 0000000..6f482d02 --- /dev/null +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.cc
@@ -0,0 +1,102 @@ +// 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/child_accounts/on_device_controls/blocked_app_store.h" + +#include "ash/constants/ash_pref_names.h" +#include "base/json/values_util.h" +#include "base/logging.h" +#include "base/time/time.h" +#include "base/values.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" + +namespace ash::on_device_controls { + +namespace { + +constexpr char kAppIdKey[] = "app_id"; +constexpr char kBlockTimestampKey[] = "block_timestamp"; +constexpr char kUninstallTimestampKey[] = "uninstall_timestamp"; + +} // namespace + +// static +void BlockedAppStore::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterListPref(prefs::kOnDeviceAppControlsBlockedApps); +} + +BlockedAppStore::BlockedAppStore(PrefService* pref_service) + : pref_service_(pref_service) { + CHECK(pref_service_); +} + +BlockedAppStore::~BlockedAppStore() = default; + +BlockedAppMap BlockedAppStore::GetFromPref() const { + VLOG(1) << "app-controls: reading blocked apps from pref "; + + const base::Value::List& list = + pref_service_->GetList(prefs::kOnDeviceAppControlsBlockedApps); + + BlockedAppMap apps_from_pref; + for (const auto& item : list) { + const base::Value::Dict* dict = item.GetIfDict(); + if (!dict) { + LOG(WARNING) << "app-controls: invalid block app dictionary"; + continue; + } + + const std::string* app_id = dict->FindString(kAppIdKey); + if (!app_id) { + LOG(WARNING) << "app-controls: invalid app id string"; + continue; + } + + std::optional<base::Time> block_timestamp = + base::ValueToTime(dict->Find(kBlockTimestampKey)); + if (!block_timestamp) { + LOG(WARNING) << "app-controls: invalid app blocked timestamp"; + continue; + } + + std::optional<base::Time> uninstall_timestamp = + base::ValueToTime(dict->Find(kUninstallTimestampKey)); + + apps_from_pref[*app_id] = + uninstall_timestamp + ? BlockedAppDetails(*block_timestamp, *uninstall_timestamp) + : BlockedAppDetails(*block_timestamp); + } + return apps_from_pref; +} + +void BlockedAppStore::SaveToPref(const BlockedAppMap& apps) { + VLOG(1) << "app-controls: saving blocked apps to pref "; + + ScopedListPrefUpdate update(pref_service_, + prefs::kOnDeviceAppControlsBlockedApps); + + base::Value::List& list = update.Get(); + list.clear(); + + for (const auto& app : apps) { + const std::string& app_id = app.first; + const BlockedAppDetails& app_details = app.second; + + base::Value::Dict dict; + dict.Set(kAppIdKey, app_id); + dict.Set(kBlockTimestampKey, + base::TimeToValue(app_details.block_timestamp())); + if (!app_details.IsInstalled()) { + dict.Set(kUninstallTimestampKey, + base::TimeToValue(app_details.uninstall_timestamp().value())); + } + list.Append(std::move(dict)); + } + pref_service_->CommitPendingWrite(); +} + +} // namespace ash::on_device_controls
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.h b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.h new file mode 100644 index 0000000..7c4a710 --- /dev/null +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store.h
@@ -0,0 +1,38 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_ON_DEVICE_CONTROLS_BLOCKED_APP_STORE_H_ +#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_ON_DEVICE_CONTROLS_BLOCKED_APP_STORE_H_ + +#include "base/memory/raw_ptr.h" +#include "chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.h" + +class PrefRegistrySimple; +class PrefService; + +namespace ash::on_device_controls { + +// Persists blocked apps in the user pref and provides API to load and update +// persisted data. +class BlockedAppStore { + public: + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + + explicit BlockedAppStore(PrefService* pref_service); + BlockedAppStore(const BlockedAppStore&) = delete; + BlockedAppStore& operator=(const BlockedAppStore&) = delete; + ~BlockedAppStore(); + + // Returns the list of blocked apps stored in pref. + BlockedAppMap GetFromPref() const; + // Saves the list of blocked `apps` in pref. + void SaveToPref(const BlockedAppMap& apps); + + private: + const raw_ptr<PrefService> pref_service_; +}; + +} // namespace ash::on_device_controls + +#endif // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_ON_DEVICE_CONTROLS_BLOCKED_APP_STORE_H_
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store_unittest.cc b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store_unittest.cc new file mode 100644 index 0000000..08b0539 --- /dev/null +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_store_unittest.cc
@@ -0,0 +1,130 @@ +// 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/child_accounts/on_device_controls/blocked_app_store.h" + +#include <memory> +#include <optional> +#include <string> + +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/time/time.h" +#include "chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash::on_device_controls { + +// Tests blocked app registry. +class BlockedAppStoreTest : public testing::Test { + public: + BlockedAppStoreTest() = default; + BlockedAppStoreTest(const BlockedAppStoreTest&) = delete; + BlockedAppStoreTest& operator=(const BlockedAppStoreTest&) = delete; + + ~BlockedAppStoreTest() override = default; + + protected: + BlockedAppStore* store() { return store_.get(); } + + // testing::Test: + void SetUp() override; + + private: + content::BrowserTaskEnvironment task_environment_; + TestingProfile profile_; + + std::unique_ptr<BlockedAppStore> store_; +}; + +void BlockedAppStoreTest::SetUp() { + testing::Test::SetUp(); + + store_ = std::make_unique<BlockedAppStore>(profile_.GetPrefs()); +} + +// Tests reading from the empty preference. +TEST_F(BlockedAppStoreTest, TestGetFromEmptyPref) { + BlockedAppMap apps = store()->GetFromPref(); + + EXPECT_EQ(0UL, apps.size()); +} + +// Tests writing and reading one blocked app. +TEST_F(BlockedAppStoreTest, TestBlockedApp) { + BlockedAppMap apps_in; + + const std::string app_id = "abc"; + const base::Time timestamp = base::Time::Now(); + apps_in[app_id] = BlockedAppDetails(timestamp); + + store()->SaveToPref(apps_in); + + const BlockedAppMap apps_out = store()->GetFromPref(); + EXPECT_EQ(1UL, apps_out.size()); + ASSERT_TRUE(base::Contains(apps_out, app_id)); + EXPECT_EQ(timestamp, apps_out.at(app_id).block_timestamp()); + EXPECT_EQ(std::nullopt, apps_out.at(app_id).uninstall_timestamp()); +} + +// Tests writing and reading one uninstalled app. +TEST_F(BlockedAppStoreTest, TestUninstalledApp) { + BlockedAppMap apps_in; + + const std::string app_id = "abc"; + const base::Time block_timestamp = base::Time::Now(); + const base::Time uninstall_timestamp = base::Time::Now() + base::Minutes(5); + apps_in[app_id] = BlockedAppDetails(block_timestamp, uninstall_timestamp); + + store()->SaveToPref(apps_in); + + const BlockedAppMap apps_out = store()->GetFromPref(); + EXPECT_EQ(1UL, apps_out.size()); + ASSERT_TRUE(base::Contains(apps_out, app_id)); + EXPECT_EQ(block_timestamp, apps_out.at(app_id).block_timestamp()); + EXPECT_EQ(uninstall_timestamp, *apps_out.at(app_id).uninstall_timestamp()); +} + +// Tests writing and reading multiple apps. +TEST_F(BlockedAppStoreTest, TestMultipleApps) { + const std::string base_app_id = "abc"; + const base::Time initial_time = base::Time::Now(); + const base::TimeDelta uninstall_delta = base::Hours(5); + const base::TimeDelta block_delta = base::Minutes(13); + const size_t apps_count = 10; + + BlockedAppMap apps_in; + base::Time timestamp = initial_time; + // Adds apps with the different block and uninstall timestamps. + for (size_t i = 0; i < apps_count; ++i) { + const std::string app_id = + base::StrCat({base_app_id, base::NumberToString(i)}); + apps_in[app_id] = BlockedAppDetails(timestamp, timestamp + uninstall_delta); + timestamp += block_delta; + } + + store()->SaveToPref(apps_in); + + const BlockedAppMap apps_out = store()->GetFromPref(); + EXPECT_EQ(apps_count, apps_out.size()); + + for (size_t i = 0; i < apps_count; ++i) { + const std::string app_id = + base::StrCat({base_app_id, base::NumberToString(i)}); + ASSERT_TRUE(base::Contains(apps_out, app_id)); + + const BlockedAppDetails& details = apps_out.at(app_id); + + const base::Time expected_block_time = initial_time + i * block_delta; + EXPECT_EQ(expected_block_time, details.block_timestamp()); + + const base::Time expected_uninstall_time = + expected_block_time + uninstall_delta; + EXPECT_EQ(expected_uninstall_time, *details.uninstall_timestamp()); + } +} + +} // namespace ash::on_device_controls
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.cc b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.cc new file mode 100644 index 0000000..1fb6988e --- /dev/null +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.cc
@@ -0,0 +1,53 @@ +// 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/child_accounts/on_device_controls/blocked_app_types.h" + +#include "base/logging.h" +#include "base/time/time.h" + +namespace ash::on_device_controls { + +BlockedAppDetails::BlockedAppDetails() : BlockedAppDetails(base::Time::Now()) {} + +BlockedAppDetails::BlockedAppDetails(base::Time block_timestamp) + : block_timestamp_(block_timestamp) {} + +BlockedAppDetails::BlockedAppDetails(base::Time block_timestamp, + base::Time uninstall_timestamp) + : block_timestamp_(block_timestamp), + uninstall_timestamp_(uninstall_timestamp) { + if (uninstall_timestamp_ && block_timestamp_ > uninstall_timestamp_) { + LOG(WARNING) << "app-controls: block timestamp after uninstall timestamp"; + } +} + +BlockedAppDetails::~BlockedAppDetails() = default; + +bool BlockedAppDetails::IsInstalled() const { + return !uninstall_timestamp_.has_value(); +} + +void BlockedAppDetails::MarkInstalled() { + if (IsInstalled()) { + LOG(WARNING) << "app-controls: installed app marked installed again"; + } + uninstall_timestamp_.reset(); +} + +void BlockedAppDetails::SetUninstallTimestamp(base::Time timestamp) { + if (!IsInstalled()) { + LOG(WARNING) << "app-controls: uninstalled timestamp updated"; + } + uninstall_timestamp_ = timestamp; +} + +void BlockedAppDetails::SetBlockTimestamp(base::Time timestamp) { + if (uninstall_timestamp_ && block_timestamp_ > uninstall_timestamp_) { + LOG(WARNING) << "app-controls: block timestamp after uninstall timestamp"; + } + block_timestamp_ = timestamp; +} + +} // namespace ash::on_device_controls
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.h b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.h new file mode 100644 index 0000000..6336842 --- /dev/null +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types.h
@@ -0,0 +1,68 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_CHILD_ACCOUNTS_ON_DEVICE_CONTROLS_BLOCKED_APP_TYPES_H_ +#define CHROME_BROWSER_ASH_CHILD_ACCOUNTS_ON_DEVICE_CONTROLS_BLOCKED_APP_TYPES_H_ + +#include <map> +#include <optional> +#include <string> + +#include "base/time/time.h" + +namespace ash::on_device_controls { + +// State of the app in the context of on device app controls. +enum class LocalAppState { + // App is not blocked by on device controls. + kAvailable = 0, + // App installed and blocked by on device controls. + kBlocked = 1, + // App uninstalled and blocked by on device controls. + // Used to block the app upon reinstallation. + kBlockedUninstalled = 2, +}; + +// The details of the app blocked on device. +// Note: Those details are preserved in-between the sessions. +class BlockedAppDetails { + public: + BlockedAppDetails(); + explicit BlockedAppDetails(base::Time block_timestamp); + BlockedAppDetails(base::Time block_timestamp, base::Time uninstall_timestamp); + + ~BlockedAppDetails(); + + base::Time block_timestamp() const { return block_timestamp_; } + std::optional<base::Time> uninstall_timestamp() const { + return uninstall_timestamp_; + } + + // Returns whether the blocked app is currently installed. + bool IsInstalled() const; + // Marks app as installed by resetting the uninstall timestamp. + void MarkInstalled(); + + // Sets un-installation timestamp. + // Marks app as uninstalled if that timestamp was not previously set. + void SetUninstallTimestamp(base::Time timestamp); + // Sets block timestamp. + void SetBlockTimestamp(base::Time timestamp); + + private: + // The timestamp when the app was blocked. + base::Time block_timestamp_; + + // The timestamp when the app was uninstalled.. + // If not populated app is currently installed. + std::optional<base::Time> uninstall_timestamp_; +}; + +// The map containing the record of the apps blocked on device. +// Keyed by the App Service app id. +typedef std::map<std::string, BlockedAppDetails> BlockedAppMap; + +} // namespace ash::on_device_controls + +#endif // CHROME_BROWSER_ASH_CHILD_ACCOUNTS_ON_DEVICE_CONTROLS_BLOCKED_APP_TYPES_H_
diff --git a/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types_unittest.cc b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types_unittest.cc new file mode 100644 index 0000000..501ab08 --- /dev/null +++ b/chrome/browser/ash/child_accounts/on_device_controls/blocked_app_types_unittest.cc
@@ -0,0 +1,64 @@ +// 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/child_accounts/on_device_controls/blocked_app_types.h" + +#include <optional> + +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash::on_device_controls { + +using BlockedAppTypesTest = testing::Test; + +TEST_F(BlockedAppTypesTest, AppDetailsWithBlockTimestamp) { + const base::Time timestamp = base::Time::Now() + base::Hours(12); + BlockedAppDetails details = BlockedAppDetails(timestamp); + + EXPECT_EQ(timestamp, details.block_timestamp()); + EXPECT_EQ(std::nullopt, details.uninstall_timestamp()); + EXPECT_TRUE(details.IsInstalled()); +} + +TEST_F(BlockedAppTypesTest, UninstalledAppDetails) { + const base::Time block_time = base::Time::Now() + base::Hours(12); + const base::Time uninstall_time = base::Time::Now() + base::Days(30); + + BlockedAppDetails details = BlockedAppDetails(block_time, uninstall_time); + + EXPECT_EQ(block_time, details.block_timestamp()); + EXPECT_FALSE(details.IsInstalled()); + EXPECT_EQ(uninstall_time, *details.uninstall_timestamp()); +} + +TEST_F(BlockedAppTypesTest, MarkUninstalled) { + const base::Time timestamp; + BlockedAppDetails details = BlockedAppDetails(timestamp, timestamp); + EXPECT_FALSE(details.IsInstalled()); + + details.MarkInstalled(); + EXPECT_TRUE(details.IsInstalled()); +} + +TEST_F(BlockedAppTypesTest, SetBlockTimestamp) { + const base::Time timestamp = base::Time::Now(); + BlockedAppDetails details = BlockedAppDetails(timestamp); + EXPECT_EQ(timestamp, details.block_timestamp()); + + base::Time new_block_time = base::Time::Now() + base::Minutes(30); + details.SetBlockTimestamp(new_block_time); + EXPECT_EQ(new_block_time, details.block_timestamp()); +} + +TEST_F(BlockedAppTypesTest, SetUninstallTimestamp) { + BlockedAppDetails details = BlockedAppDetails(); + EXPECT_EQ(std::nullopt, details.uninstall_timestamp()); + + base::Time uninstall_time = base::Time::Now() + base::Minutes(30); + details.SetUninstallTimestamp(uninstall_time); + EXPECT_EQ(uninstall_time, details.uninstall_timestamp()); +} + +} // namespace ash::on_device_controls
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index c7b601a..93b9b39 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -1072,7 +1072,6 @@ PRINT_IF_NOT_DEFAULT(arc) PRINT_IF_NOT_DEFAULT(browser) - PRINT_IF_NOT_DEFAULT(files_experimental) PRINT_IF_NOT_DEFAULT(generic_documents_provider) PRINT_IF_NOT_DEFAULT(mount_volumes) PRINT_IF_NOT_DEFAULT(native_smb) @@ -2366,12 +2365,6 @@ // Make sure to run the ARC storage UI toast tests. enabled_features.push_back(arc::kUsbStorageUIFeature); - if (options.files_experimental) { - enabled_features.push_back(ash::features::kFilesAppExperimental); - } else { - disabled_features.push_back(ash::features::kFilesAppExperimental); - } - if (options.enable_conflict_dialog) { enabled_features.push_back(ash::features::kFilesConflictDialog); } else { @@ -2886,14 +2879,6 @@ return; } - if (name == "isFilesAppExperimental") { - // Return whether the flag Files Experimental is enabled. - *output = base::FeatureList::IsEnabled(ash::features::kFilesAppExperimental) - ? "true" - : "false"; - return; - } - if (name == "isInGuestMode") { // Obtain if the test runs in guest or incognito mode. LOG(INFO) << GetTestCaseName() << " is in " << options.guest_mode @@ -3844,11 +3829,6 @@ return; } - if (name == "isFilesExperimentalEnabled") { - *output = options.files_experimental ? "true" : "false"; - return; - } - if (name == "switchLanguage") { const std::string* language = value.FindString("language"); ASSERT_TRUE(language);
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h index ed310f91..768bcb67 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
@@ -141,9 +141,6 @@ // Whether Drive should act as if offline. bool offline = false; - // Whether test needs the files-app-experimental feature. - bool files_experimental = false; - // Whether test should enable the conflict dialog. bool enable_conflict_dialog = false;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc index bd6fdd86..8bfaae8 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.cc
@@ -68,11 +68,6 @@ return *this; } -TestCase& TestCase::FilesExperimental() { - options.files_experimental = true; - return *this; -} - TestCase& TestCase::EnableConflictDialog() { options.enable_conflict_dialog = true; return *this; @@ -254,10 +249,6 @@ full_name += "_Offline"; } - if (options.files_experimental) { - full_name += "_FilesExperimental"; - } - if (options.enable_conflict_dialog) { full_name += "_ConflictDialog"; }
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h index 4aef0de..c50aacc 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_utils.h
@@ -48,8 +48,6 @@ TestCase& Offline(); - TestCase& FilesExperimental(); - TestCase& EnableConflictDialog(); TestCase& DisableNativeSmb();
diff --git a/chrome/browser/ash/growth/show_notification_action_performer.cc b/chrome/browser/ash/growth/show_notification_action_performer.cc index 5bc65bad..bf25cc8 100644 --- a/chrome/browser/ash/growth/show_notification_action_performer.cc +++ b/chrome/browser/ash/growth/show_notification_action_performer.cc
@@ -20,6 +20,9 @@ #include "chromeos/ash/components/growth/campaigns_manager.h" #include "chromeos/ash/components/growth/campaigns_model.h" #include "chromeos/ash/components/growth/growth_metrics.h" +#include "chromeos/ash/grit/ash_resources.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/vector_icon_utils.h" #include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/notification.h" @@ -30,16 +33,18 @@ constexpr char kTitlePath[] = "title"; constexpr char kMessagePath[] = "message"; -constexpr char kIconPath[] = "icon"; +constexpr char kIconPath[] = "sourceIcon"; constexpr char kButtonsPath[] = "buttons"; constexpr char kLabelPath[] = "label"; constexpr char kActionPath[] = "action"; +constexpr char kImagePath[] = "image"; constexpr char kNotificationIdTemplate[] = "growth_campaign_%d"; struct ShowNotificationParams { std::string title; std::string message; raw_ptr<const gfx::VectorIcon> icon = nullptr; + raw_ptr<const gfx::Image> image = nullptr; std::vector<message_center::ButtonInfo> buttons_info; }; @@ -68,7 +73,7 @@ return nullptr; } - const auto* icon = growth::Image(icon_value).GetVectorIcon(); + const auto* icon = growth::VectorIcon(icon_value).GetVectorIcon(); if (!icon) { growth::RecordCampaignsManagerError( growth::CampaignsManagerError::kNotificationPayloadInvalidIcon); @@ -76,6 +81,13 @@ } show_notification_params->icon = icon; + const auto* image_dict = params->FindDict(kImagePath); + if (image_dict) { + // TODO: b/341368196 - consider skip showing the notification if the image + // type is not recognized. The payload is invalid in this case. + show_notification_params->image = growth::Image(image_dict).GetImage(); + } + // Set buttons info. const auto* buttons = params->FindList(kButtonsPath); if (buttons) { @@ -124,6 +136,9 @@ message_center::RichNotificationData optional_fields; optional_fields.buttons = std::move(show_notification_params->buttons_info); + if (show_notification_params->image) { + optional_fields.image = *show_notification_params->image; + } auto id = base::StringPrintf(kNotificationIdTemplate, campaign_id); std::unique_ptr<message_center::Notification> notification =
diff --git a/chrome/browser/ash/growth/show_notification_action_performer_unittest.cc b/chrome/browser/ash/growth/show_notification_action_performer_unittest.cc index 6529c5e1..a770722 100644 --- a/chrome/browser/ash/growth/show_notification_action_performer_unittest.cc +++ b/chrome/browser/ash/growth/show_notification_action_performer_unittest.cc
@@ -13,10 +13,13 @@ #include "base/scoped_observation.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "build/branding_buildflags.h" #include "chrome/browser/ash/growth/mock_ui_performer_observer.h" +#include "chromeos/ash/grit/ash_resources.h" #include "chromeos/ui/vector_icons/vector_icons.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/resource/resource_bundle.h" #include "ui/message_center/message_center.h" #include "url/gurl.h" @@ -26,8 +29,11 @@ { "title": "%s", "message": "%s", - "icon": { - "builtInIcon": 0 + "sourceIcon": { + "builtInVectorIcon": 0 + }, + "image": { + "builtInImage": 2 } } )"; @@ -127,6 +133,17 @@ EXPECT_EQ(notification->title(), base::UTF8ToUTF16(std::string(kTestTitle))); EXPECT_EQ(notification->message(), base::UTF8ToUTF16(std::string(kTestMessage))); + EXPECT_EQ(chromeos::kRedeemIcon.name, + notification->vector_small_image().name); + +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + const auto& expected_image = + ui::ResourceBundle::GetSharedInstance().GetImageNamed( + IDR_GROWTH_FRAMEWORK_REBUY_PNG); + EXPECT_EQ(expected_image, notification->rich_notification_data().image); +#else + EXPECT_EQ(gfx::Image(), notification->rich_notification_data().image); +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) } TEST_F(ShowNotificationActionPerformerTest, TestInvalidParams) {
diff --git a/chrome/browser/ash/growth/show_nudge_action_performer.cc b/chrome/browser/ash/growth/show_nudge_action_performer.cc index 6d07ec5..67576175 100644 --- a/chrome/browser/ash/growth/show_nudge_action_performer.cc +++ b/chrome/browser/ash/growth/show_nudge_action_performer.cc
@@ -134,7 +134,7 @@ return; } - auto image_model = growth::Image(image_value).GetImage(); + auto image_model = growth::ImageModel(image_value).GetImageModel(); if (!image_model) { // No image model matched the image payload. growth::RecordCampaignsManagerError(
diff --git a/chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.cc b/chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.cc new file mode 100644 index 0000000..12fc0e3 --- /dev/null +++ b/chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.cc
@@ -0,0 +1,38 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.h" + +#include <memory> + +#include "base/functional/callback.h" +#include "base/memory/scoped_refptr.h" +#include "base/task/sequenced_task_runner.h" +#include "chrome/browser/ash/login/users/avatar/user_image_loader.h" +#include "components/user_manager/user_image/user_image.h" + +namespace ash::test { + +namespace { + +std::unique_ptr<user_manager::UserImage> MakeUserImage() { + return std::make_unique<user_manager::UserImage>(); +} + +} // namespace + +MockUserImageLoaderDelegate::MockUserImageLoaderDelegate() { + ON_CALL(*this, FromGURLAnimated) + .WillByDefault([](const GURL& default_image_url, + user_image_loader::LoadedCallback loaded_cb) { + base::SequencedTaskRunner::GetCurrentDefault() + ->PostTaskAndReplyWithResult(FROM_HERE, + base::BindOnce(&MakeUserImage), + std::move(loaded_cb)); + }); +} + +MockUserImageLoaderDelegate::~MockUserImageLoaderDelegate() = default; + +} // namespace ash::test
diff --git a/chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.h b/chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.h new file mode 100644 index 0000000..6d26aadd --- /dev/null +++ b/chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.h
@@ -0,0 +1,34 @@ +// 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_LOGIN_USERS_AVATAR_MOCK_USER_IMAGE_LOADER_DELEGATE_H_ +#define CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_MOCK_USER_IMAGE_LOADER_DELEGATE_H_ + +#include "chrome/browser/ash/login/users/avatar/user_image_loader.h" +#include "chrome/browser/ash/login/users/avatar/user_image_loader_delegate.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "url/gurl.h" + +namespace ash::test { + +class MockUserImageLoaderDelegate : public UserImageLoaderDelegate { + public: + MockUserImageLoaderDelegate(); + + MockUserImageLoaderDelegate(const MockUserImageLoaderDelegate&) = delete; + MockUserImageLoaderDelegate& operator=(const MockUserImageLoaderDelegate&) = + delete; + + ~MockUserImageLoaderDelegate() override; + + MOCK_METHOD(void, + FromGURLAnimated, + (const GURL& default_image_url, + user_image_loader::LoadedCallback loaded_cb), + (override)); +}; + +} // namespace ash::test + +#endif // CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_MOCK_USER_IMAGE_LOADER_DELEGATE_H_
diff --git a/chrome/browser/ash/login/users/avatar/user_image_loader_delegate.h b/chrome/browser/ash/login/users/avatar/user_image_loader_delegate.h new file mode 100644 index 0000000..e88cd5d5 --- /dev/null +++ b/chrome/browser/ash/login/users/avatar/user_image_loader_delegate.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_LOGIN_USERS_AVATAR_USER_IMAGE_LOADER_DELEGATE_H_ +#define CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_LOADER_DELEGATE_H_ + +#include "chrome/browser/ash/login/users/avatar/user_image_loader.h" +#include "url/gurl.h" + +namespace ash { + +// An interface for downloading user avatar images from network. Can be mocked +// in tests. +class UserImageLoaderDelegate { + public: + virtual ~UserImageLoaderDelegate() = default; + + virtual void FromGURLAnimated( + const GURL& default_image_url, + user_image_loader::LoadedCallback loaded_cb) = 0; +}; + +} // namespace ash + +#endif // CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_LOADER_DELEGATE_H_
diff --git a/chrome/browser/ash/login/users/avatar/user_image_loader_delegate_impl.cc b/chrome/browser/ash/login/users/avatar/user_image_loader_delegate_impl.cc new file mode 100644 index 0000000..f4ce10f3 --- /dev/null +++ b/chrome/browser/ash/login/users/avatar/user_image_loader_delegate_impl.cc
@@ -0,0 +1,22 @@ +// 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/login/users/avatar/user_image_loader_delegate_impl.h" + +#include "chrome/browser/ash/login/users/avatar/user_image_loader.h" + +namespace ash { + +UserImageLoaderDelegateImpl::UserImageLoaderDelegateImpl() = default; + +UserImageLoaderDelegateImpl::~UserImageLoaderDelegateImpl() = default; + +void UserImageLoaderDelegateImpl::FromGURLAnimated( + const GURL& default_image_url, + user_image_loader::LoadedCallback loaded_cb) { + user_image_loader::StartWithGURLAnimated(default_image_url, + std::move(loaded_cb)); +} + +} // namespace ash
diff --git a/chrome/browser/ash/login/users/avatar/user_image_loader_delegate_impl.h b/chrome/browser/ash/login/users/avatar/user_image_loader_delegate_impl.h new file mode 100644 index 0000000..499dee3 --- /dev/null +++ b/chrome/browser/ash/login/users/avatar/user_image_loader_delegate_impl.h
@@ -0,0 +1,30 @@ +// 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_LOGIN_USERS_AVATAR_USER_IMAGE_LOADER_DELEGATE_IMPL_H_ +#define CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_LOADER_DELEGATE_IMPL_H_ + +#include "chrome/browser/ash/login/users/avatar/user_image_loader_delegate.h" +namespace ash { + +// Concrete implementation. Makes real network requests to download avatar +// images. +class UserImageLoaderDelegateImpl : public UserImageLoaderDelegate { + public: + UserImageLoaderDelegateImpl(); + + UserImageLoaderDelegateImpl(const UserImageLoaderDelegateImpl&) = delete; + UserImageLoaderDelegateImpl& operator=(const UserImageLoaderDelegateImpl&) = + delete; + + ~UserImageLoaderDelegateImpl() override; + + // UserImageLoaderDelegate: + void FromGURLAnimated(const GURL& default_image_url, + user_image_loader::LoadedCallback loaded_cb) override; +}; + +} // namespace ash + +#endif // CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_LOADER_DELEGATE_IMPL_H_
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc index ba76af44..1e70aa7b 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
@@ -97,33 +97,6 @@ return policy_manager->core()->store(); } -class UserImageChangeWaiter : public user_manager::UserManager::Observer { - public: - UserImageChangeWaiter() {} - - UserImageChangeWaiter(const UserImageChangeWaiter&) = delete; - UserImageChangeWaiter& operator=(const UserImageChangeWaiter&) = delete; - - ~UserImageChangeWaiter() override {} - - void Wait() { - user_manager::UserManager::Get()->AddObserver(this); - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - user_manager::UserManager::Get()->RemoveObserver(this); - } - - // user_manager::UserManager::Observer: - void OnUserImageChanged(const user_manager::User& user) override { - if (run_loop_) { - run_loop_->Quit(); - } - } - - private: - std::unique_ptr<base::RunLoop> run_loop_; -}; - } // namespace class UserImageManagerTestBase : public LoginManagerTest, @@ -352,7 +325,7 @@ ASSERT_TRUE(user); // Wait for image load. if (user->image_index() == user_manager::User::USER_IMAGE_INVALID) { - UserImageChangeWaiter().Wait(); + test::UserImageChangeWaiter().Wait(); } // Check image dimensions. Images can't be compared since JPEG is lossy. const gfx::ImageSkia& saved_image = default_user_image::GetStubDefaultImage();
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc index 47c143e..6847c0b 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc
@@ -26,7 +26,7 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/browser/ash/login/helper.h" -#include "chrome/browser/ash/login/users/avatar/user_image_loader.h" +#include "chrome/browser/ash/login/users/avatar/user_image_loader_delegate.h" #include "chrome/browser/ash/login/users/avatar/user_image_prefs.h" #include "chrome/browser/ash/login/users/avatar/user_image_sync_observer.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" @@ -54,13 +54,13 @@ namespace { // Delay between user login and attempt to update user's profile data. -const int kProfileDataDownloadDelaySec = 10; +constexpr int kProfileDataDownloadDelaySec = 10; // Interval between retries to update user's profile data. -const int kProfileDataDownloadRetryIntervalSec = 300; +constexpr int kProfileDataDownloadRetryIntervalSec = 300; // Delay between subsequent profile refresh attempts (24 hrs). -const int kProfileRefreshIntervalSec = 24 * 3600; +constexpr int kProfileRefreshIntervalSec = 24 * 3600; static bool g_ignore_profile_data_download_delay_ = false; @@ -234,6 +234,10 @@ const AccountId& account_id() const { return parent_->account_id_; } + UserImageLoaderDelegate* user_image_loader_delegate() { + return parent_->user_image_loader_delegate_; + } + raw_ptr<UserImageManagerImpl, DanglingUntriaged> parent_; // Whether one of the Load*() or Set*() methods has been run already. @@ -288,7 +292,7 @@ } // Fetch the default image from cloud before caching it. image_url_ = default_user_image::GetDefaultImageUrl(image_index_); - user_image_loader::StartWithGURLAnimated( + user_image_loader_delegate()->FromGURLAnimated( image_url_, base::BindOnce(&Job::OnLoadImageDone, weak_factory_.GetWeakPtr(), true)); } @@ -335,7 +339,7 @@ return; } - user_image_loader::StartWithGURLAnimated( + user_image_loader_delegate()->FromGURLAnimated( image_url_, base::BindOnce(&Job::OnLoadImageDone, weak_factory_.GetWeakPtr(), true)); } @@ -538,9 +542,11 @@ UserImageManagerImpl::UserImageManagerImpl( const AccountId& account_id, - user_manager::UserManager* user_manager) + user_manager::UserManager* user_manager, + UserImageLoaderDelegate* user_image_loader_delegate) : account_id_(account_id), user_manager_(user_manager), + user_image_loader_delegate_(user_image_loader_delegate), downloading_profile_image_(false), has_managed_image_(false) { background_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner( @@ -620,7 +626,8 @@ // correspond to (a) special constants and (b) indexes of an array // containing resource IDs. base::UmaHistogramExactLinear( - "UserImage.LoggedIn3", ImageIndexToHistogramIndex(user->image_index()), + kUserImageLoggedInHistogramName, + ImageIndexToHistogramIndex(user->image_index()), default_user_image::kHistogramImagesCount + 1); }
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h index 71c0f69..aac25c54 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.h
@@ -32,6 +32,7 @@ namespace ash { +class UserImageLoaderDelegate; class UserImageSyncObserver; // Provides a mechanism for updating user images. There is an instance of this @@ -42,6 +43,10 @@ inline static constexpr char kUserImageChangedHistogramName[] = "UserImage.Changed2"; + // The name of the histogram that records the user's chosen image at login. + inline static constexpr char kUserImageLoggedInHistogramName[] = + "UserImage.LoggedIn3"; + // Converts `image_index` to UMA histogram value. static int ImageIndexToHistogramIndex(int image_index); @@ -52,7 +57,8 @@ static void RegisterPrefs(PrefRegistrySimple* registry); UserImageManagerImpl(const AccountId& account_id, - user_manager::UserManager* user_manager); + user_manager::UserManager* user_manager, + UserImageLoaderDelegate* user_image_loader_delegate); UserImageManagerImpl(const UserImageManagerImpl&) = delete; UserImageManagerImpl& operator=(const UserImageManagerImpl&) = delete; @@ -139,6 +145,7 @@ private: friend class UserImageManagerTestBase; + friend class UserImageManagerImplTest; // ID of user which images are managed by current instance of // UserImageManager. @@ -225,6 +232,10 @@ // The user manager. raw_ptr<user_manager::UserManager> user_manager_; + // A delegate to retrieve user images from disk and network. Allows injecting + // a mock for testing. + raw_ptr<UserImageLoaderDelegate> user_image_loader_delegate_; + // Whether the `profile_downloader_` is downloading the profile image for the // currently logged-in user (and not just the full name). Only valid when a // download is currently in progress.
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_impl_unittest.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_impl_unittest.cc new file mode 100644 index 0000000..a2594da --- /dev/null +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_impl_unittest.cc
@@ -0,0 +1,182 @@ +// 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/login/users/avatar/user_image_manager_impl.h" + +#include <memory> +#include <string_view> + +#include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" +#include "chrome/browser/ash/login/users/avatar/mock_user_image_loader_delegate.h" +#include "chrome/browser/ash/login/users/avatar/user_image_loader.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h" +#include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" +#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/test/base/scoped_testing_local_state.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/account_id/account_id.h" +#include "components/user_manager/fake_user_manager.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/user.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace ash { +namespace { + +constexpr std::string_view kFakeRegularUserEmail = "test@example.com"; + +} // namespace + +class UserImageManagerImplTest : public testing::Test { + public: + UserImageManagerImplTest() = default; + UserImageManagerImplTest(const UserImageManagerImplTest&) = delete; + UserImageManagerImplTest& operator=(const UserImageManagerImplTest&) = delete; + ~UserImageManagerImplTest() override = default; + + void SetUp() override { + testing::Test::SetUp(); + + ASSERT_TRUE(profile_manager_.SetUp()); + + auto mock_user_image_loader_delegate = std::make_unique< + testing::StrictMock<test::MockUserImageLoaderDelegate>>(); + mock_user_image_loader_delegate_ = mock_user_image_loader_delegate.get(); + + user_image_manager_registry_ = std::make_unique<UserImageManagerRegistry>( + fake_chrome_user_manager(), std::move(mock_user_image_loader_delegate)); + } + + void TearDown() override { + mock_user_image_loader_delegate_ = nullptr; + testing::Test::TearDown(); + } + + user_manager::User* AddUser(const AccountId& account_id) { + user_manager::User* user = fake_chrome_user_manager()->AddUser(account_id); + TestingProfile* profile = + profile_manager_.CreateTestingProfile(account_id.GetUserEmail()); + fake_chrome_user_manager()->OnUserProfileCreated(account_id, + profile->GetPrefs()); + return user; + } + + FakeChromeUserManager* fake_chrome_user_manager() { + return fake_chrome_user_manager_.Get(); + } + + UserImageManagerRegistry* user_image_manager_registry() { + return user_image_manager_registry_.get(); + } + + UserImageManagerImpl* user_image_manager_impl(const AccountId& account_id) { + return user_image_manager_registry()->GetManager(account_id); + } + + testing::StrictMock<test::MockUserImageLoaderDelegate>* + mock_user_image_loader_delegate() { + return mock_user_image_loader_delegate_.get(); + } + + bool is_random_image_set(const AccountId& account_id) { + return user_image_manager_impl(account_id)->is_random_image_set_; + } + + bool is_downloading_profile_image(const AccountId& account_id) { + return user_image_manager_impl(account_id)->downloading_profile_image_; + } + + bool NeedProfileImage(const AccountId& account_id) { + return user_image_manager_impl(account_id)->NeedProfileImage(); + } + + private: + ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; + content::BrowserTaskEnvironment task_environment_; + TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal(), + &local_state_}; + user_manager::TypedScopedUserManager<FakeChromeUserManager> + fake_chrome_user_manager_{std::make_unique<FakeChromeUserManager>()}; + raw_ptr<testing::StrictMock<test::MockUserImageLoaderDelegate>> + mock_user_image_loader_delegate_; + std::unique_ptr<UserImageManagerRegistry> user_image_manager_registry_; +}; + +// TODO(b/339503132) should set to google profile image. +TEST_F(UserImageManagerImplTest, SetsRandomDefaultInitialImageForNewUsers) { + const AccountId account_id = AccountId::FromUserEmailGaiaId( + std::string(kFakeRegularUserEmail), std::string(kFakeRegularUserEmail)); + user_manager::User* user = AddUser(account_id); + + GURL requested_url; + + EXPECT_CALL(*mock_user_image_loader_delegate(), FromGURLAnimated) + .WillOnce(testing::DoAll( + testing::SaveArg<0>(&requested_url), + testing::Invoke([](const GURL& default_image_url, + user_image_loader::LoadedCallback loaded_cb) { + base::SequencedTaskRunner::GetCurrentDefault() + ->PostTaskAndReplyWithResult( + FROM_HERE, base::BindLambdaForTesting([]() { + return std::make_unique<user_manager::UserImage>(); + }), + std::move(loaded_cb)); + }))); + + fake_chrome_user_manager()->SetIsCurrentUserNew(true); + fake_chrome_user_manager()->UserLoggedIn( + account_id, /*user_id_hash=*/ + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); + + test::UserImageChangeWaiter user_image_change_waiter; + user_image_change_waiter.Wait(); + + EXPECT_TRUE(default_user_image::IsInCurrentImageSet(user->image_index())); + EXPECT_EQ(requested_url, + default_user_image::GetDefaultImageUrl(user->image_index())); + + EXPECT_FALSE(is_downloading_profile_image(account_id)); + EXPECT_FALSE(NeedProfileImage(account_id)); + EXPECT_TRUE( + user_image_manager_impl(account_id)->DownloadedProfileImage().isNull()); + EXPECT_TRUE(is_random_image_set(account_id)); +} + +TEST_F(UserImageManagerImplTest, RecordsUserImageLoggedInHistogram) { + constexpr int kDefaultImageIndex = 85; + ASSERT_TRUE(default_user_image::IsInCurrentImageSet(kDefaultImageIndex)); + + base::HistogramTester histogram_tester; + + const AccountId account_id = AccountId::FromUserEmailGaiaId( + std::string(kFakeRegularUserEmail), std::string(kFakeRegularUserEmail)); + AddUser(account_id); + + EXPECT_CALL(*mock_user_image_loader_delegate(), FromGURLAnimated); + + user_image_manager_impl(account_id) + ->SaveUserDefaultImageIndex(kDefaultImageIndex); + + fake_chrome_user_manager()->SetIsCurrentUserNew(false); + fake_chrome_user_manager()->UserLoggedIn( + account_id, /*user_id_hash=*/ + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, + /*is_child=*/false); + + histogram_tester.ExpectUniqueSample( + UserImageManagerImpl::kUserImageLoggedInHistogramName, + UserImageManagerImpl::ImageIndexToHistogramIndex(kDefaultImageIndex), 1); +} + +} // namespace ash
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc index 4c30d92..1b74d92 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.cc
@@ -4,7 +4,10 @@ #include "chrome/browser/ash/login/users/avatar/user_image_manager_registry.h" -#include "base/notreached.h" +#include <memory> + +#include "chrome/browser/ash/login/users/avatar/user_image_loader_delegate.h" +#include "chrome/browser/ash/login/users/avatar/user_image_loader_delegate_impl.h" #include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h" #include "components/account_id/account_id.h" #include "components/user_manager/user.h" @@ -22,7 +25,15 @@ UserImageManagerRegistry::UserImageManagerRegistry( user_manager::UserManager* user_manager) - : user_manager_(user_manager) { + : UserImageManagerRegistry( + user_manager, + std::make_unique<UserImageLoaderDelegateImpl>()) {} + +UserImageManagerRegistry::UserImageManagerRegistry( + user_manager::UserManager* user_manager, + std::unique_ptr<UserImageLoaderDelegate> user_image_loader_delegate) + : user_image_loader_delegate_(std::move(user_image_loader_delegate)), + user_manager_(user_manager) { CHECK(!g_instance); g_instance = this; observation_.Observe(user_manager); @@ -38,7 +49,8 @@ auto it = map_.find(account_id); if (it == map_.end()) { it = map_.emplace(account_id, std::make_unique<UserImageManagerImpl>( - account_id, user_manager_.get())) + account_id, user_manager_.get(), + user_image_loader_delegate_.get())) .first; } return it->second.get();
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h index e59a1c2..080b186 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_registry.h
@@ -21,6 +21,7 @@ namespace ash { class UserImageManagerImpl; +class UserImageLoaderDelegate; // UserImageManger is per user. This manages the mapping from each user // identified by AccountId to UserImageManager. @@ -32,8 +33,15 @@ // Given user_manager's lifetime needs to outlive this instance. explicit UserImageManagerRegistry(user_manager::UserManager* user_manager); + + // Constructor to inject a test version of `UserImageLoaderDelegate`. + UserImageManagerRegistry( + user_manager::UserManager* user_manager, + std::unique_ptr<UserImageLoaderDelegate> user_image_loader_delegate); + UserImageManagerRegistry(const UserImageManagerRegistry&) = delete; UserImageManagerRegistry operator=(UserImageManagerRegistry&) = delete; + ~UserImageManagerRegistry() override; // Returns the manager for the given avator. @@ -51,7 +59,12 @@ void OnUserProfileCreated(const user_manager::User& user) override; private: + // Owned. Expected to outlive `map_` as it is shared by every + // `UserImageManagerImpl`. + const std::unique_ptr<UserImageLoaderDelegate> user_image_loader_delegate_; + const raw_ptr<user_manager::UserManager> user_manager_; + std::map<AccountId, std::unique_ptr<UserImageManagerImpl>> map_; base::ScopedObservation<user_manager::UserManager,
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc index 187f5a7..8741b4f 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc
@@ -7,16 +7,12 @@ #include <stddef.h> #include <stdint.h> #include <string> -#include <utility> #include "base/files/file_util.h" -#include "base/memory/ref_counted.h" #include "base/threading/thread_restrictions.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/image/image_skia_rep.h" -namespace ash { -namespace test { +namespace ash::test { const char kUserAvatarImage1RelativePath[] = "chromeos/avatars/avatar1.jpg"; const char kUserAvatarImage2RelativePath[] = "chromeos/avatars/avatar2.jpg"; @@ -50,6 +46,10 @@ return true; } +// ***************************************************************************** +// ImageLoader +// ***************************************************************************** + ImageLoader::ImageLoader(const base::FilePath& path) : path_(path) {} ImageLoader::~ImageLoader() {} @@ -79,5 +79,25 @@ run_loop_.Quit(); } -} // namespace test -} // namespace ash +// ***************************************************************************** +// UserImageChangeWaiter +// ***************************************************************************** + +UserImageChangeWaiter::UserImageChangeWaiter() = default; + +UserImageChangeWaiter::~UserImageChangeWaiter() = default; + +void UserImageChangeWaiter::Wait() { + user_manager::UserManager::Get()->AddObserver(this); + run_loop_ = std::make_unique<base::RunLoop>(); + run_loop_->Run(); + user_manager::UserManager::Get()->RemoveObserver(this); +} + +void UserImageChangeWaiter::OnUserImageChanged(const user_manager::User& user) { + if (run_loop_) { + run_loop_->Quit(); + } +} + +} // namespace ash::test
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h b/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h index 5152514..ba736d42 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h
@@ -8,14 +8,14 @@ #include "base/files/file_path.h" #include "base/run_loop.h" #include "chrome/browser/image_decoder/image_decoder.h" +#include "components/user_manager/user_manager.h" #include "ui/gfx/image/image_skia.h" namespace base { class FilePath; } -namespace ash { -namespace test { +namespace ash::test { extern const char kUserAvatarImage1RelativePath[]; extern const char kUserAvatarImage2RelativePath[]; @@ -47,7 +47,24 @@ gfx::ImageSkia decoded_image_; }; -} // namespace test -} // namespace ash +class UserImageChangeWaiter : public user_manager::UserManager::Observer { + public: + UserImageChangeWaiter(); + + UserImageChangeWaiter(const UserImageChangeWaiter&) = delete; + UserImageChangeWaiter& operator=(const UserImageChangeWaiter&) = delete; + + ~UserImageChangeWaiter() override; + + void Wait(); + + // user_manager::UserManager::Observer: + void OnUserImageChanged(const user_manager::User& user) override; + + private: + std::unique_ptr<base::RunLoop> run_loop_; +}; + +} // namespace ash::test #endif // CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_MANAGER_TEST_UTIL_H_
diff --git a/chrome/browser/ash/power/ml/smart_dim/smart_dim_integration_test.cc b/chrome/browser/ash/power/ml/smart_dim/smart_dim_integration_test.cc index ef7cf6b..49361d28 100644 --- a/chrome/browser/ash/power/ml/smart_dim/smart_dim_integration_test.cc +++ b/chrome/browser/ash/power/ml/smart_dim/smart_dim_integration_test.cc
@@ -198,7 +198,8 @@ base::test::ScopedFeatureList feature_list_; }; -IN_PROC_BROWSER_TEST_F(SmartDimLacrosIntegrationTest, SmartDim) { +// TODO(b/341659658): Fails to initialize Lacros window. +IN_PROC_BROWSER_TEST_F(SmartDimLacrosIntegrationTest, DISABLED_SmartDim) { // Lacros fails to start up correctly on VM tryservers like // chromeos-amd64-generic (Lacros restarts in a loop). b/303359438 if (base::CPU().is_running_in_vm()) {
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.cc index dbfb617..5efa12e 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.cc
@@ -70,14 +70,15 @@ return ::ash::personalization_app::IsEligibleForSeaPen(profile_); } -void PersonalizationAppSeaPenProviderBase::SearchWallpaper( +void PersonalizationAppSeaPenProviderBase::GetSeaPenThumbnails( const mojom::SeaPenQueryPtr query, - SearchWallpaperCallback callback) { + GetSeaPenThumbnailsCallback callback) { // Search for wallpaper. - if (query->is_text_query() && query->get_text_query().length() > - mojom::kMaximumSearchWallpaperTextBytes) { + if (query->is_text_query() && + query->get_text_query().length() > + mojom::kMaximumGetSeaPenThumbnailsTextBytes) { sea_pen_receiver_.ReportBadMessage( - "SearchWallpaper exceeded maximum text length"); + "GetSeaPenThumbnails exceeded maximum text length"); return; } last_query_ = query.Clone(); @@ -104,8 +105,8 @@ if (feature_name_ == manta::proto::FeatureName::CHROMEOS_WALLPAPER) { auto* sea_pen_fetcher = GetOrCreateSeaPenFetcher(); CHECK(sea_pen_fetcher); - // |last_query_| is set when calling SearchWallpaper() to fetch thumbnails. - // It should not be null when a thumbnail is selected. + // |last_query_| is set when calling GetSeaPenThumbnails() to fetch + // thumbnails. It should not be null when a thumbnail is selected. CHECK(last_query_); sea_pen_fetcher->FetchWallpaper( feature_name_, it->second, last_query_, @@ -141,10 +142,10 @@ weak_ptr_factory_.GetWeakPtr())); } -void PersonalizationAppSeaPenProviderBase::GetRecentSeaPenImages( - GetRecentSeaPenImagesCallback callback) { - GetRecentSeaPenImagesInternal(base::BindOnce( - &PersonalizationAppSeaPenProviderBase::OnGetRecentSeaPenImages, +void PersonalizationAppSeaPenProviderBase::GetRecentSeaPenImageIds( + GetRecentSeaPenImageIdsCallback callback) { + GetRecentSeaPenImageIdsInternal(base::BindOnce( + &PersonalizationAppSeaPenProviderBase::OnGetRecentSeaPenImageIds, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } @@ -174,7 +175,7 @@ } void PersonalizationAppSeaPenProviderBase::OnFetchThumbnailsDone( - SearchWallpaperCallback callback, + GetSeaPenThumbnailsCallback callback, std::optional<std::vector<SeaPenImage>> images, manta::MantaStatusCode status_code) { if (!images) { @@ -211,8 +212,8 @@ std::move(pending_select_recent_sea_pen_image_callback_).Run(success); } -void PersonalizationAppSeaPenProviderBase::OnGetRecentSeaPenImages( - GetRecentSeaPenImagesCallback callback, +void PersonalizationAppSeaPenProviderBase::OnGetRecentSeaPenImageIds( + GetRecentSeaPenImageIdsCallback callback, const std::vector<uint32_t>& ids) { recent_sea_pen_image_ids_ = std::set<uint32_t>(ids.begin(), ids.end()); std::move(callback).Run(ids);
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.h b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.h index 591af243..0e99849 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.h +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_base.h
@@ -58,8 +58,8 @@ bool IsEligibleForSeaPen() override; // ::ash::personalization_app::mojom::SeaPenProvider: - void SearchWallpaper(mojom::SeaPenQueryPtr query, - SearchWallpaperCallback callback) override; + void GetSeaPenThumbnails(mojom::SeaPenQueryPtr query, + GetSeaPenThumbnailsCallback callback) override; void SelectSeaPenThumbnail(uint32_t id, SelectSeaPenThumbnailCallback callback) override; @@ -68,7 +68,8 @@ uint32_t id, SelectRecentSeaPenImageCallback callback) override; - void GetRecentSeaPenImages(GetRecentSeaPenImagesCallback callback) override; + void GetRecentSeaPenImageIds( + GetRecentSeaPenImageIdsCallback callback) override; void GetRecentSeaPenImageThumbnail( uint32_t id, @@ -88,8 +89,8 @@ uint32_t id, SelectRecentSeaPenImageCallback callback) = 0; - virtual void GetRecentSeaPenImagesInternal( - GetRecentSeaPenImagesCallback callback) = 0; + virtual void GetRecentSeaPenImageIdsInternal( + GetRecentSeaPenImageIdsCallback callback) = 0; virtual void GetRecentSeaPenImageThumbnailInternal( uint32_t id, @@ -119,8 +120,7 @@ mojo::Receiver<mojom::SeaPenProvider> sea_pen_receiver_{this}; private: - - void OnFetchThumbnailsDone(SearchWallpaperCallback callback, + void OnFetchThumbnailsDone(GetSeaPenThumbnailsCallback callback, std::optional<std::vector<SeaPenImage>> images, manta::MantaStatusCode status_code); @@ -129,8 +129,8 @@ void OnRecentSeaPenImageSelected(bool success); - void OnGetRecentSeaPenImages(GetRecentSeaPenImagesCallback callback, - const std::vector<uint32_t>& ids); + void OnGetRecentSeaPenImageIds(GetRecentSeaPenImageIdsCallback callback, + const std::vector<uint32_t>& ids); void OnGetRecentSeaPenImageThumbnail( uint32_t id, @@ -148,7 +148,7 @@ std::map<uint32_t, const SeaPenImage> sea_pen_images_; // The last query made to the sea pen provider. This can be null when - // SearchWallpaper() is never called. + // GetSeaPenThumbnails() is never called. mojom::SeaPenQueryPtr last_query_; // Perform a network request to search/upscale available wallpapers.
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc index 8235463..888c0b5cb 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.cc
@@ -93,8 +93,8 @@ std::move(callback)); } -void PersonalizationAppSeaPenProviderImpl::GetRecentSeaPenImagesInternal( - GetRecentSeaPenImagesCallback callback) { +void PersonalizationAppSeaPenProviderImpl::GetRecentSeaPenImageIdsInternal( + GetRecentSeaPenImageIdsCallback callback) { auto* sea_pen_wallpaper_manager = SeaPenWallpaperManager::GetInstance(); DCHECK(sea_pen_wallpaper_manager); sea_pen_wallpaper_manager->GetImageIds(GetAccountId(profile_),
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.h b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.h index d07f428..3d541147 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.h +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.h
@@ -49,8 +49,8 @@ uint32_t id, SelectRecentSeaPenImageCallback callback) override; - void GetRecentSeaPenImagesInternal( - GetRecentSeaPenImagesCallback callback) override; + void GetRecentSeaPenImageIdsInternal( + GetRecentSeaPenImageIdsCallback callback) override; void GetRecentSeaPenImageThumbnailInternal( uint32_t id,
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl_unittest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl_unittest.cc index 4a94ad0..7d9db8a 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl_unittest.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl_unittest.cc
@@ -327,7 +327,7 @@ mojom::SeaPenQueryPtr search_query = mojom::SeaPenQuery::NewTextQuery("search_query"); - sea_pen_provider_remote()->SearchWallpaper( + sea_pen_provider_remote()->GetSeaPenThumbnails( std::move(search_query), search_wallpaper_future.GetCallback()); EXPECT_THAT( @@ -358,7 +358,7 @@ mojom::SeaPenUserVisibleQuery::New("test template query", "test template title"))); - sea_pen_provider_remote()->SearchWallpaper( + sea_pen_provider_remote()->GetSeaPenThumbnails( std::move(search_query), search_wallpaper_future.GetCallback()); EXPECT_THAT( @@ -376,11 +376,11 @@ // "\uFFFF" is picked because `.size()` differs by a factor of three // between UTF-8 (C++ std::string) and UTF-16 (javascript string). std::string long_unicode_string = - RepeatToSize("\uFFFF", mojom::kMaximumSearchWallpaperTextBytes); - ASSERT_EQ(mojom::kMaximumSearchWallpaperTextBytes, + RepeatToSize("\uFFFF", mojom::kMaximumGetSeaPenThumbnailsTextBytes); + ASSERT_EQ(mojom::kMaximumGetSeaPenThumbnailsTextBytes, long_unicode_string.size()); // In javascript UTF-16, `long_unicode_string.length` is 1/3. - ASSERT_EQ(mojom::kMaximumSearchWallpaperTextBytes / 3, + ASSERT_EQ(mojom::kMaximumGetSeaPenThumbnailsTextBytes / 3, base::UTF8ToUTF16(long_unicode_string).size()); base::test::TestFuture< @@ -391,31 +391,31 @@ mojom::SeaPenQueryPtr long_query = mojom::SeaPenQuery::NewTextQuery(long_unicode_string); - sea_pen_provider_remote()->SearchWallpaper( + sea_pen_provider_remote()->GetSeaPenThumbnails( std::move(long_query), search_wallpaper_future.GetCallback()); EXPECT_EQ(4u, search_wallpaper_future.Get<0>().value().size()) - << "SearchWallpaper succeeds if text is exactly max length"; + << "GetSeaPenThumbnails succeeds if text is exactly max length"; } TEST_F(PersonalizationAppSeaPenProviderImplTest, QueryLengthExceeded) { SetUpProfileForTesting(kFakeTestEmail, GetTestAccountId()); std::string max_length_unicode_string = - RepeatToSize("\uFFFF", mojom::kMaximumSearchWallpaperTextBytes); + RepeatToSize("\uFFFF", mojom::kMaximumGetSeaPenThumbnailsTextBytes); mojom::SeaPenQueryPtr bad_long_query = mojom::SeaPenQuery::NewTextQuery(max_length_unicode_string + 'a'); mojo::test::BadMessageObserver bad_message_observer; - sea_pen_provider_remote()->SearchWallpaper( + sea_pen_provider_remote()->GetSeaPenThumbnails( std::move(bad_long_query), base::BindLambdaForTesting( [](std::optional<std::vector< ash::personalization_app::mojom::SeaPenThumbnailPtr>>, manta::MantaStatusCode) { NOTREACHED_IN_MIGRATION(); })); - EXPECT_EQ("SearchWallpaper exceeded maximum text length", + EXPECT_EQ("GetSeaPenThumbnails exceeded maximum text length", bad_message_observer.WaitForBadMessage()) - << "SearchWallpaper fails if text is longer than max length"; + << "GetSeaPenThumbnails fails if text is longer than max length"; } TEST_F(PersonalizationAppSeaPenProviderImplTest, @@ -434,7 +434,7 @@ manta::MantaStatusCode> search_wallpaper_future; - sea_pen_provider_remote()->SearchWallpaper( + sea_pen_provider_remote()->GetSeaPenThumbnails( query->Clone(), search_wallpaper_future.GetCallback()); ASSERT_EQ(963u, search_wallpaper_future.Get<0>().value().front()->id); @@ -456,7 +456,7 @@ test_wallpaper_controller()->wallpaper_info()->type); } -TEST_F(PersonalizationAppSeaPenProviderImplTest, GetRecentSeaPenImages) { +TEST_F(PersonalizationAppSeaPenProviderImplTest, GetRecentSeaPenImageIds) { SetUpProfileForTesting(kFakeTestEmail, GetTestAccountId()); // Create two images in the Sea Pen directory for the 1st user, then get the @@ -464,7 +464,7 @@ CreateSeaPenFilesForTesting(GetTestAccountId(), {kSeaPenId1, kSeaPenId2}); base::test::TestFuture<const std::vector<uint32_t>&> recent_images_future; - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); std::vector<uint32_t> recent_images = recent_images_future.Take(); @@ -474,7 +474,7 @@ // Log in the second user, get the list of recent images. SetUpProfileForTesting(kFakeTestEmail2, GetTestAccountId2()); - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); ASSERT_EQ(0u, recent_images_future.Take().size()); @@ -482,7 +482,7 @@ // of recent images again. CreateSeaPenFilesForTesting(GetTestAccountId2(), {kSeaPenId1}); - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); recent_images = recent_images_future.Take(); EXPECT_THAT(recent_images, @@ -508,7 +508,7 @@ std::vector<ash::personalization_app::mojom::SeaPenThumbnailPtr>>, manta::MantaStatusCode> search_wallpaper_future; - sea_pen_provider_remote()->SearchWallpaper( + sea_pen_provider_remote()->GetSeaPenThumbnails( search_query.Clone(), search_wallpaper_future.GetCallback()); // Select the first returned thumbnail. base::test::TestFuture<bool> select_wallpaper_future; @@ -562,7 +562,7 @@ manta::MantaStatusCode> search_wallpaper_future; - sea_pen_provider_remote()->SearchWallpaper( + sea_pen_provider_remote()->GetSeaPenThumbnails( search_query->Clone(), search_wallpaper_future.GetCallback()); // Select the first returned thumbnail. @@ -594,7 +594,7 @@ CreateSeaPenFilesForTesting(GetTestAccountId(), {kSeaPenId1}); base::test::TestFuture<const std::vector<uint32_t>&> recent_images_future; - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); std::vector<uint32_t> recent_images = recent_images_future.Take(); @@ -621,7 +621,7 @@ CreateSeaPenFilesForTesting(GetTestAccountId(), {kSeaPenId1}); base::test::TestFuture<const std::vector<uint32_t>&> recent_images_future; - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); std::vector<uint32_t> recent_images = recent_images_future.Take(); @@ -657,7 +657,7 @@ } base::test::TestFuture<const std::vector<uint32_t>&> recent_images_future; - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); std::vector<uint32_t> recent_images = recent_images_future.Take(); @@ -677,7 +677,7 @@ CreateSeaPenFilesForTesting(GetTestAccountId(), {kSeaPenId1, kSeaPenId2}); base::test::TestFuture<const std::vector<uint32_t>&> recent_images_future; - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); EXPECT_THAT(recent_images_future.Take(), testing::UnorderedElementsAre(kSeaPenId1, kSeaPenId2)); @@ -695,7 +695,7 @@ kSeaPenId2, delete_future.GetCallback()); EXPECT_TRUE(delete_future.Take()); - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); EXPECT_THAT(recent_images_future.Take(), testing::UnorderedElementsAre(kSeaPenId1)); @@ -709,7 +709,7 @@ kSeaPenId1, delete_future.GetCallback()); EXPECT_TRUE(delete_future.Take()); - sea_pen_provider_remote()->GetRecentSeaPenImages( + sea_pen_provider_remote()->GetRecentSeaPenImageIds( recent_images_future.GetCallback()); EXPECT_THAT(recent_images_future.Take(), testing::ContainerEq(std::vector<uint32_t>({})));
diff --git a/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.cc b/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.cc index f668c01..1ee89713 100644 --- a/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.cc +++ b/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.cc
@@ -84,8 +84,8 @@ CameraEffectsController::SeaPenIdToRelativePath(id), std::move(callback)); } -void VcBackgroundUISeaPenProviderImpl::GetRecentSeaPenImagesInternal( - GetRecentSeaPenImagesCallback callback) { +void VcBackgroundUISeaPenProviderImpl::GetRecentSeaPenImageIdsInternal( + GetRecentSeaPenImageIdsCallback callback) { GetCameraEffectsController()->GetBackgroundImageFileNames( base::BindOnce(&GetIdsFromFilePaths).Then(std::move(callback))); }
diff --git a/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.h b/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.h index e6709da..0198349 100644 --- a/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.h +++ b/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl.h
@@ -47,8 +47,8 @@ uint32_t id, SelectRecentSeaPenImageCallback callback) override; - void GetRecentSeaPenImagesInternal( - GetRecentSeaPenImagesCallback callback) override; + void GetRecentSeaPenImageIdsInternal( + GetRecentSeaPenImageIdsCallback callback) override; void GetRecentSeaPenImageThumbnailInternal( uint32_t id,
diff --git a/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl_browsertest.cc b/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl_browsertest.cc index 6335bc2..2b03074 100644 --- a/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl_browsertest.cc +++ b/chrome/browser/ash/system_web_apps/apps/vc_background_ui/vc_background_ui_sea_pen_provider_impl_browsertest.cc
@@ -119,7 +119,7 @@ IN_PROC_BROWSER_TEST_F(VcBackgroundUISeaPenProviderImplTest, AllTests) { // Get all background images. base::RunLoop run_loop; - sea_pen_provider_->GetRecentSeaPenImages( + sea_pen_provider_->GetRecentSeaPenImageIds( base::BindLambdaForTesting([&](const std::vector<uint32_t>& ids) { EXPECT_EQ(existing_image_ids_, ids); run_loop.Quit();
diff --git a/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.cc b/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.cc index 155a7ad..1f8635ce 100644 --- a/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.cc +++ b/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.cc
@@ -209,7 +209,8 @@ if (query->is_text_query() && query->get_text_query().size() > - ash::personalization_app::mojom::kMaximumSearchWallpaperTextBytes) { + ash::personalization_app::mojom:: + kMaximumGetSeaPenThumbnailsTextBytes) { LOG(WARNING) << "Query too long. Size received: " << query->get_text_query().size(); std::move(callback).Run(std::nullopt, @@ -254,9 +255,9 @@ } if (query->is_text_query()) { - CHECK_LE( - query->get_text_query().size(), - ash::personalization_app::mojom::kMaximumSearchWallpaperTextBytes); + CHECK_LE(query->get_text_query().size(), + ash::personalization_app::mojom:: + kMaximumGetSeaPenThumbnailsTextBytes); } fetch_wallpaper_timer_.Stop();
diff --git a/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.h b/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.h index dded8026..b0ab723 100644 --- a/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.h +++ b/chrome/browser/ash/wallpaper_handlers/sea_pen_fetcher.h
@@ -42,7 +42,7 @@ virtual ~SeaPenFetcher(); // Run `query` against the Manta API. `query` is required to be a valid UTF-8 - // string no longer than `kMaximumSearchWallpaperTextBytes`. + // string no longer than `kMaximumGetSeaPenThumbnailsTextBytes`. virtual void FetchThumbnails( manta::proto::FeatureName feature_name, const ash::personalization_app::mojom::SeaPenQueryPtr& query,
diff --git a/chrome/browser/companion/core/features.cc b/chrome/browser/companion/core/features.cc index 4a1d4d4c9..c0990f7 100644 --- a/chrome/browser/companion/core/features.cc +++ b/chrome/browser/companion/core/features.cc
@@ -46,11 +46,6 @@ "CompanionEnableSearchWebInNewTabContextMenuItem", base::FEATURE_ENABLED_BY_DEFAULT); -// When search companion is enabled, show new badges on the context menu items -// that open the companion. -BASE_FEATURE(kCompanionEnableNewBadgesInContextMenu, - "CompanionEnableNewBadgesInContextMenu", - base::FEATURE_DISABLED_BY_DEFAULT); // Allow sharing page content with CSC. Enabling this flag alone isn't enough to // share page content - the user still needs to opt in either through a promo or // chrome://settings. When disabled, page content will not be shared even if the
diff --git a/chrome/browser/companion/core/features.h b/chrome/browser/companion/core/features.h index 6be10f8..b4aa8b9 100644 --- a/chrome/browser/companion/core/features.h +++ b/chrome/browser/companion/core/features.h
@@ -22,7 +22,6 @@ } // namespace internal BASE_DECLARE_FEATURE(kCompanionEnableSearchWebInNewTabContextMenuItem); -BASE_DECLARE_FEATURE(kCompanionEnableNewBadgesInContextMenu); BASE_DECLARE_FEATURE(kCompanionEnablePageContent); } // namespace features
diff --git a/chrome/browser/compose/chrome_compose_client.cc b/chrome/browser/compose/chrome_compose_client.cc index 8efdce1..b1f820e 100644 --- a/chrome/browser/compose/chrome_compose_client.cc +++ b/chrome/browser/compose/chrome_compose_client.cc
@@ -112,7 +112,12 @@ nudge_tracker_.StartObserving(web_contents); } -ChromeComposeClient::~ChromeComposeClient() = default; +ChromeComposeClient::~ChromeComposeClient() { + // Sessions may call back during destruction through ComposeSession::Observer. + // Let's ensure that happens before destroying anything else. + sessions_.clear(); + debug_session_.reset(); +} void ChromeComposeClient::BindComposeDialog( mojo::PendingReceiver<compose::mojom::ComposeClientUntrustedPageHandler> @@ -129,7 +134,8 @@ url::Origin::Create(GURL(chrome::kChromeUIUntrustedComposeUrl))) { debug_session_ = std::make_unique<ComposeSession>( &GetWebContents(), GetModelExecutor(), GetModelQualityLogsUploader(), - GetSessionId(), GetInnerTextProvider(), autofill::FieldRendererId(-1)); + GetSessionId(), GetInnerTextProvider(), autofill::FieldRendererId(-1), + this); debug_session_->set_collect_inner_text(false); debug_session_->set_fre_complete( pref_service_->GetBoolean(prefs::kPrefHasCompletedComposeFRE)); @@ -328,7 +334,7 @@ auto new_session = std::make_unique<ComposeSession>( &GetWebContents(), GetModelExecutor(), GetModelQualityLogsUploader(), GetSessionId(), GetInnerTextProvider(), - trigger_field.global_id().renderer_id, std::move(callback)); + trigger_field.global_id().renderer_id, this, std::move(callback)); current_session = new_session.get(); sessions_.insert_or_assign(active_compose_ids_.value().first, std::move(new_session)); @@ -547,6 +553,7 @@ } void ChromeComposeClient::DisableProactiveNudge() { + nudge_tracker_.OnUserDisabledNudge(/*single_site_only=*/false); proactive_nudge_enabled_.SetValue(false); } @@ -562,6 +569,7 @@ } void ChromeComposeClient::AddSiteToNeverPromptList(const url::Origin& origin) { + nudge_tracker_.OnUserDisabledNudge(/*single_site_only=*/true); ScopedDictPrefUpdate update(pref_service_, prefs::kProactiveNudgeDisabledSitesWithTime); update->Set(origin.Serialize(), base::TimeToValue(base::Time::Now())); @@ -580,6 +588,14 @@ return allow_context_menu; } +void ChromeComposeClient::OnSessionComplete( + autofill::FieldRendererId field_renderer_id, + compose::ComposeSessionCloseReason close_reason, + const compose::ComposeSessionEvents& events) { + nudge_tracker_.ComposeSessionCompleted(field_renderer_id, close_reason, + events); +} + void ChromeComposeClient::OnAfterFocusOnFormField( autofill::AutofillManager& manager, autofill::FormGlobalId form, @@ -662,6 +678,8 @@ page_ukm_tracker_ = std::make_unique<compose::PageUkmTracker>( page.GetMainDocument().GetPageUkmSourceId()); + nudge_tracker_.Clear(); + compose::ComposeTextUsageLogger::GetOrCreateForCurrentDocument( &page.GetMainDocument()); }
diff --git a/chrome/browser/compose/chrome_compose_client.h b/chrome/browser/compose/chrome_compose_client.h index 4f0effc..e0fd554 100644 --- a/chrome/browser/compose/chrome_compose_client.h +++ b/chrome/browser/compose/chrome_compose_client.h
@@ -50,6 +50,7 @@ public autofill::AutofillManager::Observer, public compose::mojom::ComposeClientUntrustedPageHandler, public compose::ProactiveNudgeTracker::Delegate, + public ComposeSession::Observer, public InnerTextProvider { public: using EntryPoint = autofill::AutofillComposeDelegate::UiEntryPoint; @@ -74,6 +75,11 @@ void OpenProactiveNudgeSettings() override; void AddSiteToNeverPromptList(const url::Origin& origin) override; + // ComposeSession::Observer: + void OnSessionComplete(autofill::FieldRendererId field_renderer_id, + compose::ComposeSessionCloseReason close_reason, + const compose::ComposeSessionEvents& events) override; + // autofill::AutofillManager::Observer: // Used to observe field focus changes so that the saved state notification // is only shown when an autofill suggestion will not be shown on another
diff --git a/chrome/browser/compose/chrome_compose_client_unittest.cc b/chrome/browser/compose/chrome_compose_client_unittest.cc index 6a335dc..5be802d 100644 --- a/chrome/browser/compose/chrome_compose_client_unittest.cc +++ b/chrome/browser/compose/chrome_compose_client_unittest.cc
@@ -9,6 +9,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" +#include "base/run_loop.h" #include "base/strings/utf_string_conversion_utils.h" #include "base/test/bind.h" #include "base/test/gmock_callback_support.h" @@ -19,7 +20,9 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" +#include "base/time/time.h" #include "chrome/browser/compose/compose_enabling.h" +#include "chrome/browser/segmentation_platform/segmentation_platform_service_factory.h" #include "chrome/common/compose/compose.mojom.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/browser_with_test_window_test.h" @@ -38,6 +41,8 @@ #include "components/optimization_guide/proto/features/compose.pb.h" #include "components/optimization_guide/proto/model_execution.pb.h" #include "components/optimization_guide/proto/model_quality_service.pb.h" +#include "components/segmentation_platform/public/constants.h" +#include "components/segmentation_platform/public/testing/mock_segmentation_platform_service.h" #include "components/ukm/test_ukm_recorder.h" #include "components/unified_consent/pref_names.h" #include "content/public/browser/navigation_entry.h" @@ -61,11 +66,14 @@ OptimizationGuideModelExecutionResultStreamingCallback; using optimization_guide::OptimizationGuideModelStreamingExecutionResult; using optimization_guide::StreamingResponse; +using segmentation_platform::MockSegmentationPlatformService; namespace { const uint64_t kSessionIdHigh = 1234; const uint64_t kSessionIdLow = 5678; +const segmentation_platform::TrainingRequestId kTrainingRequestId = + segmentation_platform::TrainingRequestId(456); constexpr char kTypeURL[] = "type.googleapis.com/optimization_guide.proto.ComposeResponse"; @@ -161,6 +169,15 @@ scoped_compose_enabled_ = ComposeEnabling::ScopedEnableComposeForTesting(); BrowserWithTestWindowTest::SetUp(); + segmentation_platform::SegmentationPlatformServiceFactory::GetInstance() + ->SetTestingFactory( + GetProfile(), + base::BindLambdaForTesting([](content::BrowserContext* context) { + std::unique_ptr<KeyedService> result = + std::make_unique<MockSegmentationPlatformService>(); + return result; + })); + scoped_feature_list_.InitWithFeatures( {compose::features::kEnableCompose, optimization_guide::features::kOptimizationGuideModelExecution}, @@ -211,10 +228,25 @@ LogAiDataRequest>(), nullptr)))); }))); + + ON_CALL(GetSegmentationPlatformService(), + GetClassificationResult(_, _, _, _)) + .WillByDefault(testing::WithArg<3>(testing::Invoke( + [](segmentation_platform::ClassificationResultCallback callback) { + auto result = segmentation_platform::ClassificationResult( + segmentation_platform::PredictionStatus::kSucceeded); + result.request_id = kTrainingRequestId; + result.ordered_labels = { + segmentation_platform::kComposePrmotionLabelShow}; + std::move(callback).Run(result); + }))); + test_timer_ = std::make_unique<base::ScopedMockElapsedTimersForTest>(); } void TearDown() override { + // Clear default actions for safe teardown. + testing::Mock::VerifyAndClear(&GetSegmentationPlatformService()); client_ = nullptr; scoped_feature_list_.Reset(); ukm_recorder_.reset(); @@ -327,6 +359,12 @@ field_data().set_selected_text(selection.substr(0, max_length)); } + MockSegmentationPlatformService& GetSegmentationPlatformService() { + return *static_cast<MockSegmentationPlatformService*>( + segmentation_platform::SegmentationPlatformServiceFactory:: + GetForProfile(GetProfile())); + } + protected: optimization_guide::proto::ComposePageMetadata ComposePageMetadata() { optimization_guide::proto::ComposePageMetadata page_metadata; @@ -736,6 +774,55 @@ ukm::builders::Compose_PageEvents::kProactiveNudgeShownName, 0))); } +TEST_F(ChromeComposeClientTest, TestProactiveNudgeEngagementIsRecorded) { + // Enable and trigger the proactive nudge. + compose::Config& config = compose::GetMutableConfigForTesting(); + config.proactive_nudge_enabled = true; + config.proactive_nudge_show_probability = 1.0; + config.proactive_nudge_delay = base::Microseconds(1); + config.proactive_nudge_segmentation = true; + + autofill::FormData form_data; + form_data.url = web_contents()->GetPrimaryMainFrame()->GetLastCommittedURL(); + form_data.fields = {autofill::test::CreateTestFormField( + "label0", "name0", "value0", autofill::FormControlType::kTextArea)}; + + autofill::FormFieldData selected_field_data = form_data.fields[0]; + selected_field_data.set_origin( + web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin()); + const autofill::AutofillSuggestionTriggerSource trigger_source = + autofill::AutofillSuggestionTriggerSource::kTextFieldDidChange; + + while (!client().ShouldTriggerPopup(selected_field_data, trigger_source)) { + task_environment()->RunUntilIdle(); + } + + // Simulate clicking on the nudge to open compose. + ShowDialogAndBindMojoWithFieldData( + selected_field_data, base::NullCallback(), + autofill::AutofillComposeDelegate::UiEntryPoint::kAutofillPopup); + + base::test::TestFuture<segmentation_platform::TrainingLabels> training_labels; + EXPECT_CALL(GetSegmentationPlatformService(), + CollectTrainingData( + segmentation_platform::proto::SegmentId:: + OPTIMIZATION_TARGET_SEGMENTATION_COMPOSE_PROMOTION, + kTrainingRequestId, _, _)) + .Times(1) + .WillOnce(testing::WithArg<2>(testing::Invoke( + [&](auto labels) { training_labels.SetValue(labels); }))); + + client().CloseUI(compose::mojom::CloseReason::kInsertButton); + + // Trigger session deletion and verify that the engagement is recorded. + NavigateAndCommitActiveTab(GURL("about:blank")); + EXPECT_EQ(training_labels.Get().output_metric, + std::make_pair("Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + compose::ProactiveNudgeDerivedEngagement:: + kAcceptedComposeSuggestion))); +} + TEST_F(ChromeComposeClientTest, TestShouldTriggerProactiveNudgeDisabledUKM) { autofill::FormData form_data; form_data.url = web_contents()->GetPrimaryMainFrame()->GetLastCommittedURL();
diff --git a/chrome/browser/compose/compose_session.cc b/chrome/browser/compose/compose_session.cc index 29fdd416..ea012aa7 100644 --- a/chrome/browser/compose/compose_session.cc +++ b/chrome/browser/compose/compose_session.cc
@@ -202,6 +202,7 @@ base::Token session_id, InnerTextProvider* inner_text, autofill::FieldRendererId node_id, + Observer* observer, ComposeCallback callback) : executor_(executor), handler_receiver_(this), @@ -214,6 +215,7 @@ close_reason_(compose::ComposeSessionCloseReason::kEndedImplicitly), final_status_(optimization_guide::proto::FinalStatus::STATUS_UNSPECIFIED), web_contents_(web_contents), + observer_(observer), collect_inner_text_( base::FeatureList::IsEnabled(compose::features::kComposeInnerText)), inner_text_caller_(inner_text), @@ -261,6 +263,10 @@ std::optional<compose::EvalLocation> eval_location = compose::GetEvalLocationFromEvents(session_events_); + if (observer_) { + observer_->OnSessionComplete(node_id_, close_reason_, session_events_); + } + if (session_events_.fre_dialog_shown_count > 0 && (!fre_complete_ || session_events_.fre_completed_in_session)) { compose::LogComposeFirstRunSessionCloseReason(fre_close_reason_);
diff --git a/chrome/browser/compose/compose_session.h b/chrome/browser/compose/compose_session.h index 3aab636..34b6ab28 100644 --- a/chrome/browser/compose/compose_session.h +++ b/chrome/browser/compose/compose_session.h
@@ -76,6 +76,13 @@ // form field on which it was triggered. using ComposeCallback = base::OnceCallback<void(const std::u16string&)>; + class Observer { + public: + virtual void OnSessionComplete( + autofill::FieldRendererId node_id, + compose::ComposeSessionCloseReason close_reason, + const compose::ComposeSessionEvents& events) = 0; + }; ComposeSession( content::WebContents* web_contents, optimization_guide::OptimizationGuideModelExecutor* executor, @@ -83,6 +90,7 @@ base::Token session_id, InnerTextProvider* inner_text, autofill::FieldRendererId node_id, + Observer* observer, ComposeCallback callback = base::NullCallback()); ~ComposeSession() override; @@ -335,6 +343,8 @@ // `this`. raw_ptr<content::WebContents> web_contents_; + raw_ptr<Observer> observer_; + // A callback to Autofill that triggers filling the field. ComposeCallback callback_;
diff --git a/chrome/browser/compose/proactive_nudge_tracker.cc b/chrome/browser/compose/proactive_nudge_tracker.cc index 4467608..5ee3e82c 100644 --- a/chrome/browser/compose/proactive_nudge_tracker.cc +++ b/chrome/browser/compose/proactive_nudge_tracker.cc
@@ -4,11 +4,69 @@ #include "chrome/browser/compose/proactive_nudge_tracker.h" +#include <memory> + +#include "base/functional/callback_helpers.h" +#include "components/compose/core/browser/compose_metrics.h" #include "components/compose/core/browser/config.h" #include "components/segmentation_platform/public/constants.h" namespace compose { +// Tracks user engagement as a result of the nudge. +class ProactiveNudgeTracker::EngagementTracker { + public: + EngagementTracker( + autofill::FieldRendererId field_renderer_id, + segmentation_platform::TrainingRequestId training_request_id, + ProactiveNudgeTracker* nudge_tracker) + : field_renderer_id_(field_renderer_id), + training_request_id_(training_request_id), + nudge_tracker_(nudge_tracker) {} + EngagementTracker(const EngagementTracker&) = delete; + EngagementTracker& operator=(const EngagementTracker&) = delete; + + ~EngagementTracker() { + ReportIfFirst(ProactiveNudgeDerivedEngagement::kIgnored); + } + + void ComposeSessionCompleted(ComposeSessionCloseReason session_close_reason, + const compose::ComposeSessionEvents& events) { + if (events.inserted_results) { + ReportIfFirst( + ProactiveNudgeDerivedEngagement::kAcceptedComposeSuggestion); + } else if (events.compose_count > 0) { + ReportIfFirst( + ProactiveNudgeDerivedEngagement::kGeneratedComposeSuggestion); + } else { + ReportIfFirst(ProactiveNudgeDerivedEngagement::kOpenedComposeMinimalUse); + } + } + + void UserDisabledNudge(bool single_site_only) { + if (single_site_only) { + ReportIfFirst( + ProactiveNudgeDerivedEngagement::kNudgeDisabledOnSingleSite); + } else { + ReportIfFirst(ProactiveNudgeDerivedEngagement::kNudgeDisabledOnAllSites); + } + } + + private: + void ReportIfFirst(ProactiveNudgeDerivedEngagement engagement) { + if (reported_) { + return; + } + nudge_tracker_->CollectTrainingData(training_request_id_, engagement); + reported_ = true; + } + + bool reported_ = false; + autofill::FieldRendererId field_renderer_id_; + segmentation_platform::TrainingRequestId training_request_id_; + raw_ptr<ProactiveNudgeTracker> nudge_tracker_; +}; + ProactiveNudgeTracker::State::State() = default; ProactiveNudgeTracker::State::~State() = default; @@ -27,7 +85,11 @@ InitializationPolicy::kObservePreexistingManagers); } -ProactiveNudgeTracker::~ProactiveNudgeTracker() = default; +ProactiveNudgeTracker::~ProactiveNudgeTracker() { + // Destroy all engagement trackers first to ensure CollectTrainingData() is + // called before other parts of this class are destroyed. + engagement_trackers_.clear(); +} bool ProactiveNudgeTracker::ProactiveNudgeRequestedForFormField( const autofill::FormFieldData& field_to_track) { @@ -61,8 +123,6 @@ segmentation_platform::kComposePromotionKey, options, nullptr, base::BindOnce(&ProactiveNudgeTracker::GotClassificationResult, weak_ptr_factory_.GetWeakPtr(), state_->AsWeakPtr())); - } else { - state_->segmentation_result = true; } base::TimeDelta delay = compose::GetComposeConfig().proactive_nudge_delay; @@ -74,7 +134,7 @@ &ProactiveNudgeTracker::ShowTimerElapsed); } - if (state_->segmentation_result && state_->timer_complete) { + if (ShouldShow(*state_)) { // If the timer is 0-duration and no segmentation result is required, then // just transition to Shown state directly before returning true. state_->show_state = ShowState::kShown; @@ -83,10 +143,27 @@ return false; } +bool ProactiveNudgeTracker::ShouldShow(const State& state) { + if (!state.timer_complete) { + return false; + } + if (!compose::GetComposeConfig().proactive_nudge_segmentation) { + return true; + } + return state.segmentation_result && + state.segmentation_result->ordered_labels[0] == + segmentation_platform::kComposePrmotionLabelShow; +} + void ProactiveNudgeTracker::FocusChangedInPage() { ResetState(); } +void ProactiveNudgeTracker::Clear() { + engagement_trackers_.clear(); + ResetState(); +} + void ProactiveNudgeTracker::OnAfterFocusOnFormField( autofill::AutofillManager& manager, autofill::FormGlobalId form, @@ -127,12 +204,20 @@ void ProactiveNudgeTracker::MaybeShowProactiveNudge() { DVLOG(2) << "ProactiveNudgeTracker: MaybeShowProactiveNudge "; - if (state_ && state_->segmentation_result.value_or(false) && - state_->timer_complete) { - // Transition to the SHOWN state. - delegate_->ShowProactiveNudge(state_->form, state_->field); - state_->show_state = ShowState::kCanBeShown; + if (!state_ || !ShouldShow(*state_)) { + return; } + + // Transition to the SHOWN state. + + if (state_->segmentation_result) { + engagement_trackers_[state_->field.renderer_id] = + std::make_unique<EngagementTracker>( + state_->field.renderer_id, state_->segmentation_result->request_id, + this); + } + delegate_->ShowProactiveNudge(state_->form, state_->field); + state_->show_state = ShowState::kCanBeShown; } void ProactiveNudgeTracker::GotClassificationResult( @@ -148,14 +233,46 @@ ResetState(); return; } - state->segmentation_result = result.ordered_labels[0] == - segmentation_platform::kComposePrmotionLabelShow; + state->segmentation_result = std::move(result); + MaybeShowProactiveNudge(); } +void ProactiveNudgeTracker::CollectTrainingData( + const segmentation_platform::TrainingRequestId training_request_id, + ProactiveNudgeDerivedEngagement engagement) { + segmentation_platform::TrainingLabels training_labels; + // TODO(harringtond): Add UMA for Compose.ProactiveNudge.DerivedEngagement. + training_labels.output_metric = + std::make_pair("Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>(engagement)); + segmentation_service_->CollectTrainingData( + segmentation_platform::proto::SegmentId:: + OPTIMIZATION_TARGET_SEGMENTATION_COMPOSE_PROMOTION, + training_request_id, training_labels, base::DoNothing()); +} + bool ProactiveNudgeTracker::MatchesCurrentField(autofill::FormGlobalId form, autofill::FieldGlobalId field) { return state_ && state_->form == form && state_->field == field; } +void ProactiveNudgeTracker::ComposeSessionCompleted( + autofill::FieldRendererId field_renderer_id, + ComposeSessionCloseReason session_close_reason, + const compose::ComposeSessionEvents& events) { + auto iter = engagement_trackers_.find(field_renderer_id); + if (iter != engagement_trackers_.end()) { + iter->second->ComposeSessionCompleted(session_close_reason, events); + engagement_trackers_.erase(iter); + } +} + +void ProactiveNudgeTracker::OnUserDisabledNudge(bool single_site_only) { + for (auto& iter : engagement_trackers_) { + iter.second->UserDisabledNudge(single_site_only); + } + engagement_trackers_.clear(); +} + } // namespace compose
diff --git a/chrome/browser/compose/proactive_nudge_tracker.h b/chrome/browser/compose/proactive_nudge_tracker.h index 41e2b10..0d0f962 100644 --- a/chrome/browser/compose/proactive_nudge_tracker.h +++ b/chrome/browser/compose/proactive_nudge_tracker.h
@@ -5,14 +5,18 @@ #ifndef CHROME_BROWSER_COMPOSE_PROACTIVE_NUDGE_TRACKER_H_ #define CHROME_BROWSER_COMPOSE_PROACTIVE_NUDGE_TRACKER_H_ +#include <map> +#include <memory> #include <optional> #include <string> +#include "base/functional/callback_forward.h" #include "base/memory/raw_ref.h" #include "base/memory/weak_ptr.h" #include "components/autofill/content/browser/scoped_autofill_managers_observation.h" #include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/common/unique_ids.h" +#include "components/compose/core/browser/compose_metrics.h" #include "components/segmentation_platform/public/segmentation_platform_service.h" namespace compose { @@ -57,7 +61,8 @@ autofill::FormGlobalId form; autofill::FieldGlobalId field; std::u16string initial_text_value; - std::optional<bool> segmentation_result = std::nullopt; + std::optional<segmentation_platform::ClassificationResult> + segmentation_result = std::nullopt; base::OneShotTimer timer; bool timer_complete = false; @@ -88,12 +93,20 @@ void FocusChangedInPage(); + void Clear(); + + void ComposeSessionCompleted(autofill::FieldRendererId field_renderer_id, + ComposeSessionCloseReason session_close_reason, + const compose::ComposeSessionEvents& events); + void OnUserDisabledNudge(bool single_site_only); + // autofill::AutofillManager::Observer: void OnAfterFocusOnFormField(autofill::AutofillManager& manager, autofill::FormGlobalId form, autofill::FieldGlobalId field) override; private: + class EngagementTracker; bool SegmentationStateIsValid(); void ResetState(); void ShowTimerElapsed(); @@ -103,9 +116,16 @@ void MaybeShowProactiveNudge(); bool MatchesCurrentField(autofill::FormGlobalId form, autofill::FieldGlobalId field); + void CollectTrainingData( + const segmentation_platform::TrainingRequestId training_request_id, + ProactiveNudgeDerivedEngagement engagement); + bool ShouldShow(const State& state); std::unique_ptr<State> state_; + std::map<autofill::FieldRendererId, std::unique_ptr<EngagementTracker>> + engagement_trackers_; + raw_ptr<segmentation_platform::SegmentationPlatformService> segmentation_service_; raw_ptr<Delegate> delegate_;
diff --git a/chrome/browser/compose/proactive_nudge_tracker_unittest.cc b/chrome/browser/compose/proactive_nudge_tracker_unittest.cc index 4166b353..38ea9a3 100644 --- a/chrome/browser/compose/proactive_nudge_tracker_unittest.cc +++ b/chrome/browser/compose/proactive_nudge_tracker_unittest.cc
@@ -4,48 +4,69 @@ #include "chrome/browser/compose/proactive_nudge_tracker.h" +#include <memory> + #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "components/autofill/core/common/autofill_test_utils.h" #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/unique_ids.h" +#include "components/compose/core/browser/compose_metrics.h" #include "components/compose/core/browser/config.h" #include "components/segmentation_platform/public/constants.h" #include "components/segmentation_platform/public/testing/mock_segmentation_platform_service.h" +#include "components/segmentation_platform/public/trigger.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::_; namespace compose { +namespace { + +using base::test::TestFuture; +using testing::_; +const autofill::FieldRendererId kFieldRendererId(123); +const autofill::FieldRendererId kFieldRendererId2(4); + +segmentation_platform::TrainingRequestId TrainingRequestId( + int request_number = 0) { + return segmentation_platform::TrainingRequestId(request_number + 456); +} + +autofill::FormFieldData CreateTestFormFieldData( + autofill::FieldRendererId renderer_id = kFieldRendererId) { + autofill::FormFieldData f; + f.set_host_frame(autofill::test::MakeLocalFrameToken()); + f.set_renderer_id(renderer_id); + f.set_value(u"FormFieldDataInitialValue"); + return f; +} class MockProactiveNudgeTrackerDelegate : public ProactiveNudgeTracker::Delegate { public: MOCK_METHOD(void, ShowProactiveNudge, - (autofill::FormGlobalId, autofill::FieldGlobalId), - (override)); + (autofill::FormGlobalId, autofill::FieldGlobalId)); }; -class ProactiveNudgeTrackerTest : public testing::TestWithParam<bool> { +class ProactiveNudgeTrackerTestBase : public testing::Test { public: - ProactiveNudgeTrackerTest() = default; + ProactiveNudgeTrackerTestBase() = default; - ProactiveNudgeTrackerTest(const ProactiveNudgeTrackerTest&) = delete; - ProactiveNudgeTrackerTest& operator=(const ProactiveNudgeTrackerTest&) = - delete; + ProactiveNudgeTrackerTestBase(const ProactiveNudgeTrackerTestBase&) = delete; + ProactiveNudgeTrackerTestBase& operator=( + const ProactiveNudgeTrackerTestBase&) = delete; - ~ProactiveNudgeTrackerTest() override = default; + ~ProactiveNudgeTrackerTestBase() override = default; - void SetUp() override { - testing::TestWithParam<bool>::SetUp(); + void SetUpNudgeTrackerTest(bool use_segmentation) { compose::GetMutableConfigForTesting().proactive_nudge_segmentation = - GetParam(); + use_segmentation; nudge_tracker_ = std::make_unique<ProactiveNudgeTracker>( &segmentation_service_, &delegate_); - if (uses_segmentation()) { + if (use_segmentation) { SetSegmentationResult(); } else { EXPECT_CALL(segmentation_service(), GetClassificationResult(_, _, _, _)) @@ -54,7 +75,6 @@ } void TearDown() override { - testing::TestWithParam<bool>::TearDown(); compose::ResetConfigForTesting(); } @@ -68,21 +88,14 @@ } ProactiveNudgeTracker& nudge_tracker() { return *nudge_tracker_; } - autofill::FormFieldData CreateTestFormFieldData() { - autofill::FormFieldData f; - f.set_host_frame(autofill::test::MakeLocalFrameToken()); - f.set_renderer_id(autofill::FieldRendererId(123)); - f.set_value(u"FormFieldDataInitialValue"); - return f; - } - void SetSegmentationResult(std::string label = "Show") { ON_CALL(segmentation_service(), GetClassificationResult(_, _, _, _)) .WillByDefault(testing::WithArg<3>(testing::Invoke( - [label]( + [label, this]( segmentation_platform::ClassificationResultCallback callback) { auto result = segmentation_platform::ClassificationResult( segmentation_platform::PredictionStatus::kSucceeded); + result.request_id = TrainingRequestId(training_request_number_++); result.ordered_labels = {label}; std::move(callback).Run(result); }))); @@ -100,8 +113,6 @@ }))); } - bool uses_segmentation() { return GetParam(); } - private: base::test::SingleThreadTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; @@ -112,6 +123,21 @@ testing::NiceMock<segmentation_platform::MockSegmentationPlatformService> segmentation_service_; std::unique_ptr<ProactiveNudgeTracker> nudge_tracker_; + int training_request_number_ = 0; +}; + +class ProactiveNudgeTrackerTest : public ProactiveNudgeTrackerTestBase, + public testing::WithParamInterface<bool> { + public: + ProactiveNudgeTrackerTest() = default; + + ~ProactiveNudgeTrackerTest() override = default; + + void SetUp() override { + ProactiveNudgeTrackerTestBase::SetUpNudgeTrackerTest(uses_segmentation()); + } + + bool uses_segmentation() { return GetParam(); } }; TEST_P(ProactiveNudgeTrackerTest, TestWait) { @@ -128,7 +154,7 @@ // Should not nudge if nudge is requested too soon. EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); - task_environment().FastForwardBy(base::Seconds(4)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); if (uses_segmentation()) { EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); auto result = segmentation_platform::ClassificationResult( @@ -159,7 +185,7 @@ // Should not nudge if nudge is requested too soon. EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); - task_environment().FastForwardBy(base::Seconds(4)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); EXPECT_TRUE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); } @@ -172,7 +198,7 @@ EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); nudge_tracker().FocusChangedInPage(); - task_environment().FastForwardBy(base::Seconds(4)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); } @@ -189,7 +215,7 @@ EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field2)); - task_environment().FastForwardBy(base::Seconds(4)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); } @@ -200,7 +226,7 @@ .Times(0); nudge_tracker().FocusChangedInPage(); - task_environment().FastForwardBy(base::Seconds(4)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); } TEST_P(ProactiveNudgeTrackerTest, TestNoNudgeDelay) { @@ -226,7 +252,7 @@ .Times(0); EXPECT_TRUE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); // Wait just in case the timer could be pending. - task_environment().FastForwardBy(base::Seconds(4)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); } } @@ -243,7 +269,7 @@ .Times(uses_segmentation() ? 0 : 1); EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); - task_environment().FastForwardBy(base::Seconds(4)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); if (uses_segmentation()) { EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); @@ -258,7 +284,194 @@ nudge_tracker().ProactiveNudgeRequestedForFormField(field)); } -INSTANTIATE_TEST_SUITE_P(ProactiveNudgeTrackerTest, +INSTANTIATE_TEST_SUITE_P(, ProactiveNudgeTrackerTest, - ::testing::Bool()); + ::testing::Bool(), + [](const auto& info) { + return info.param ? "SegmentationON" + : "SegmentationOFF"; + }); + +class ProactiveNudgeTrackerDerivedEngagementTest + : public ProactiveNudgeTrackerTestBase { + public: + void SetUp() override { + ProactiveNudgeTrackerTestBase::SetUpNudgeTrackerTest(true); + } + + // Set up a scenario where the nudge is shown for a field. + TestFuture<segmentation_platform::TrainingLabels>& TriggerNudgeForField( + int request_number, + const autofill::FormFieldData& field) { + EXPECT_CALL(delegate(), + ShowProactiveNudge(field.renderer_form_id(), field.global_id())) + .Times(1); + + EXPECT_FALSE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); + task_environment().FastForwardBy(GetComposeConfig().proactive_nudge_delay); + EXPECT_TRUE(nudge_tracker().ProactiveNudgeRequestedForFormField(field)); + + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + training_labels_futures_.emplace_back(); + EXPECT_CALL(segmentation_service(), + CollectTrainingData( + segmentation_platform::proto::SegmentId:: + OPTIMIZATION_TARGET_SEGMENTATION_COMPOSE_PROMOTION, + TrainingRequestId(request_number), _, _)) + .Times(1) + .WillOnce(testing::Invoke([&](auto, auto, auto labels, auto) { + training_labels.SetValue(labels); + })); + return training_labels; + } + + // Destroy the nudge tracker. This triggers CollectTrainingData() if + // necessary. + void Reset() { SetUpNudgeTrackerTest(true); } + + private: + // Just holds memory for futures created in TriggerNudgeForField(), not for + // direct use. + std::deque<TestFuture<segmentation_platform::TrainingLabels>> + training_labels_futures_; +}; + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, NoEngagement) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + TriggerNudgeForField(0, CreateTestFormFieldData()); + Reset(); + + EXPECT_EQ(training_labels.Get().output_metric, + std::make_pair("Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kIgnored))); +} + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, MinimalUse) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + TriggerNudgeForField(0, CreateTestFormFieldData()); + compose::ComposeSessionEvents events; + nudge_tracker().ComposeSessionCompleted( + kFieldRendererId, ComposeSessionCloseReason::kCloseButtonPressed, events); + Reset(); + + EXPECT_EQ( + training_labels.Get().output_metric, + std::make_pair( + "Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kOpenedComposeMinimalUse))); +} + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, SuggestionGenerated) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + TriggerNudgeForField(0, CreateTestFormFieldData()); + compose::ComposeSessionEvents events; + events.compose_count = 1; + nudge_tracker().ComposeSessionCompleted( + kFieldRendererId, ComposeSessionCloseReason::kCloseButtonPressed, events); + // This test should work with or without deleting the tracker. + Reset(); + + EXPECT_EQ( + training_labels.Get().output_metric, + std::make_pair( + "Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kGeneratedComposeSuggestion))); +} + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, AcceptedSuggestion) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + TriggerNudgeForField(0, CreateTestFormFieldData()); + compose::ComposeSessionEvents events; + events.compose_count = 1; + events.inserted_results = true; + nudge_tracker().ComposeSessionCompleted( + kFieldRendererId, ComposeSessionCloseReason::kAcceptedSuggestion, events); + + EXPECT_EQ( + training_labels.Get().output_metric, + std::make_pair( + "Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kAcceptedComposeSuggestion))); +} + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, + IgnoresSessionForDifferentField) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + TriggerNudgeForField(0, CreateTestFormFieldData()); + compose::ComposeSessionEvents events; + // This one is ignored because it has the wrong field id. + nudge_tracker().ComposeSessionCompleted( + autofill::FieldRendererId(999), + ComposeSessionCloseReason::kEndedImplicitly, events); + + events.compose_count = 1; + events.inserted_results = true; + nudge_tracker().ComposeSessionCompleted( + kFieldRendererId, ComposeSessionCloseReason::kAcceptedSuggestion, events); + + EXPECT_EQ( + training_labels.Get().output_metric, + std::make_pair( + "Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kAcceptedComposeSuggestion))); +} + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, TwoSessions) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels1 = + TriggerNudgeForField(0, CreateTestFormFieldData()); + TestFuture<segmentation_platform::TrainingLabels>& training_labels2 = + TriggerNudgeForField(1, CreateTestFormFieldData(kFieldRendererId2)); + compose::ComposeSessionEvents events; + events.compose_count = 1; + events.inserted_results = true; + nudge_tracker().ComposeSessionCompleted( + kFieldRendererId, ComposeSessionCloseReason::kAcceptedSuggestion, events); + Reset(); + + EXPECT_EQ( + training_labels1.Get().output_metric, + std::make_pair( + "Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kAcceptedComposeSuggestion))); + EXPECT_EQ(training_labels2.Get().output_metric, + std::make_pair("Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kIgnored))); +} + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, NudgeDisabledSingleSite) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + TriggerNudgeForField(0, CreateTestFormFieldData()); + nudge_tracker().OnUserDisabledNudge(/*single_site_only=*/true); + Reset(); + + EXPECT_EQ( + training_labels.Get().output_metric, + std::make_pair( + "Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kNudgeDisabledOnSingleSite))); +} + +TEST_F(ProactiveNudgeTrackerDerivedEngagementTest, NudgeDisabledAllSites) { + TestFuture<segmentation_platform::TrainingLabels>& training_labels = + TriggerNudgeForField(0, CreateTestFormFieldData()); + nudge_tracker().OnUserDisabledNudge(/*single_site_only=*/false); + Reset(); + + EXPECT_EQ( + training_labels.Get().output_metric, + std::make_pair( + "Compose.ProactiveNudge.DerivedEngagement", + static_cast<base::HistogramBase::Sample>( + ProactiveNudgeDerivedEngagement::kNudgeDisabledOnAllSites))); +} + +} // namespace } // namespace compose
diff --git a/chrome/browser/data_sharing/BUILD.gn b/chrome/browser/data_sharing/BUILD.gn index 94b9122..e036cc21 100644 --- a/chrome/browser/data_sharing/BUILD.gn +++ b/chrome/browser/data_sharing/BUILD.gn
@@ -121,6 +121,7 @@ "//chrome/browser/flags:java", "//chrome/browser/profiles/android:java", "//chrome/test/android:chrome_java_integration_test_support", + "//components/data_sharing:test_support_java", "//components/data_sharing/public:public_java", "//content/public/test/android:content_java_test_support", "//third_party/androidx:androidx_test_runner_java",
diff --git a/chrome/browser/data_sharing/DEPS b/chrome/browser/data_sharing/DEPS index 2d2a5921..50313c3 100644 --- a/chrome/browser/data_sharing/DEPS +++ b/chrome/browser/data_sharing/DEPS
@@ -2,5 +2,5 @@ # Minimize dependencies on internal code, but allow service construction. "+components/data_sharing/internal/data_sharing_service_impl.h", "+components/data_sharing/internal/empty_data_sharing_service.h", - "+components/data_sharing/test_support/mock_data_sharing_service.h", + "+components/data_sharing/test_support", ]
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingServiceFactoryTest.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingServiceFactoryTest.java index e3f13f0..2453566a 100644 --- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingServiceFactoryTest.java +++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingServiceFactoryTest.java
@@ -13,7 +13,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.UserDataHost; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Batch; @@ -25,9 +24,12 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.components.data_sharing.DataSharingNetworkLoader; import org.chromium.components.data_sharing.DataSharingService; +import org.chromium.components.data_sharing.PeopleGroupActionFailure; +import org.chromium.components.data_sharing.PeopleGroupActionOutcome; +import org.chromium.components.data_sharing.TestDataSharingService; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; @RunWith(BaseJUnit4ClassRunner.class) @@ -42,23 +44,7 @@ @Test @MediumTest public void testSettingTestFactory() throws TimeoutException { - DataSharingService testService = - new DataSharingService() { - @Override - public boolean isEmptyService() { - return true; - } - - @Override - public DataSharingNetworkLoader getNetworkLoader() { - return null; - } - - @Override - public UserDataHost getUserDataHost() { - return null; - } - }; + DataSharingService testService = new TestDataSharingService(); DataSharingServiceFactory.setForTesting(testService); LibraryLoader.getInstance().ensureInitialized(); @@ -84,16 +70,83 @@ LibraryLoader.getInstance().ensureInitialized(); mActivityTestRule.startMainActivityOnBlankPage(); + CountDownLatch countDownLatch = new CountDownLatch(6); // 6 method calls to wait for. + mActivityTestRule.runOnUiThread( new Runnable() { + void callbackReceived() { + countDownLatch.countDown(); + } + @Override public void run() { DataSharingService dataSharingService = DataSharingServiceFactory.getForProfile( ProfileManager.getLastUsedRegularProfile()); Assert.assertFalse(dataSharingService.isEmptyService()); + + // TODO(ssid): Add tests with SDK delegate once available. + dataSharingService.readAllGroups( + result -> { + Assert.assertTrue(result.groupDataSet == null); + Assert.assertEquals( + result.actionFailure, + PeopleGroupActionFailure.PERSISTENT_FAILURE); + callbackReceived(); + }); + dataSharingService.readGroup( + "bad_id", + result -> { + Assert.assertTrue(result.groupData == null); + Assert.assertEquals( + result.actionFailure, + PeopleGroupActionFailure.PERSISTENT_FAILURE); + callbackReceived(); + }); + dataSharingService.createGroup( + "bad_name", + result -> { + Assert.assertTrue(result.groupData == null); + Assert.assertEquals( + result.actionFailure, + PeopleGroupActionFailure.PERSISTENT_FAILURE); + callbackReceived(); + }); + dataSharingService.deleteGroup( + "bad_id", + result -> { + Assert.assertEquals( + result.intValue(), + PeopleGroupActionOutcome.PERSISTENT_FAILURE); + callbackReceived(); + }); + dataSharingService.inviteMember( + "bad_id", + "bad_email", + result -> { + Assert.assertEquals( + result.intValue(), + PeopleGroupActionOutcome.PERSISTENT_FAILURE); + callbackReceived(); + }); + dataSharingService.removeMember( + "bad_id", + "bad_email", + result -> { + Assert.assertEquals( + result.intValue(), + PeopleGroupActionOutcome.PERSISTENT_FAILURE); + callbackReceived(); + }); } }); + + // Wait for all the callbacks to return. + try { + countDownLatch.await(); + } catch (InterruptedException e) { + Assert.assertTrue(false); + } } @Test
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index a81aa61f..4caf7082 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -790,6 +790,8 @@ settings_api::PrefType::kBoolean; // App - On-Device Parental Controls + (*s_allowlist)[::ash::prefs::kOnDeviceAppControlsPin] = + settings_api::PrefType::kString; (*s_allowlist)[::ash::prefs::kOnDeviceAppControlsSetupCompleted] = settings_api::PrefType::kBoolean;
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 0dccd42a..d566e5f 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -1036,8 +1036,8 @@ << message_; } -// TODO: crbug.com/1450976 - Re-enable tests on Mac and Lacros. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO: crbug.com/1450976 - Re-enable tests on Mac and CrOS. +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) #define MAYBE_WebRequestCORSWithExtraHeaders \ DISABLED_WebRequestCORSWithExtraHeaders #else
diff --git a/chrome/browser/feed/android/java/res/drawable/header_title_section_tab_background.xml b/chrome/browser/feed/android/java/res/drawable/header_title_section_tab_background.xml index 78304210d..8254883 100644 --- a/chrome/browser/feed/android/java/res/drawable/header_title_section_tab_background.xml +++ b/chrome/browser/feed/android/java/res/drawable/header_title_section_tab_background.xml
@@ -11,7 +11,7 @@ <org.chromium.components.browser_ui.widget.SurfaceColorDrawable android:shape="rectangle" app:surfaceElevation="@dimen/feed_header_section_tab_bg_elevation_enabled"> - <corners android:radius="@dimen/feed_header_background_corner_radius_polished"/> + <corners android:radius="@dimen/feed_header_background_corner_radius"/> </org.chromium.components.browser_ui.widget.SurfaceColorDrawable> </item> </selector> \ No newline at end of file
diff --git a/chrome/browser/feed/android/java/res/values-night/dimens.xml b/chrome/browser/feed/android/java/res/values-night/dimens.xml index af0d318d..d6e0ce7 100644 --- a/chrome/browser/feed/android/java/res/values-night/dimens.xml +++ b/chrome/browser/feed/android/java/res/values-night/dimens.xml
@@ -7,6 +7,5 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- Dynamic color dimensions. --> - <dimen name="feed_header_section_tab_bg_elevation_enabled">@dimen/default_elevation_1</dimen> <dimen name="feed_header_tab_selected_bg_elevation">@dimen/default_elevation_4</dimen> </resources> \ No newline at end of file
diff --git a/chrome/browser/feed/android/java/res/values/dimens.xml b/chrome/browser/feed/android/java/res/values/dimens.xml index 1ccbb8bc..541b00b 100644 --- a/chrome/browser/feed/android/java/res/values/dimens.xml +++ b/chrome/browser/feed/android/java/res/values/dimens.xml
@@ -44,7 +44,7 @@ <dimen name="feed_options_chip_margin">8dp</dimen> <dimen name="feed_header_dropdown_size">15dp</dimen> <dimen name="feed_header_tab_extra_margin_right">7dp</dimen> - <dimen name="feed_header_background_corner_radius">60dp</dimen> + <dimen name="feed_header_background_corner_radius">12dp</dimen> <dimen name="feed_header_background_corner_radius_polished">8dp</dimen> <dimen name="feed_header_background_outer_corner_radius_polished">12dp</dimen> <dimen name="feed_header_tab_layout_width_max">165dp</dimen>
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 4236d24..0bb28550 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -4561,11 +4561,6 @@ "expiry_milestone": 130 }, { - "name": "files-app-experimental", - "owners": ["lucmult@chromium.org", "benreich@chromium.org", "simmonsjosh@google.com"], - "expiry_milestone": 127 - }, - { "name": "files-conflict-dialog", "owners": [ "simmonsjosh@google.com", "//ui/file_manager/OWNERS" ], "expiry_milestone": 135 @@ -5808,7 +5803,7 @@ { "name": "mutation-events", "owners": [ "masonf@chromium.org" ], - "expiry_milestone": 127 + "expiry_milestone": 134 }, { "name": "mute-notification-snooze-action", @@ -6463,6 +6458,12 @@ "owners": [ "manukh@chromium.org", "christianxu@chromium.org", "chrome-omnibox-team@google.com" ], "expiry_milestone": 130 }, + + { + "name": "omnibox-rich-autocompletion-android", + "owners": [ "gangwu@chromium.org", "chrome-mobile-search@google.com" ], + "expiry_milestone": 140 + }, { "name": "omnibox-rich-autocompletion-promising", "owners": [ "manukh@chromium.org", "chrome-omnibox-team@google.com" ],
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index a73dc48..60fa1ed 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4432,6 +4432,12 @@ "Allow revoking site-level notification permission if Chrome has no " "app-level notification permission on Android."; +const char kRichAutocompletionAndroidName[] = + "Omnibox rich inline autocompletion on Android"; +const char kRichAutocompletionAndroidDescription[] = + "Enables omnibox rich inline autocompletion. Expands inline autocomplete " + "to any type of input that users repeatedly use to get to specific URLs."; + const char kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheckName[] = "Safe Browsing new GMS API for browse URL database check"; const char kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheckDescription[] = @@ -6634,12 +6640,6 @@ const char kFileTransferEnterpriseConnectorUIDescription[] = "Enable the UI for the File Transfer Enterprise Connector."; -const char kFilesAppExperimentalName[] = - "Experimental UI features for Files app"; -const char kFilesAppExperimentalDescription[] = - "Enable experimental UI features for Files app. Experimental features are " - "expected to be non functional to end users."; - const char kFilesConflictDialogName[] = "Files app conflict dialog"; const char kFilesConflictDialogDescription[] = "When enabled, the conflict dialog will be shown during file transfers "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 1e52b03b..bf3b4b528 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2629,6 +2629,9 @@ extern const char kRevokeNotificationsPermissionIfDisabledOnAppLevelDescription[]; +extern const char kRichAutocompletionAndroidName[]; +extern const char kRichAutocompletionAndroidDescription[]; + extern const char kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheckName[]; extern const char kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheckDescription[]; @@ -3848,9 +3851,6 @@ extern const char kFileTransferEnterpriseConnectorUIName[]; extern const char kFileTransferEnterpriseConnectorUIDescription[]; -extern const char kFilesAppExperimentalName[]; -extern const char kFilesAppExperimentalDescription[]; - extern const char kFilesConflictDialogName[]; extern const char kFilesConflictDialogDescription[];
diff --git a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc index 9c95e8de..fcea8a5 100644 --- a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc +++ b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
@@ -1298,11 +1298,12 @@ ValidateForMemCacheLoadedImages(); } -#if BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC) #define MAYBE_NativeLazyLoadingImage DISABLED_NativeLazyLoadingImage #else #define MAYBE_NativeLazyLoadingImage NativeLazyLoadingImage #endif +// TODO(crbug.com/335901379): Re-enable test IN_PROC_BROWSER_TEST_F(LcpBreakdownTimingsTest, MAYBE_NativeLazyLoadingImage) { std::string test_url = "/lcp_breakdown_timings_native_lazy_loading_images.html";
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java index cbdb331c..9bf5cdc 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java
@@ -1175,7 +1175,6 @@ promise.then( playback -> { Log.d(TAG, "Voice preview playback created."); - ReadAloudMetrics.recordVoicePreviewed(voice.getVoiceId()); mVoicePreviewPlayback = playback; playback.addListener(mVoicePreviewPlaybackListener); mVoicePreviewPlayback.play();
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java index 6e9669e..377162a 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java
@@ -1417,28 +1417,6 @@ } @Test - public void testPreviewVoice_metric() { - final String histogramName = ReadAloudMetrics.VOICE_PREVIEWED; - - var histogram = HistogramWatcher.newSingleRecordWatcher(histogramName + "abc", true); - - // Play tab. - requestAndStartPlayback(); - - reset(mPlaybackHooks); - // Preview a voice. - var voice = new PlaybackVoice("en", "abc", ""); - doReturn(List.of(voice)).when(mPlaybackHooks).getVoicesFor(anyString()); - doReturn(List.of(voice)).when(mPlaybackHooks).getPlaybackVoiceList(any()); - mController.previewVoice(voice); - verify(mPlaybackHooks).createPlayback(any(), mPlaybackCallbackCaptor.capture()); - Playback previewPlayback = Mockito.mock(Playback.class); - onPlaybackSuccess(previewPlayback); - - histogram.assertExpected(); - } - - @Test public void testRestorePlaybackState_whileLoading() { // Request playback but don't succeed yet. mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR);
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudMetrics.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudMetrics.java index b840719..706ce0b 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudMetrics.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudMetrics.java
@@ -24,8 +24,6 @@ public static String TAB_PLAYBACK_CREATION_FAILURE = "ReadAloud.TabPlaybackCreationFailure"; public static String TAB_PLAYBACK_WITHOUT_READABILITY_CHECK_ERROR = "ReadAloud.ReadAloudPlaybackWithoutReadabilityCheckError"; - public static String VOICE_CHANGED = "ReadAloud.VoiceChanged."; - public static String VOICE_PREVIEWED = "ReadAloud.VoicePreviewed."; public static String TIME_SPENT_LISTENING = "ReadAloud.DurationListened"; public static String TIME_SPENT_LISTENING_LOCKED_SCREEN = "ReadAloud.DurationListened.LockedScreen"; @@ -186,14 +184,6 @@ RecordUserAction.record("ReadAloud.PlaybackStarted"); } - public static void recordVoiceChanged(String voiceID) { - RecordHistogram.recordBooleanHistogram(VOICE_CHANGED + voiceID, true); - } - - public static void recordVoicePreviewed(String voiceID) { - RecordHistogram.recordBooleanHistogram(VOICE_PREVIEWED + voiceID, true); - } - public static void recordHasDateModified(boolean hasDateModified) { RecordHistogram.recordBooleanHistogram(HAS_DATE_MODIFIED, hasDateModified); }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefs.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefs.java index ded68fe..0605e81 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefs.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefs.java
@@ -51,7 +51,6 @@ if (language == null || language.isEmpty() || voiceId == null || voiceId.isEmpty()) { return; } - ReadAloudMetrics.recordVoiceChanged(voiceId); ReadAloudPrefsJni.get().setVoice(prefs, language, voiceId); }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefsUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefsUnitTest.java index 5ca0a6b..29d41f6 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefsUnitTest.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudPrefsUnitTest.java
@@ -82,19 +82,6 @@ } @Test - public void testSetVoice_metric() { - final String histogramName = ReadAloudMetrics.VOICE_CHANGED; - - var histogram = HistogramWatcher.newSingleRecordWatcher(histogramName + "abc", true); - ReadAloudPrefs.setVoice(mPrefService, "en", "abc"); - histogram.assertExpected(); - - histogram = HistogramWatcher.newSingleRecordWatcher(histogramName + "def", true); - ReadAloudPrefs.setVoice(mPrefService, "es", "def"); - histogram.assertExpected(); - } - - @Test public void testDefaultSpeed() { assertEquals(1f, ReadAloudPrefs.getSpeed(mPrefService), /* delta= */ 0f); }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 2fa78e59..60b8c2bf 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1773,11 +1773,9 @@ } #if !BUILDFLAG(IS_ANDROID) - // TODO(b:315076421): Remove "New" badge for preview. if (base::FeatureList::IsEnabled(blink::features::kLinkPreview)) { menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKPREVIEW, IDS_CONTENT_CONTEXT_OPENLINKPREVIEW); - menu_model_.SetIsNewFeatureAt(menu_model_.GetItemCount() - 1, true); // We don't show in-production-help for ChromeOS for now because we should // use a different trigger. // @@ -2036,10 +2034,6 @@ menu_model_.GetIndexOfCommandId(search_for_image_idc).value(); menu_model_.SetElementIdentifierAt(command_index, kSearchForImageItem); - if (companion::IsNewBadgeEnabledForSearchMenuItem(GetBrowser())) { - menu_model_.SetIsNewFeatureAt(menu_model_.GetItemCount() - 1, true); - } - MaybePrepareForLensQuery(); auto* service = TemplateURLServiceFactory::GetForProfile(GetProfile()); @@ -2112,7 +2106,6 @@ GetSearchForVideoFrameIdc(), l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHFORVIDEOFRAME, GetImageSearchProviderName(provider))); - menu_model_.SetIsNewFeatureAt(menu_model_.GetItemCount() - 1, true); MaybePrepareForLensQuery(); } } @@ -2368,9 +2361,6 @@ l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_SEARCHWEBFOR, default_provider->short_name(), printable_selection_text)); - if (companion::IsNewBadgeEnabledForSearchMenuItem(GetBrowser())) { - menu_model_.SetIsNewFeatureAt(menu_model_.GetItemCount() - 1, true); - } if (companion::IsSearchWebInCompanionSidePanelSupported(GetBrowser())) { // Add an "in new tab" item performing the non-side panel behavior. if (base::FeatureList::IsEnabled( @@ -2437,8 +2427,8 @@ // TODO(b/303646344): Remove new feature tag when no longer new. menu_model_.SetIsNewFeatureAt( menu_model_.GetItemCount() - 1, - GetBrowser()->window()->MaybeShowNewBadgeFor( - compose::features::kEnableCompose)); + UserEducationService::MaybeShowNewBadge( + GetBrowserContext(), compose::features::kEnableCompose)); render_separator = true; } } @@ -2700,10 +2690,6 @@ menu_model_.AddItem(region_search_idc, l10n_util::GetStringFUTF16( resource_id, GetImageSearchProviderName(provider))); - if (companion::IsNewBadgeEnabledForSearchMenuItem(GetBrowser())) { - menu_model_.SetIsNewFeatureAt(menu_model_.GetItemCount() - 1, true); - } - menu_model_.SetElementIdentifierAt( menu_model_.GetIndexOfCommandId(region_search_idc).value(), kRegionSearchItem);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc index e4a260d..874318d1 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
@@ -1980,110 +1980,6 @@ ASSERT_EQ(initial_num_processes, mock_rph_factory().GetProcesses()->size()); } -// Verify that the new badge is added to region search context menu items if -// appropriate feature is enabled. -TEST_F(RenderViewContextMenuPrefsTest, - CompanionNewBadgeEnabledForRegionSearchContextMenuItem) { - base::test::ScopedFeatureList features; - features.InitAndEnableFeature( - companion::features::kCompanionEnableNewBadgesInContextMenu); - SetUserSelectedDefaultSearchProvider("https://www.google.com", - /*supports_image_search=*/true); - content::ContextMenuParams params = CreateParams(MenuItem::PAGE); - TestRenderViewContextMenu menu(*web_contents()->GetPrimaryMainFrame(), - params); - menu.SetBrowser(GetBrowser()); - menu.Init(); - - size_t index = 0; - ui::MenuModel* model = nullptr; - - ASSERT_TRUE(menu.GetMenuModelAndItemIndex( - IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH, &model, &index)); - EXPECT_TRUE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH)); - EXPECT_TRUE(model->IsNewFeatureAt(index)); -} - -// Verify that the new badge is NOT added to region search context menu items if -// appropriate feature is disabled. -TEST_F(RenderViewContextMenuPrefsTest, - CompanionNewBadgeDisabledForRegionSearchContextMenuItem) { - base::test::ScopedFeatureList features; - features.InitAndDisableFeature( - companion::features::kCompanionEnableNewBadgesInContextMenu); - SetUserSelectedDefaultSearchProvider("https://www.google.com", - /*supports_image_search=*/true); - content::ContextMenuParams params = CreateParams(MenuItem::PAGE); - TestRenderViewContextMenu menu(*web_contents()->GetPrimaryMainFrame(), - params); - menu.SetBrowser(GetBrowser()); - menu.Init(); - - size_t index = 0; - ui::MenuModel* model = nullptr; - - ASSERT_TRUE(menu.GetMenuModelAndItemIndex( - IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH, &model, &index)); - EXPECT_TRUE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH)); - EXPECT_FALSE(model->IsNewFeatureAt(index)); -} - -// Verify that the new badge is added to image search context menu items if -// appropriate feature is enabled. -TEST_F(RenderViewContextMenuPrefsTest, - CompanionNewBadgeEnabledForImageSearchContextMenuItems) { - base::test::ScopedFeatureList features; - features.InitAndEnableFeature( - companion::features::kCompanionEnableNewBadgesInContextMenu); - SetUserSelectedDefaultSearchProvider("https://www.google.com", - /*supports_image_search=*/true); - content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); - params.has_image_contents = true; - TestRenderViewContextMenu menu(*web_contents()->GetPrimaryMainFrame(), - params); - menu.SetBrowser(GetBrowser()); - menu.Init(); - - size_t index = 0; - ui::MenuModel* model = nullptr; - - ASSERT_TRUE(menu.GetMenuModelAndItemIndex( - IDC_CONTENT_CONTEXT_SEARCHLENSFORIMAGE, &model, &index)); - EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE)); - EXPECT_TRUE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_SEARCHLENSFORIMAGE)); - EXPECT_TRUE(model->IsNewFeatureAt(index)); - EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATEIMAGEWITHWEB)); - EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATEIMAGEWITHLENS)); -} - -// Verify that the new badge is NOT added to image search context menu items if -// appropriate feature is disabled. -TEST_F(RenderViewContextMenuPrefsTest, - CompanionNewBadgeDisabledForImageSearchContextMenuItems) { - base::test::ScopedFeatureList features; - features.InitAndDisableFeature( - companion::features::kCompanionEnableNewBadgesInContextMenu); - SetUserSelectedDefaultSearchProvider("https://www.google.com", - /*supports_image_search=*/true); - content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); - params.has_image_contents = true; - TestRenderViewContextMenu menu(*web_contents()->GetPrimaryMainFrame(), - params); - menu.SetBrowser(GetBrowser()); - menu.Init(); - - size_t index = 0; - ui::MenuModel* model = nullptr; - - ASSERT_TRUE(menu.GetMenuModelAndItemIndex( - IDC_CONTENT_CONTEXT_SEARCHLENSFORIMAGE, &model, &index)); - EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE)); - EXPECT_TRUE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_SEARCHLENSFORIMAGE)); - EXPECT_FALSE(model->IsNewFeatureAt(index)); - EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATEIMAGEWITHWEB)); - EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATEIMAGEWITHLENS)); -} - // Verify that the Lens Region Search menu item is enabled for Progressive Web // Apps. Region Search on PWAs is currently broken and therefore disabled on // Mac. b/250074889
diff --git a/chrome/browser/resources/ash/settings/internet_page/internet_subpage.html b/chrome/browser/resources/ash/settings/internet_page/internet_subpage.html index 2cdfe58..705ec74 100644 --- a/chrome/browser/resources/ash/settings/internet_page/internet_subpage.html +++ b/chrome/browser/resources/ash/settings/internet_page/internet_subpage.html
@@ -1,9 +1,9 @@ <style include="cr-shared-style os-settings-icons settings-shared iron-flex"> #networkListDiv { - min-height: var(--cr-section-min-height); + min-height: var(--cr-section-two-line-min-height); } - :host(:not([is-showing-vpn_])) #networkListDiv { + :host(:not([is-showing-vpn_], [is-showing-tether_])) #networkListDiv { margin-top: var(--cr-section-vertical-margin); } @@ -44,7 +44,7 @@ } .no-networks { - margin: 4px; + min-height: var(--cr-section-two-line-min-height); } network-list { @@ -83,9 +83,8 @@ </style> <template is="dom-if" if="[[shouldShowBluetoothDisabledTetherErrorMessage_(deviceState)]]"> - <div id="networkListDiv" class="layout vertical flex"> + <div id="networkListDiv" class="layout horizontal center"> <localized-link - class="no-networks" localized-string="[[getBluetoothDisabledErrorMessageForTether_()]]"> </localized-link> </div> @@ -164,6 +163,7 @@ <div id="your-device-hotspots-title">$i18n{internetYourDeviceHotspots}</div> </template> <network-list id="networkList" show-buttons + class="layout horizontal center" show-technology-badge="[[showTechnologyBadge_]]" networks="[[networkStateList_]]" global-policy="[[globalPolicy]]" @@ -211,12 +211,13 @@ </template> <!-- Text shown if no networks exist. --> - <localized-link - class="no-networks" - hidden="[[hideNoNetworksMessage_(networkStateList_, deviceState)]]" - localized-string= - "[[getNoNetworksInnerHtml_(deviceState, tetherDeviceState)]]"> - </localized-link> + <template is="dom-if" if="[[!hideNoNetworksMessage_(networkStateList_, deviceState)]]"> + <div class="layout horizontal center no-networks"> + <localized-link + localized-string="[[getNoNetworksInnerHtml_(deviceState, tetherDeviceState)]]"> + </localized-link> + </div> + </template> <template is="dom-if" if="[[isShowingVpn_]]"> <!-- Third party VPNs. -->
diff --git a/chrome/browser/resources/ash/settings/internet_page/internet_subpage.ts b/chrome/browser/resources/ash/settings/internet_page/internet_subpage.ts index 90c4529..8c7fe70 100644 --- a/chrome/browser/resources/ash/settings/internet_page/internet_subpage.ts +++ b/chrome/browser/resources/ash/settings/internet_page/internet_subpage.ts
@@ -154,6 +154,12 @@ reflectToAttribute: true, }, + isShowingTether_: { + type: Boolean, + computed: 'computeIsShowingTether_(deviceState)', + reflectToAttribute: true, + }, + /** * Whether the browser/ChromeOS is managed by their organization * through enterprise policies. @@ -258,6 +264,7 @@ private hasCompletedScanSinceLastEnabled_: boolean; private isInstantHotspotRebrandEnabled_: boolean; private isManaged_: boolean; + private isShowingTether_: boolean; private isShowingVpn_: boolean; private networkConfig_: CrosNetworkConfigInterface; private networkStateList_: OncMojo.NetworkStateProperties[]; @@ -957,6 +964,13 @@ OncMojo.getNetworkTypeString(NetworkType.kVPN), this.deviceState); } + private computeIsShowingTether_(): boolean { + return !!this.deviceState && + this.matchesType_( + OncMojo.getNetworkTypeString(NetworkType.kTether), + this.deviceState); + } + /** * Tells when VPN preferences section should be displayed. It is * displayed when the preferences are applicable to the current device.
diff --git a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.html b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.html index 70608aa..b42651c 100644 --- a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.html +++ b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.html
@@ -20,7 +20,7 @@ <div id="pinSetupDialogSubtitle">[[getSubtitle_(isConfirmStep_)]]</div> <div id="setupPinKeyboardDiv" class="settings-box continuation"> <app-setup-pin-keyboard id="setupPinKeyboard" - is-confirm-step="{{isConfirmStep_}}"> + is-confirm-step="{{isConfirmStep_}}" prefs="{{prefs}}"> </app-setup-pin-keyboard> </div> </div>
diff --git a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.ts b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.ts index 5996ad7..00b19b33 100644 --- a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.ts +++ b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_dialog.ts
@@ -16,6 +16,8 @@ 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'; +import {Router, routes} from '../../router.js'; + import {getTemplate} from './app_setup_pin_dialog.html.js'; import {AppSetupPinKeyboardElement} from './app_setup_pin_keyboard.js'; @@ -42,12 +44,21 @@ /** * Whether the user is at the PIN confirmation step. */ - isConfirmStep_: {type: Boolean, value: false}, + isConfirmStep_: { + type: Boolean, + value: false, + }, }; } private isConfirmStep_: boolean; + override ready(): void { + super.ready(); + + this.addEventListener('set-app-pin-done', this.onSetPinDone_); + } + override connectedCallback(): void { super.connectedCallback(); @@ -66,23 +77,21 @@ private onCancelClick_(e: Event): void { // Stop propagation to keep the subpage from opening. e.stopPropagation(); - this.$.setupPinKeyboard.resetState(); this.close(); } private onPinSubmit_(e: Event): void { - // TODO(b/332936223): This method currently naively switches from the - // initial screen to the submit screen. It will be updated when the - // actual PIN setup flow is implemented. - // Stop propagation to keep the subpage from opening. e.stopPropagation(); - if (!this.isConfirmStep_) { - this.$.setupPinKeyboard.doSubmit(); - this.isConfirmStep_ = true; - } else { - this.close(); - } + this.$.setupPinKeyboard.doSubmit(); + } + + /** + * Called when the setup PIN keyboard successfully saves the PIN. + */ + private onSetPinDone_(): void { + this.close(); + Router.getInstance().navigateTo(routes.APP_PARENTAL_CONTROLS); } private getTitle_(isConfirmStep: boolean): string {
diff --git a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.html b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.html index 704c044d..ac13330 100644 --- a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.html +++ b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.html
@@ -1,5 +1,5 @@ <style include="settings-shared"> - #problemDiv { + #pinMismatchErrorDiv { align-items: center; display: flex; flex-direction: row; @@ -11,12 +11,15 @@ /* Hide this using 'visibility: hidden' instead of 'hidden' so that the dialog does not resize when there are no problems to display. */ - #problemDiv[invisible] { + #pinMismatchErrorDiv[invisible] { visibility: hidden; } </style> -<pin-keyboard id="pinKeyboard" value="{{pinKeyboardValue_}}"> - <div id="problemDiv"> - <!--TODO(b/332936223): Add problem message here.--> +<pin-keyboard id="pinKeyboard" on-submit="onPinSubmit_" + value="{{pinKeyboardValue_}}" disabled="[[isSetPinCallPending_]]"> + <div id="pinMismatchErrorDiv" invisible$="[[!showPinMismatchError_]]"> + <span aria-live="assertive"> + $i18n{appParentalControlsPinMismatchErrorText} + </span> </div> </pin-keyboard> \ No newline at end of file
diff --git a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.ts b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.ts index 493fd33d..0f0b9b7 100644 --- a/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.ts +++ b/chrome/browser/resources/ash/settings/os_apps_page/app_parental_controls/app_setup_pin_keyboard.ts
@@ -13,13 +13,14 @@ import 'chrome://resources/ash/common/cr_elements/cr_shared_vars.css.js'; import '../../settings_shared.css.js'; +import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {PinKeyboardElement} from 'chrome://resources/ash/common/quick_unlock/pin_keyboard.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './app_setup_pin_keyboard.html.js'; -const AppSetupPinKeyboardElementBase = I18nMixin(PolymerElement); +const AppSetupPinKeyboardElementBase = (PrefsMixin(I18nMixin(PolymerElement))); export interface AppSetupPinKeyboardElement { $: { @@ -62,12 +63,34 @@ type: String, value: '', }, + + /** + * Whether the pin is currently being set as a pref. + * If true, the pin keyboard input should be disabled. + */ + isSetPinCallPending_: { + notify: true, + type: Boolean, + value: false, + }, + + /** + * Whether the PIN mismatch error message should be shown after the user + * attempts to submit. + */ + showPinMismatchError_: { + notify: true, + type: Boolean, + value: false, + }, }; } isConfirmStep: boolean; private pinKeyboardValue_: string; private initialPin_: string; + private isSetPinCallPending_: boolean; + private showPinMismatchError_: boolean; override focus(): void { this.$.pinKeyboard.focusInput(); @@ -81,6 +104,22 @@ this.initialPin_ = ''; this.pinKeyboardValue_ = ''; this.isConfirmStep = false; + this.showPinMismatchError_ = false; + } + + /** + * Returns true if the user has re-entered the same PIN at the confirmation + * step. + */ + private isPinConfirmed_(): boolean { + return this.isConfirmStep && (this.initialPin_ === this.pinKeyboardValue_); + } + + /** + * Called when the user presses enter/return during PIN entry. + */ + private onPinSubmit_(): void { + this.doSubmit(); } /** @@ -88,14 +127,28 @@ * to submit the PIN. */ doSubmit(): void { - // TODO(b/332936223): Implement actual PIN submission logic. if (!this.isConfirmStep) { this.initialPin_ = this.pinKeyboardValue_; this.pinKeyboardValue_ = ''; - this.$.pinKeyboard.focusInput(); this.isConfirmStep = true; + this.$.pinKeyboard.focusInput(); return; } + + if (!this.isPinConfirmed_()) { + this.showPinMismatchError_ = true; + // Focus the PIN keyboard and highlight the entire PIN so the user can + // replace it. + this.$.pinKeyboard.focusInput(0, this.pinKeyboardValue_.length + 1); + return; + } + + this.isSetPinCallPending_ = true; + this.setPrefValue('on_device_app_controls.pin', this.pinKeyboardValue_); + this.setPrefValue('on_device_app_controls.setup_completed', true); + this.isSetPinCallPending_ = false; + + this.dispatchEvent(new Event('set-app-pin-done', {composed: true})); } }
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 c04a749c..1cb4356 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
@@ -38,7 +38,7 @@ "[[prefs.on_device_app_controls.setup_completed.value]]" on-click="onClickParentalControls_"> <iron-icon id="parentalControlsRowIcon" - icon="[[rowIcons_.manageApps]]"> + icon="[[rowIcons_.parentalControls]]"> </iron-icon> <div class="start settings-box-text"> $i18n{appParentalControlsTitle} @@ -70,19 +70,19 @@ <template is="dom-if" if="[[showParentalControlsSetupPinDialog_]]" restamp> <app-setup-pin-dialog id="setupPin" - on-close="onSetupPinDialogClose_"> + on-close="onSetupPinDialogClose_" prefs="{{prefs}}"> </app-setup-pin-dialog> </template> <template is="dom-if" if="[[showParentalControlsVerifyPinDialog_]]" restamp> <app-verify-pin-dialog id="verifyPin" - on-close="onVerifyPinDialogClose_"> + on-close="onVerifyPinDialogClose_"> </app-verify-pin-dialog> </template> <template is="dom-if" if="[[showParentalControlsDisablePinDialog_]]" restamp> <app-verify-pin-dialog id="disableDialog" - on-close="onDisablePinDialogClose_"> + on-close="onDisablePinDialogClose_"> </app-verify-pin-dialog> </template> </div>
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 037b67f..b7b5e121 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
@@ -245,6 +245,7 @@ androidSettings: 'os-settings:apps-android-settings', manageIsolatedWebApps: 'os-settings:apps-manage-isolated-web-apps', + parentalControls: 'os-settings:apps-parental-controls', }; } @@ -254,6 +255,7 @@ googlePlayPreferences: '', androidSettings: '', manageIsolatedWebApps: '', + parentalControls: '', }; }, }, @@ -392,10 +394,6 @@ private onSetupPinDialogClose_(): void { this.showParentalControlsSetupPinDialog_ = false; - // TODO(b/332936223): Only set setup pref to true and navigate to the - // subpage on PIN submission success. - this.setPrefValue('on_device_app_controls.setup_completed', true); - Router.getInstance().navigateTo(routes.APP_PARENTAL_CONTROLS); } private onClickManageIsolatedWebApps_(): void {
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/input_page.html b/chrome/browser/resources/ash/settings/os_languages_page/input_page.html index 62aaf75..cfd0753 100644 --- a/chrome/browser/resources/ash/settings/os_languages_page/input_page.html +++ b/chrome/browser/resources/ash/settings/os_languages_page/input_page.html
@@ -145,7 +145,7 @@ </settings-toggle-button> <div class="hr bottom-margin"> - <template is="dom-if" if="[[!shouldShowShortcutReminder_( + <template is="dom-if" if="[[shouldShowShortcutReminder_( shortcutReminderBody_.length)]]"> <keyboard-shortcut-banner header="$i18n{imeShortcutReminderTitle}" body="[[shortcutReminderBody_]]"
diff --git a/chrome/browser/resources/ash/settings/os_settings_icons.html b/chrome/browser/resources/ash/settings/os_settings_icons.html index 8c02dd1e..9be3bd74 100644 --- a/chrome/browser/resources/ash/settings/os_settings_icons.html +++ b/chrome/browser/resources/ash/settings/os_settings_icons.html
@@ -48,6 +48,9 @@ <g id="apps-manage-isolated-web-apps" viewBox="0 0 20 20"> <path fill-rule="evenodd" d="M3.646 16.396a2.02 2.02 0 0 1-1.458-.584 2.023 2.023 0 0 1-.584-1.458V5.625c0-.57.195-1.049.583-1.437a2.023 2.023 0 0 1 1.459-.584h12.708c.57 0 1.049.202 1.438.604.402.39.604.868.604 1.438v8.729a1.92 1.92 0 0 1-.604 1.438 1.953 1.953 0 0 1-1.438.583H3.646Zm0-2.042h8.208v-2.5H3.646v2.5Zm9.708 0h3v-6.5h-3v6.5Zm-9.708-4h8.208v-2.5H3.646v2.5Z"></path> </g> + <g id="apps-parental-controls" viewBox="0 -960 960 960"> + <path fill-rule="evenodd" d="M480-48q-182.62 0-307.31-67T48-281.81Q48-350 112-406t176-86v75q-77 23-122.5 59.83T120-282.48Q120-217 227.5-168.5T480-120q145 0 252.5-48.73T840-282.44Q840-320 794.5-357T672-417v-75q111 29 175.5 85.69 64.5 56.7 64.5 124.73Q912-182 787.31-115 662.62-48 480-48ZM360-192v-408H192v-72h576v72H600v408h-72v-192h-96v192h-72Zm119.75-540q-34.75 0-59.25-24.75t-24.5-59.5q0-34.75 24.75-59.25t59.5-24.5q34.75 0 59.25 24.75t24.5 59.5q0 34.75-24.75 59.25t-59.5 24.5Z"></path> + </g> <!-- About page section --> <g id="counter-1">
diff --git a/chrome/browser/resources/commerce/product_specifications/app.html b/chrome/browser/resources/commerce/product_specifications/app.html index e548a45..d5602c9 100644 --- a/chrome/browser/resources/commerce/product_specifications/app.html +++ b/chrome/browser/resources/commerce/product_specifications/app.html
@@ -72,7 +72,7 @@ </style> <product-specifications-header id="header" subtitle="[[setName_]]" on-add-to-new-group-click="addToNewGroup_" - on-delete-click="removeSet_" + on-delete-click="deleteSet_" on-name-change="updateSetName_" on-see-all-click="seeAllSets_"> </product-specifications-header> @@ -90,7 +90,8 @@ id="summaryTable" columns="[[specsTable_.columns]]" rows="[[specsTable_.rows]]" - on-url-change="onUrlChange_"> + on-url-change="onUrlChange_" + on-url-remove="onUrlRemove_"> </product-specifications-table> <new-column-selector on-selected-url-change="onUrlAdd_"> </new-column-selector>
diff --git a/chrome/browser/resources/commerce/product_specifications/app.ts b/chrome/browser/resources/commerce/product_specifications/app.ts index 8c2faca3..b82ed3b 100644 --- a/chrome/browser/resources/commerce/product_specifications/app.ts +++ b/chrome/browser/resources/commerce/product_specifications/app.ts
@@ -85,6 +85,7 @@ private shoppingApi_: BrowserProxy = BrowserProxyImpl.getInstance(); private callbackRouter_: PageCallbackRouter; private listenerIds_: number[] = []; + private id_: Uuid|null = null; constructor() { super(); @@ -105,6 +106,7 @@ const params = new URLSearchParams(router.getCurrentQuery()); const idParam = params.get('id'); if (idParam) { + this.id_ = {value: idParam}; const {set} = await this.shoppingApi_.getProductSpecificationsSetByUuid( {value: idParam}); if (set) { @@ -126,12 +128,12 @@ return; } - // TODO(b/338427523): Add UI for choosing the name. const setName = 'Product specs'; this.setName_ = setName; const {createdSet} = await this.shoppingApi_.addProductSpecificationsSet( setName, urls.map(url => ({url}))); if (createdSet) { + this.id_ = createdSet.uuid; window.history.replaceState( undefined, '', '?id=' + createdSet.uuid.value); } @@ -140,31 +142,32 @@ } private async populateTable_(urls: string[]) { - const {productSpecs} = - await this.shoppingApi_.getProductSpecificationsForUrls( - urls.map(url => ({url}))); - + let aggregatedDatas: Record<string, AggregatedProductData> = {}; const rows: TableRow[] = []; - productSpecs.productDimensionMap.forEach((value: string, key: bigint) => { - rows.push({ - title: value, - values: productSpecs.products.map( - (p: ProductSpecificationsProduct) => - p.productDimensionValues.get(key)!.join(',')), + if (urls.length) { + const {productSpecs} = + await this.shoppingApi_.getProductSpecificationsForUrls( + urls.map(url => ({url}))); + productSpecs.productDimensionMap.forEach((value: string, key: bigint) => { + rows.push({ + title: value, + values: productSpecs.products.map( + (p: ProductSpecificationsProduct) => + p.productDimensionValues.get(key)!.join(',')), + }); }); - }); + const infos = await this.getInfoForUrls_(urls); + aggregatedDatas = + aggregateProductDataByClusterId(infos, productSpecs.products); + } - const infos = await this.getInfoForUrls_(urls); - const aggregatedDatas = - aggregateProductDataByClusterId(infos, productSpecs.products); this.specsTable_ = { columns: Object.values(aggregatedDatas).map((data: AggregatedProductData) => { return { selectedItem: { title: data.spec ? data.spec.title : '', - // TODO(b/335637140): Replace with actual URL once available. - url: 'https://example.com', + url: data.info.productUrl.url, imageUrl: data.info.imageUrl.url, }, }; @@ -195,7 +198,9 @@ } private deleteSet_() { - // TODO(b/330345730): Plumb through mojom + if (this.id_) { + this.shoppingApi_.deleteProductSpecificationsSet(this.id_); + } } private updateSetName_(_: CustomEvent<{name: string}>) { @@ -209,30 +214,49 @@ private onUrlAdd_(e: CustomEvent<{url: string}>) { const urls = this.getTableUrls_(); urls.push(e.detail.url); + // TODO(b/330345730): Plumb through mojom instead of calling populateTable + // directly. Then, onSetUpdated should handle the table change. this.populateTable_(urls); } private onUrlChange_(e: CustomEvent<{url: string, index: number}>) { const urls = this.getTableUrls_(); urls[e.detail.index] = e.detail.url; + // TODO(b/330345730): Plumb through mojom instead of calling populateTable + // directly. Then, onSetUpdated should handle the table change. + this.populateTable_(urls); + } + + private onUrlRemove_(e: CustomEvent<{index: number}>) { + const urls = this.getTableUrls_(); + urls.splice(e.detail.index, 1); + // TODO(b/330345730): Plumb through mojom instead of calling populateTable + // directly. Then, onSetUpdated should handle the table change. this.populateTable_(urls); } private getTableUrls_(): string[] { - // Until b/335637140 is resolved, these will all be the same placeholder - // URL and the table will not update as expected. return this.specsTable_.columns.map( (column: TableColumn) => column.selectedItem.url); } - private onSetUpdated_(_: ProductSpecificationsSet) { - // TODO(b:333378234): If the update is for the currently shown set, apply - // the updates. + private onSetUpdated_(set: ProductSpecificationsSet) { + if (set.uuid.value !== this.id_?.value) { + return; + } + this.setName_ = set.name; + this.populateTable_(set.urls.map(url => url.url)); } - private onSetRemoved_(_: Uuid) { - // TODO(b:333378234): If the UUID is for the shown set, clear the UI or - // refresh to load the zero-state. + private onSetRemoved_(id: Uuid) { + if (id.value !== this.id_?.value) { + return; + } + this.id_ = null; + this.specsTable_ = { + columns: [], + rows: [], + }; } }
diff --git a/chrome/browser/resources/commerce/product_specifications/images/icons.html b/chrome/browser/resources/commerce/product_specifications/images/icons.html index fc65ca2..a293c77 100644 --- a/chrome/browser/resources/commerce/product_specifications/images/icons.html +++ b/chrome/browser/resources/commerce/product_specifications/images/icons.html
@@ -13,6 +13,9 @@ <g id="delete"> <path d="m11.9 13.5 2.1-2.1 2.1 2.1 1.4-1.4-2.1-2.1 2.1-2.1-1.4-1.4L14 8.6l-2.1-2.1-1.4 1.4 2.1 2.1-2.1 2.1zM8 18a1.99 1.99 0 0 1-1.425-.575A1.99 1.99 0 0 1 6 16V4c0-.55.192-1.017.575-1.4.4-.4.875-.6 1.425-.6h12c.55 0 1.017.2 1.4.6.4.383.6.85.6 1.4v12c0 .55-.2 1.025-.6 1.425-.383.383-.85.575-1.4.575zm0-2h12V4H8zm-4 6a1.99 1.99 0 0 1-1.425-.575A1.99 1.99 0 0 1 2 20V6h2v14h14v2zM8 4v12z"></path> </g> + <g id="remove"> + <path d="M7 13h10v-2H7zm5 9a9.873 9.873 0 0 1-3.9-.775 10.274 10.274 0 0 1-3.175-2.15c-.9-.9-1.617-1.958-2.15-3.175A9.873 9.873 0 0 1 2 12c0-1.383.258-2.683.775-3.9a10.275 10.275 0 0 1 2.15-3.175c.9-.9 1.958-1.608 3.175-2.125A9.607 9.607 0 0 1 12 2c1.383 0 2.683.267 3.9.8a9.927 9.927 0 0 1 3.175 2.125c.9.9 1.608 1.958 2.125 3.175.533 1.217.8 2.517.8 3.9a9.607 9.607 0 0 1-.8 3.9 9.927 9.927 0 0 1-2.125 3.175c-.9.9-1.958 1.617-3.175 2.15A9.873 9.873 0 0 1 12 22m0-2c2.233 0 4.125-.775 5.675-2.325C19.225 16.125 20 14.233 20 12c0-2.233-.775-4.125-2.325-5.675C16.125 4.775 14.233 4 12 4c-2.233 0-4.125.775-5.675 2.325C4.775 7.875 4 9.767 4 12c0 2.233.775 4.125 2.325 5.675C7.875 19.225 9.767 20 12 20"></path> + </g> </defs> </svg> </iron-iconset-svg> \ No newline at end of file
diff --git a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html index 9cad807..82f6388 100644 --- a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html +++ b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.html
@@ -14,6 +14,13 @@ padding: 6px 16px; } + hr { + background: var(--color-product-specifications-divider); + border: none; + height: 1px; + margin: 0; + } + .dropdown-item { padding: 0 16px; } @@ -44,6 +51,17 @@ padding: 12px; width: var(--product-selector-width); } + + #remove { + --icon-size: 16px; + --iron-icon-height: var(--icon-size); + --iron-icon-width: var(--icon-size); + color: var(--cr-secondary-text-color); + font-weight: 400; + font-size: 12px; + gap: 8px; + padding: 16px; + } </style> <cr-lazy-render id="menu"> @@ -71,6 +89,14 @@ </template> <div id="empty" hidden="[[sections]]">$i18n{emptyMenu}</div> </div> + <template is="dom-if" if="[[selectedUrl.length]]"> + <hr> + <button id="remove" class="dropdown-item" role="menuitem" + on-click="onRemoveClick_"> + <cr-icon icon="product-specifications:remove"></cr-icon> + $i18n{removeColumn} + </button> + </template> </cr-action-menu> </template> </cr-lazy-render>
diff --git a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts index 4a43202..b89a9a11 100644 --- a/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts +++ b/chrome/browser/resources/commerce/product_specifications/product_selection_menu.ts
@@ -123,6 +123,14 @@ })); } + private onRemoveClick_() { + this.close(); + this.dispatchEvent(new CustomEvent('remove-url', { + bubbles: true, + composed: true, + })); + } + private onClose_() { this.dispatchEvent(new CustomEvent('close-menu', { bubbles: true,
diff --git a/chrome/browser/resources/commerce/product_specifications/product_selector.html b/chrome/browser/resources/commerce/product_specifications/product_selector.html index 92c17564..e04c795 100644 --- a/chrome/browser/resources/commerce/product_specifications/product_selector.html +++ b/chrome/browser/resources/commerce/product_specifications/product_selector.html
@@ -77,6 +77,6 @@ </div> <product-selection-menu id="productSelectionMenu" - selected-url="[[selectedItem.url]]" + selected-url="[[getSelectedUrl_(selectedItem)]]" on-close-menu="onCloseMenu_"> </product-selection-menu>
diff --git a/chrome/browser/resources/commerce/product_specifications/product_selector.ts b/chrome/browser/resources/commerce/product_specifications/product_selector.ts index 5ae26d2..57aeb11 100644 --- a/chrome/browser/resources/commerce/product_specifications/product_selector.ts +++ b/chrome/browser/resources/commerce/product_specifications/product_selector.ts
@@ -63,6 +63,10 @@ private getUrl_(item: UrlListEntry) { return getAbbreviatedUrl(item.url); } + + private getSelectedUrl_() { + return this.selectedItem?.url ?? ''; + } } declare global {
diff --git a/chrome/browser/resources/commerce/product_specifications/table.html b/chrome/browser/resources/commerce/product_specifications/table.html index 84fd9d0..e277ff0 100644 --- a/chrome/browser/resources/commerce/product_specifications/table.html +++ b/chrome/browser/resources/commerce/product_specifications/table.html
@@ -50,7 +50,8 @@ <th class="col"> <product-selector selected-item="[[column.selectedItem]]" - on-selected-url-change="onSelectedUrlChange_"> + on-selected-url-change="onSelectedUrlChange_" + on-remove-url="onUrlRemove_"> </product-selector> <div id="imgContainer"> <img is="cr-auto-img"
diff --git a/chrome/browser/resources/commerce/product_specifications/table.ts b/chrome/browser/resources/commerce/product_specifications/table.ts index c4e919c..0e739372 100644 --- a/chrome/browser/resources/commerce/product_specifications/table.ts +++ b/chrome/browser/resources/commerce/product_specifications/table.ts
@@ -63,6 +63,16 @@ }, })); } + + private onUrlRemove_(e: DomRepeatEvent<TableColumn>) { + this.dispatchEvent(new CustomEvent('url-remove', { + bubbles: true, + composed: true, + detail: { + index: e.model.index, + }, + })); + } } declare global {
diff --git a/chrome/browser/resources/lens/overlay/post_selection_renderer.html b/chrome/browser/resources/lens/overlay/post_selection_renderer.html index d69fa8e..26b1860 100644 --- a/chrome/browser/resources/lens/overlay/post_selection_renderer.html +++ b/chrome/browser/resources/lens/overlay/post_selection_renderer.html
@@ -32,9 +32,11 @@ } #postSelection { + background-color: #151C26; height: var(--selection-height); left: var(--selection-left); margin: auto; + opacity: 5%; position: absolute; top: var(--selection-top); width: var(--selection-width);
diff --git a/chrome/browser/resources/lens/overlay/selection_overlay.html b/chrome/browser/resources/lens/overlay/selection_overlay.html index f7b5688..bf1d567 100644 --- a/chrome/browser/resources/lens/overlay/selection_overlay.html +++ b/chrome/browser/resources/lens/overlay/selection_overlay.html
@@ -65,6 +65,12 @@ opacity: 0; } + #defaultScrim { + background-color: #151C26; + opacity: 5%; + pointer-events: none; + } + #selectionElements > * { inset: 0; position: absolute; @@ -165,6 +171,7 @@ background image. --> <div id="selectionElements"> <!-- Other elements that need to be bounded to the image go here --> + <div id="defaultScrim"></div> <overlay-shimmer id="overlayShimmer"></overlay-shimmer> <post-selection-renderer id="postSelectionRenderer" screenshot-data-uri="[[screenshotDataUri]]">
diff --git a/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts b/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts index a74b3024..f291ec5d 100644 --- a/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts +++ b/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts
@@ -10,7 +10,6 @@ openBatterySaverFeedbackDialog(): void; openMemorySaverFeedbackDialog(): void; openSpeedFeedbackDialog(): void; - onDiscardRingTreatmentEnabledChanged(): void; validateTabDiscardExceptionRule(rule: string): Promise<boolean>; } @@ -35,10 +34,6 @@ chrome.send('openSpeedFeedbackDialog'); } - onDiscardRingTreatmentEnabledChanged() { - chrome.send('onDiscardRingTreatmentEnabledChanged'); - } - validateTabDiscardExceptionRule(rule: string) { return sendWithPromise('validateTabDiscardExceptionRule', rule); }
diff --git a/chrome/browser/resources/settings/performance_page/performance_page.ts b/chrome/browser/resources/settings/performance_page/performance_page.ts index ea95792..eb94a98f 100644 --- a/chrome/browser/resources/settings/performance_page/performance_page.ts +++ b/chrome/browser/resources/settings/performance_page/performance_page.ts
@@ -18,8 +18,6 @@ import type {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; import {loadTimeData} from '../i18n_setup.js'; -import type {PerformanceBrowserProxy} from './performance_browser_proxy.js'; -import {PerformanceBrowserProxyImpl} from './performance_browser_proxy.js'; import type {PerformanceMetricsProxy} from './performance_metrics_proxy.js'; import {MemorySaverModeAggressiveness, MemorySaverModeState, PerformanceMetricsProxyImpl} from './performance_metrics_proxy.js'; import {getTemplate} from './performance_page.html.js'; @@ -96,8 +94,6 @@ private numericUncheckedValues_: MemorySaverModeState[]; private numericCheckedValue_: MemorySaverModeState[]; - private browserProxy_: PerformanceBrowserProxy = - PerformanceBrowserProxyImpl.getInstance(); private metricsProxy_: PerformanceMetricsProxy = PerformanceMetricsProxyImpl.getInstance(); @@ -131,7 +127,6 @@ } private onDiscardRingChange_() { - this.browserProxy_.onDiscardRingTreatmentEnabledChanged(); this.metricsProxy_.recordDiscardRingTreatmentEnabledChanged( this.getPref<boolean>(DISCARD_RING_PREF).value); }
diff --git a/chrome/browser/resources/webui_gallery/BUILD.gn b/chrome/browser/resources/webui_gallery/BUILD.gn index 3be5dc0..b670e20 100644 --- a/chrome/browser/resources/webui_gallery/BUILD.gn +++ b/chrome/browser/resources/webui_gallery/BUILD.gn
@@ -19,6 +19,9 @@ "demos/buttons/buttons_demo.css", "demos/card/card_demo.css", "demos/cr_action_menu/cr_action_menu_demo.css", + "demos/cr_dialog/cr_dialog_demo.css", + "demos/cr_icons/cr_icons_demo.css", + "demos/cr_input/cr_input_demo.css", "demos/demo.css", "demos/demo_lit.css", ]
diff --git a/chrome/browser/resources/webui_gallery/app.html b/chrome/browser/resources/webui_gallery/app.html index c509a65..ee7b2f8 100644 --- a/chrome/browser/resources/webui_gallery/app.html +++ b/chrome/browser/resources/webui_gallery/app.html
@@ -52,7 +52,9 @@ on-iron-select="onMenuItemSelect_"> <template is="dom-repeat" items="[[demos_]]"> <a role="menuitem" href="[[item.path]]" - class="cr-nav-menu-item">[[item.name]]</a> + class="cr-nav-menu-item" on-click="onMenuItemClick_"> + [[item.name]] + </a> </template> </cr-menu-selector>
diff --git a/chrome/browser/resources/webui_gallery/app.ts b/chrome/browser/resources/webui_gallery/app.ts index 50986544..894463f 100644 --- a/chrome/browser/resources/webui_gallery/app.ts +++ b/chrome/browser/resources/webui_gallery/app.ts
@@ -185,6 +185,13 @@ private onMenuItemSelect_(e: CustomEvent<{item: HTMLAnchorElement}>): void { const newUrl = new URL(e.detail.item.href); CrRouter.getInstance().setPath(newUrl.pathname); + this.onPathChanged_(newUrl.pathname); + } + + // Prevent clicks on sidebar items from navigating and therefore reloading + // the page. onMenuItemSelect_() handles loading new demos when selected. + private onMenuItemClick_(e: MouseEvent) { + e.preventDefault(); } private async onPathChanged_(newPath: string) {
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.html index e4a39c3..4520617 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.html +++ b/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.html
@@ -1,6 +1,3 @@ -<style include="demo"> -</style> - <h1>cr-chip</h1> <div class="demos"> <cr-chip>
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.ts b/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.ts index 76f70a5..8cb88da 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.ts +++ b/chrome/browser/resources/webui_gallery/demos/cr_chip/cr_chip_demo.ts
@@ -5,19 +5,24 @@ import '//resources/cr_elements/cr_chip/cr_chip.js'; import '//resources/cr_elements/cr_icon/cr_icon.js'; import '//resources/cr_elements/icons_lit.html.js'; -import '../demo.css.js'; -import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; -import {getTemplate} from './cr_chip_demo.html.js'; +import {getCss} from '../demo_lit.css.js'; -class CrChipDemoElement extends PolymerElement { +import {getHtml} from './cr_chip_demo.html.js'; + +export class CrChipDemoElement extends CrLitElement { static get is() { return 'cr-chip-demo'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); + } + + override render() { + return getHtml.bind(this)(); } }
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.css b/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.css new file mode 100644 index 0000000..eceb21f --- /dev/null +++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.css
@@ -0,0 +1,28 @@ +/* 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. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #import=../demo_lit.css.js + * #scheme=relative + * #include=demo-lit + * #css_wrapper_metadata_end */ + +cr-input:first-of-type { + margin-block-start: 16px; +} + +[slot='header'] { + padding: 0 20px 16px; +} + +cr-dialog::part(body-container) { + max-height: 300px; +} + +#tallBlock { + background: var(--google-grey-200); + height: 800px; + margin: 16px 0; +}
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.html index 439da758..bd81b35 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.html +++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.html
@@ -1,76 +1,64 @@ -<style include="demo"> - cr-input:first-of-type { - margin-block-start: 16px; - } - - [slot='header'] { - padding: 0 20px 16px; - } - - cr-dialog::part(body-container) { - max-height: 300px; - } - - #tallBlock { - background: var(--google-grey-200); - height: 800px; - margin: 16px 0; - } -</style> - <h1>cr-dialog</h1> <div class="demos"> - <cr-checkbox checked="{{showHeader_}}">Show header</cr-checkbox> - <cr-checkbox checked="{{showFooter_}}">Show footer</cr-checkbox> - <cr-checkbox checked="{{showScrollingBody_}}"> + <cr-checkbox ?checked="${this.showHeader_}" + @checked-changed="${this.onShowHeaderChanged_}">Show header</cr-checkbox> + <cr-checkbox ?checked="${this.showFooter_}" + @checked-changed="${this.onShowFooterChanged_}">Show footer</cr-checkbox> + <cr-checkbox ?checked="${this.showScrollingBody_}" + @checked-changed="${this.onShowScrollingBodyChanged_}"> Show tall scrolling body </cr-checkbox> - <cr-checkbox checked="{{showInputs_}}">Show inputs</cr-checkbox> - <cr-checkbox checked="{{autofocusInput_}}" disabled$="[[!showInputs_]]"> + <cr-checkbox ?checked="${this.showInputs_}" + @checked-changed="${this.onShowInputsChanged_}"> + Show inputs + </cr-checkbox> + <cr-checkbox ?checked="${this.autofocusInput_}" + @checked-changed="${this.onAutofocusInputChanged_}" + ?disabled="${!this.showInputs_}"> Autofocus input when dialog opens </cr-checkbox> - <cr-button on-click="openDialog_">Open dialog</cr-button> + <cr-button @click="${this.openDialog_}">Open dialog</cr-button> <div> - <template is="dom-repeat" items="[[statusTexts_]]"> - <div>[[item]]</div> - </template> + ${this.statusTexts_.map(item => html` + <div>${item}</div> + `)} </div> </div> -<template is="dom-if" if="[[isDialogOpen_]]" restamp> +${this.isDialogOpen_ ? html` <cr-dialog id="dialog" - on-cr-dialog-open="onOpenDialog_" - on-cancel="onCancelDialog_" - on-close="onCloseDialog_" + @cr-dialog-open="${this.onOpenDialog_}" + @cancel="${this.onCancelDialog_}" + @close="${this.onCloseDialog_}" show-on-attach> <div slot="title">Dialog title</div> - <div slot="header" hidden$="[[!showHeader_]]"> + <div slot="header" ?hidden="${!this.showHeader_}"> Dialogs can also include a header between the title and the body. It is commonly used to display status updates or tabs. </div> <div slot="body"> <div>Here is where some description text would go.</div> - <div hidden$="[[!showInputs_]]"> - <cr-input label="Example input" autofocus$="[[autofocusInput_]]"> + <div ?hidden="${!this.showInputs_}"> + <cr-input label="Example input" ?autofocus="${this.autofocusInput_}"> </cr-input> <cr-input label="Example input"></cr-input> </div> - <div hidden$="[[!showScrollingBody_]]"> + <div ?hidden="${!this.showScrollingBody_}"> <div id="tallBlock"></div> </div> </div> <div slot="button-container"> - <cr-button class="cancel-button" on-click="onClickCancel_"> + <cr-button class="cancel-button" @click="${this.onClickCancel_}"> Cancel </cr-button> - <cr-button class="action-button" on-click="onClickConfirm_"> + <cr-button class="action-button" @click="${this.onClickConfirm_}"> Confirm </cr-button> </div> - <div slot="footer" hidden$="[[!showFooter_]]"> + <div slot="footer" ?hidden="${!this.showFooter_}"> Dialogs also have a slot for text or other elements in the footer. </div> </cr-dialog> -</template> +` : ''}
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.ts b/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.ts index 333eb711..a9668c0 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.ts +++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog/cr_dialog_demo.ts
@@ -10,80 +10,105 @@ import '../demo.css.js'; import type {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.js'; -import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; -import {getTemplate} from './cr_dialog_demo.html.js'; +import {getCss} from './cr_dialog_demo.css.js'; +import {getHtml} from './cr_dialog_demo.html.js'; -interface CrDialogDemoElement { +export interface CrDialogDemoElement { $: { dialog: CrDialogElement, }; } -class CrDialogDemoElement extends PolymerElement { +export class CrDialogDemoElement extends CrLitElement { static get is() { return 'cr-dialog-demo'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); } - static get properties() { + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { return { - autofocusInputs_: Boolean, - isDialogOpen_: Boolean, - showHeader_: Boolean, - showFooter_: Boolean, - showInputs_: Boolean, - showScrollingBody_: Boolean, - statusTexts_: Array, + autofocusInput_: {type: Boolean}, + isDialogOpen_: {type: Boolean}, + showHeader_: {type: Boolean}, + showFooter_: {type: Boolean}, + showInputs_: {type: Boolean}, + showScrollingBody_: {type: Boolean}, + statusTexts_: {type: Array}, }; } - private autofocusInputs_: boolean = false; - private isDialogOpen_: boolean = false; - private showHeader_: boolean = false; - private showFooter_: boolean = false; - private showInputs_: boolean = false; - private showScrollingBody_: boolean = false; - private statusTexts_: string[] = []; + protected autofocusInput_: boolean = false; + protected isDialogOpen_: boolean = false; + protected showHeader_: boolean = false; + protected showFooter_: boolean = false; + protected showInputs_: boolean = false; + protected showScrollingBody_: boolean = false; + protected statusTexts_: string[] = []; private getDialog_(): CrDialogElement|null { return this.shadowRoot!.querySelector('cr-dialog'); } - private openDialog_() { + protected openDialog_() { this.isDialogOpen_ = true; } - private onClickCancel_() { + protected onClickCancel_() { const dialog = this.getDialog_(); if (dialog) { dialog.cancel(); } } - private onClickConfirm_() { + protected onClickConfirm_() { const dialog = this.getDialog_(); if (dialog) { dialog.close(); } } - private onOpenDialog_() { + protected onOpenDialog_() { this.statusTexts_ = ['Dialog was opened and fired a `cr-dialog-open` event.']; } - private onCancelDialog_() { - this.push( - 'statusTexts_', 'Dialog was canceled and fired a `cancel` event.'); + protected onCancelDialog_() { + this.statusTexts_.push('Dialog was canceled and fired a `cancel` event.'); + this.requestUpdate(); } - private onCloseDialog_() { + protected onCloseDialog_() { this.isDialogOpen_ = false; - this.push('statusTexts_', 'Dialog was closed and fired a `close` event.'); + this.statusTexts_.push('Dialog was closed and fired a `close` event.'); + } + + protected onShowHeaderChanged_(e: CustomEvent<{value: boolean}>) { + this.showHeader_ = e.detail.value; + } + + protected onShowFooterChanged_(e: CustomEvent<{value: boolean}>) { + this.showFooter_ = e.detail.value; + } + + protected onShowScrollingBodyChanged_(e: CustomEvent<{value: boolean}>) { + this.showScrollingBody_ = e.detail.value; + } + + protected onShowInputsChanged_(e: CustomEvent<{value: boolean}>) { + this.showInputs_ = e.detail.value; + } + + protected onAutofocusInputChanged_(e: CustomEvent<{value: boolean}>) { + this.autofocusInput_ = e.detail.value; } }
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.css b/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.css new file mode 100644 index 0000000..2ca8ef85 --- /dev/null +++ b/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.css
@@ -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. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #import=../demo_lit.css.js + * #scheme=relative + * #include=demo-lit + * #css_wrapper_metadata_end */ + +.icons { + display: grid; + font-size: 11px; + gap: 12px; + grid-auto-rows: 75px; + grid-template-columns: repeat(auto-fill, 75px); + text-align: center; + width: 100%; +} + +.icon { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center; +} + +.icon cr-icon, +.icon .cr-icon { + margin-block-end: 12px; +} + +.label { + height: 30%; +} + +cr-input { + --cr-input-error-display: none; +}
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.html index f81e1a7..90c7128 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.html +++ b/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.html
@@ -1,49 +1,17 @@ -<style include="cr-icons demo"> - .icons { - display: grid; - font-size: 11px; - gap: 12px; - grid-auto-rows: 75px; - grid-template-columns: repeat(auto-fill, 75px); - text-align: center; - width: 100%; - } - - .icon { - align-items: center; - display: flex; - flex-direction: column; - justify-content: center; - } - - .icon cr-icon, - .icon .cr-icon { - margin-block-end: 12px; - } - - .label { - height: 30%; - } - - cr-input { - --cr-input-error-display: none; - } -</style> - <h1>cr-icons from the common cr-iconsets defined in icons_lit.html</h1> <div class="demos"> <div>Commonly used cr-icons across WebUI built with SVG.</div> - <div class="icons" style$=" - --iron-icon-fill-color: [[iconColor_]]; - --iron-icon-height: [[iconSize_]]px; - --iron-icon-width: [[iconSize_]]px; + <div class="icons" .style=" + --iron-icon-fill-color: ${this.iconColor_}; + --iron-icon-height: ${this.iconSize_}px; + --iron-icon-width: ${this.iconSize_}px; "> - <template is="dom-repeat" items="[[icons_]]" as="icon"> + ${this.icons_.map(icon => html` <div class="icon"> - <cr-icon icon="[[icon]]"></cr-icon> - <div class="label">[[icon]]</div> + <cr-icon icon="${icon}"></cr-icon> + <div class="label">${icon}</div> </div> - </template> + `)} </div> </div> @@ -57,10 +25,10 @@ </defs> </svg> </cr-iconset> - <div class="icons" style$=" - --iron-icon-fill-color: [[iconColor_]]; - --iron-icon-height: [[iconSize_]]px; - --iron-icon-width: [[iconSize_]]px; + <div class="icons" .style=" + --iron-icon-fill-color: ${this.iconColor_}; + --iron-icon-height: ${this.iconSize_}px; + --iron-icon-width: ${this.iconSize_}px; "> <div class="icon"> <cr-icon icon="desserts:cake"></cr-icon> @@ -72,27 +40,29 @@ <h1>CSS classes for icons, defined in cr_icons.css</h1> <div class="demos"> <div>CSS classes to display icons, typically for cr-icon-button.</div> - <div class="icons" style$=" - --cr-icon-color: [[iconColor_]]; - --cr-icon-ripple-size: [[iconSize_]]px; - --cr-icon-size: [[iconSize_]]px; + <div class="icons" .style=" + --cr-icon-color: ${this.iconColor_}; + --cr-icon-ripple-size: ${this.iconSize_}px; + --cr-icon-size: ${this.iconSize_}px; "> - <template is="dom-repeat" items="[[crIcons_]]" as="icon"> + ${this.crIcons_.map(icon => html` <div class="icon"> - <div class$="cr-icon no-overlap [[icon]]"></div> - <div class="label">.[[icon]]</div> + <div class="cr-icon no-overlap ${icon}"></div> + <div class="label">.${icon}</div> </div> - </template> + `)} </div> </div> <h1>Custom controls</h1> <div class="demos"> - <cr-input type="number" min="12" max="128" value="{{iconSize_}}" + <cr-input type="number" min="12" max="128" .value="${this.iconSize_}" + @value-changed="${this.onIconSizeChanged_}" label="Icon size"></cr-input> <label> - <input type="color" value="[[iconColor_]]" on-input="onIconColorInput_"> + <input type="color" .value="${this.iconColor_}" + @input="${this.onIconColorInput_}"> Icon fill color </label> </div>
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.ts b/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.ts index 0015cb58..cf5d6d5 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.ts +++ b/chrome/browser/resources/webui_gallery/demos/cr_icons/cr_icons_demo.ts
@@ -11,29 +11,34 @@ import type {CrIconsetElement} from '//resources/cr_elements/cr_icon/cr_iconset.js'; import {assert} from '//resources/js/assert.js'; -import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; -import {getTemplate} from './cr_icons_demo.html.js'; +import {getCss} from './cr_icons_demo.css.js'; +import {getHtml} from './cr_icons_demo.html.js'; -class CrIconsDemoElement extends PolymerElement { +export class CrIconsDemoElement extends CrLitElement { static get is() { return 'cr-icons-demo'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); } - static get properties() { + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { return { - crIcons_: Array, - iconColor_: String, - iconSize_: String, - icons_: Array, + crIcons_: {type: Array}, + iconColor_: {type: String}, + iconSize_: {type: String}, + icons_: {type: Array}, }; } - private crIcons_: string[] = [ + protected crIcons_: string[] = [ 'icon-arrow-back', 'icon-arrow-dropdown', 'icon-cancel', 'icon-clear', 'icon-copy-content', 'icon-delete-gray', 'icon-edit', 'icon-folder-open', 'icon-picture-delete', @@ -42,13 +47,11 @@ 'icon-settings', 'icon-visibility', 'icon-visibility-off', 'subpage-arrow', ]; - private iconColor_: string = '#000000'; - private iconSize_: string = '24'; - private icons_: string[] = []; + protected iconColor_: string = '#000000'; + protected iconSize_: string = '24'; + protected icons_: string[] = []; - override ready() { - super.ready(); - + override firstUpdated() { function getIconNames(iconset: CrIconsetElement) { return Array.from(iconset.querySelectorAll('g[id]')) .map((el: Element) => { @@ -61,18 +64,24 @@ const crIconsSet = document.head.querySelector<CrIconsetElement>( 'cr-iconset[name=cr]'); assert(crIconsSet); - this.push('icons_', ...getIconNames(crIconsSet)); + this.icons_.push(...getIconNames(crIconsSet)); const cr20IconsSet = document.head.querySelector<CrIconsetElement>( 'cr-iconset[name=cr20]'); assert(cr20IconsSet); - this.push('icons_', ...getIconNames(cr20IconsSet)); + this.icons_.push(...getIconNames(cr20IconsSet)); + + this.requestUpdate(); } - private onIconColorInput_(e: Event) { + protected onIconColorInput_(e: Event) { const color = (e.target as HTMLInputElement).value; this.iconColor_ = color; } + + protected onIconSizeChanged_(e: CustomEvent<{value: string}>) { + this.iconSize_ = e.detail.value; + } } export const tagName = CrIconsDemoElement.is;
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.css b/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.css new file mode 100644 index 0000000..e8629569 --- /dev/null +++ b/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.css
@@ -0,0 +1,31 @@ +/* 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. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #import=../demo_lit.css.js + * #import=//resources/cr_elements/cr_hidden_style_lit.css.js + * #import=//resources/cr_elements/cr_icons_lit.css.js + * #scheme=relative + * #include=cr-hidden-style-lit cr-icons-lit demo-lit + * #css_wrapper_metadata_end */ + +cr-input, +cr-textarea { + max-width: 400px; + width: 100%; +} + +.no-error { + --cr-input-error-display: none; +} + +.domain-name { + padding-inline-end: 8px; +} + +label { + flex: 1; + white-space: nowrap; +}
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.html index 81d8875..5951df5 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.html +++ b/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.html
@@ -1,24 +1,3 @@ -<style include="cr-hidden-style cr-icons demo"> - cr-input, - cr-textarea { - max-width: 400px; - width: 100%; - } - - .no-error { - --cr-input-error-display: none; - } - - .domain-name { - padding-inline-end: 8px; - } - - label { - flex: 1; - white-space: nowrap; - } -</style> - <h1>cr-input</h1> <h2>Default "filled" inputs with built-in labels</h2> <div class="demos"> @@ -27,18 +6,20 @@ type="text" label="Standard input" placeholder="Placeholder text" - value="{{textValue_}}"> + .value="${this.textValue_}" + @value-changed="${this.onTextValueChanged_}"> </cr-input> <cr-input class="no-error" type="search" placeholder="Search a query" - value="{{searchValue_}}"> + .value="${this.searchValue_}" + @value-changed="${this.onSearchValueChanged_}"> <div slot="inline-prefix" class="cr-icon icon-search" alt=""></div> <cr-icon-button class="icon-cancel" - hidden$="[[!searchValue_]]" slot="inline-suffix" - on-click="onClearSearchClick_" + ?hidden="${!this.searchValue_}" slot="inline-suffix" + @click="${this.onClearSearchClick_}" title="Clear search"> </cr-icon-button> </cr-input> @@ -48,7 +29,8 @@ label="Email address" type="text" placeholder="username" - value="{{emailValue_}}"> + .value="${this.emailValue_}" + @value-changed="${this.onEmailValueChanged_}"> <div slot="inline-suffix" class="domain-name">@chromium.org</div> </cr-input> @@ -60,8 +42,9 @@ max="200" placeholder="A number between 5 and 200" error-message="Number needs to be between 5 and 200" - value="{{numberValue_}}"> - <cr-button slot="suffix" on-click="onValidateClick_">Validate</cr-button> + .value="${this.numberValue_}" + @value-changed="${this.onNumberValueChanged_}"> + <cr-button slot="suffix" @click="${this.onValidateClick_}">Validate</cr-button> </cr-input> <cr-input @@ -70,7 +53,7 @@ placeholder="Enter a pin of 4 digits" pattern="[0-9]{4}" error-message="Pin must be 4 digits" - value="{{pinValue_}}" + .value="${this.pinValue_}" @value-changed="${this.onPinValueChanged_}" auto-validate> </cr-input> @@ -93,16 +76,17 @@ <cr-textarea type="text" label="Textarea" - value="{{textareaValue_}}"> + .value="${this.textareaValue_}" + @value-changed="${this.onTextareaValueChanged_}"> </cr-textarea> <div> - <div>Text input value: [[textValue_]]</div> - <div>Search input value: [[searchValue_]]</div> - <div>Email input value: [[emailValue_]]</div> - <div>Number input value: [[numberValue_]]</div> - <div>Pin input value: [[pinValue_]]</div> - <div>Textarea value: [[textareaValue_]]</div> + <div>Text input value: ${this.textValue_}</div> + <div>Search input value: ${this.searchValue_}</div> + <div>Email input value: ${this.emailValue_}</div> + <div>Number input value: ${this.numberValue_}</div> + <div>Pin input value: ${this.pinValue_}</div> + <div>Textarea value: ${this.textareaValue_}</div> </div> </div>
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.ts b/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.ts index 5f3d055c..c030bff2 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.ts +++ b/chrome/browser/resources/webui_gallery/demos/cr_input/cr_input_demo.ts
@@ -3,58 +3,84 @@ // found in the LICENSE file. import '//resources/cr_elements/cr_button/cr_button.js'; -import '//resources/cr_elements/cr_hidden_style.css.js'; import '//resources/cr_elements/cr_icon_button/cr_icon_button.js'; -import '//resources/cr_elements/cr_icons.css.js'; import '//resources/cr_elements/cr_input/cr_input.js'; import '//resources/cr_elements/cr_textarea/cr_textarea.js'; -import '../demo.css.js'; import type {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.js'; -import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; -import {getTemplate} from './cr_input_demo.html.js'; +import {getCss} from './cr_input_demo.css.js'; +import {getHtml} from './cr_input_demo.html.js'; -interface CrInputDemoElement { +export interface CrInputDemoElement { $: { numberInput: CrInputElement, }; } -class CrInputDemoElement extends PolymerElement { +export class CrInputDemoElement extends CrLitElement { static get is() { return 'cr-input-demo'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); } - static get properties() { + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { return { - emailValue_: String, - numberValue_: String, - pinValue_: String, - searchValue_: String, - textValue_: String, - textareaValue_: String, + emailValue_: {type: String}, + numberValue_: {type: String}, + pinValue_: {type: String}, + searchValue_: {type: String}, + textValue_: {type: String}, + textareaValue_: {type: String}, }; } - private emailValue_: string; - private numberValue_: string; - private pinValue_: string; - private searchValue_: string; - private textValue_: string; - private textareaValue_: string; + protected emailValue_: string; + protected numberValue_: string; + protected pinValue_: string; + protected searchValue_: string; + protected textValue_: string; + protected textareaValue_: string; - private onClearSearchClick_() { + protected onClearSearchClick_() { this.searchValue_ = ''; } - private onValidateClick_() { + protected onValidateClick_() { this.$.numberInput.validate(); } + + protected onTextValueChanged_(e: CustomEvent<{value: string}>) { + this.textValue_ = e.detail.value; + } + + protected onSearchValueChanged_(e: CustomEvent<{value: string}>) { + this.searchValue_ = e.detail.value; + } + + protected onEmailValueChanged_(e: CustomEvent<{value: string}>) { + this.emailValue_ = e.detail.value; + } + + protected onNumberValueChanged_(e: CustomEvent<{value: string}>) { + this.numberValue_ = e.detail.value; + } + + protected onPinValueChanged_(e: CustomEvent<{value: string}>) { + this.pinValue_ = e.detail.value; + } + + protected onTextareaValueChanged_(e: CustomEvent<{value: string}>) { + this.textareaValue_ = e.detail.value; + } } export const tagName = CrInputDemoElement.is;
diff --git a/chrome/browser/shortcuts/shortcut_creator_win.cc b/chrome/browser/shortcuts/shortcut_creator_win.cc index 77ce845c..38a2812 100644 --- a/chrome/browser/shortcuts/shortcut_creator_win.cc +++ b/chrome/browser/shortcuts/shortcut_creator_win.cc
@@ -73,8 +73,8 @@ ShortcutCreatorResult::kError); return; } - base::FilePath shortcut_path = desktop.Append(base::StrCat( - {base::UTF16ToWide(shortcut_metadata.shortcut_title), L".lnk"})); + base::FilePath shortcut_path = GetUniquePath(desktop.Append(base::StrCat( + {base::UTF16ToWide(shortcut_metadata.shortcut_title), L".lnk"}))); base::win::ShortcutProperties target_and_args_properties; target_and_args_properties.set_target(chrome_proxy_path);
diff --git a/chrome/browser/storage/shared_storage_browsertest.cc b/chrome/browser/storage/shared_storage_browsertest.cc index 2fd2c15..0183f27 100644 --- a/chrome/browser/storage/shared_storage_browsertest.cc +++ b/chrome/browser/storage/shared_storage_browsertest.cc
@@ -6,11 +6,14 @@ #include <map> #include <memory> #include <string> +#include <tuple> #include <vector> #include "base/containers/contains.h" +#include "base/json/json_reader.h" #include "base/memory/weak_ptr.h" #include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_base.h" #include "base/run_loop.h" #include "base/strings/strcat.h" #include "base/strings/string_util.h" @@ -231,6 +234,52 @@ } } +int GetSampleCountForHistogram(const std::string& histogram_name) { + auto* histogram = base::StatisticsRecorder::FindHistogram(histogram_name); + if (!histogram) { + return 0; + } + std::string json_output; + histogram->WriteJSON( + &json_output, + base::JSONVerbosityLevel::JSON_VERBOSITY_LEVEL_OMIT_BUCKETS); + std::optional<base::Value::Dict> json_dict = + base::JSONReader::ReadDict(json_output); + if (!json_dict) { + LOG(ERROR) << "Error parsing JSON of histogram data"; + return 0; + } + std::optional<int> count = json_dict->FindInt("count"); + if (!count) { + LOG(ERROR) << "Error: count missing from histogram data"; + return 0; + } + return *count; +} + +void WaitForHistogramsWithSampleCounts( + std::vector<std::tuple<std::string, int>> histogram_names_and_counts) { + while (true) { + content::FetchHistogramsFromChildProcesses(); + metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); + + std::vector<std::tuple<std::string, int>> still_waiting; + for (const auto& [name, count] : histogram_names_and_counts) { + if (GetSampleCountForHistogram(name) < count) { + still_waiting.emplace_back(name, count); + } + } + + histogram_names_and_counts = std::move(still_waiting); + + if (histogram_names_and_counts.empty()) { + break; + } + + DelayBy(base::Seconds(1)); + } +} + // Return the active RenderFrameHost loaded in the last iframe in `parent_rfh`. content::RenderFrameHost* LastChild(content::RenderFrameHost* parent_rfh) { int child_end = 0; @@ -1021,14 +1070,14 @@ EXPECT_TRUE(attestations_console_observer.messages().empty()); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kWorkletNumPerPageHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram}); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -1066,15 +1115,17 @@ GetSharedStorageDisabledErrorMessage())); VerifyDebugErrorMessage(run_op_result.error); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kErrorTypeHistogram, kWorkletNumPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kRunWebVisible, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); return; } @@ -1088,14 +1139,16 @@ EXPECT_EQ("Finish executing \'test-operation\'", base::UTF16ToUTF8(run_op_console_observer.messages()[0].message)); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kTimingDocumentRunHistogram, kWorkletNumPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kErrorTypeHistogram, 2), + std::make_tuple(kTimingDocumentRunHistogram, 1)}); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -1168,17 +1221,18 @@ GetSharedStorageSelectURLDisabledErrorMessage())); VerifyDebugErrorMessage(run_url_op_result.error); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kErrorTypeHistogram, kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSelectURLWebVisible, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); return; @@ -1203,18 +1257,17 @@ "Finish executing \'test-url-selection-operation\'", base::UTF16ToUTF8(run_url_op_console_observer.messages()[0].message)); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kErrorTypeHistogram, 2), + std::make_tuple(kTimingDocumentSelectUrlHistogram, 1)}); + histogram_tester_.ExpectUniqueSample( + kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); + histogram_tester_.ExpectTotalCount(kTimingDocumentSelectUrlHistogram, 1); + // Navigate away to record `kWorkletNumPerPageHistogram`, // `kSelectUrlCallsPerPageHistogram` histograms. EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), GURL(url::kAboutBlankURL))); - WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kTimingDocumentSelectUrlHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); - histogram_tester_.ExpectUniqueSample( - kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); - histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); - histogram_tester_.ExpectTotalCount(kTimingDocumentSelectUrlHistogram, 1); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); } @@ -1334,16 +1387,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletSetHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletSetHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletAppend) { @@ -1366,16 +1418,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletAppendHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletAppendHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletDelete) { @@ -1398,16 +1449,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletDeleteHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletDeleteHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletClear) { @@ -1430,16 +1480,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletClearHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletClearHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletGet) { @@ -1472,17 +1521,16 @@ EXPECT_TRUE(ExecuteScriptInWorkletWithOuterPermissionsBypassed( GetActiveWebContents(), script, "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletSetHistogram, kTimingWorkletGetHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletSetHistogram, 1); histogram_tester_.ExpectTotalCount(kTimingWorkletGetHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletKeys) { @@ -1507,16 +1555,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletKeysHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletKeysHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletEntries) { @@ -1541,16 +1588,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletEntriesHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletEntriesHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletLength) { @@ -1573,16 +1619,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingWorkletLengthHistogram}); histogram_tester_.ExpectTotalCount(kTimingWorkletLengthHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrefBrowserTest, WorkletRemainingBudget) { @@ -1605,16 +1650,15 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); - if (SuccessExpected()) { WaitForHistograms({kTimingRemainingBudgetHistogram}); histogram_tester_.ExpectTotalCount(kTimingRemainingBudgetHistogram, 1); } + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStorageChromeBrowserTest, @@ -1642,17 +1686,13 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms( - {kWorkletNumPerPageHistogram, kErrorTypeHistogram, - kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram, - kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram, - kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram, - kIteratedEntriesBenchmarksHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentRunHistogram, kTimingWorkletKeysHistogram, + kTimingWorkletEntriesHistogram, + kEntriesQueuedCountHistogram, + kReceivedEntriesBenchmarksHistogram, + kIteratedEntriesBenchmarksHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); @@ -1704,6 +1744,11 @@ 2); histogram_tester_.ExpectBucketCount(kIteratedEntriesBenchmarksHistogram, 100, 2); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } // See crbug.com/1453981: A CL on V8 side (https://crrev.com/c/4582948) made @@ -1746,17 +1791,12 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram, kErrorTypeHistogram, - kTimingDocumentAddModuleHistogram, + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram, kTimingWorkletKeysHistogram, kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram, kIteratedEntriesBenchmarksHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); @@ -1807,6 +1847,11 @@ 0); histogram_tester_.ExpectBucketCount(kIteratedEntriesBenchmarksHistogram, 100, 0); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } // See crbug.com/1453981: A CL on V8 side (https://crrev.com/c/4582948) made @@ -1849,17 +1894,12 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); WaitForHistograms( - {kWorkletNumPerPageHistogram, kErrorTypeHistogram, - kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram, - kTimingWorkletEntriesHistogram, kEntriesQueuedCountHistogram, - kReceivedEntriesBenchmarksHistogram, + {kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentRunHistogram, kTimingWorkletEntriesHistogram, + kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram, kIteratedEntriesBenchmarksHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); @@ -1910,6 +1950,11 @@ 1); histogram_tester_.ExpectBucketCount(kIteratedEntriesBenchmarksHistogram, 100, 0); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStorageChromeBrowserTest, @@ -1937,17 +1982,13 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms( - {kWorkletNumPerPageHistogram, kErrorTypeHistogram, - kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram, - kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram, - kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram, - kIteratedEntriesBenchmarksHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentRunHistogram, kTimingWorkletKeysHistogram, + kTimingWorkletEntriesHistogram, + kEntriesQueuedCountHistogram, + kReceivedEntriesBenchmarksHistogram, + kIteratedEntriesBenchmarksHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); @@ -1999,6 +2040,11 @@ 2); histogram_tester_.ExpectBucketCount(kIteratedEntriesBenchmarksHistogram, 100, 2); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStorageChromeBrowserTest, @@ -2040,17 +2086,13 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms( - {kWorkletNumPerPageHistogram, kErrorTypeHistogram, - kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram, - kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram, - kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram, - kIteratedEntriesBenchmarksHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentRunHistogram, kTimingWorkletKeysHistogram, + kTimingWorkletEntriesHistogram, + kEntriesQueuedCountHistogram, + kReceivedEntriesBenchmarksHistogram, + kIteratedEntriesBenchmarksHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); @@ -2100,6 +2142,11 @@ 1); histogram_tester_.ExpectBucketCount(kIteratedEntriesBenchmarksHistogram, 90, 0); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStorageChromeBrowserTest, @@ -2125,17 +2172,13 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms( - {kWorkletNumPerPageHistogram, kErrorTypeHistogram, - kTimingDocumentAddModuleHistogram, kTimingDocumentRunHistogram, - kTimingWorkletKeysHistogram, kTimingWorkletEntriesHistogram, - kEntriesQueuedCountHistogram, kReceivedEntriesBenchmarksHistogram, - kIteratedEntriesBenchmarksHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentRunHistogram, kTimingWorkletKeysHistogram, + kTimingWorkletEntriesHistogram, + kEntriesQueuedCountHistogram, + kReceivedEntriesBenchmarksHistogram, + kIteratedEntriesBenchmarksHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); @@ -2169,6 +2212,11 @@ 2); histogram_tester_.ExpectBucketCount(kIteratedEntriesBenchmarksHistogram, 10, 0); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStorageChromeBrowserTest, @@ -2305,17 +2353,19 @@ result.error, testing::HasSubstr("addModule() can only be invoked once per worklet")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kAddModuleWebVisible, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -2359,11 +2409,9 @@ 'test-operation-1', {data: {}}); )")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); @@ -2371,6 +2419,10 @@ kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kRunNonWebVisibleOperationNotFound, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -2395,17 +2447,19 @@ 'test-operation', {data: {}}); )")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kRunNonWebVisibleOther, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -2430,17 +2484,19 @@ 'test-operation', {data: {}}); )")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kRunNonWebVisibleOther, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -2466,17 +2522,19 @@ 'test-operation', {data: {'customField': 'customValue123'}}); )")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kRunNonWebVisibleOther, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -2561,13 +2619,9 @@ })() )")); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); @@ -2576,6 +2630,11 @@ blink::SharedStorageWorkletErrorType:: kSelectURLNonWebVisibleOperationNotFound, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); } @@ -2621,19 +2680,20 @@ })() )")); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisibleOther, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); } @@ -2678,19 +2738,20 @@ })() )")); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisibleOther, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); } @@ -2736,19 +2797,20 @@ })() )")); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSelectURLNonWebVisibleOther, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); } @@ -2794,13 +2856,9 @@ })() )")); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); @@ -2809,6 +2867,11 @@ blink::SharedStorageWorkletErrorType:: kSelectURLNonWebVisibleReturnValueOutOfRange, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); } @@ -2854,13 +2917,9 @@ })() )")); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kTimingDocumentAddModuleHistogram, kErrorTypeHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + WaitForHistogramsWithSampleCounts( + {std::make_tuple(kTimingDocumentAddModuleHistogram, 1), + std::make_tuple(kErrorTypeHistogram, 2)}); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 1); histogram_tester_.ExpectBucketCount( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 1); @@ -2869,6 +2928,11 @@ blink::SharedStorageWorkletErrorType:: kSelectURLNonWebVisibleReturnValueToInt, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 1, 1); } @@ -3467,16 +3531,12 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL( - GetActiveWebContents(), - https_server()->GetURL(kCrossOriginHost, kSimplePagePath))); - WaitForHistograms( - {kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kTimingDocumentRunHistogram, kTimingWorkletSetHistogram, - kTimingWorkletAppendHistogram, kTimingWorkletGetHistogram, - kTimingWorkletLengthHistogram, kTimingWorkletDeleteHistogram, - kTimingWorkletClearHistogram, kWorkletNumPerPageHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentRunHistogram, kTimingWorkletSetHistogram, + kTimingWorkletAppendHistogram, kTimingWorkletGetHistogram, + kTimingWorkletLengthHistogram, + kTimingWorkletDeleteHistogram, + kTimingWorkletClearHistogram}); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 2); @@ -3488,6 +3548,10 @@ histogram_tester_.ExpectTotalCount(kTimingWorkletLengthHistogram, 1); histogram_tester_.ExpectTotalCount(kTimingWorkletDeleteHistogram, 2); histogram_tester_.ExpectTotalCount(kTimingWorkletClearHistogram, 1); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } @@ -3523,15 +3587,16 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kTimingDocumentRunHistogram, kWorkletNumPerPageHistogram}); + kTimingDocumentRunHistogram}); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 4); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 2); histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 2); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 2, 1); } @@ -3582,18 +3647,17 @@ "Finished script", /*use_select_url=*/true)); - // Navigate away to record `kWorkletNumPerPageHistogram`, - // `kSelectUrlCallsPerPageHistogram` histograms. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kTimingDocumentSelectUrlHistogram, - kWorkletNumPerPageHistogram, - kSelectUrlCallsPerPageHistogram}); + kTimingDocumentSelectUrlHistogram}); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 6); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 3); histogram_tester_.ExpectTotalCount(kTimingDocumentSelectUrlHistogram, 3); + + // Navigate away to record `kWorkletNumPerPageHistogram`, + // `kSelectUrlCallsPerPageHistogram` histograms. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 3, 1); histogram_tester_.ExpectUniqueSample(kSelectUrlCallsPerPageHistogram, 3, 1); } @@ -3780,13 +3844,10 @@ EXPECT_DOUBLE_EQ(RemainingBudget(new_iframe, /*should_add_module=*/true), kBudgetAllowed - std::log2(3)); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms( - {kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kTimingDocumentSelectUrlHistogram, kTimingDocumentRunHistogram, - kTimingRemainingBudgetHistogram, kWorkletNumPerPageHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentSelectUrlHistogram, + kTimingDocumentRunHistogram, + kTimingRemainingBudgetHistogram}); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 5); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 2); @@ -3794,6 +3855,10 @@ histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 2); histogram_tester_.ExpectTotalCount(kTimingRemainingBudgetHistogram, 2); + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + // In the MPArch case, some additional pageloads with worklet count 0 are // recorded, so we do not use `ExpectUniqueSample()` here. histogram_tester_.ExpectBucketCount(kWorkletNumPerPageHistogram, 1, 2); @@ -3852,13 +3917,10 @@ EXPECT_DOUBLE_EQ(RemainingBudget(iframe3, /*should_add_module=*/true), kBudgetAllowed - std::log2(3) - std::log2(3)); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms( - {kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, - kTimingDocumentSelectUrlHistogram, kTimingDocumentRunHistogram, - kTimingRemainingBudgetHistogram, kWorkletNumPerPageHistogram}); + WaitForHistograms({kErrorTypeHistogram, kTimingDocumentAddModuleHistogram, + kTimingDocumentSelectUrlHistogram, + kTimingDocumentRunHistogram, + kTimingRemainingBudgetHistogram}); histogram_tester_.ExpectUniqueSample( kErrorTypeHistogram, blink::SharedStorageWorkletErrorType::kSuccess, 9); histogram_tester_.ExpectTotalCount(kTimingDocumentAddModuleHistogram, 3); @@ -3866,6 +3928,10 @@ histogram_tester_.ExpectTotalCount(kTimingDocumentRunHistogram, 4); histogram_tester_.ExpectTotalCount(kTimingRemainingBudgetHistogram, 4); + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + // In the MPArch case, some additional pageloads with worklet count 0 are // recorded, so we do not use `ExpectUniqueSample()` here. histogram_tester_.ExpectBucketCount(kWorkletNumPerPageHistogram, 1, 3); @@ -3961,12 +4027,7 @@ )", "Finished script")); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram, - kPrivateAggregationHostPipeResultHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); + WaitForHistograms({kPrivateAggregationHostPipeResultHistogram}); histogram_tester_.ExpectUniqueSample( kPrivateAggregationHostPipeResultHistogram, SuccessExpected() @@ -3977,6 +4038,11 @@ histogram_tester_.ExpectTotalCount( kPrivateAggregationHostTimeToGenerateReportRequestWithContextIdHistogram, 0); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrivateAggregationChromeBrowserTest, @@ -4000,12 +4066,7 @@ "Finished script", /*use_select_url=*/true)); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram, - kPrivateAggregationHostPipeResultHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); + WaitForHistograms({kPrivateAggregationHostPipeResultHistogram}); histogram_tester_.ExpectUniqueSample( kPrivateAggregationHostPipeResultHistogram, SuccessExpected() @@ -4015,6 +4076,11 @@ histogram_tester_.ExpectTotalCount( kPrivateAggregationHostTimeToGenerateReportRequestWithContextIdHistogram, 0); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } IN_PROC_BROWSER_TEST_P(SharedStoragePrivateAggregationChromeBrowserTest, @@ -4038,12 +4104,7 @@ 'example_id'}}); )"); - // Navigate away to record `kWorkletNumPerPageHistogram` histogram. - EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), - GURL(url::kAboutBlankURL))); - WaitForHistograms({kWorkletNumPerPageHistogram, - kPrivateAggregationHostPipeResultHistogram}); - histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); + WaitForHistograms({kPrivateAggregationHostPipeResultHistogram}); histogram_tester_.ExpectUniqueSample( kPrivateAggregationHostPipeResultHistogram, SuccessExpected() @@ -4053,6 +4114,11 @@ histogram_tester_.ExpectTotalCount( kPrivateAggregationHostTimeToGenerateReportRequestWithContextIdHistogram, SuccessExpected() ? 1 : 0); + + // Navigate away to record `kWorkletNumPerPageHistogram` histogram. + EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(), + GURL(url::kAboutBlankURL))); + histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1); } class SharedStorageHeaderPrefBrowserTest : public SharedStoragePrefBrowserTest {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e8093d3..e494ebb 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3028,7 +3028,7 @@ "views/bruschetta/bruschetta_installer_view.h", "views/bruschetta/bruschetta_uninstaller_view.cc", "views/bruschetta/bruschetta_uninstaller_view.h", - "views/chrome_views_delegate_chromeos.cc", + "views/chrome_views_delegate_ash.cc", "views/crostini/crostini_ansible_software_config_view.cc", "views/crostini/crostini_ansible_software_config_view.h", "views/crostini/crostini_app_restart_dialog.cc", @@ -3813,6 +3813,7 @@ "//ash/webui/print_preview_cros", "//ash/webui/projector_app", "//ash/webui/projector_app/public/mojom:projector_mojo_bindings", + "//ash/webui/sanitize_ui", "//ash/webui/scanning", "//ash/webui/shimless_rma", "//ash/webui/shortcut_customization_ui", @@ -4220,6 +4221,8 @@ "lens/lens_overlay_side_panel_coordinator.h", "lens/lens_overlay_side_panel_navigation_throttle.cc", "lens/lens_overlay_side_panel_navigation_throttle.h", + "lens/lens_overlay_theme_utils.cc", + "lens/lens_overlay_theme_utils.h", "lens/lens_search_bubble_controller.cc", "lens/lens_search_bubble_controller.h", "lens/lens_untrusted_ui.cc",
diff --git a/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_even.xml b/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_even.xml index 5aae015d..8217be5e 100644 --- a/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_even.xml +++ b/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_even.xml
@@ -12,14 +12,12 @@ android:id="@+id/google_bottom_bar_container" android:layout_width="match_parent" android:layout_height="@dimen/google_bottom_bar_height" - android:paddingLeft="@dimen/google_bottom_bar_padding" - android:paddingRight="@dimen/google_bottom_bar_padding" android:background="@color/google_bottom_bar_background_color" android:baselineAligned="false" android:orientation="horizontal"> - <ImageView + <ImageButton android:id="@+id/google_bottom_bar_save_button" - android:layout_width="0dp" + android:layout_width="@dimen/google_bottom_bar_button_size" android:layout_weight="1" android:layout_height="@dimen/google_bottom_bar_button_size" android:layout_marginTop="@dimen/google_bottom_bar_button_margin_vertical" @@ -28,10 +26,11 @@ android:layout_gravity="center_vertical" android:importantForAccessibility="yes" android:contentDescription="@null" - android:src="@drawable/bookmark" /> - <ImageView + android:src="@drawable/bookmark" + android:background="@color/google_bottom_bar_background_color" /> + <ImageButton android:id="@+id/google_bottom_bar_page_insights_button" - android:layout_width="0dp" + android:layout_width="@dimen/google_bottom_bar_button_size" android:layout_weight="1" android:layout_height="@dimen/google_bottom_bar_button_size" android:layout_marginTop="@dimen/google_bottom_bar_button_margin_vertical" @@ -42,10 +41,10 @@ android:contentDescription="@null" android:visibility="visible" android:src="@drawable/page_insights_icon" - app:tint="@color/default_icon_color_baseline" /> - <ImageView + android:background="@color/google_bottom_bar_background_color" /> + <ImageButton android:id="@+id/google_bottom_bar_share_button" - android:layout_width="0dp" + android:layout_width="@dimen/google_bottom_bar_button_size" android:layout_weight="1" android:layout_height="@dimen/google_bottom_bar_button_size" android:layout_marginTop="@dimen/google_bottom_bar_button_margin_vertical" @@ -56,5 +55,5 @@ android:contentDescription="@null" android:visibility="visible" android:src="@drawable/ic_share_white_24dp" - app:tint="@color/default_icon_color_baseline" /> + android:background="@color/google_bottom_bar_background_color" /> </LinearLayout>
diff --git a/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_spotlight.xml b/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_spotlight.xml index bae524a..ca2d8e5e 100644 --- a/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_spotlight.xml +++ b/chrome/browser/ui/android/google_bottom_bar/java/res/layout/google_bottom_bar_spotlight.xml
@@ -17,19 +17,17 @@ android:background="@color/google_bottom_bar_background_color" android:baselineAligned="false" android:orientation="horizontal"> - <ImageView + <ImageButton android:id="@+id/google_bottom_bar_page_insights_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingStart="2dp" - android:paddingTop="2dp" + android:layout_width="@dimen/google_bottom_bar_button_size" + android:layout_height="@dimen/google_bottom_bar_button_size" android:scaleType="centerInside" android:layout_gravity="center" android:importantForAccessibility="yes" android:contentDescription="@null" android:visibility="visible" android:src="@drawable/page_insights_icon" - app:tint="@color/default_icon_color_baseline" /> + android:background="@color/google_bottom_bar_background_color" /> <LinearLayout android:id="@+id/google_bottom_bar_non_spotlit_buttons_container" android:layout_width="0dp" @@ -40,7 +38,7 @@ android:paddingStart="@dimen/google_bottom_bar_expanded_button_padding_horizontal" android:paddingEnd="@dimen/google_bottom_bar_expanded_button_padding_horizontal" android:orientation="horizontal"> - <ImageView + <ImageButton android:id="@+id/google_bottom_bar_save_button" android:layout_width="@dimen/google_bottom_bar_button_size" android:layout_height="@dimen/google_bottom_bar_button_size" @@ -49,8 +47,9 @@ android:layout_marginStart="@dimen/google_bottom_bar_button_padding" android:importantForAccessibility="yes" android:contentDescription="@null" - android:src="@drawable/bookmark" /> - <ImageView + android:src="@drawable/bookmark" + android:background="@color/google_bottom_bar_background_color" /> + <ImageButton android:id="@+id/google_bottom_bar_share_button" android:layout_width="@dimen/google_bottom_bar_button_size" android:layout_height="@dimen/google_bottom_bar_button_size" @@ -61,6 +60,6 @@ android:contentDescription="@null" android:visibility="visible" android:src="@drawable/ic_share_white_24dp" - app:tint="@color/default_icon_color_baseline" /> + android:background="@color/google_bottom_bar_background_color" /> </LinearLayout> </LinearLayout>
diff --git a/chrome/browser/ui/android/google_bottom_bar/java/src/org/chromium/chrome/browser/ui/google_bottom_bar/GoogleBottomBarViewCreator.java b/chrome/browser/ui/android/google_bottom_bar/java/src/org/chromium/chrome/browser/ui/google_bottom_bar/GoogleBottomBarViewCreator.java index 93e18fce..ba392865 100644 --- a/chrome/browser/ui/android/google_bottom_bar/java/src/org/chromium/chrome/browser/ui/google_bottom_bar/GoogleBottomBarViewCreator.java +++ b/chrome/browser/ui/android/google_bottom_bar/java/src/org/chromium/chrome/browser/ui/google_bottom_bar/GoogleBottomBarViewCreator.java
@@ -8,7 +8,7 @@ import android.content.Context; import android.view.LayoutInflater; import android.view.View; -import android.widget.ImageView; +import android.widget.ImageButton; import androidx.annotation.Nullable; @@ -83,7 +83,7 @@ private void initButton(int viewId, @ButtonId int buttonConfigId) { assert mRootView != null; - ImageView button = mRootView.findViewById(viewId); + ImageButton button = mRootView.findViewById(viewId); ButtonConfig buttonConfig = findButtonConfig(buttonConfigId); maybeUpdateButton(button, buttonConfig, /* isFirstTimeShown= */ true); } @@ -92,7 +92,7 @@ if (buttonConfig == null) { return false; } - ImageView button = mRootView.findViewById(buttonConfig.getId()); + ImageButton button = mRootView.findViewById(buttonConfig.getId()); return maybeUpdateButton(button, buttonConfig, /* isFirstTimeShown= */ false); } @@ -114,7 +114,7 @@ } private boolean maybeUpdateButton( - @Nullable ImageView button, + @Nullable ImageButton button, @Nullable ButtonConfig buttonConfig, boolean isFirstTimeShown) { if (button == null || buttonConfig == null) {
diff --git a/chrome/browser/ui/ash/quick_settings_integration_test.cc b/chrome/browser/ui/ash/quick_settings_integration_test.cc index 8848ecc..094fa93 100644 --- a/chrome/browser/ui/ash/quick_settings_integration_test.cc +++ b/chrome/browser/ui/ash/quick_settings_integration_test.cc
@@ -167,7 +167,9 @@ base::test::ScopedFeatureList feature_list_; }; -IN_PROC_BROWSER_TEST_F(QuickSettingsLacrosIntegrationTest, ManagedDeviceInfo) { +// TODO(b/341659658): Fails to open Lacros window. +IN_PROC_BROWSER_TEST_F(QuickSettingsLacrosIntegrationTest, + DISABLED_ManagedDeviceInfo) { // On VM tryservers like chromeos-amd64-generic Lacros fails to start up // correctly (it restarts in a loop). b/303359438 if (base::CPU().is_running_in_vm()) {
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 1e312b74..99af967 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -435,14 +435,30 @@ void ReloadInternal(Browser* browser, WindowOpenDisposition disposition, bool bypass_cache) { - const WebContents* active_contents = + const WebContents* const active_contents = browser->tab_strip_model()->GetActiveWebContents(); - const auto& selected_indices = - browser->tab_strip_model()->selection_model().selected_indices(); - for (int index : selected_indices) { - WebContents* selected_tab = - browser->tab_strip_model()->GetWebContentsAt(index); - WebContents* new_tab = + + // Reloading a tab may change the selection (see crbug.com/339061099), so take + // a defensive copy into a more stable form before we begin. We take + // WebContents* so we can follow the tabs as they shift within the same + // tabstrip (e.g. if `disposition` is NEW_BACKGROUND_TAB). + std::vector<WebContents*> selected_tabs; + for (const int selected_index : + browser->tab_strip_model()->selection_model().selected_indices()) { + selected_tabs.push_back( + browser->tab_strip_model()->GetWebContentsAt(selected_index)); + } + + for (WebContents* const selected_tab : selected_tabs) { + // Skip this tab if it is no longer part of this tabstrip. N.B. we do this + // instead of using WeakPtr<WebContents> because we do not want to reload + // tabs that move to another browser. + if (browser->tab_strip_model()->GetIndexOfWebContents(selected_tab) == + TabStripModel::kNoTab) { + continue; + } + + WebContents* const new_tab = GetTabAndRevertIfNecessaryHelper(browser, disposition, selected_tab); // If the selected_tab is the activated page, give the focus to it, as this @@ -455,7 +471,7 @@ // User reloads is a possible breakage indicator from blocking 3P cookies. RecordReloadWithCookieBlocking(browser, selected_tab); - DevToolsWindow* devtools = + DevToolsWindow* const devtools = DevToolsWindow::GetInstanceForInspectedWebContents(new_tab); constexpr content::ReloadType kBypassingType = content::ReloadType::BYPASSING_CACHE;
diff --git a/chrome/browser/ui/color/chrome_color_mixers.cc b/chrome/browser/ui/color/chrome_color_mixers.cc index dbc6656..9698e807 100644 --- a/chrome/browser/ui/color/chrome_color_mixers.cc +++ b/chrome/browser/ui/color/chrome_color_mixers.cc
@@ -22,7 +22,6 @@ #include "chrome/browser/ui/color/omnibox_color_mixer.h" #include "chrome/browser/ui/color/product_specifications_color_mixer.h" #include "chrome/browser/ui/color/tab_strip_color_mixer.h" -#include "ui/base/ui_base_features.h" #include "ui/color/color_provider_utils.h" namespace { @@ -66,13 +65,11 @@ AddProductSpecificationsColorMixer(provider, key); AddTabStripColorMixer(provider, key); - if (features::IsChromeRefresh2023()) { - AddMaterialChromeColorMixer(provider, key); - AddMaterialNewTabPageColorMixer(provider, key); - AddMaterialOmniboxColorMixer(provider, key); - AddMaterialSidePanelColorMixer(provider, key); - AddMaterialTabStripColorMixer(provider, key); - } + AddMaterialChromeColorMixer(provider, key); + AddMaterialNewTabPageColorMixer(provider, key); + AddMaterialOmniboxColorMixer(provider, key); + AddMaterialSidePanelColorMixer(provider, key); + AddMaterialTabStripColorMixer(provider, key); // Must be the last one in order to override other mixer colors. AddNativeChromeColorMixer(provider, key);
diff --git a/chrome/browser/ui/color/chrome_color_provider_utils.cc b/chrome/browser/ui/color/chrome_color_provider_utils.cc index 0297792..357e9bf 100644 --- a/chrome/browser/ui/color/chrome_color_provider_utils.cc +++ b/chrome/browser/ui/color/chrome_color_provider_utils.cc
@@ -128,6 +128,5 @@ // contrast. // TODO(tluk): Switch to using the high contrast configuration for ref tokens // generated by the material_color_utilities when supported. - return features::IsChromeRefresh2023() && !key.custom_theme && - !ShouldApplyHighContrastColors(key); + return !key.custom_theme && !ShouldApplyHighContrastColors(key); }
diff --git a/chrome/browser/ui/color/win/native_chrome_color_mixer_win.cc b/chrome/browser/ui/color/win/native_chrome_color_mixer_win.cc index d349459..543e515 100644 --- a/chrome/browser/ui/color/win/native_chrome_color_mixer_win.cc +++ b/chrome/browser/ui/color/win/native_chrome_color_mixer_win.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/win/titlebar_config.h" #include "chrome/grit/theme_resources.h" -#include "ui/base/ui_base_features.h" #include "ui/color/color_id.h" #include "ui/color/color_mixer.h" #include "ui/color/color_provider.h" @@ -101,11 +100,9 @@ SkColorSetRGB(0xE8, 0xE8, 0xE8); constexpr SkColor kSystemMicaDarkFrameColor = SkColorSetRGB(0x20, 0x20, 0x20); - // Dwm colors should always be applied if present for pervasive accent colors - // pre-refresh. With refresh enabled we should only attempt to paint - // system-style frames if configured to do so in the key. + // We should only attempt to paint system-style frames if configured to do so + // in the key. const bool use_native_colors = - !features::IsChromeRefresh2023() || (key.frame_type == ui::ColorProviderKey::FrameType::kChromium && key.frame_style == ui::ColorProviderKey::FrameStyle::kSystem);
diff --git a/chrome/browser/ui/color/win/native_chrome_color_mixer_win_browsertest.cc b/chrome/browser/ui/color/win/native_chrome_color_mixer_win_browsertest.cc index ef508980..381e805 100644 --- a/chrome/browser/ui/color/win/native_chrome_color_mixer_win_browsertest.cc +++ b/chrome/browser/ui/color/win/native_chrome_color_mixer_win_browsertest.cc
@@ -57,13 +57,9 @@ accent_color_observer->SetAccentColorForTesting(kAccentColor); accent_color_observer->SetUseDwmFrameColorForTesting(true); - // When running refresh the header color should be unaffected as the theme - // service has not been set to follow the device theme. When running - // pre-refresh the header color should be set to the accent color as part of - // pervasive accent colors. - EXPECT_EQ( - features::IsChromeRefresh2023() ? initial_header_color : kAccentColor, - get_header_color()); + // The header color should be unaffected as the theme service has not been set + // to follow the device theme. + EXPECT_EQ(initial_header_color, get_header_color()); // Set the browser to follow the device colors. The header color should be // updated to track the accent color.
diff --git a/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc b/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc index 5bd6670..5a5f01a5 100644 --- a/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc +++ b/chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc
@@ -204,6 +204,7 @@ manager->fullscreen_controller()->HandleUserPressedEscape(); manager->pointer_lock_controller()->HandleUserPressedEscape(); HandleUserPressedEscape(); + base::RecordAction(base::UserMetricsAction("UnlockKeyboard_PressAndHoldEsc")); } void KeyboardLockController::ReShowExitBubbleIfNeeded() {
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.cc b/chrome/browser/ui/lens/lens_overlay_controller.cc index 856764a..c3e76ab 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/lens/lens_overlay_permission_utils.h" #include "chrome/browser/ui/lens/lens_overlay_query_controller.h" #include "chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h" +#include "chrome/browser/ui/lens/lens_overlay_theme_utils.h" #include "chrome/browser/ui/lens/lens_overlay_url_builder.h" #include "chrome/browser/ui/lens/lens_permission_bubble_controller.h" #include "chrome/browser/ui/lens/lens_search_bubble_controller.h" @@ -159,18 +160,6 @@ return top_level_widget->GetNativeView(); } -// TODO(b/341360519): Move this to a separate file. -bool SidePanelShouldUseDarkMode(ThemeService* theme_service) { - if (!lens::features::UseBrowserDarkModeSettingForLensOverlay()) { - return false; - } - ThemeService::BrowserColorScheme color_scheme = - theme_service->GetBrowserColorScheme(); - return color_scheme == ThemeService::BrowserColorScheme::kSystem - ? ui::NativeTheme::GetInstanceForNativeUi()->ShouldUseDarkColors() - : color_scheme == ThemeService::BrowserColorScheme::kDark; -} - } // namespace LensOverlayController::LensOverlayController( @@ -339,7 +328,7 @@ base::BindRepeating(&LensOverlayController::HandleThumbnailCreated, weak_factory_.GetWeakPtr()), variations_client_, identity_manager_, invocation_source, - SidePanelShouldUseDarkMode(theme_service_)); + lens::LensOverlayShouldUseDarkMode(theme_service_)); side_panel_coordinator_ = SidePanelUtil::GetSidePanelCoordinatorForBrowser(tab_browser); @@ -441,7 +430,7 @@ page_.Bind(std::move(page)); InitializeOverlayUI(*initialization_data_); - base::UmaHistogramBoolean("Desktop.LensOverlay.Shown", true); + base::UmaHistogramBoolean("Lens.Overlay.Shown", true); state_ = State::kOverlay; // Only start the query flow again if we don't already have a full image
diff --git a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc index ce31730..7a318a9 100644 --- a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc +++ b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
@@ -166,6 +166,9 @@ void LensOverlaySidePanelCoordinator::DidStartNavigation( content::NavigationHandle* navigation_handle) { + // Focus the web contents immediately, so that hotkey presses (i.e. escape) + // are handled. + GetSidePanelWebContents()->Focus(); // We only care about the navigation if it is the results frame, is HTTPS, // renderer initiated and NOT a same document navigation. if (!navigation_handle->IsRendererInitiated() ||
diff --git a/chrome/browser/ui/lens/lens_overlay_theme_utils.cc b/chrome/browser/ui/lens/lens_overlay_theme_utils.cc new file mode 100644 index 0000000..fa12a18 --- /dev/null +++ b/chrome/browser/ui/lens/lens_overlay_theme_utils.cc
@@ -0,0 +1,24 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/lens/lens_overlay_theme_utils.h" + +#include "chrome/browser/themes/theme_service.h" +#include "components/lens/lens_features.h" +#include "ui/native_theme/native_theme.h" + +namespace lens { + +bool LensOverlayShouldUseDarkMode(ThemeService* theme_service) { + if (!lens::features::UseBrowserDarkModeSettingForLensOverlay()) { + return false; + } + ThemeService::BrowserColorScheme color_scheme = + theme_service->GetBrowserColorScheme(); + return color_scheme == ThemeService::BrowserColorScheme::kSystem + ? ui::NativeTheme::GetInstanceForNativeUi()->ShouldUseDarkColors() + : color_scheme == ThemeService::BrowserColorScheme::kDark; +} + +} // namespace lens
diff --git a/chrome/browser/ui/lens/lens_overlay_theme_utils.h b/chrome/browser/ui/lens/lens_overlay_theme_utils.h new file mode 100644 index 0000000..98ef64e --- /dev/null +++ b/chrome/browser/ui/lens/lens_overlay_theme_utils.h
@@ -0,0 +1,18 @@ +// 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_LENS_LENS_OVERLAY_THEME_UTILS_H_ +#define CHROME_BROWSER_UI_LENS_LENS_OVERLAY_THEME_UTILS_H_ + +class ThemeService; + +namespace lens { + +// Returns true if the lens overlay results and searchbox in the +// side panel should use dark mode. +bool LensOverlayShouldUseDarkMode(ThemeService* theme_service); + +} // namespace lens + +#endif // CHROME_BROWSER_UI_LENS_LENS_OVERLAY_THEME_UTILS_H_
diff --git a/chrome/browser/ui/lens/lens_untrusted_ui.cc b/chrome/browser/ui/lens/lens_untrusted_ui.cc index c65ec6d..390f778e 100644 --- a/chrome/browser/ui/lens/lens_untrusted_ui.cc +++ b/chrome/browser/ui/lens/lens_untrusted_ui.cc
@@ -6,7 +6,9 @@ #include "base/strings/strcat.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/lens/lens_overlay_controller.h" +#include "chrome/browser/ui/lens/lens_overlay_theme_utils.h" #include "chrome/browser/ui/webui/searchbox/realbox_handler.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/pref_names.h" @@ -85,6 +87,10 @@ lens::features::GetLensOverlayTapRegionHeight()); html_source->AddInteger("tapRegionWidth", lens::features::GetLensOverlayTapRegionWidth()); + html_source->AddBoolean( + "darkMode", + lens::LensOverlayShouldUseDarkMode( + ThemeServiceFactory::GetForProfile(Profile::FromWebUI(web_ui)))); // Allow FrameSrc from all Google subdomains as redirects can occur. GURL results_side_panel_url =
diff --git a/chrome/browser/ui/side_panel/companion/companion_utils.cc b/chrome/browser/ui/side_panel/companion/companion_utils.cc index ccf0f94..70a6fe03 100644 --- a/chrome/browser/ui/side_panel/companion/companion_utils.cc +++ b/chrome/browser/ui/side_panel/companion/companion_utils.cc
@@ -140,14 +140,6 @@ ShouldEnableOpenCompanionForImageSearch(); } -bool IsNewBadgeEnabledForSearchMenuItem(const Browser* browser) { - if (!browser) { - return false; - } - return base::FeatureList::IsEnabled( - features::kCompanionEnableNewBadgesInContextMenu); -} - void UpdateCompanionDefaultPinnedToToolbarState(Profile* profile) { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) CHECK(profile);
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_web_contents_listener.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_web_contents_listener.cc index a3eddedc..805f601 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_web_contents_listener.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_web_contents_listener.cc
@@ -29,11 +29,16 @@ if (ui::PageTransitionIsRedirect(page_transition)) { return false; } + if (!ui::PageTransitionIsMainFrame(page_transition)) { return false; } - if (navigation_handle->IsSameDocument()) { + if (!navigation_handle->HasCommitted()) { + return false; + } + + if (!navigation_handle->ShouldUpdateHistory()) { return false; } @@ -109,8 +114,6 @@ return; } - handle_from_sync_update_ = nullptr; - if (!IsSaveableNavigation(navigation_handle)) { return; }
diff --git a/chrome/browser/ui/tabs/tab_renderer_data.cc b/chrome/browser/ui/tabs/tab_renderer_data.cc index 3bfec8e..7a3f599 100644 --- a/chrome/browser/ui/tabs/tab_renderer_data.cc +++ b/chrome/browser/ui/tabs/tab_renderer_data.cc
@@ -7,7 +7,6 @@ #include "base/process/kill.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/favicon/favicon_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-shared.h" @@ -22,7 +21,6 @@ #include "chrome/browser/ui/web_applications/web_app_browser_controller.h" #include "chrome/browser/ui/web_applications/web_app_tabbed_utils.h" #include "components/performance_manager/public/features.h" -#include "components/performance_manager/public/user_tuning/prefs.h" #include "components/security_interstitials/content/security_interstitial_tab_helper.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" @@ -112,10 +110,7 @@ memory_saver::IsURLSupported(contents->GetURL()) && contents->WasDiscarded() && discard_reason.has_value() && (discard_reason.value() == mojom::LifecycleUnitDiscardReason::PROACTIVE || - discard_reason.value() == - mojom::LifecycleUnitDiscardReason::SUGGESTED) && - performance_manager::user_tuning::prefs::ShouldShowDiscardRingTreatment( - g_browser_process->local_state()); + discard_reason.value() == mojom::LifecycleUnitDiscardReason::SUGGESTED); if (contents->WasDiscarded()) { data.discarded_memory_savings_in_bytes =
diff --git a/chrome/browser/ui/views/DEPS b/chrome/browser/ui/views/DEPS index 9ee592f..fba5f9b 100644 --- a/chrome/browser/ui/views/DEPS +++ b/chrome/browser/ui/views/DEPS
@@ -17,7 +17,7 @@ "browser_user_education_service.cc": [ "+ash/user_education/views/help_bubble_factory_views_ash.h", ], - "chrome_views_delegate_chromeos\.cc": [ + "chrome_views_delegate_ash\.cc": [ "+ash/shell.h", ], "isolated_web_app_installer_view_browsertest\.cc": [
diff --git a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc b/chrome/browser/ui/views/chrome_views_delegate_ash.cc similarity index 100% rename from chrome/browser/ui/views/chrome_views_delegate_chromeos.cc rename to chrome/browser/ui/views/chrome_views_delegate_ash.cc
diff --git a/chrome/browser/ui/views/chrome_views_delegate_lacros.cc b/chrome/browser/ui/views/chrome_views_delegate_lacros.cc index 38181b7d..e1baa9e5 100644 --- a/chrome/browser/ui/views/chrome_views_delegate_lacros.cc +++ b/chrome/browser/ui/views/chrome_views_delegate_lacros.cc
@@ -2,17 +2,67 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/chrome_views_delegate.h" - #include <memory> +#include "chrome/browser/ui/views/chrome_views_delegate.h" +#include "chromeos/ui/base/window_properties.h" +#include "chromeos/ui/base/window_state_type.h" #include "chromeos/ui/frame/frame_utils.h" +#include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h" #include "chromeos/ui/frame/non_client_frame_view_base.h" +#include "ui/aura/window_observer.h" #include "ui/gfx/native_widget_types.h" +#include "ui/views/widget/widget.h" + +namespace { + +// A NonClientFrameView for framed lacros widgets supporting immersive +// fullscreen. +class NonClientFrameViewLacros : public chromeos::NonClientFrameViewBase, + public aura::WindowObserver { + METADATA_HEADER(NonClientFrameViewLacros, chromeos::NonClientFrameViewBase) + + public: + explicit NonClientFrameViewLacros(views::Widget* frame) + : NonClientFrameViewBase(frame) { + window_observation_.Observe(frame->GetNativeWindow()); + immersive_fullscreen_controller_.Init(GetHeaderView(), frame, + GetHeaderView()); + } + NonClientFrameViewLacros(const NonClientFrameViewLacros&) = delete; + NonClientFrameViewLacros& operator=(const NonClientFrameViewLacros&) = delete; + ~NonClientFrameViewLacros() override = default; + + // aura::WindowObserver: + void OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) override { + if (key == chromeos::kWindowStateTypeKey) { + const bool is_fullscreen = + window->GetProperty(chromeos::kWindowStateTypeKey) == + chromeos::WindowStateType::kFullscreen; + chromeos::ImmersiveFullscreenController::EnableForWidget(frame_, + is_fullscreen); + } + } + void OnWindowDestroying(aura::Window* window) override { + window_observation_.Reset(); + } + + private: + chromeos::ImmersiveFullscreenController immersive_fullscreen_controller_; + base::ScopedObservation<aura::Window, aura::WindowObserver> + window_observation_{this}; +}; + +BEGIN_METADATA(NonClientFrameViewLacros) +END_METADATA + +} // namespace std::unique_ptr<views::NonClientFrameView> ChromeViewsDelegate::CreateDefaultNonClientFrameView(views::Widget* widget) { - return std::make_unique<chromeos::NonClientFrameViewBase>(widget); + return std::make_unique<NonClientFrameViewLacros>(widget); } bool ChromeViewsDelegate::ShouldWindowHaveRoundedCorners(
diff --git a/chrome/browser/ui/views/chrome_views_delegate_lacros_browsertest.cc b/chrome/browser/ui/views/chrome_views_delegate_lacros_browsertest.cc new file mode 100644 index 0000000..1c4775cb --- /dev/null +++ b/chrome/browser/ui/views/chrome_views_delegate_lacros_browsertest.cc
@@ -0,0 +1,40 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/run_until.h" +#include "chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_test_api.h" +#include "content/public/test/browser_test.h" +#include "ui/views/widget/unique_widget_ptr.h" +#include "ui/views/widget/widget.h" + +using ChromeViewsDelegateLacrosBrowsertest = InProcessBrowserTest; + +IN_PROC_BROWSER_TEST_F(ChromeViewsDelegateLacrosBrowsertest, + DefaultNonClientFrameViewEntersImmersiveMode) { + views::UniqueWidgetPtr widget(std::make_unique<views::Widget>()); + widget->Init( + views::Widget::InitParams(views::Widget::InitParams::TYPE_WINDOW)); + widget->Show(); + + auto* immersive_fullscreen_controller = + chromeos::ImmersiveFullscreenController::Get(widget.get()); + chromeos::ImmersiveFullscreenControllerTestApi( + immersive_fullscreen_controller) + .SetupForTest(); + + EXPECT_FALSE(immersive_fullscreen_controller->IsEnabled()); + + // Fullscreen the framed widget, it should enter immersive mode. + widget->SetFullscreen(true); + EXPECT_TRUE(base::test::RunUntil( + [&]() { return immersive_fullscreen_controller->IsEnabled(); })); + + // Exiting fullscreen should also exit immersive mode. + widget->SetFullscreen(false); + EXPECT_TRUE(base::test::RunUntil( + [&]() { return !immersive_fullscreen_controller->IsEnabled(); })); +}
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_pane_view.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_pane_view.cc index c0c2a6c..6a71de0 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_pane_view.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_pane_view.cc
@@ -6,7 +6,6 @@ #include "chrome/browser/ui/views/desktop_capture/desktop_media_permission_pane_view.h" #include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/views/background.h" #include "ui/views/controls/scroll_view.h"
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc index c03b8ae..17de0338 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -280,9 +280,7 @@ std::unique_ptr<views::ScrollView> CreateScrollView(bool audio_requested) { auto scroll_view = std::make_unique<views::ScrollView>(); - scroll_view->SetBackgroundThemeColorId( - features::IsChromeRefresh2023() ? ui::kColorSysSurface4 - : ui::kColorSubtleEmphasisBackground); + scroll_view->SetBackgroundThemeColorId(ui::kColorSysSurface4); // The overflow indicator is disabled to reduce clutter next to the // separator to the audio control when audio is requested or the bottom of // the dialog when audio is not requested. @@ -367,9 +365,7 @@ SetModalType(params.modality); SetButtonLabel(ui::DIALOG_BUTTON_OK, l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SHARE)); - if (features::IsChromeRefresh2023()) { - SetButtonStyle(ui::DIALOG_BUTTON_CANCEL, ui::ButtonStyle::kTonal); - } + SetButtonStyle(ui::DIALOG_BUTTON_CANCEL, ui::ButtonStyle::kTonal); RegisterDeleteDelegateCallback(base::BindOnce( [](DesktopMediaPickerDialogView* dialog) { // If the dialog is being closed then notify the parent about it.
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc index 61b72fe..6f35ee64 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc
@@ -13,7 +13,6 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/base/ui_base_features.h" #include "ui/color/color_id.h" #include "ui/color/color_provider.h" #include "ui/gfx/canvas.h" @@ -55,19 +54,15 @@ source_id_(source_id), selected_(false) { icon_view_ = AddChildView(std::make_unique<views::ImageView>()); - image_view_ = AddChildView(features::IsChromeRefresh2023() - ? std::make_unique<RoundedCornerImageView>() - : std::make_unique<views::ImageView>()); + image_view_ = AddChildView(std::make_unique<RoundedCornerImageView>()); label_ = AddChildView(std::make_unique<views::Label>()); icon_view_->SetCanProcessEventsWithinSubtree(false); image_view_->SetCanProcessEventsWithinSubtree(false); SetFocusBehavior(FocusBehavior::ALWAYS); SetStyle(style); views::FocusRing::Install(this); - if (features::IsChromeRefresh2023()) { - views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), - kCornerRadius); - } + views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), + kCornerRadius); } DesktopMediaSourceView::~DesktopMediaSourceView() {} @@ -102,23 +97,14 @@ } } - if (features::IsChromeRefresh2023()) { - SetBackground(views::CreateRoundedRectBackground( - GetColorProvider()->GetColor(ui::kColorSysTonalContainer), - kCornerRadius)); - } else { - image_view_->SetBackground(views::CreateSolidBackground( - GetColorProvider()->GetColor(ui::kColorMenuItemBackgroundSelected))); - } + SetBackground(views::CreateRoundedRectBackground( + GetColorProvider()->GetColor(ui::kColorSysTonalContainer), + kCornerRadius)); label_->SetFontList(label_->font_list().Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); parent_->OnSelectionChanged(); } else { - if (features::IsChromeRefresh2023()) { - SetBackground(nullptr); - } else { - image_view_->SetBackground(nullptr); - } + SetBackground(nullptr); label_->SetFontList(label_->font_list().Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL)); }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc index b60c6707..b899d42 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list.cc
@@ -18,7 +18,6 @@ #include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/base/ui_base_features.h" #include "ui/color/color_provider.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/geometry/rounded_corners_f.h" @@ -200,17 +199,13 @@ std::unique_ptr<views::ScrollView> CreateScrollViewWithTable( std::unique_ptr<views::TableView> table) { - if (features::IsChromeRefresh2023()) { - auto scroll_view = std::make_unique<views::ScrollView>( - views::ScrollView::ScrollWithLayers::kEnabled); - scroll_view->SetDrawOverflowIndicator(false); - scroll_view->SetViewportRoundedCornerRadius(gfx::RoundedCornersF(8)); - scroll_view->SetContents(std::move(table)); - scroll_view->SetBorder(nullptr); - return scroll_view; - } else { - return views::TableView::CreateScrollViewWithTable(std::move(table)); - } + auto scroll_view = std::make_unique<views::ScrollView>( + views::ScrollView::ScrollWithLayers::kEnabled); + scroll_view->SetDrawOverflowIndicator(false); + scroll_view->SetViewportRoundedCornerRadius(gfx::RoundedCornersF(8)); + scroll_view->SetContents(std::move(table)); + scroll_view->SetBorder(nullptr); + return scroll_view; } } // namespace @@ -352,33 +347,17 @@ DesktopMediaListController::ListView::OnThemeChanged(); const ui::ColorProvider* const color_provider = GetColorProvider(); - if (features::IsChromeRefresh2023()) { - table_->SetBorder(nullptr); - } else { - table_->SetBorder(views::CreateSolidBorder( - /*thickness=*/1, - color_provider->GetColor(kColorDesktopMediaTabListBorder))); - } + table_->SetBorder(nullptr); - if (features::IsChromeRefresh2023()) { - scroll_view_->SetBackground(views::CreateRoundedRectBackground( - GetColorProvider()->GetColor(ui::kColorSysSurface4), 8)); - const SkColor background_color = - color_provider->GetColor(ui::kColorSysTonalContainer); - preview_wrapper_->SetBackground( - views::CreateRoundedRectBackground(background_color, 8)); - empty_preview_label_->SetBackground( - views::CreateRoundedRectBackground(background_color, 8)); - empty_preview_label_->SetBackgroundColor(background_color); - } else { - const SkColor background_color = - color_provider->GetColor(kColorDesktopMediaTabListPreviewBackground); - preview_wrapper_->SetBackground( - views::CreateSolidBackground(background_color)); - empty_preview_label_->SetBackground( - views::CreateSolidBackground(background_color)); - empty_preview_label_->SetBackgroundColor(background_color); - } + scroll_view_->SetBackground(views::CreateRoundedRectBackground( + GetColorProvider()->GetColor(ui::kColorSysSurface4), 8)); + const SkColor background_color = + color_provider->GetColor(ui::kColorSysTonalContainer); + preview_wrapper_->SetBackground( + views::CreateRoundedRectBackground(background_color, 8)); + empty_preview_label_->SetBackground( + views::CreateRoundedRectBackground(background_color, 8)); + empty_preview_label_->SetBackgroundColor(background_color); } std::optional<content::DesktopMediaID> DesktopMediaTabList::GetSelection() {
diff --git a/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc b/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc index 45de6e08..fb6514a3 100644 --- a/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc +++ b/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc
@@ -172,19 +172,14 @@ CreateDialogWidget(this, params.context, nullptr)->Show(); } - source_view_->SetBorder(features::IsChromeRefresh2023() - ? views::CreateThemedRoundedRectBorder( - 1, 4, ui::kColorSysPrimaryContainer) - : views::CreateThemedRoundedRectBorder( - 1, 2, kColorShareThisTabSourceViewBorder)); + source_view_->SetBorder(views::CreateThemedRoundedRectBorder( + 1, 4, ui::kColorSysPrimaryContainer)); SetButtonLabel(ui::DIALOG_BUTTON_OK, l10n_util::GetStringUTF16(IDS_SHARE_THIS_TAB_DIALOG_ALLOW)); SetButtonEnabled(ui::DIALOG_BUTTON_OK, false); - if (features::IsChromeRefresh2023()) { - SetButtonStyle(ui::DIALOG_BUTTON_OK, ui::ButtonStyle::kTonal); - SetButtonStyle(ui::DIALOG_BUTTON_CANCEL, ui::ButtonStyle::kTonal); - } + SetButtonStyle(ui::DIALOG_BUTTON_OK, ui::ButtonStyle::kTonal); + SetButtonStyle(ui::DIALOG_BUTTON_CANCEL, ui::ButtonStyle::kTonal); // Simply pressing ENTER without tab-key navigating to the button // must not accept the dialog, or else that'd be a security issue. @@ -272,10 +267,7 @@ audio_toggle_container->SetProperty(views::kMarginsKey, gfx::Insets::TLBR(8, 0, 0, 0)); audio_toggle_container->SetBackground( - features::IsChromeRefresh2023() - ? views::CreateThemedRoundedRectBackground(ui::kColorSysSurface4, 8) - : views::CreateThemedRoundedRectBackground( - kColorShareThisTabAudioToggleBackground, 4)); + views::CreateThemedRoundedRectBackground(ui::kColorSysSurface4, 8)); views::ImageView* audio_icon_view = audio_toggle_container->AddChildView( std::make_unique<views::ImageView>());
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc index c604017..4416e0f 100644 --- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc
@@ -253,14 +253,17 @@ } void CookieControlsIconView::ShowCookieControlsBubble() { - bubble_coordinator_->ShowBubble( - delegate()->GetWebContentsForPageActionIconView(), controller_.get()); CHECK(browser_->window()); - CHECK(ShouldBeVisible()); + // Need to close IPH before opening bubble view, as on some platforms closing + // the IPH bubble can cause activation to move between windows, and cookie + // control bubble is close-on-deactivate. browser_->window()->CloseFeaturePromo( feature_engagement::kIPHCookieControlsFeature); browser_->window()->NotifyFeatureEngagementEvent( feature_engagement::events::kCookieControlsBubbleShown); + bubble_coordinator_->ShowBubble( + delegate()->GetWebContentsForPageActionIconView(), controller_.get()); + CHECK(ShouldBeVisible()); RecordOpenedAction(icon_visible_, protections_on_); if (did_animate_) { base::RecordAction(base::UserMetricsAction(
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc index 07c74ab3..68a90c8d 100644 --- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc +++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
@@ -443,7 +443,7 @@ // Check that IPH shows, then open cookie controls bubble via icon. InAnyContext(WaitForShow( user_education::HelpBubbleView::kHelpBubbleElementIdForTesting)), - PressButton(kCookieControlsIconElementId), + FlushEvents(), PressButton(kCookieControlsIconElementId), // Cookie controls bubble should show and IPH should close. InAnyContext( WaitForShow(CookieControlsBubbleView::kCookieControlsBubble)),
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.cc b/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.cc index 1b95c6d4..12690ec 100644 --- a/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.cc +++ b/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.cc
@@ -9,11 +9,14 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/lens/lens_overlay_controller.h" +#include "chrome/browser/ui/lens/lens_overlay_dismissal_source.h" #include "chrome/browser/ui/lens/lens_untrusted_ui.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/file_select_listener.h" +#include "content/public/common/input/native_web_keyboard_event.h" #include "ui/base/metadata/metadata_impl_macros.h" using SidePanelWebUIViewT_LensUntrustedUI = @@ -22,6 +25,26 @@ SidePanelWebUIViewT) END_METADATA +namespace { + +bool IsEscapeEvent(const content::NativeWebKeyboardEvent& event) { + return event.GetType() == + content::NativeWebKeyboardEvent::Type::kRawKeyDown && + event.windows_key_code == ui::VKEY_ESCAPE; +} + +Browser* BrowserFromWebContents(content::WebContents* web_contents) { + BrowserWindow* window = + BrowserWindow::FindBrowserWindowWithWebContents(web_contents); + auto* browser_view = static_cast<BrowserView*>(window); + if (browser_view) { + return browser_view->browser(); + } + return nullptr; +} + +} // namespace + LensOverlaySidePanelWebView::LensOverlaySidePanelWebView(Profile* profile) : SidePanelWebUIViewT( base::RepeatingClosure(), @@ -44,16 +67,36 @@ const content::OpenURLParams& params, base::OnceCallback<void(content::NavigationHandle&)> navigation_handle_callback) { - BrowserWindow* window = - BrowserWindow::FindBrowserWindowWithWebContents(web_contents()); - auto* browser_view = static_cast<BrowserView*>(window); - if (browser_view && browser_view->browser()) { - browser_view->browser()->OpenURL(params, - std::move(navigation_handle_callback)); + Browser* browser = BrowserFromWebContents(web_contents()); + if (browser) { + browser->OpenURL(params, std::move(navigation_handle_callback)); } return nullptr; } +bool LensOverlaySidePanelWebView::HandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event) { + if (IsEscapeEvent(event)) { + Browser* browser = BrowserFromWebContents(web_contents()); + if (browser) { + content::WebContents* tab_web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + LensOverlayController* controller = + LensOverlayController::GetController(tab_web_contents); + DCHECK(controller); + + if (controller->IsOverlayShowing()) { + controller->CloseUIAsync( + lens::LensOverlayDismissalSource::kEscapeKeyPress); + return true; + } + } + } + return unhandled_keyboard_event_handler_.HandleKeyboardEvent( + event, GetFocusManager()); +} + LensOverlaySidePanelWebView::~LensOverlaySidePanelWebView() = default; BEGIN_METADATA(LensOverlaySidePanelWebView)
diff --git a/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.h b/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.h index dca39ee..e4eb80d3 100644 --- a/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.h +++ b/chrome/browser/ui/views/side_panel/lens/lens_overlay_side_panel_web_view.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/webui/top_chrome/webui_contents_wrapper.h" #include "content/public/browser/file_select_listener.h" #include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" #include "ui/views/controls/webview/webview.h" class Profile; @@ -41,8 +42,15 @@ navigation_handle_callback) override; bool HandleContextMenu(content::RenderFrameHost& render_frame_host, const content::ContextMenuParams& params) override; + bool HandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event) override; private: + // A handler to handle unhandled keyboard messages coming back from the + // renderer process. + views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; + base::WeakPtrFactory<LensOverlaySidePanelWebView> weak_factory_{this}; };
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 6737e17..cc6f387 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -57,6 +57,7 @@ #include "components/feature_engagement/public/tracker.h" #include "components/omnibox/browser/autocomplete_classifier.h" #include "components/omnibox/browser/autocomplete_match.h" +#include "components/performance_manager/public/user_tuning/prefs.h" #include "components/saved_tab_groups/features.h" #include "components/tab_groups/tab_group_color.h" #include "components/tab_groups/tab_group_id.h" @@ -199,6 +200,15 @@ menu_model_factory_ = std::make_unique<TabMenuModelFactory>(); } model_->SetTabStripUI(this); + + should_show_discard_indicator_ = g_browser_process->local_state()->GetBoolean( + performance_manager::user_tuning::prefs::kDiscardRingTreatmentEnabled); + local_state_registrar_.Init(g_browser_process->local_state()); + local_state_registrar_.Add( + performance_manager::user_tuning::prefs::kDiscardRingTreatmentEnabled, + base::BindRepeating( + &BrowserTabStripController::OnDiscardRingTreatmentEnabledChanged, + base::Unretained(this))); } BrowserTabStripController::~BrowserTabStripController() { @@ -805,6 +815,9 @@ tabstrip_->AddTabAt(index, TabRendererData::FromTabInModel(model_, index)); + tabstrip_->tab_at(index)->SetShouldShowDiscardIndicator( + should_show_discard_indicator_); + // Try to show tab search IPH if needed. constexpr int kTabSearchIPHTriggerThreshold = 8; if (tabstrip_->GetTabCount() >= kTabSearchIPHTriggerThreshold) { @@ -812,3 +825,12 @@ feature_engagement::kIPHTabSearchFeature); } } + +void BrowserTabStripController::OnDiscardRingTreatmentEnabledChanged() { + should_show_discard_indicator_ = g_browser_process->local_state()->GetBoolean( + performance_manager::user_tuning::prefs::kDiscardRingTreatmentEnabled); + for (int tab_index = 0; tab_index < tabstrip_->GetTabCount(); ++tab_index) { + tabstrip_->tab_at(tab_index)->SetShouldShowDiscardIndicator( + should_show_discard_indicator_); + } +}
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index af30168..46ef73c 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -158,6 +158,8 @@ // Adds a tab. void AddTab(content::WebContents* contents, int index); + void OnDiscardRingTreatmentEnabledChanged(); + raw_ptr<TabStripModel> model_; raw_ptr<TabStrip> tabstrip_; @@ -175,9 +177,11 @@ // tabs. std::unique_ptr<ImmersiveRevealedLock> immersive_reveal_lock_; - PrefChangeRegistrar local_pref_registrar_; + PrefChangeRegistrar local_state_registrar_; std::unique_ptr<TabMenuModelFactory> menu_model_factory_; + + bool should_show_discard_indicator_ = true; }; #endif // CHROME_BROWSER_UI_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 660bde8..07f93f0a 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -998,6 +998,10 @@ return alert_states[0]; } +void Tab::SetShouldShowDiscardIndicator(bool enabled) { + icon_->SetShouldShowDiscardIndicator(enabled); +} + void Tab::MaybeAdjustLeftForPinnedTab(gfx::Rect* bounds, int visual_width) const { if (ShouldRenderAsNormalTab()) {
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index 7a7cfdf9..c5bf5d6 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -191,6 +191,8 @@ return alert_indicator_button_; } + void SetShouldShowDiscardIndicator(bool enabled); + private: class TabCloseButtonObserver; friend class AlertIndicatorButtonTest;
diff --git a/chrome/browser/ui/views/tabs/tab_icon.cc b/chrome/browser/ui/views/tabs/tab_icon.cc index fc97943..9ebdb23 100644 --- a/chrome/browser/ui/views/tabs/tab_icon.cc +++ b/chrome/browser/ui/views/tabs/tab_icon.cc
@@ -11,6 +11,7 @@ #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "cc/paint/paint_flags.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/favicon/favicon_utils.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/browser.h" @@ -23,6 +24,7 @@ #include "chrome/common/webui_url_constants.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/grit/components_scaled_resources.h" +#include "components/performance_manager/public/user_tuning/prefs.h" #include "content/public/common/url_constants.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/resource/resource_bundle.h" @@ -240,6 +242,24 @@ increased_discard_indicator_radius_ = radius; } +void TabIcon::SetShouldShowDiscardIndicator(bool enabled) { + should_show_discard_indicator_ = enabled; + bool show_discard_indicator = is_discarded_ && should_show_discard_indicator_; + if (was_discard_indicator_shown_ != show_discard_indicator) { + was_discard_indicator_shown_ = show_discard_indicator; + + // Directly set animations to their end states and do not animate. + if (show_discard_indicator) { + tab_discard_animation_.SetCurrentValue(1); + favicon_size_animation_.Reset(0); + } else { + tab_discard_animation_.SetCurrentValue(0); + favicon_size_animation_.Reset(1); + } + SchedulePaint(); + } +} + void TabIcon::OnPaint(gfx::Canvas* canvas) { // Compute the bounds adjusted for the hiding fraction. gfx::Rect contents_bounds = GetContentsBounds(); @@ -521,10 +541,12 @@ UpdateThemedFavicon(); } -void TabIcon::SetDiscarded(bool should_show_discard_status) { - if (was_discard_indicator_shown_ != should_show_discard_status) { - was_discard_indicator_shown_ = should_show_discard_status; - if (should_show_discard_status) { +void TabIcon::SetDiscarded(bool discarded) { + is_discarded_ = discarded; + bool show_discard_indicator = is_discarded_ && should_show_discard_indicator_; + if (was_discard_indicator_shown_ != show_discard_indicator) { + was_discard_indicator_shown_ = show_discard_indicator; + if (show_discard_indicator) { tab_discard_animation_.Start(); favicon_size_animation_.Hide();
diff --git a/chrome/browser/ui/views/tabs/tab_icon.h b/chrome/browser/ui/views/tabs/tab_icon.h index caca980..1843712 100644 --- a/chrome/browser/ui/views/tabs/tab_icon.h +++ b/chrome/browser/ui/views/tabs/tab_icon.h
@@ -83,6 +83,7 @@ bool GetActiveStateForTesting() { return is_active_tab_; } void EnlargeDiscardIndicatorRadius(int radius); + void SetShouldShowDiscardIndicator(bool enabled); private: class CrashAnimation; @@ -191,6 +192,13 @@ // fade out gfx::LinearAnimation tab_discard_animation_; + // The discard indicator will be shown only if the tab is discarded and the + // discard ring treatment pref is enabled. Keep track of both of the component + // booleans, in order to determine if the discard indicator is shown/unshown + // due to a change in the discard status or a change to the pref, because + // we don't want to animate the discard ring in the latter case. + bool is_discarded_ = false; + bool should_show_discard_indicator_ = true; bool was_discard_indicator_shown_ = false; // Crash animation (in place of favicon). Lazily created since most of the
diff --git a/chrome/browser/ui/views/user_education/feature_promo_lifecycle_interactive_uitest.cc b/chrome/browser/ui/views/user_education/feature_promo_lifecycle_interactive_uitest.cc index 9b302d7..ef793333 100644 --- a/chrome/browser/ui/views/user_education/feature_promo_lifecycle_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/feature_promo_lifecycle_interactive_uitest.cc
@@ -41,6 +41,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event_modifiers.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/views/interaction/widget_focus_observer.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -438,8 +439,22 @@ IN_PROC_BROWSER_TEST_F(FeaturePromoLifecycleUiTest, PressingEscRecordsHistogram) { const ui::Accelerator kEsc(ui::VKEY_ESCAPE, ui::MODIFIER_NONE); + views::Widget* bubble_widget = nullptr; RunTestSequence( ShowPromoRecordingTime(kFeaturePromoLifecycleTestPromo), + // Ensure that the bubble is active before trying to send an accelerator; + // widgets cannot accept accelerators before they become active. + // TODO(dfried): need to create a common WaitForActivation() verb. + WithView(user_education::HelpBubbleView::kHelpBubbleElementIdForTesting, + [&bubble_widget](views::View* view) { + bubble_widget = view->GetWidget(); + }), + If([&bubble_widget]() { return !bubble_widget->IsActive(); }, + Steps(ObserveState(views::test::kCurrentWidgetFocus), + WaitForState(views::test::kCurrentWidgetFocus, + [&bubble_widget]() { + return bubble_widget->GetNativeView(); + }))), SendAccelerator( user_education::HelpBubbleView::kHelpBubbleElementIdForTesting, kEsc), WaitForHide(
diff --git a/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc index 6b0ebc4b..b8030fd5 100644 --- a/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc
@@ -128,10 +128,11 @@ ShowHelpBubble(kTabGroupEditorBubbleId, std::move(params)), // Activate the help bubble. This should not cause the editor to close. ActivateSurface(HelpBubbleView::kHelpBubbleElementIdForTesting), - // Re-Activate the dialog. - ActivateSurface(kTabGroupEditorBubbleId), // Close the help bubble. CloseHelpBubble(), + // Re-Activate the dialog. It may or may not receive activation when the + // help bubble closes. + ActivateSurface(kTabGroupEditorBubbleId), // Now that the help bubble is gone, locate the editor again and transfer // activation to its primary window widget (the browser window) - this // should close the editor as it is no longer pinned by the help bubble.
diff --git a/chrome/browser/ui/webui/BUILD.gn b/chrome/browser/ui/webui/BUILD.gn index 61554ef..9ca13c6e 100644 --- a/chrome/browser/ui/webui/BUILD.gn +++ b/chrome/browser/ui/webui/BUILD.gn
@@ -51,6 +51,7 @@ "//ash/webui/os_feedback_ui", "//ash/webui/print_management", "//ash/webui/print_preview_cros", + "//ash/webui/sanitize_ui", "//ash/webui/scanning", "//ash/webui/shimless_rma", "//ash/webui/shortcut_customization_ui",
diff --git a/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc b/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc index d66ab17..362f4a2 100644 --- a/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc +++ b/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc
@@ -33,6 +33,7 @@ #include "ash/webui/personalization_app/personalization_app_ui.h" #include "ash/webui/print_management/print_management_ui.h" #include "ash/webui/print_preview_cros/print_preview_cros_ui.h" +#include "ash/webui/sanitize_ui/sanitize_ui.h" #include "ash/webui/scanning/scanning_ui.h" #include "ash/webui/shimless_rma/shimless_rma.h" #include "ash/webui/shortcut_customization_ui/shortcut_customization_app_ui.h" @@ -203,6 +204,15 @@ return std::make_unique<eche_app::EcheAppUIConfig>(create_controller_func); } +std::unique_ptr<content::WebUIConfig> MakeSanitizeUIConfig() { + CreateWebUIControllerFunc create_controller_func = base::BindRepeating( + [](content::WebUI* web_ui, + const GURL& url) -> std::unique_ptr<content::WebUIController> { + return std::make_unique<SanitizeDialogUI>(web_ui); + }); + return std::make_unique<SanitizeDialogUIConfig>(create_controller_func); +} + void RegisterAshChromeWebUIConfigs() { // Add `WebUIConfig`s for Ash ChromeOS to the list here. // @@ -296,6 +306,7 @@ std::make_unique<printing::print_preview::PrintPreviewCrosUIConfig>()); map.AddWebUIConfig(std::make_unique<multidevice::ProximityAuthUIConfig>()); map.AddWebUIConfig(std::make_unique<RemoteMaintenanceCurtainUIConfig>()); + map.AddWebUIConfig(MakeSanitizeUIConfig()); map.AddWebUIConfig( MakeComponentConfigWithDelegate<ScanningUIConfig, ScanningUI, ChromeScanningAppDelegate>());
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 17c9955..6a0c524 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
@@ -418,6 +418,8 @@ IDS_SETTINGS_APP_PARENTAL_CONTROLS_CONFIRM_PIN_TITLE}, {"appParentalControlsForgotPinLinkName", IDS_SETTINGS_APP_PARENTAL_CONTROLS_FORGOT_PIN_LINK_NAME}, + {"appParentalControlsPinMismatchErrorText", + IDS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_MISMATCH_ERROR_TEXT}, {"appParentalControlsTitle", IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_LABEL}, {"appParentalControlsSubtitle", IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_SUBLABEL},
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index c3064ce..8b7ba4e 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -1072,6 +1072,7 @@ GURL(chrome::kChromeUIOSSettingsURL), GURL(chrome::kChromeUIPowerUrl), GURL(chrome::kChromeUIPrintManagementUrl), + GURL(chrome::kChromeUISanitizeAppURL), GURL(chrome::kChromeUIScanningAppURL), GURL(chrome::kChromeUISensorInfoURL), GURL(chrome::kChromeUISetTimeURL),
diff --git a/chrome/browser/ui/webui/commerce/product_specifications_ui.cc b/chrome/browser/ui/webui/commerce/product_specifications_ui.cc index a252fff..0c57e2f 100644 --- a/chrome/browser/ui/webui/commerce/product_specifications_ui.cc +++ b/chrome/browser/ui/webui/commerce/product_specifications_ui.cc
@@ -68,6 +68,7 @@ {"openTabs", IDS_PRODUCT_SPECIFICATIONS_OPEN_TABS_SECTION}, {"recentlyViewedTabs", IDS_PRODUCT_SPECIFICATIONS_RECENTLY_VIEWED_TABS_SECTION}, + {"removeColumn", IDS_PRODUCT_SPECIFICATIONS_REMOVE_COLUMN}, {"renameGroup", IDS_PRODUCT_SPECIFICATIONS_RENAME_GROUP}, {"seeAll", IDS_PRODUCT_SPECIFICATIONS_SEE_ALL}, };
diff --git a/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc b/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc index 54ad810..6239981a 100644 --- a/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc +++ b/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
@@ -468,11 +468,6 @@ file_value->has_safe_browsing_verdict = WasSafeBrowsingVerdictObtained(download_item); - if (download_model.IsDangerous()) { - base::UmaHistogramBoolean( - "Download.DownloadsPageDangerousWarningWasShownBefore", - download_model.WasUIWarningShown()); - } MaybeRecordDangerousDownloadWarningShown(download_model); if (download_item->IsDangerous()) {
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc index a33d79d..2162bcb 100644 --- a/chrome/browser/ui/webui/downloads/downloads_ui.cc +++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -134,11 +134,15 @@ {"controlOpenAnyway", IDS_OPEN_DOWNLOAD_ANYWAY}, {"toastClearedAll", IDS_DOWNLOAD_TOAST_CLEARED_ALL}, {"toastRemovedFromList", IDS_DOWNLOAD_TOAST_REMOVED_FROM_LIST}, + {"toastDeletedFromHistoryStillOnDevice", + IDS_DOWNLOADS_TOAST_DELETED_FROM_HISTORY_STILL_ON_DEVICE}, + {"toastDeletedFromHistory", IDS_DOWNLOADS_TOAST_DELETED_FROM_HISTORY}, {"undo", IDS_DOWNLOAD_UNDO}, {"controlKeepDangerous", IDS_DOWNLOAD_KEEP_DANGEROUS_FILE}, {"controlKeepSuspicious", IDS_DOWNLOAD_KEEP_SUSPICIOUS_FILE}, {"controlKeepUnverified", IDS_DOWNLOAD_KEEP_UNVERIFIED_FILE}, {"controlKeepInsecure", IDS_DOWNLOAD_KEEP_INSECURE_FILE}, + {"controlDeleteFromHistory", IDS_DOWNLOAD_DELETE_FROM_HISTORY}, // Accessible labels for file icons. {"accessibleLabelDangerous", @@ -172,6 +176,9 @@ {"esbDownloadRowPromoString", IDS_DOWNLOAD_ROW_ESB_PROMOTION}, {"esbDownloadRowPromoA11y", IDS_DOWNLOAD_ROW_ESB_PROMO_A11Y}, #endif + // Dangerous File + {"noSafeBrowsingDesc", + IDS_BLOCK_DOWNLOAD_REASON_UNVERIFIED_NO_SAFE_BROWSING}, }; source->AddLocalizedStrings(kStrings); @@ -221,16 +228,6 @@ improved_download_warnings_ux ? IDS_BLOCK_DOWNLOAD_REASON_INSECURE : IDS_BLOCK_REASON_INSECURE_DOWNLOAD); - source->AddLocalizedString( - "noSafeBrowsingDesc", - IDS_BLOCK_DOWNLOAD_REASON_UNVERIFIED_NO_SAFE_BROWSING); - source->AddLocalizedString("controlDeleteFromHistory", - IDS_DOWNLOAD_DELETE_FROM_HISTORY); - source->AddLocalizedString( - "toastDeletedFromHistoryStillOnDevice", - IDS_DOWNLOADS_TOAST_DELETED_FROM_HISTORY_STILL_ON_DEVICE); - source->AddLocalizedString("toastDeletedFromHistory", - IDS_DOWNLOADS_TOAST_DELETED_FROM_HISTORY); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // Download Row ESB Promo:
diff --git a/chrome/browser/ui/webui/settings/performance_handler.cc b/chrome/browser/ui/webui/settings/performance_handler.cc index b3739d4..c361130 100644 --- a/chrome/browser/ui/webui/settings/performance_handler.cc +++ b/chrome/browser/ui/webui/settings/performance_handler.cc
@@ -47,11 +47,6 @@ base::BindRepeating(&PerformanceHandler::HandleOpenSpeedFeedbackDialog, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "onDiscardRingTreatmentEnabledChanged", - base::BindRepeating( - &PerformanceHandler::HandleSetDiscardRingTreatmentEnabled, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( "validateTabDiscardExceptionRule", base::BindRepeating( &PerformanceHandler::HandleValidateTabDiscardExceptionRule, @@ -155,21 +150,6 @@ unused, unused, category_tag, unused); } -void PerformanceHandler::HandleSetDiscardRingTreatmentEnabled( - const base::Value::List& args) { - for (Browser* browser : *BrowserList::GetInstance()) { - TabStripModel* tab_strip_model = browser->tab_strip_model(); - TabStrip* tab_strip = - BrowserView::GetBrowserViewForBrowser(browser)->tabstrip(); - - for (int tab_index = 0; tab_index < tab_strip_model->count(); ++tab_index) { - TabRendererData tab_data = - TabRendererData::FromTabInModel(tab_strip_model, tab_index); - tab_strip->SetTabData(tab_index, tab_data); - } - } -} - void PerformanceHandler::HandleValidateTabDiscardExceptionRule( const base::Value::List& args) { CHECK_EQ(2U, args.size());
diff --git a/chrome/browser/ui/webui/settings/performance_handler.h b/chrome/browser/ui/webui/settings/performance_handler.h index f7db51f9..d64af3e 100644 --- a/chrome/browser/ui/webui/settings/performance_handler.h +++ b/chrome/browser/ui/webui/settings/performance_handler.h
@@ -54,7 +54,6 @@ void HandleOpenMemorySaverFeedbackDialog(const base::Value::List& args); void HandleOpenSpeedFeedbackDialog(const base::Value::List& args); void HandleOpenFeedbackDialog(const std::string category_tag); - void HandleSetDiscardRingTreatmentEnabled(const base::Value::List& args); void HandleValidateTabDiscardExceptionRule(const base::Value::List& args); };
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index effe1ea9..2898ada 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1716198910-7302f5984cf26e384d93e0ba7cac1e687a2f3214-949984c85d55f282b8c4481e6521278779bc834b.profdata +chrome-android64-main-1716220190-2c2a5c796ffdc7b4a581384157167f4f7fab8cdf-678d8f10d39d33e2e735073ce1601c09c8a8bd15.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 7533bcfe..9745d35 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1716206072-48d789455a742d3d2e83fa237677da00074a3ea9-867547ce2c98b7406af3c55b71159380f29396ff.profdata +chrome-linux-main-1716227899-0d1c76fe8e7ff6a9c05f6fd9f90cd5de8ab61b73-bf4aa26514a0038ceeb4b7a7d5b8c4fa06818c41.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index d5c7684..3508422 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1716206072-7219c4e08bddc0fd39739921ec25dfd4b5ae95e7-867547ce2c98b7406af3c55b71159380f29396ff.profdata +chrome-win-arm64-main-1716227899-a68315bb1cb209581be07e6c4093562aa63685c7-bf4aa26514a0038ceeb4b7a7d5b8c4fa06818c41.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 4083d039..a0e6475 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1716206072-127069e7622c3a5304876e728addd92257e09c71-867547ce2c98b7406af3c55b71159380f29396ff.profdata +chrome-win32-main-1716227899-54f9bf9c31c7f04e926f3c3841ddaf2d3cfecc9c-bf4aa26514a0038ceeb4b7a7d5b8c4fa06818c41.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index ceb1e5e..b050d0d 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1716206072-926e9a255408f922e88a7d2c9a37b36963a17ecc-867547ce2c98b7406af3c55b71159380f29396ff.profdata +chrome-win64-main-1716227899-626552aa2f4c2428da68fcfe649ad94790346a6a-bf4aa26514a0038ceeb4b7a7d5b8c4fa06818c41.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 81bbfbf..64d0d048 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -255,6 +255,7 @@ "$root_gen_dir/ash/webui/ash_projector_annotator_untrusted_resources.pak", "$root_gen_dir/ash/webui/ash_projector_app_untrusted_resources.pak", "$root_gen_dir/ash/webui/ash_projector_common_resources.pak", + "$root_gen_dir/ash/webui/ash_sanitize_app_resources.pak", "$root_gen_dir/ash/webui/ash_scanning_app_resources.pak", "$root_gen_dir/ash/webui/ash_shimless_rma_resources.pak", "$root_gen_dir/ash/webui/ash_shortcut_customization_app_resources.pak", @@ -349,6 +350,7 @@ "//ash/webui/resources:projector_app_bundle_resources", "//ash/webui/resources:projector_app_untrusted_resources", "//ash/webui/resources:projector_common_resources", + "//ash/webui/sanitize_ui/resources:resources", "//ash/webui/scanning/resources:resources", "//ash/webui/shimless_rma/resources:resources", "//ash/webui/shortcut_customization_ui/resources:resources",
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 3f61499..3bf43d72 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -412,6 +412,7 @@ const char kChromeUIPowerHost[] = "power"; const char kChromeUIPowerUrl[] = "chrome://power"; const char kChromeUIRemoteManagementCurtainHost[] = "security-curtain"; +const char kChromeUISanitizeAppURL[] = "chrome://sanitize"; const char kChromeUIScanningAppURL[] = "chrome://scanning"; const char kChromeUISetTimeHost[] = "set-time"; const char kChromeUISetTimeURL[] = "chrome://set-time/";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 56ed503..86dfd75c 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -377,6 +377,7 @@ extern const char kChromeUIPowerHost[]; extern const char kChromeUIPowerUrl[]; extern const char kChromeUIRemoteManagementCurtainHost[]; +extern const char kChromeUISanitizeAppURL[]; extern const char kChromeUIScanningAppURL[]; extern const char kChromeUISetTimeHost[]; extern const char kChromeUISetTimeURL[];
diff --git a/chrome/services/sharing/nearby/platform/BUILD.gn b/chrome/services/sharing/nearby/platform/BUILD.gn index fae85f9..9d5c3d5 100644 --- a/chrome/services/sharing/nearby/platform/BUILD.gn +++ b/chrome/services/sharing/nearby/platform/BUILD.gn
@@ -70,6 +70,8 @@ "webrtc.h", "wifi_direct_medium.cc", "wifi_direct_medium.h", + "wifi_direct_server_socket.cc", + "wifi_direct_server_socket.h", "wifi_lan_medium.cc", "wifi_lan_medium.h", "wifi_lan_server_socket.cc",
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.cc b/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.cc index 70801d0..14ee75d 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.cc
@@ -123,12 +123,29 @@ namespace nearby::chrome { +std::unique_ptr<BleV2GattClient::GattService> +BleV2GattClient::GattService::Factory::Create() { + return base::WrapUnique(new BleV2GattClient::GattService()); +} + +BleV2GattClient::GattService::Factory::~Factory() = default; + +BleV2GattClient::GattService::GattService() = default; +BleV2GattClient::GattService::~GattService() = default; + BleV2GattClient::BleV2GattClient( - mojo::PendingRemote<bluetooth::mojom::Device> device) + mojo::PendingRemote<bluetooth::mojom::Device> device, + std::unique_ptr<GattService::Factory> gatt_service_factory) : task_runner_( base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})), + gatt_service_factory_(std::move(gatt_service_factory)), remote_device_(std::move(device), /*bind_task_runner=*/task_runner_) { CHECK(remote_device_.is_bound()); + + remote_device_.set_disconnect_handler( + base::BindOnce(&BleV2GattClient::OnMojoDisconnect, + weak_ptr_factory_.GetWeakPtr()), + task_runner_); } BleV2GattClient::~BleV2GattClient() { @@ -288,10 +305,6 @@ remote_device_->Disconnect(); } -BleV2GattClient::GattService::GattService() = default; - -BleV2GattClient::GattService::~GattService() = default; - void BleV2GattClient::DoDiscoverServices( base::WaitableEvent* discover_services_waitable_event) { CHECK(task_runner_->RunsTasksInCurrentSequence()); @@ -323,7 +336,7 @@ for (const auto& service : services) { Uuid nearby_service_uuid = BluetoothUuidToNearbyUuid(service->uuid); uuid_to_discovered_gatt_service_map_.insert_or_assign( - std::string(nearby_service_uuid), std::make_unique<GattService>()); + std::string(nearby_service_uuid), gatt_service_factory_->Create()); uuid_to_discovered_gatt_service_map_.at(std::string(nearby_service_uuid)) ->service_info = service.Clone(); } @@ -476,11 +489,15 @@ void BleV2GattClient::Shutdown(base::WaitableEvent* shutdown_waitable_event) { CHECK(task_runner_->RunsTasksInCurrentSequence()); - Disconnect(); + // The `remote_device_` might have already been reset in `OnMojoDisconnect()`. + if (remote_device_.is_bound()) { + Disconnect(); - // Note that resetting the Remote will cancel any pending callbacks, including - // those already in the task queue. - remote_device_.reset(); + // Note that resetting the Remote will cancel any pending callbacks, + // including those already in the task queue. + remote_device_.reset(); + } + uuid_to_discovered_gatt_service_map_.clear(); // Cancel all pending calls. This is sequence safe because all @@ -493,4 +510,10 @@ shutdown_waitable_event->Signal(); } +void BleV2GattClient::OnMojoDisconnect() { + LOG(WARNING) << __func__ << ": Device remote unexpectedly disconnected"; + remote_device_.reset(); + uuid_to_discovered_gatt_service_map_.clear(); +} + } // namespace nearby::chrome
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.h b/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.h index add77b3..c6b88c8 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.h +++ b/chrome/services/sharing/nearby/platform/ble_v2_gatt_client.h
@@ -5,6 +5,7 @@ #ifndef CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLE_V2_GATT_CLIENT_H_ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_BLE_V2_GATT_CLIENT_H_ +#include "base/memory/weak_ptr.h" #include "device/bluetooth/public/mojom/device.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" @@ -19,8 +20,31 @@ class BleV2GattClient : public ::nearby::api::ble_v2::GattClient { public: - explicit BleV2GattClient( - mojo::PendingRemote<bluetooth::mojom::Device> device); + // Representation of the remote GattServices discovered by BleV2GattClient. + class GattService { + public: + class Factory { + public: + virtual std::unique_ptr<GattService> Create(); + + virtual ~Factory(); + }; + + virtual ~GattService(); + GattService(GattService&) = delete; + GattService& operator=(GattService&) = delete; + + bluetooth::mojom::ServiceInfoPtr service_info; + std::optional<std::vector<bluetooth::mojom::CharacteristicInfoPtr>> + characteristics; + + protected: + GattService(); + }; + + BleV2GattClient(mojo::PendingRemote<bluetooth::mojom::Device> device, + std::unique_ptr<GattService::Factory> gatt_service_factory = + std::make_unique<GattService::Factory>()); ~BleV2GattClient() override; BleV2GattClient(const BleV2GattClient&) = delete; @@ -47,15 +71,6 @@ void Disconnect() override; private: - struct GattService { - GattService(); - ~GattService(); - - bluetooth::mojom::ServiceInfoPtr service_info; - std::optional<std::vector<bluetooth::mojom::CharacteristicInfoPtr>> - characteristics; - }; - void DoDiscoverServices( base::WaitableEvent* discover_services_waitable_event); void OnGetGattServices( @@ -87,6 +102,7 @@ const Uuid& characteristic_uuid); void Shutdown(base::WaitableEvent* shutdown_waitable_event); + void OnMojoDisconnect(); bool have_gatt_services_been_discovered_ = false; std::map<std::string, std::unique_ptr<GattService>> @@ -102,7 +118,11 @@ base::flat_set<raw_ptr<base::WaitableEvent>> pending_read_characteristic_waitable_events_; + std::unique_ptr<GattService::Factory> gatt_service_factory_; + mojo::SharedRemote<bluetooth::mojom::Device> remote_device_; + + base::WeakPtrFactory<BleV2GattClient> weak_ptr_factory_{this}; }; } // namespace nearby::chrome
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_gatt_client_unittest.cc b/chrome/services/sharing/nearby/platform/ble_v2_gatt_client_unittest.cc index c8d30c2..724b795 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_gatt_client_unittest.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_gatt_client_unittest.cc
@@ -6,11 +6,13 @@ #include "base/memory/raw_ptr.h" #include "base/task/thread_pool.h" +#include "base/test/bind.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "base/threading/thread_restrictions.h" #include "chrome/services/sharing/nearby/test_support/fake_device.h" +#include "device/bluetooth/public/mojom/device.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/bindings/shared_remote.h" @@ -46,6 +48,40 @@ return characteristic_infos; } +class FakeGattService : public nearby::chrome::BleV2GattClient::GattService { + public: + explicit FakeGattService(base::OnceClosure on_destroyed_callback) + : on_destroyed_callback_(std::move(on_destroyed_callback)) {} + + ~FakeGattService() override { + if (on_destroyed_callback_) { + std::move(on_destroyed_callback_).Run(); + } + } + + private: + base::OnceClosure on_destroyed_callback_; +}; + +class FakeGattServiceFactory + : public nearby::chrome::BleV2GattClient::GattService::Factory { + public: + std::unique_ptr<nearby::chrome::BleV2GattClient::GattService> Create() + override { + return std::make_unique<FakeGattService>( + std::move(next_fake_gatt_service_destroyed_callback_)); + } + + void SetNextFakeGattServiceDestroyedCallback( + base::OnceClosure on_destroyed_callback) { + next_fake_gatt_service_destroyed_callback_ = + std::move(on_destroyed_callback); + } + + private: + base::OnceClosure next_fake_gatt_service_destroyed_callback_; +}; + } // namespace namespace nearby::chrome { @@ -61,22 +97,29 @@ auto fake_device = std::make_unique<bluetooth::FakeDevice>(); fake_device_ = fake_device.get(); mojo::PendingRemote<bluetooth::mojom::Device> pending_device; - mojo::MakeSelfOwnedReceiver( + device_receiver_ = mojo::MakeSelfOwnedReceiver( std::move(fake_device), pending_device.InitWithNewPipeAndPassReceiver()); - ble_v2_gatt_client_ = - std::make_unique<BleV2GattClient>(std::move(pending_device)); + + auto fake_gatt_service_factory = std::make_unique<FakeGattServiceFactory>(); + fake_gatt_service_factory_ = fake_gatt_service_factory.get(); + ble_v2_gatt_client_ = std::make_unique<BleV2GattClient>( + std::move(pending_device), std::move(fake_gatt_service_factory)); } void TearDown() override { - base::RunLoop run_loop; - fake_device_->set_on_disconnected_callback(run_loop.QuitClosure()); - ble_v2_gatt_client_->Disconnect(); - run_loop.Run(); + // `fake_device_` might be invalided if this is run during the + // `DisconnectHandler()` test. + if (fake_device_) { + base::RunLoop run_loop; + fake_device_->set_on_disconnected_callback(run_loop.QuitClosure()); + ble_v2_gatt_client_->Disconnect(); + run_loop.Run(); - // Need to reset `fake_device_` since it gets deleted on disconnect to avoid - // dangling raw_ptr. - fake_device_ = nullptr; + // Need to reset `fake_device_` since it gets deleted on disconnect to + // avoid dangling raw_ptr. + fake_device_ = nullptr; + } } void CallDiscoverServiceAndCharacteristics( @@ -125,7 +168,9 @@ protected: base::test::TaskEnvironment task_environment_; std::unique_ptr<BleV2GattClient> ble_v2_gatt_client_; + raw_ptr<FakeGattServiceFactory> fake_gatt_service_factory_; raw_ptr<bluetooth::FakeDevice> fake_device_; + mojo::SelfOwnedReceiverRef<bluetooth::mojom::Device> device_receiver_; }; TEST_F(BleV2GattClientTest, DiscoverServiceAndCharacteristics_Success) { @@ -268,4 +313,24 @@ run_loop.Run(); } +TEST_F(BleV2GattClientTest, DisconnectHandler) { + base::RunLoop run_loop; + bool fake_gatt_service_destroyed = false; + fake_gatt_service_factory_->SetNextFakeGattServiceDestroyedCallback( + base::BindLambdaForTesting([&]() { + fake_gatt_service_destroyed = true; + run_loop.Quit(); + })); + + SuccessfullyDiscoverServiceAndCharacteristics(kServiceUuid1, + kCharacteristicUuid1); + + // Close the Mojo pipe. + fake_device_ = nullptr; + device_receiver_->Close(); + + run_loop.Run(); + EXPECT_TRUE(fake_gatt_service_destroyed); +} + } // namespace nearby::chrome
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc b/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc index eabbf185..4b86d8c 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc
@@ -32,11 +32,7 @@ device::BluetoothUUID("00001102-0000-1000-8000-00805f9b34fc"); const char kNewCharacteristicValue[] = "1010101"; -} // namespace - -namespace nearby::chrome { - -class FakeGattService : public BleV2GattServer::GattService { +class FakeGattService : public nearby::chrome::BleV2GattServer::GattService { public: explicit FakeGattService(base::OnceClosure on_destroyed_callback) : on_destroyed_callback_(std::move(on_destroyed_callback)) {} @@ -51,9 +47,11 @@ base::OnceClosure on_destroyed_callback_; }; -class FakeGattServiceFactory : public BleV2GattServer::GattService::Factory { +class FakeGattServiceFactory + : public nearby::chrome::BleV2GattServer::GattService::Factory { public: - std::unique_ptr<BleV2GattServer::GattService> Create() override { + std::unique_ptr<nearby::chrome::BleV2GattServer::GattService> Create() + override { return std::make_unique<FakeGattService>( std::move(next_fake_gatt_service_destroyed_callback_)); } @@ -68,6 +66,10 @@ base::OnceClosure next_fake_gatt_service_destroyed_callback_; }; +} // namespace + +namespace nearby::chrome { + class BleV2GattServerTest : public testing::Test { public: BleV2GattServerTest() = default;
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_medium.cc b/chrome/services/sharing/nearby/platform/ble_v2_medium.cc index 07f593e..451976c 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_medium.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_medium.cc
@@ -518,8 +518,20 @@ bool BleV2Medium::GetRemotePeripheral(api::ble_v2::BlePeripheral::UniqueId id, GetRemotePeripheralCallback callback) { - NOTIMPLEMENTED(); - return false; + auto it = + std::find_if(discovered_ble_peripherals_map_.begin(), + discovered_ble_peripherals_map_.end(), + [&](const auto& address_device_pair) { + return address_device_pair.second.GetUniqueId() == id; + }); + + if (it == discovered_ble_peripherals_map_.end()) { + LOG(WARNING) << __func__ << ": no match for device at id = " << id; + return false; + } + + std::move(callback)(it->second); + return true; } void BleV2Medium::PresentChanged(bool present) {
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_medium_unittest.cc b/chrome/services/sharing/nearby/platform/ble_v2_medium_unittest.cc index 29b2b83..7318af0d 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_medium_unittest.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_medium_unittest.cc
@@ -46,6 +46,7 @@ kTestServiceUuid2.data().size())}; const char kServiceId[] = "TestServiceId"; const char kCharacteristicUuid[] = "1234"; +const uint64_t kUniqueId = 1053256082272529; std::vector<uint8_t> GetByteVector(const std::string& str) { return std::vector<uint8_t>(str.begin(), str.end()); @@ -58,7 +59,7 @@ std::string GetAddress() const override { return kDeviceAddress; } - UniqueId GetUniqueId() const override { NOTREACHED_NORETURN(); } + UniqueId GetUniqueId() const override { return kUniqueId; } }; } // namespace @@ -192,6 +193,12 @@ kDeviceServiceData1ByteArray); found_advertisement_latch.CountDown(); OnPeripheralDiscovered(); + + EXPECT_TRUE(ble_v2_medium_->GetRemotePeripheral( + peripheral.GetUniqueId(), + [&](api::ble_v2::BlePeripheral& device) { + EXPECT_EQ(kDeviceAddress, device.GetAddress()); + })); }}; auto scanning_session = ble_v2_medium_->StartScanning( @@ -236,6 +243,12 @@ const api::ble_v2::BleAdvertisementData& advertisement_data) { session_1_found_advertisement_latch.CountDown(); OnPeripheralDiscovered(); + + EXPECT_TRUE(ble_v2_medium_->GetRemotePeripheral( + peripheral.GetUniqueId(), + [&](api::ble_v2::BlePeripheral& device) { + EXPECT_EQ(kDeviceAddress, device.GetAddress()); + })); }}; api::ble_v2::BleMedium::ScanningCallback scanning_callback_2 = { .start_scanning_result = @@ -248,6 +261,12 @@ const api::ble_v2::BleAdvertisementData& advertisement_data) { session_2_found_advertisement_latch.CountDown(); OnPeripheralDiscovered(); + + EXPECT_TRUE(ble_v2_medium_->GetRemotePeripheral( + peripheral.GetUniqueId(), + [&](api::ble_v2::BlePeripheral& device) { + EXPECT_EQ(kDeviceAddress, device.GetAddress()); + })); }}; auto scanning_session_1 = ble_v2_medium_->StartScanning(
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.cc b/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.cc index c5625ba3..88cea73 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.cc
@@ -4,11 +4,31 @@ #include "chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.h" +#include "device/bluetooth/public/cpp/bluetooth_address.h" + +namespace { + +nearby::chrome::BleV2RemotePeripheral::UniqueId GenerateUniqueId( + const std::string& device_address) { + std::array<uint8_t, 6> address_bytes; + if (!device::ParseBluetoothAddress(device_address, address_bytes)) { + LOG(WARNING) << __func__ << ": failed to parse device address"; + return 0; + } + + uint64_t unique_id = 0; + std::memcpy(&unique_id, address_bytes.data(), address_bytes.size()); + return unique_id; +} + +} // namespace + namespace nearby::chrome { BleV2RemotePeripheral::BleV2RemotePeripheral( bluetooth::mojom::DeviceInfoPtr device_info) - : device_info_(std::move(device_info)) {} + : device_info_(std::move(device_info)), + unique_id_(GenerateUniqueId(device_info_->address)) {} BleV2RemotePeripheral::BleV2RemotePeripheral(BleV2RemotePeripheral&&) = default; @@ -22,8 +42,7 @@ } BleV2RemotePeripheral::UniqueId BleV2RemotePeripheral::GetUniqueId() const { - NOTIMPLEMENTED(); - return 0; + return unique_id_; } void BleV2RemotePeripheral::UpdateDeviceInfo(
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.h b/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.h index 4cf3e7d..f0d03a8 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.h +++ b/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral.h
@@ -30,6 +30,7 @@ private: bluetooth::mojom::DeviceInfoPtr device_info_; + uint64_t unique_id_; }; } // namespace nearby::chrome
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral_unittest.cc b/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral_unittest.cc index 78d821f6..f547382 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral_unittest.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_remote_peripheral_unittest.cc
@@ -11,7 +11,10 @@ namespace nearby::chrome { namespace { -const char kAddress[] = "address"; + +const char kAddress[] = "11:12:13:14:15:16"; +constexpr uint64_t kUniqueId = 24279786918417; + } // namespace class BleV2RemotePeripheralTest : public testing::Test { @@ -26,6 +29,13 @@ EXPECT_EQ(peripheral.GetAddress(), kAddress); } +TEST_F(BleV2RemotePeripheralTest, GetUniqueId) { + auto device_info = bluetooth::mojom::DeviceInfo::New(); + device_info->address = kAddress; + BleV2RemotePeripheral peripheral{std::move(device_info)}; + EXPECT_EQ(kUniqueId, peripheral.GetUniqueId()); +} + TEST_F(BleV2RemotePeripheralTest, CanUpdateWithSameAddress) { auto device_info = bluetooth::mojom::DeviceInfo::New(); device_info->address = kAddress;
diff --git a/chrome/services/sharing/nearby/platform/wifi_direct_medium.cc b/chrome/services/sharing/nearby/platform/wifi_direct_medium.cc index cd5ee47..ba04210 100644 --- a/chrome/services/sharing/nearby/platform/wifi_direct_medium.cc +++ b/chrome/services/sharing/nearby/platform/wifi_direct_medium.cc
@@ -45,7 +45,10 @@ } bool WifiDirectMedium::StopWifiDirect() { - NOTIMPLEMENTED(); + if (connection_) { + connection_.reset(); + return true; + } return false; } @@ -136,12 +139,27 @@ connection_.set_disconnect_handler( base::BindOnce(&WifiDirectMedium::OnDisconnect, base::Unretained(this)), task_runner_); + + // Fetch the IPv4 address from the connection. + connection_->GetProperties(base::BindOnce(&WifiDirectMedium::OnProperties, + base::Unretained(this), + credentials, waitable_event)); + return; } // Trigger sync signal. waitable_event->Signal(); } +void WifiDirectMedium::OnProperties( + WifiDirectCredentials* credentials, + base::WaitableEvent* waitable_event, + ash::wifi_direct::mojom::WifiDirectConnectionPropertiesPtr properties) { + credentials->SetIPAddress(properties->ipv4_address); + credentials->SetGateway(properties->ipv4_address); + waitable_event->Signal(); +} + void WifiDirectMedium::OnDisconnect() { // Reset the connection, since it has been disconnected at this point. connection_.reset();
diff --git a/chrome/services/sharing/nearby/platform/wifi_direct_medium.h b/chrome/services/sharing/nearby/platform/wifi_direct_medium.h index a99641b..b5b282354 100644 --- a/chrome/services/sharing/nearby/platform/wifi_direct_medium.h +++ b/chrome/services/sharing/nearby/platform/wifi_direct_medium.h
@@ -5,6 +5,7 @@ #ifndef CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_DIRECT_MEDIUM_H_ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_DIRECT_MEDIUM_H_ +#include "base/synchronization/waitable_event.h" #include "chromeos/ash/services/nearby/public/mojom/firewall_hole.mojom.h" #include "chromeos/ash/services/wifi_direct/public/mojom/wifi_direct_manager.mojom.h" #include "mojo/public/cpp/bindings/shared_remote.h" @@ -53,6 +54,10 @@ ash::wifi_direct::mojom::WifiDirectOperationResult result, mojo::PendingRemote<ash::wifi_direct::mojom::WifiDirectConnection> connection); + void OnProperties( + WifiDirectCredentials* credentials, + base::WaitableEvent* waitable_event, + ash::wifi_direct::mojom::WifiDirectConnectionPropertiesPtr properties); void OnDisconnect();
diff --git a/chrome/services/sharing/nearby/platform/wifi_direct_medium_unittest.cc b/chrome/services/sharing/nearby/platform/wifi_direct_medium_unittest.cc index d4d7fb4..5e9cd740 100644 --- a/chrome/services/sharing/nearby/platform/wifi_direct_medium_unittest.cc +++ b/chrome/services/sharing/nearby/platform/wifi_direct_medium_unittest.cc
@@ -13,10 +13,16 @@ namespace { +constexpr char kTestIPv4Address[] = "127.0.0.1"; + class FakeWifiDirectConnection : public ash::wifi_direct::mojom::WifiDirectConnection { void GetProperties(GetPropertiesCallback callback) override { - NOTIMPLEMENTED(); + auto properties = + ash::wifi_direct::mojom::WifiDirectConnectionProperties::New(); + properties->ipv4_address = kTestIPv4Address; + properties->credentials = ash::wifi_direct::mojom::WifiCredentials::New(); + std::move(callback).Run(std::move(properties)); } void AssociateSocket(::mojo::PlatformHandle socket, @@ -156,6 +162,47 @@ base::ScopedAllowBaseSyncPrimitivesForTesting allow; WifiDirectCredentials credentials; EXPECT_TRUE(medium->StartWifiDirect(&credentials)); + EXPECT_EQ(credentials.GetIPAddress(), kTestIPv4Address); + EXPECT_EQ(credentials.GetGateway(), kTestIPv4Address); + }, + medium())); +} + +TEST_F(WifiDirectMediumTest, StopWifiDirect_MissingConnection) { + manager()->SetWifiDirectConnection(nullptr); + + RunOnTaskRunner(base::BindOnce( + [](WifiDirectMedium* medium) { + base::ScopedAllowBaseSyncPrimitivesForTesting allow; + WifiDirectCredentials credentials; + EXPECT_FALSE(medium->StartWifiDirect(&credentials)); + }, + medium())); + + RunOnTaskRunner(base::BindOnce( + [](WifiDirectMedium* medium) { + base::ScopedAllowBaseSyncPrimitivesForTesting allow; + EXPECT_FALSE(medium->StopWifiDirect()); + }, + medium())); +} + +TEST_F(WifiDirectMediumTest, StopWifiDirect_ExistingConnection) { + manager()->SetWifiDirectConnection( + std::make_unique<FakeWifiDirectConnection>()); + + RunOnTaskRunner(base::BindOnce( + [](WifiDirectMedium* medium) { + base::ScopedAllowBaseSyncPrimitivesForTesting allow; + WifiDirectCredentials credentials; + EXPECT_TRUE(medium->StartWifiDirect(&credentials)); + }, + medium())); + + RunOnTaskRunner(base::BindOnce( + [](WifiDirectMedium* medium) { + base::ScopedAllowBaseSyncPrimitivesForTesting allow; + EXPECT_TRUE(medium->StopWifiDirect()); }, medium())); }
diff --git a/chrome/services/sharing/nearby/platform/wifi_direct_server_socket.cc b/chrome/services/sharing/nearby/platform/wifi_direct_server_socket.cc new file mode 100644 index 0000000..d0319fe --- /dev/null +++ b/chrome/services/sharing/nearby/platform/wifi_direct_server_socket.cc
@@ -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. + +#include "chrome/services/sharing/nearby/platform/wifi_direct_server_socket.h" + +namespace nearby::chrome { + +WifiDirectServerSocket::WifiDirectServerSocket() = default; +WifiDirectServerSocket::~WifiDirectServerSocket() = default; + +// api::WifiDirectServerSocket +std::string WifiDirectServerSocket::GetIPAddress() const { + NOTIMPLEMENTED(); + return std::string(); +} + +int WifiDirectServerSocket::GetPort() const { + NOTIMPLEMENTED(); + return -1; +} + +std::unique_ptr<api::WifiDirectSocket> WifiDirectServerSocket::Accept() { + NOTIMPLEMENTED(); + return nullptr; +} + +Exception WifiDirectServerSocket::Close() { + NOTIMPLEMENTED(); + return {Exception::kSuccess}; +} +} // namespace nearby::chrome
diff --git a/chrome/services/sharing/nearby/platform/wifi_direct_server_socket.h b/chrome/services/sharing/nearby/platform/wifi_direct_server_socket.h new file mode 100644 index 0000000..97d8c80b --- /dev/null +++ b/chrome/services/sharing/nearby/platform/wifi_direct_server_socket.h
@@ -0,0 +1,30 @@ +// 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_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_DIRECT_SERVER_SOCKET_H_ +#define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_DIRECT_SERVER_SOCKET_H_ + +#include "chromeos/ash/services/nearby/public/mojom/firewall_hole.mojom.h" +#include "third_party/nearby/src/internal/platform/exception.h" +#include "third_party/nearby/src/internal/platform/implementation/wifi_direct.h" + +namespace nearby::chrome { + +class WifiDirectServerSocket : public api::WifiDirectServerSocket { + public: + WifiDirectServerSocket(); + WifiDirectServerSocket(const WifiDirectServerSocket&) = delete; + WifiDirectServerSocket& operator=(const WifiDirectServerSocket&) = delete; + ~WifiDirectServerSocket() override; + + // api::WifiDirectServerSocket + std::string GetIPAddress() const override; + int GetPort() const override; + std::unique_ptr<api::WifiDirectSocket> Accept() override; + Exception Close() override; +}; + +} // namespace nearby::chrome + +#endif // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WIFI_DIRECT_SERVER_SOCKET_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index a02e378a..f4e0850 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -815,6 +815,8 @@ "../browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.h", "../browser/ash/login/test/network_portal_detector_mixin.cc", "../browser/ash/login/test/network_portal_detector_mixin.h", + "../browser/ash/login/users/avatar/mock_user_image_loader_delegate.cc", + "../browser/ash/login/users/avatar/mock_user_image_loader_delegate.h", "../browser/ash/login/users/avatar/user_image_manager_test_util.cc", "../browser/ash/login/users/avatar/user_image_manager_test_util.h", "../browser/ash/policy/dlp/test/files_policy_notification_manager_test_utils.cc", @@ -860,6 +862,7 @@ "//ash/webui/personalization_app:test_support", "//ash/webui/print_management:url_constants", "//ash/webui/print_preview_cros:url_constants", + "//ash/webui/sanitize_ui:url_constants", "//ash/webui/scanning:url_constants", "//ash/webui/shortcut_customization_ui:url_constants", "//chrome/browser/ash", @@ -5742,6 +5745,7 @@ "../browser/ui/lacros/screen_capture_notification_ui_lacros_browsertest.cc", "../browser/ui/sharing_hub/sharing_hub_bubble_controller_chromeos_lacros_browsertest.cc", "../browser/ui/startup/first_run_service_browsertest.cc", + "../browser/ui/views/chrome_views_delegate_lacros_browsertest.cc", "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc", "../browser/ui/views/frame/immersive_mode_browser_view_test.cc", "../browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc",
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 92e0ff9c..3f2170a 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -117,6 +117,7 @@ "chromeos/personalization_app/personalization_app_sea_pen_browsertest.cc", "chromeos/print_management/print_management_browsertest.cc", "chromeos/print_preview_cros/print_preview_cros_browsertest.cc", + "chromeos/sanitize_ui/sanitize_ui_browsertest.cc", "chromeos/scanning/scanning_app_browsertest.cc", "chromeos/settings/os_settings_browsertest.cc", "chromeos/shimless_rma/shimless_rma_browsertest.cc", @@ -525,6 +526,7 @@ "chromeos/personalization_app:build_grdp", "chromeos/print_management:build_grdp", "chromeos/print_preview_cros:build_grdp", + "chromeos/sanitize_ui:build_grdp", "chromeos/scanning:build_grdp", "chromeos/settings:build_grdp", "chromeos/shimless_rma:build_grdp", @@ -557,6 +559,7 @@ "$target_gen_dir/chromeos/print_preview_cros/resources.grdp", "$target_gen_dir/chromeos/resources.grdp", "$target_gen_dir/chromeos/vc_background_ui/resources.grdp", + "$target_gen_dir/chromeos/sanitize_ui/resources.grdp", "$target_gen_dir/chromeos/scanning/resources.grdp", "$target_gen_dir/chromeos/settings/resources.grdp", "$target_gen_dir/chromeos/shimless_rma/resources.grdp",
diff --git a/chrome/test/data/webui/chromeos/ash_common/shortcut_input_test.ts b/chrome/test/data/webui/chromeos/ash_common/shortcut_input_test.ts index a47d519c..31ccde7 100644 --- a/chrome/test/data/webui/chromeos/ash_common/shortcut_input_test.ts +++ b/chrome/test/data/webui/chromeos/ash_common/shortcut_input_test.ts
@@ -17,36 +17,65 @@ function getConfirmKeyElement(shortcutInputElement: ShortcutInputElement| null): ShortcutInputKeyElement|null { + if (shortcutInputElement === null) { + return null; + } return shortcutInputElement!.shadowRoot!.querySelector('#confirmKey'); } function getPendingKeyElement(shortcutInputElement: ShortcutInputElement| null): ShortcutInputKeyElement|null { + if (shortcutInputElement === null) { + return null; + } return shortcutInputElement!.shadowRoot!.querySelector('#pendingKey'); } function getCtrlElement(shortcutInputElement: ShortcutInputElement| null): ShortcutInputKeyElement|null { + if (shortcutInputElement === null) { + return null; + } return shortcutInputElement!.shadowRoot!.querySelector('#ctrlKey'); } function getShiftElement(shortcutInputElement: ShortcutInputElement| null): ShortcutInputKeyElement|null { + if (shortcutInputElement === null) { + return null; + } return shortcutInputElement!.shadowRoot!.querySelector('#shiftKey'); } function getAltElement(shortcutInputElement: ShortcutInputElement| null): ShortcutInputKeyElement|null { + if (shortcutInputElement === null) { + return null; + } return shortcutInputElement!.shadowRoot!.querySelector('#altKey'); } function getSearchElement(shortcutInputElement: ShortcutInputElement| null): ShortcutInputKeyElement|null { + if (shortcutInputElement === null) { + return null; + } return shortcutInputElement!.shadowRoot!.querySelector('#searchKey'); } +function getFunctionElement(shortcutInputElement: ShortcutInputElement| + null): ShortcutInputKeyElement|null { + if (shortcutInputElement === null) { + return null; + } + return shortcutInputElement!.shadowRoot!.querySelector('#functionKey'); +} + function getKeySeparator(shortcutInputElement: ShortcutInputElement| null): Element|null { + if (shortcutInputElement === null) { + return null; + } return shortcutInputElement!.shadowRoot!.querySelector('#keySeparator'); } @@ -64,6 +93,7 @@ document.body.appendChild(element); element.shortcutInputProvider = shortcutInputProvider; element.showSeparator = true; + element.hasFunctionKey = true; element.addEventListener('shortcut-input-event', function() { ++numShortcutInputEvents; }); @@ -107,11 +137,13 @@ const altKey = getAltElement(shortcutInputElement); const searchKey = getSearchElement(shortcutInputElement); const shiftKey = getShiftElement(shortcutInputElement); + const functionKey = getFunctionElement(shortcutInputElement); assertFalse(isVisible(pendingKey)); assertFalse(isVisible(ctrlKey)); assertFalse(isVisible(altKey)); assertFalse(isVisible(searchKey)); assertFalse(isVisible(shiftKey)); + assertFalse(isVisible(functionKey)); }); test('DisplayAlphaKey', async () => { @@ -136,15 +168,18 @@ const altKey = getAltElement(shortcutInputElement); const searchKey = getSearchElement(shortcutInputElement); const shiftKey = getShiftElement(shortcutInputElement); + const functionKey = getFunctionElement(shortcutInputElement); // All keys should be visible and not selected. assertTrue(isVisible(ctrlKey)); assertTrue(isVisible(altKey)); assertTrue(isVisible(searchKey)); assertTrue(isVisible(shiftKey)); + assertTrue(isVisible(functionKey)); assertEquals(KeyInputState.NOT_SELECTED, ctrlKey!.keyState); assertEquals(KeyInputState.NOT_SELECTED, altKey!.keyState); assertEquals(KeyInputState.NOT_SELECTED, searchKey!.keyState); assertEquals(KeyInputState.NOT_SELECTED, shiftKey!.keyState); + assertEquals(KeyInputState.NOT_SELECTED, functionKey!.keyState); const confirmContainer = shortcutInputElement!.shadowRoot!.querySelector('#confirmContainer'); @@ -172,16 +207,19 @@ const ctrlKey = getCtrlElement(shortcutInputElement); const altKey = getAltElement(shortcutInputElement); const searchKey = getSearchElement(shortcutInputElement); + const functionKey = getFunctionElement(shortcutInputElement); const shiftKey = getShiftElement(shortcutInputElement); // Only shift key should be selected, but all should be visible. assertTrue(isVisible(ctrlKey)); assertTrue(isVisible(altKey)); assertTrue(isVisible(searchKey)); + assertTrue(isVisible(functionKey)); assertTrue(isVisible(shiftKey)); assertEquals(KeyInputState.NOT_SELECTED, ctrlKey!.keyState); assertEquals(KeyInputState.NOT_SELECTED, altKey!.keyState); assertEquals(KeyInputState.NOT_SELECTED, searchKey!.keyState); + assertEquals(KeyInputState.NOT_SELECTED, functionKey!.keyState); assertEquals(KeyInputState.MODIFIER_SELECTED, shiftKey!.keyState); const confirmContainer = @@ -196,8 +234,8 @@ vkey: VKey.kKeyA, domCode: 0, domKey: 0, - modifiers: - Modifier.SHIFT | Modifier.CONTROL | Modifier.ALT | Modifier.COMMAND, + modifiers: Modifier.SHIFT | Modifier.CONTROL | Modifier.ALT | + Modifier.COMMAND | Modifier.FN_KEY, keyDisplay: 'a', }; shortcutInputProvider.sendKeyPressEvent(keyEvent, keyEvent); @@ -212,16 +250,19 @@ const altKey = getAltElement(shortcutInputElement); const searchKey = getSearchElement(shortcutInputElement); const shiftKey = getShiftElement(shortcutInputElement); + const functionKey = getFunctionElement(shortcutInputElement); // All modifier keys should be selected. assertTrue(isVisible(ctrlKey)); assertTrue(isVisible(altKey)); assertTrue(isVisible(searchKey)); assertTrue(isVisible(shiftKey)); + assertTrue(isVisible(functionKey)); assertEquals(KeyInputState.MODIFIER_SELECTED, ctrlKey!.keyState); assertEquals(KeyInputState.MODIFIER_SELECTED, altKey!.keyState); assertEquals(KeyInputState.MODIFIER_SELECTED, searchKey!.keyState); assertEquals(KeyInputState.MODIFIER_SELECTED, shiftKey!.keyState); + assertEquals(KeyInputState.MODIFIER_SELECTED, functionKey!.keyState); const confirmContainer = shortcutInputElement!.shadowRoot!.querySelector('#confirmContainer');
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts index 52d027f..91ee11d 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_controller_test.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {beginLoadRecentSeaPenImagesAction, beginLoadSelectedImageAction, beginLoadSelectedRecentSeaPenImageAction, beginSearchSeaPenThumbnailsAction, beginSelectRecentSeaPenImageAction, beginSelectSeaPenThumbnailAction, endSelectRecentSeaPenImageAction, endSelectSeaPenThumbnailAction, getRecentSeaPenImages, getSeaPenStore, SeaPenState, SeaPenStoreAdapter, SeaPenStoreInterface, searchSeaPenThumbnails, selectRecentSeaPenImage, selectSeaPenWallpaper, setCurrentSeaPenQueryAction, setRecentSeaPenImagesAction, setSeaPenThumbnailsAction, setSelectedRecentSeaPenImageAction, setThumbnailResponseStatusCodeAction, WallpaperLayout, WallpaperType} from 'chrome://personalization/js/personalization_app.js'; +import {beginLoadRecentSeaPenImagesAction, beginLoadSelectedImageAction, beginLoadSelectedRecentSeaPenImageAction, beginSearchSeaPenThumbnailsAction, beginSelectRecentSeaPenImageAction, beginSelectSeaPenThumbnailAction, endSelectRecentSeaPenImageAction, endSelectSeaPenThumbnailAction, getRecentSeaPenImageIds, getSeaPenStore, getSeaPenThumbnails, SeaPenState, SeaPenStoreAdapter, SeaPenStoreInterface, selectRecentSeaPenImage, selectSeaPenThumbnail, setCurrentSeaPenQueryAction, setRecentSeaPenImagesAction, setSeaPenThumbnailsAction, setSelectedRecentSeaPenImageAction, setThumbnailResponseStatusCodeAction, WallpaperLayout, WallpaperType} from 'chrome://personalization/js/personalization_app.js'; import {MantaStatusCode} from 'chrome://resources/ash/common/sea_pen/sea_pen.mojom-webui.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; @@ -27,7 +27,7 @@ }); test('sets recent sea pen images in store', async () => { - await getRecentSeaPenImages(seaPenProvider, seaPenStore); + await getRecentSeaPenImageIds(seaPenProvider, seaPenStore); assertDeepEquals( [ @@ -44,13 +44,13 @@ test('sets sea pen thumbnails in store', async () => { const query = {textQuery: 'test_query'}; - await searchSeaPenThumbnails(query, seaPenProvider, seaPenStore); + await getSeaPenThumbnails(query, seaPenProvider, seaPenStore); assertDeepEquals( [ beginSearchSeaPenThumbnailsAction(query), setCurrentSeaPenQueryAction(query), setThumbnailResponseStatusCodeAction(MantaStatusCode.kOk), - setSeaPenThumbnailsAction(query, seaPenProvider.images), + setSeaPenThumbnailsAction(query, seaPenProvider.thumbnails), ], personalizationStore.actions, 'expected actions match'); @@ -128,7 +128,7 @@ recentImageData: {}, recentImages: null, thumbnailResponseStatusCode: MantaStatusCode.kOk, - thumbnails: seaPenProvider.images, + thumbnails: seaPenProvider.thumbnails, currentSeaPenQuery: query, pendingSelected: null, currentSelected: null, @@ -154,7 +154,7 @@ }; personalizationStore.data.wallpaper.seaPen.currentSelected = 123; - const promise = selectSeaPenWallpaper( + const promise = selectSeaPenThumbnail( {image: {url: ''}, id: 456}, seaPenProvider, seaPenStore); assertDeepEquals( @@ -235,7 +235,7 @@ Promise.resolve({success: false}); const thumbnail = {image: {url: ''}, id: 456}; - await selectSeaPenWallpaper(thumbnail, seaPenProvider, seaPenStore); + await selectSeaPenThumbnail(thumbnail, seaPenProvider, seaPenStore); assertDeepEquals( [ @@ -258,7 +258,7 @@ // Try and fail again. const promise = - selectSeaPenWallpaper(thumbnail, seaPenProvider, seaPenStore); + selectSeaPenThumbnail(thumbnail, seaPenProvider, seaPenStore); // Error reset to null while attempting to select again. assertEquals(null, personalizationStore.data.wallpaper.seaPen.error);
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_images_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_images_element_test.ts index 0fac820..c17af884 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_images_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_images_element_test.ts
@@ -75,7 +75,7 @@ test('displays loading thumbnail placeholders', async () => { personalizationStore.data.wallpaper.seaPen.loading.thumbnails = true; personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; // Initialize |seaPenImagesElement|. seaPenImagesElement = initElement(SeaPenImagesElement); @@ -95,7 +95,7 @@ test('thumbnail placeholders not active when hidden', async () => { personalizationStore.data.wallpaper.seaPen.loading.thumbnails = false; personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; // Initialize |seaPenImagesElement|. seaPenImagesElement = initElement(SeaPenImagesElement); @@ -112,7 +112,7 @@ test('displays image thumbnails', async () => { personalizationStore.data.wallpaper.seaPen.loading.thumbnails = false; personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; // Initialize |seaPenImagesElement|. seaPenImagesElement = initElement(SeaPenImagesElement); @@ -127,10 +127,10 @@ personalizationStore.setReducersEnabled(true); personalizationStore.data.wallpaper.seaPen.loading.thumbnails = false; personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; // Index 1 is currently set as wallpaper. personalizationStore.data.wallpaper.seaPen.currentSelected = - seaPenProvider.images[1]!.id; + seaPenProvider.thumbnails[1]!.id; seaPenImagesElement = initElement(SeaPenImagesElement); await waitAfterNextRender(seaPenImagesElement); @@ -205,7 +205,7 @@ await waitAfterNextRender(seaPenImagesElement); // Simulate receiving a confirmation that the sea pen image was selected. personalizationStore.dispatch( - setSelectedRecentSeaPenImageAction(seaPenProvider.images[0]!.id)); + setSelectedRecentSeaPenImageAction(seaPenProvider.thumbnails[0]!.id)); await waitAfterNextRender(seaPenImagesElement); thumbnails = getWallpaperGridItems(); @@ -227,7 +227,7 @@ test('display feedback buttons', async () => { personalizationStore.data.wallpaper.seaPen.loading.thumbnails = false; personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; seaPenImagesElement = initElement(SeaPenImagesElement); await waitAfterNextRender(seaPenImagesElement); @@ -348,7 +348,7 @@ personalizationStore.setReducersEnabled(true); personalizationStore.data.wallpaper.seaPen.loading.thumbnails = true; personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; // Initialize |seaPenImagesElement|. seaPenImagesElement = initElement(SeaPenImagesElement);
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_input_query_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_input_query_element_test.ts index 6bf580c..c35050b 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_input_query_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_input_query_element_test.ts
@@ -33,7 +33,7 @@ test('displays recreate button if thumbnails exist', async () => { personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; seaPenInputQueryElement = initElement(SeaPenInputQueryElement); await waitAfterNextRender(seaPenInputQueryElement);
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_router_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_router_element_test.ts index 3f6bb93..8671e13 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_router_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_router_element_test.ts
@@ -157,7 +157,7 @@ await waitAfterNextRender(routerElement); personalizationStore.data.wallpaper.seaPen.loading.thumbnails = false; personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; personalizationStore.notifyObservers(); assertEquals( @@ -202,7 +202,7 @@ // Clicking the inspire button should match the rendered template. const initialQuery: SeaPenQuery = - await seaPenProvider.whenCalled('searchWallpaper'); + await seaPenProvider.whenCalled('getSeaPenThumbnails'); assertEquals( initialQuery.templateQuery!.id, initialTemplate, 'Initial query template id should match'); @@ -219,7 +219,7 @@ // After switching templates, we should match the new template. const finalQuery: SeaPenQuery = - await seaPenProvider.whenCalled('searchWallpaper'); + await seaPenProvider.whenCalled('getSeaPenThumbnails'); assertEquals( finalQuery.templateQuery!.id, finalTemplate, 'Final query template id should match');
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_template_query_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_template_query_element_test.ts index 5f4168d..70917790 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_template_query_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_template_query_element_test.ts
@@ -80,7 +80,7 @@ test('displays recreate button if thumbnails exist', async () => { personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; seaPenTemplateQueryElement = initElement(SeaPenTemplateQueryElement, { templateId: SeaPenTemplateId.kFlower.toString(), }); @@ -117,7 +117,7 @@ test('displays create button when selected option changes', async () => { personalizationStore.data.wallpaper.seaPen.thumbnails = - seaPenProvider.images; + seaPenProvider.thumbnails; seaPenTemplateQueryElement = initElement(SeaPenTemplateQueryElement, { templateId: SeaPenTemplateId.kFlower.toString(), }); @@ -442,7 +442,7 @@ await waitAfterNextRender(seaPenTemplateQueryElement); const query: SeaPenQuery = - await seaPenProvider.whenCalled('searchWallpaper'); + await seaPenProvider.whenCalled('getSeaPenThumbnails'); assertEquals( query.templateQuery!.id, SeaPenTemplateId.kFlower, 'Query template id should match');
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_sea_pen_interface_provider.ts b/chrome/test/data/webui/chromeos/personalization_app/test_sea_pen_interface_provider.ts index 0904e1f..d71ed88 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/test_sea_pen_interface_provider.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/test_sea_pen_interface_provider.ts
@@ -12,7 +12,7 @@ export class TestSeaPenProvider extends TestBrowserProxy implements SeaPenProviderInterface { - images: SeaPenThumbnail[] = [ + thumbnails: SeaPenThumbnail[] = [ { id: 1, image: {url: 'https://sea-pen-images.googleusercontent.com/1'}, @@ -94,10 +94,10 @@ constructor() { super([ - 'searchWallpaper', + 'getSeaPenThumbnails', 'selectSeaPenThumbnail', 'selectRecentSeaPenImage', - 'getRecentSeaPenImages', + 'getRecentSeaPenImageIds', 'getRecentSeaPenImageThumbnail', 'deleteRecentSeaPenImage', 'shouldShowSeaPenIntroductionDialog', @@ -105,10 +105,10 @@ ]); } - searchWallpaper(query: SeaPenQuery) { - this.methodCalled('searchWallpaper', query); + getSeaPenThumbnails(query: SeaPenQuery) { + this.methodCalled('getSeaPenThumbnails', query); return Promise.resolve({ - images: this.images, + thumbnails: this.thumbnails, statusCode: MantaStatusCode.kOk, }); } @@ -127,8 +127,8 @@ return this.selectSeaPenRecentImageResponse; } - getRecentSeaPenImages() { - this.methodCalled('getRecentSeaPenImages'); + getRecentSeaPenImageIds() { + this.methodCalled('getRecentSeaPenImageIds'); return Promise.resolve({ids: this.recentImageIds}); }
diff --git a/chrome/test/data/webui/chromeos/sanitize_ui/BUILD.gn b/chrome/test/data/webui/chromeos/sanitize_ui/BUILD.gn new file mode 100644 index 0000000..1c4c8d4 --- /dev/null +++ b/chrome/test/data/webui/chromeos/sanitize_ui/BUILD.gn
@@ -0,0 +1,21 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../../build_webui_tests.gni") + +build_webui_tests("build_webui_tests") { + ts_path_mappings = + [ "chrome://sanitize/*|" + + rebase_path("$root_gen_dir/ash/webui/sanitize_ui/resources/tsc/*", + target_gen_dir) ] + files = [ "sanitize_ui_test.ts" ] + ts_deps = [ + "//ash/webui/common/resources:build_ts", + "//ash/webui/common/resources/cr_elements:build_ts", + "//ash/webui/sanitize_ui/resources:build_ts", + "//chrome/test/data/webui/chromeos:build_ts", + "//third_party/polymer/v3_0:library", + "//ui/webui/resources/js:build_ts", + ] +}
diff --git a/chrome/test/data/webui/chromeos/sanitize_ui/sanitize_ui_browsertest.cc b/chrome/test/data/webui/chromeos/sanitize_ui/sanitize_ui_browsertest.cc new file mode 100644 index 0000000..f1dd165 --- /dev/null +++ b/chrome/test/data/webui/chromeos/sanitize_ui/sanitize_ui_browsertest.cc
@@ -0,0 +1,40 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "ash/webui/sanitize_ui/url_constants.h" +#include "base/strings/stringprintf.h" +#include "chrome/test/base/web_ui_mocha_browser_test.h" +#include "content/public/test/browser_test.h" + +/** + * @fileoverview Test suite for chrome://sanitize. + */ + +namespace ash { + +namespace { + +class SanitizeUIBrowserTest : public WebUIMochaBrowserTest { + public: + SanitizeUIBrowserTest() { + set_test_loader_host(::ash::kChromeUISanitizeAppHost); + } + + protected: + void RunTestAtPath(const std::string& testFilePath) { + auto testPath = + base::StringPrintf("chromeos/sanitize_ui/%s", testFilePath.c_str()); + WebUIMochaBrowserTest::RunTest(testPath, "mocha.run()"); + } +}; + +IN_PROC_BROWSER_TEST_F(SanitizeUIBrowserTest, SanitizeInitialize) { + RunTestAtPath("sanitize_ui_test.js"); +} + +} // namespace + +} // namespace ash
diff --git a/chrome/test/data/webui/chromeos/sanitize_ui/sanitize_ui_test.ts b/chrome/test/data/webui/chromeos/sanitize_ui/sanitize_ui_test.ts new file mode 100644 index 0000000..5fe7dfc --- /dev/null +++ b/chrome/test/data/webui/chromeos/sanitize_ui/sanitize_ui_test.ts
@@ -0,0 +1,25 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert} from 'chrome://resources/js/assert.js'; +import {SanitizeDoneElement} from 'chrome://sanitize/sanitize_done.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; +import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; + +function initSanitizeDoneElement(): SanitizeDoneElement { + const element = new SanitizeDoneElement(); + document.body.appendChild(element); + flushTasks(); + return element; +} +suite('SanitizeUITest', function() { + test('SanitizeDonePopulation', () => { + const doneElement = initSanitizeDoneElement(); + const headerDiv = doneElement.shadowRoot!.querySelector('#header'); + // Verify the header element exists + assert(headerDiv); + // Check the header content + assertEquals('Sanitize Done', headerDiv!.textContent); + }); +});
diff --git a/chrome/test/data/webui/chromeos/settings/os_apps_page/os_apps_page_test.ts b/chrome/test/data/webui/chromeos/settings/os_apps_page/os_apps_page_test.ts index a430b90..9a23864 100644 --- a/chrome/test/data/webui/chromeos/settings/os_apps_page/os_apps_page_test.ts +++ b/chrome/test/data/webui/chromeos/settings/os_apps_page/os_apps_page_test.ts
@@ -16,7 +16,7 @@ import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; -import {clearBody} from '../utils.js'; +import {clearBody, hasStringProperty} from '../utils.js'; import {FakeAppNotificationHandler} from './app_notifications_page/fake_app_notification_handler.js'; import {TestAndroidAppsBrowserProxy} from './test_android_apps_browser_proxy.js'; @@ -54,6 +54,11 @@ }, }, on_device_app_controls: { + pin: { + key: 'on_device_app_controls.pin', + type: chrome.settingsPrivate.PrefType.STRING, + value: '', + }, setup_completed: { key: 'on_device_app_controls.setup_completed', type: chrome.settingsPrivate.PrefType.BOOLEAN, @@ -409,16 +414,37 @@ parentalControlsRow.querySelector<HTMLElement>('#setupPin'); assertTrue(!!setupPinDialog); - // TODO(b/332936223): When setup flow is implemented, simulate a - // successful PIN submission here instead. - const cancelPinSetupButton = + // Simulate PIN entry. + const pin = '123456'; + const setupPinKeyboard = + setupPinDialog.shadowRoot!.getElementById('setupPinKeyboard'); + assertTrue(!!setupPinKeyboard); + const pinKeyboard = + setupPinKeyboard.shadowRoot!.getElementById('pinKeyboard'); + assertTrue(!!pinKeyboard); + assertTrue(hasStringProperty(pinKeyboard, 'value')); + pinKeyboard.value = pin; + + const continuePinSetupButton = setupPinDialog.shadowRoot! .querySelector<HTMLElement>('#dialog')! - .querySelector<HTMLElement>('.cancel-button'); - assertTrue(!!cancelPinSetupButton); - cancelPinSetupButton.click(); + .querySelector<HTMLElement>('.action-button'); + assertTrue(!!continuePinSetupButton); + continuePinSetupButton.click(); + + // Verify that the PIN keyboard has been reset. + assertTrue(pinKeyboard.value === ''); + + // Re-enter the PIN to confirm it. + pinKeyboard.value = pin; + + assertTrue(!!continuePinSetupButton); + continuePinSetupButton.click(); await waitAfterNextRender(appsPage); + assertTrue(appsPage.prefs.on_device_app_controls.pin.value === pin); + assertTrue( + appsPage.prefs.on_device_app_controls.setup_completed.value); assertTrue(!!appsPage.shadowRoot!.querySelector( 'settings-app-parental-controls-subpage')); }); @@ -444,16 +470,37 @@ parentalControlsRow.querySelector<HTMLElement>('#setupPin'); assertTrue(!!setupPinDialog); - // TODO(b/332936223): When setup flow is implemented, simulate a - // successful PIN submission here instead. - const cancelPinSetupButton = + // Simulate PIN entry. + const pin = '123456'; + const setupPinKeyboard = + setupPinDialog.shadowRoot!.getElementById('setupPinKeyboard'); + assertTrue(!!setupPinKeyboard); + const pinKeyboard = + setupPinKeyboard.shadowRoot!.getElementById('pinKeyboard'); + assertTrue(!!pinKeyboard); + assertTrue(hasStringProperty(pinKeyboard, 'value')); + pinKeyboard.value = pin; + + const continuePinSetupButton = setupPinDialog.shadowRoot! .querySelector<HTMLElement>('#dialog')! - .querySelector<HTMLElement>('.cancel-button'); - assertTrue(!!cancelPinSetupButton); - cancelPinSetupButton.click(); + .querySelector<HTMLElement>('.action-button'); + assertTrue(!!continuePinSetupButton); + continuePinSetupButton.click(); + + // Verify that the PIN keyboard has been reset. + assertTrue(pinKeyboard.value === ''); + + // Re-enter the PIN to confirm it. + pinKeyboard.value = pin; + + assertTrue(!!continuePinSetupButton); + continuePinSetupButton.click(); await waitAfterNextRender(appsPage); + assertTrue(appsPage.prefs.on_device_app_controls.pin.value === pin); + assertTrue( + appsPage.prefs.on_device_app_controls.setup_completed.value); assertTrue(!!appsPage.shadowRoot!.querySelector( 'settings-app-parental-controls-subpage')); @@ -509,16 +556,37 @@ parentalControlsRow.querySelector<HTMLElement>('#setupPin'); assertTrue(!!setupPinDialog); - // TODO(b/332936223): When setup flow is implemented, simulate a - // successful PIN submission here instead. - const cancelPinSetupButton = + // Simulate PIN entry. + const pin = '123456'; + const setupPinKeyboard = + setupPinDialog.shadowRoot!.getElementById('setupPinKeyboard'); + assertTrue(!!setupPinKeyboard); + const pinKeyboard = + setupPinKeyboard.shadowRoot!.getElementById('pinKeyboard'); + assertTrue(!!pinKeyboard); + assertTrue(hasStringProperty(pinKeyboard, 'value')); + pinKeyboard.value = pin; + + const continuePinSetupButton = setupPinDialog.shadowRoot! .querySelector<HTMLElement>('#dialog')! - .querySelector<HTMLElement>('.cancel-button'); - assertTrue(!!cancelPinSetupButton); - cancelPinSetupButton.click(); + .querySelector<HTMLElement>('.action-button'); + assertTrue(!!continuePinSetupButton); + continuePinSetupButton.click(); + + // Verify that the PIN keyboard has been reset. + assertTrue(pinKeyboard.value === ''); + + // Re-enter the PIN to confirm it. + pinKeyboard.value = pin; + + assertTrue(!!continuePinSetupButton); + continuePinSetupButton.click(); await waitAfterNextRender(appsPage); + assertTrue(appsPage.prefs.on_device_app_controls.pin.value === pin); + assertTrue( + appsPage.prefs.on_device_app_controls.setup_completed.value); assertTrue(!!appsPage.shadowRoot!.querySelector( 'settings-app-parental-controls-subpage'));
diff --git a/chrome/test/data/webui/commerce/product_specifications/app_test.ts b/chrome/test/data/webui/commerce/product_specifications/app_test.ts index 1f676bc..0d856d6 100644 --- a/chrome/test/data/webui/commerce/product_specifications/app_test.ts +++ b/chrome/test/data/webui/commerce/product_specifications/app_test.ts
@@ -37,6 +37,7 @@ { productClusterId: BigInt(0), title: '', + productUrl: {url: ''}, imageUrl: {url: ''}, productDimensionValues: new Map<bigint, string[]>(), summary: '', @@ -261,11 +262,13 @@ const info1 = createInfo({ clusterId: BigInt(123), title: 'qux', + productUrl: {url: 'https://example.com/'}, imageUrl: {url: 'qux.com/image'}, }); const info2 = createInfo({ clusterId: BigInt(231), title: 'foobar', + productUrl: {url: 'https://example2.com/'}, imageUrl: {url: 'foobar.com/image'}, }); @@ -287,14 +290,14 @@ { selectedItem: { title: specsProduct1.title, - url: 'https://example.com', + url: 'https://example.com/', imageUrl: info1.imageUrl.url, }, }, { selectedItem: { title: '', - url: 'https://example.com', + url: 'https://example2.com/', imageUrl: info2.imageUrl.url, }, }, @@ -322,7 +325,7 @@ const table = appElement.shadowRoot!.querySelector('product-specifications-table'); assertTrue(!!table); - const newUrl = 'https://example3.com'; + const newUrl = 'https://example3.com/'; table.dispatchEvent(new CustomEvent('url-change', { detail: { url: newUrl, @@ -337,6 +340,53 @@ shoppingServiceApi.getArgs('getProductSpecificationsForUrls')[1]); }); + test('updates on removal', async () => { + const urlsParam = ['https://example.com/']; + const promiseValues = createAppPromiseValues({urlsParam: urlsParam}); + await createAppElementWithPromiseValues(promiseValues); + + assertEquals( + 1, shoppingServiceApi.getCallCount('getProductSpecificationsForUrls')); + assertEquals(1, shoppingServiceApi.getCallCount('getProductInfoForUrl')); + assertArrayEquals( + urlsParam.map(url => ({url})), + shoppingServiceApi.getArgs('getProductSpecificationsForUrls')[0]); + + const table = + appElement.shadowRoot!.querySelector('product-specifications-table'); + assertTrue(!!table); + table.dispatchEvent(new CustomEvent('url-remove', { + detail: { + index: 0, + }, + })); + + // Should not get called on an empty url list + assertEquals( + 1, shoppingServiceApi.getCallCount('getProductSpecificationsForUrls')); + assertEquals(1, shoppingServiceApi.getCallCount('getProductInfoForUrl')); + assertEquals(0, table.columns.length); + }); + + test('deletes product specification set', async () => { + const urlsParam = ['https://example.com/']; + const promiseValues = createAppPromiseValues( + {urlsParam: urlsParam, specsSet: createSpecsSet()}); + await createAppElementWithPromiseValues(promiseValues); + + const uuid = + shoppingServiceApi.getArgs('addProductSpecificationsSet')[0][2]; + const header = + appElement.shadowRoot!.querySelector('product-specifications-header'); + assertTrue(!!header); + header.dispatchEvent(new CustomEvent('delete-click')); + + assertEquals( + 1, shoppingServiceApi.getCallCount('deleteProductSpecificationsSet')); + assertEquals( + uuid, shoppingServiceApi.getArgs('deleteProductSpecificationsSet')[1]); + }); + suite('Header', () => { test('displays correct subtitle for retrieved sets', async () => { const specsSet = createSpecsSet({ @@ -395,7 +445,7 @@ }); test('hides empty state after product selection', async () => { - const url = 'https://example.com'; + const url = 'https://example.com/'; const openTabs = [{ title: 'title', url: stringToMojoUrl(url), @@ -406,7 +456,10 @@ 'getUrlInfosForRecentlyViewedTabs', Promise.resolve({urlInfos: []})); const promiseValues = createAppPromiseValues({ urlsParam: [], - infos: [createInfo({clusterId: BigInt(123)})], + infos: [createInfo({ + clusterId: BigInt(123), + productUrl: {url: 'https://example.com/'}, + })], }); createAppElementWithPromiseValues(promiseValues);
diff --git a/chrome/test/data/webui/commerce/product_specifications/product_selection_menu_test.ts b/chrome/test/data/webui/commerce/product_specifications/product_selection_menu_test.ts index 0ec1636..2f8845d 100644 --- a/chrome/test/data/webui/commerce/product_specifications/product_selection_menu_test.ts +++ b/chrome/test/data/webui/commerce/product_specifications/product_selection_menu_test.ts
@@ -198,7 +198,7 @@ const listElements = menu.$.menu.get().querySelectorAll<HTMLElement>('.dropdown-item'); - assertEquals(1, listElements.length); + assertEquals(2, listElements.length); const tabUrl = listElements[0]!.shadowRoot!.querySelector<HTMLElement>( '.description-text'); @@ -226,6 +226,24 @@ assertFalse(crActionMenu.open); }); + test('fires removal event', async () => { + initUrlInfos(); + const menu = await createMenu(); + menu.showAt(document.body); + await flushTasks(); + + const crActionMenu = menu.$.menu.get(); + assertTrue(crActionMenu.open); + const removeButton = crActionMenu.querySelector<HTMLElement>('#remove'); + assertTrue(!!removeButton); + const eventPromise = eventToPromise('remove-url', menu); + removeButton.click(); + const event = await eventPromise; + + assertTrue(!!event); + assertFalse(crActionMenu.open); + }); + test('updates when infos change', async () => { initRecentlyViewedTabUrlInfos([]); initOpenTabUrlInfos([]);
diff --git a/chrome/test/data/webui/commerce/product_specifications/table_test.ts b/chrome/test/data/webui/commerce/product_specifications/table_test.ts index 233bb38..935f66b 100644 --- a/chrome/test/data/webui/commerce/product_specifications/table_test.ts +++ b/chrome/test/data/webui/commerce/product_specifications/table_test.ts
@@ -126,6 +126,25 @@ assertEquals(0, event.detail.index); }); + test('fires url remove event', async () => { + // Arrange + tableElement.columns = [ + {selectedItem: {title: 'title', url: 'https://foo.com', imageUrl: ''}}, + {selectedItem: {title: 'title2', url: 'https://bar.com', imageUrl: ''}}, + ]; + await waitAfterNextRender(tableElement); + const productSelector = + tableElement.shadowRoot!.querySelector('product-selector'); + assertTrue(!!productSelector); + const eventPromise = eventToPromise('url-remove', tableElement); + productSelector.dispatchEvent(new CustomEvent('remove-url')); + + // Assert. + const event = await eventPromise; + assertTrue(!!event); + assertEquals(0, event.detail.index); + }); + test('opens new tab', async () => { // Arrange const testUrl = 'https://example.com';
diff --git a/chrome/test/data/webui/settings/test_performance_browser_proxy.ts b/chrome/test/data/webui/settings/test_performance_browser_proxy.ts index bdcc485..5abc130 100644 --- a/chrome/test/data/webui/settings/test_performance_browser_proxy.ts +++ b/chrome/test/data/webui/settings/test_performance_browser_proxy.ts
@@ -17,7 +17,6 @@ 'openBatterySaverFeedbackDialog', 'openMemorySaverFeedbackDialog', 'openSpeedFeedbackDialog', - 'onDiscardRingTreatmentEnabledChanged', 'validateTabDiscardExceptionRule', ]); } @@ -48,10 +47,6 @@ this.methodCalled('openSpeedFeedbackDialog'); } - onDiscardRingTreatmentEnabledChanged() { - this.methodCalled('onDiscardRingTreatmentEnabledChanged'); - } - setValidationResults(results: Record<string, boolean>) { this.validationResults_ = results; }
diff --git a/chromeos/ash/components/growth/campaigns_model.cc b/chromeos/ash/components/growth/campaigns_model.cc index b217780..662606c 100644 --- a/chromeos/ash/components/growth/campaigns_model.cc +++ b/chromeos/ash/components/growth/campaigns_model.cc
@@ -20,6 +20,7 @@ #include "ui/base/models/image_model.h" #include "ui/base/resource/resource_bundle.h" #include "ui/chromeos/styles/cros_tokens_color_mappings.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/vector_icon_types.h" @@ -114,39 +115,57 @@ inline constexpr char kShelfAppButtonId[] = "shelfAppButtonId"; // Image Model. -inline constexpr char kBuiltInIcon[] = "builtInIcon"; +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) +inline constexpr char kImage[] = "image"; +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) inline constexpr int kIconSize = 60; +inline constexpr char kVectorIcon[] = "vectorIcon"; + +// Vector Icon +inline constexpr char kBuiltInVectorIcon[] = "builtInVectorIcon"; #if BUILDFLAG(GOOGLE_CHROME_BRANDING) +// Image +inline constexpr char kBuiltInImage[] = "builtInImage"; + inline constexpr gfx::Size kBubbleIconSizeDip = gfx::Size(kIconSize, kIconSize); std::optional<int> GetBuiltInImageResourceId( - const std::optional<BuiltInIcon>& icon) { - if (!icon) { + const std::optional<BuiltInImage>& image_model_type) { + if (!image_model_type) { return std::nullopt; } - if (icon == BuiltInIcon::kContainerApp) { - return IDR_GROWTH_FRAMEWORK_CONTAINER_APP_PNG; + switch (image_model_type.value()) { + case BuiltInImage::kContainerApp: + return IDR_GROWTH_FRAMEWORK_CONTAINER_APP_PNG; + case BuiltInImage::kG1: + return IDR_GROWTH_FRAMEWORK_G1_PNG; + case BuiltInImage::kRebuy: + return IDR_GROWTH_FRAMEWORK_REBUY_PNG; } - - if (icon == BuiltInIcon::kG1) { - return IDR_GROWTH_FRAMEWORK_G1_PNG; - } - - return std::nullopt; } -#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) - -std::optional<BuiltInIcon> GetBuiltInIconType( +std::optional<BuiltInImage> GetBuiltInImageType( const base::Value::Dict* image_dict) { - auto built_in_icon_value = image_dict->FindInt(kBuiltInIcon); - if (!built_in_icon_value) { + auto built_in_image_value = image_dict->FindInt(kBuiltInImage); + if (!built_in_image_value) { return std::nullopt; } - return static_cast<BuiltInIcon>(built_in_icon_value.value()); + return static_cast<BuiltInImage>(built_in_image_value.value()); +} +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + +std::optional<BuiltInVectorIcon> GetBuiltInVectorIconType( + const base::Value::Dict* vector_icon_dict) { + auto built_in_vector_icon_value = + vector_icon_dict->FindInt(kBuiltInVectorIcon); + if (!built_in_vector_icon_value) { + return std::nullopt; + } + + return static_cast<BuiltInVectorIcon>(built_in_vector_icon_value.value()); } } // namespace @@ -575,53 +594,98 @@ return anchor_dict_->FindString(kShelfAppButtonId); } -// Image Model. +// Image. Image::Image(const base::Value::Dict* image_dict) : image_dict_(image_dict) {} Image::~Image() = default; -const gfx::VectorIcon* Image::GetVectorIcon() const { - const auto icon = GetBuiltInIconType(image_dict_); - if (!icon || icon.value() != BuiltInIcon::kRedeem) { +const gfx::Image* Image::GetImage() const { + if (!image_dict_) { + return nullptr; + } + + // TODO: b/329113710- Handle other image sources. + return GetBuiltInImage(); +} + +const gfx::Image* Image::GetBuiltInImage() const { +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + const auto image_id = + GetBuiltInImageResourceId(GetBuiltInImageType(image_dict_)); + if (image_id) { + return &ui::ResourceBundle::GetSharedInstance().GetImageNamed( + image_id.value()); + } +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + + // TODO: b/340895798 - record error metric. + LOG(ERROR) << "Unrecognized built in image."; + + return nullptr; +} + +// Vector Icon. +VectorIcon::VectorIcon(const base::Value::Dict* vector_icon_dict) + : vector_icon_dict_(vector_icon_dict) {} +VectorIcon::~VectorIcon() = default; + +const gfx::VectorIcon* VectorIcon::GetVectorIcon() const { + if (!vector_icon_dict_) { + return nullptr; + } + + // TODO:b/329113710 - Handle other vector icon sources. + return GetBuiltInVectorIcon(); +} + +const gfx::VectorIcon* VectorIcon::GetBuiltInVectorIcon() const { + const auto icon = GetBuiltInVectorIconType(vector_icon_dict_); + if (!icon || icon.value() != BuiltInVectorIcon::kRedeem) { + // TODO: b/340895798 - record error metric. + LOG(ERROR) << "Unrecognized built in vector icon."; + return nullptr; } return &chromeos::kRedeemIcon; } -const std::optional<ui::ImageModel> Image::GetImage() const { - if (!image_dict_) { +// Image Model. +ImageModel::ImageModel(const base::Value::Dict* image_model_dict) + : image_model_dict_(image_model_dict) {} +ImageModel::~ImageModel() = default; + +const std::optional<ui::ImageModel> ImageModel::GetImageModel() const { + if (!image_model_dict_) { return std::nullopt; } // TODO(b/329113710): Handle other image sources. - return GetBuiltInIcon(); + return GetBuiltInImageModel(); } -const std::optional<ui::ImageModel> Image::GetBuiltInIcon() const { - const auto* vector_icon = GetVectorIcon(); +const std::optional<ui::ImageModel> ImageModel::GetBuiltInImageModel() const { + const auto* vector_icon = + VectorIcon(image_model_dict_->FindDict(kVectorIcon)).GetVectorIcon(); if (vector_icon) { // Returns vector icon. return ui::ImageModel::FromVectorIcon( *vector_icon, cros_tokens::kCrosSysOnSurface, kIconSize); } - const auto icon = GetBuiltInIconType(image_dict_); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) - const auto resource_id = GetBuiltInImageResourceId(icon); - if (resource_id) { - gfx::ImageSkia* image = - ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( - resource_id.value()); + const auto* image = Image(image_model_dict_->FindDict(kImage)).GetImage(); + if (image) { + const gfx::ImageSkia* imageSkia = image->ToImageSkia(); gfx::ImageSkia resized_image = gfx::ImageSkiaOperations::CreateResizedImage( - *image, skia::ImageOperations::RESIZE_BEST, kBubbleIconSizeDip); + *imageSkia, skia::ImageOperations::RESIZE_BEST, kBubbleIconSizeDip); resized_image.EnsureRepsForSupportedScales(); return ui::ImageModel::FromImageSkia(resized_image); } + // TODO: b/340895798 - update the error type naming and description. + RecordCampaignsManagerError(CampaignsManagerError::kUnrecognizedBuiltInIcon); #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) - RecordCampaignsManagerError(CampaignsManagerError::kUnrecognizedBuiltInIcon); - LOG(ERROR) << "Unrecognized built in icon: " - << static_cast<int>(icon.value()); + LOG(ERROR) << "Unrecognized built in image model."; return std::nullopt; }
diff --git a/chromeos/ash/components/growth/campaigns_model.h b/chromeos/ash/components/growth/campaigns_model.h index 9ff1fa5..d833cc93 100644 --- a/chromeos/ash/components/growth/campaigns_model.h +++ b/chromeos/ash/components/growth/campaigns_model.h
@@ -18,6 +18,7 @@ } // namespace base namespace gfx { +class Image; struct VectorIcon; } // namespace gfx @@ -40,7 +41,16 @@ // These values are deserialized from Growth Campaign, so entries should not // be renumbered and numeric values should never be reused. -enum class BuiltInIcon { kRedeem, kContainerApp, kG1 }; +enum class BuiltInVectorIcon { kRedeem = 0, kMaxValue = kRedeem }; + +// These values are deserialized from Growth Campaign, so entries should not +// be renumbered and numeric values should never be reused. +enum class BuiltInImage { + kContainerApp = 0, + kG1 = 1, + kRebuy = 2, + kMaxValue = kRebuy +}; // Supported window anchor element. // These values are deserialized from Growth Campaign, so entries should not @@ -433,7 +443,7 @@ // // The structure looks like: // { -// "builtInImage": 0 +// "builtInImage": 0 // } class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_GROWTH) Image { public: @@ -442,16 +452,65 @@ Image& operator=(const Image) = delete; ~Image(); - const gfx::VectorIcon* GetVectorIcon() const; - const std::optional<ui::ImageModel> GetImage() const; + const gfx::Image* GetImage() const; private: // Get built in icon based on the given image data. - const std::optional<ui::ImageModel> GetBuiltInIcon() const; + const gfx::Image* GetBuiltInImage() const; raw_ptr<const base::Value::Dict> image_dict_; }; +// Wrapper around vector icon dictionary. +// +// The structure looks like: +// { +// "builtVectorIcon": 0 +// } +class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_GROWTH) VectorIcon { + public: + explicit VectorIcon(const base::Value::Dict* vector_icon_dict); + VectorIcon(const VectorIcon&) = delete; + VectorIcon& operator=(const VectorIcon) = delete; + ~VectorIcon(); + + const gfx::VectorIcon* GetVectorIcon() const; + + private: + // Get built in icon based on the given image data. + const gfx::VectorIcon* GetBuiltInVectorIcon() const; + + raw_ptr<const base::Value::Dict> vector_icon_dict_; +}; + +// Wrapper around image model dictionary. +// +// The structure looks like: +// { +// "image": { +// "builtInImage": 0 +// } +// } +class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_GROWTH) ImageModel { + public: + explicit ImageModel(const base::Value::Dict* image_model_dict); + ImageModel(const Image&) = delete; + ImageModel& operator=(const ImageModel) = delete; + ~ImageModel(); + + const std::optional<ui::ImageModel> GetImageModel() const; + + private: + // Get built in icon based on the given image data. + // If given data is referring to an image, the image will be resized to 60 * + // 60 so it can be used in the nudge. + // TODO: b/340945779 - consider moving the resize logic to + // `ShowNudgeActionPerformer`. + const std::optional<ui::ImageModel> GetBuiltInImageModel() const; + + raw_ptr<const base::Value::Dict> image_model_dict_; +}; + } // namespace growth #endif // CHROMEOS_ASH_COMPONENTS_GROWTH_CAMPAIGNS_MODEL_H_
diff --git a/chromeos/ash/components/growth/resources/rebuy.png b/chromeos/ash/components/growth/resources/rebuy.png new file mode 100644 index 0000000..84cafd6 --- /dev/null +++ b/chromeos/ash/components/growth/resources/rebuy.png Binary files differ
diff --git a/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc index 43723df..11bdf0d 100644 --- a/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc +++ b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc
@@ -1095,13 +1095,12 @@ << "; endpoint_id=" << endpoint_id; on_bandwidth_changed_endpoint_ids_v3_.emplace(endpoint_id); } else { - // TODO(b/325534442): Emit to a metric in the same that v1 - // `NearbyConnectionsManagerImpl::OnBandwidthChanged()` emits - // "Nearby.Share.Medium.ChangedToMedium". CD_LOG(VERBOSE, Feature::NEARBY_INFRA) << __func__ << ": (V3) Changed to medium=" << bandwidth_info->medium << " , quality=" << bandwidth_info->quality << "; endpoint_id=" << endpoint_id; + base::UmaHistogramEnumeration( + "Nearby.Connections.V3.Medium.ChangedToMedium", bandwidth_info->medium); current_upgraded_mediums_v3_.insert_or_assign(endpoint_id, bandwidth_info->medium);
diff --git a/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl_unittest.cc b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl_unittest.cc index 0df6b02..c16081f 100644 --- a/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl_unittest.cc +++ b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl_unittest.cc
@@ -11,6 +11,7 @@ #include "base/functional/callback_helpers.h" #include "base/run_loop.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" #include "chrome/test/base/testing_browser_process.h" @@ -2175,6 +2176,7 @@ } TEST_F(NearbyConnectionsManagerImplTest, OnBandwidthChangedV3) { + base::HistogramTester histogram_tester; mojo::Remote<ConnectionListenerV3> connection_listener_v3_remote; mojo::Remote<PayloadListenerV3> payload_listener_v3_remote; @@ -2227,11 +2229,15 @@ presence_device.GetEndpointId(), nearby::connections::mojom::BandwidthInfo::New(BandwidthQuality::kMedium, Medium::kBluetooth)); + histogram_tester.ExpectTotalCount( + "Nearby.Connections.V3.Medium.ChangedToMedium", 0); connection_listener_v3_remote->OnBandwidthChangedV3( presence_device.GetEndpointId(), nearby::connections::mojom::BandwidthInfo::New(BandwidthQuality::kHigh, Medium::kWebRtc)); bandwidth_run_loop.Run(); + histogram_tester.ExpectBucketCount( + "Nearby.Connections.V3.Medium.ChangedToMedium", Medium::kWebRtc, 1); } TEST_F(NearbyConnectionsManagerImplTest, PayloadListenerV3RemoteCallbacks) {
diff --git a/chromeos/ash/resources/growth_framework_resources.grdp b/chromeos/ash/resources/growth_framework_resources.grdp index bf76cb8..caecb619 100644 --- a/chromeos/ash/resources/growth_framework_resources.grdp +++ b/chromeos/ash/resources/growth_framework_resources.grdp
@@ -3,4 +3,5 @@ <!-- Resources for Growth Framework. --> <include name="IDR_GROWTH_FRAMEWORK_CONTAINER_APP_PNG" file="../resources/internal/container_app.png" type="BINDATA" /> <include name="IDR_GROWTH_FRAMEWORK_G1_PNG" file="../components/growth/resources/logo_one_color_2x_web_96dp.png" type="BINDATA" /> + <include name="IDR_GROWTH_FRAMEWORK_REBUY_PNG" file="../components/growth/resources/rebuy.png" type="BINDATA" /> </grit-part> \ No newline at end of file
diff --git a/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom b/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom index 24da67e..408ea0e 100644 --- a/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom +++ b/chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom
@@ -274,6 +274,8 @@ // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. +// This enum should be kept in sync with the `NearbyConnectionsMedium` enum at +// //tools/metrics/histograms/metadata/nearby/enums.xml enum Medium { kUnknown = 0, kMdns = 1,
diff --git a/chromeos/ui/frame/default_frame_header.cc b/chromeos/ui/frame/default_frame_header.cc index c7689b5..9cd1778 100644 --- a/chromeos/ui/frame/default_frame_header.cc +++ b/chromeos/ui/frame/default_frame_header.cc
@@ -123,8 +123,7 @@ #endif } - if (::features::IsChromeRefresh2023() && - ShouldApplyDynamicColor(GetTargetWindow())) { + if (ShouldApplyDynamicColor(GetTargetWindow())) { UpdateCaptionButtonColors(mode() == MODE_ACTIVE ? ui::kColorSysPrimary : ui::kColorFrameCaptionButtonUnfocused);
diff --git a/clank b/clank index abd3cce..aa6befe 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit abd3ccee94ac82bc22053398886ba2dfb5a518fa +Subproject commit aa6befe0ff74c3a26e310d3e119191e064b6b197
diff --git a/components/BUILD.gn b/components/BUILD.gn index 3d17be6..6c582b5 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -614,6 +614,7 @@ "//components/crash/android:java", "//components/crash/android:unit_tests", "//components/data_sharing/internal:internal_java", + "//components/data_sharing/internal:native_test_helper_java", "//components/download/internal/common:internal_java", "//components/embedder_support/android:native_java_unittests_java", "//components/embedder_support/android/metrics:test_support_java",
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc index 12408b36..376048c3 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -259,9 +259,9 @@ // Set delay as fido request timeout if available, otherwise set to default. base::TimeDelta delay = kDelayForGetUnmaskDetails; - if (unmask_details_.fido_request_options.has_value()) { + if (!unmask_details_.fido_request_options.empty()) { if (std::optional<int> request_timeout = - unmask_details_.fido_request_options->FindInt("timeout_millis")) { + unmask_details_.fido_request_options.FindInt("timeout_millis")) { delay = base::Milliseconds(*request_timeout); } } @@ -549,15 +549,15 @@ return; } - // For virtual cards the |fido_request_option| comes from the - // UnmaskResponseDetails while for masked server cards, it comes from the + // For virtual cards the `fido_request_options` come from the + // UnmaskResponseDetails while for masked server cards, they come from the // UnmaskDetails. base::Value::Dict fido_request_options; std::optional<std::string> context_token; if (card_->record_type() == CreditCard::RecordType::kVirtualCard) { context_token = virtual_card_unmask_response_details_.context_token; fido_request_options = std::move( - virtual_card_unmask_response_details_.fido_request_options.value()); + virtual_card_unmask_response_details_.fido_request_options); } else { CHECK_EQ(card_->record_type(), CreditCard::RecordType::kMaskedServerCard); @@ -568,13 +568,13 @@ CHECK(!risk_based_authentication_response_.context_token.empty()); context_token = risk_based_authentication_response_.context_token; fido_request_options = std::move( - risk_based_authentication_response_.fido_request_options.value()); + risk_based_authentication_response_.fido_request_options); } else { // If risk-based authentication is not available, the response of // UnmaskDetails preflight call will be used as the resource of // `fido_request_options`. fido_request_options = - std::move(unmask_details_.fido_request_options.value()); + std::move(unmask_details_.fido_request_options); } } GetOrCreateFidoAuthenticator()->Authenticate( @@ -704,22 +704,22 @@ unmask_auth_flow_type_ = UnmaskAuthFlowType::kNone; } else if (should_register_card_with_fido) { #if !BUILDFLAG(IS_IOS) - std::optional<base::Value::Dict> request_options = std::nullopt; - if (unmask_details_.fido_request_options.has_value()) { + base::Value::Dict request_options; + if (!unmask_details_.fido_request_options.empty()) { // For opted-in user (CVC then FIDO case), request options are returned in // unmask detail response. - request_options = unmask_details_.fido_request_options->Clone(); - } else if (response.request_options.has_value()) { + request_options = unmask_details_.fido_request_options.Clone(); + } else if (!response.request_options.empty()) { // For Android users, request_options are provided from GetRealPan if the // user has chosen to opt-in. - request_options = response.request_options->Clone(); + request_options = response.request_options.Clone(); } // Additionally authorizes the card with FIDO. It also delays the form // filling. GetOrCreateFidoAuthenticator()->Authorize(GetWeakPtr(), response.card_authorization_token, - request_options->Clone()); + request_options.Clone()); #endif } if (ShouldOfferFidoOptInDialog(response)) { @@ -738,7 +738,7 @@ #if BUILDFLAG(IS_ANDROID) bool CreditCardAccessManager::ShouldOfferFidoAuth() const { if (!unmask_details_.offer_fido_opt_in && - unmask_details_.fido_request_options.has_value()) { + !unmask_details_.fido_request_options.empty()) { // Server instructed the client to not offer fido because the client is // already opted in. This can be verified with the presence of request // options in the server response. @@ -943,7 +943,7 @@ // by the risk-based authentication call will be used as the indicator about // whether the selected card is FIDO authorized. if (IsMaskedServerCardRiskBasedAuthAvailable()) { - return risk_based_authentication_response_.fido_request_options.has_value(); + return !risk_based_authentication_response_.fido_request_options.empty(); } DCHECK_NE(unmask_details_.unmask_auth_method, AutofillClient::UnmaskAuthMethod::kUnknown); @@ -957,7 +957,7 @@ // GetRealPan did not return RequestOptions (user did not specify intent to // opt-in) AND flow is not registering a new card, so fill the form // directly. - if (!response.request_options.has_value() && + if (response.request_options.empty() && unmask_auth_flow_type_ != UnmaskAuthFlowType::kCvcThenFido) { return true; } @@ -989,11 +989,12 @@ // For Android, we will delay the form filling for both intent-to-opt-in user // opting in and opted-in user registering a new card (kCvcThenFido). So we // check one more scenario for Android here. If the GetRealPan response - // includes |request_options|, that means the user showed intention to opt-in + // includes `request_options`, that means the user showed intention to opt-in // while unmasking and must complete the challenge before successfully // opting-in and filling the form. - if (response.request_options.has_value()) + if (!response.request_options.empty()) { return true; + } #endif // No conditions to offer FIDO registration are met, so we return false. @@ -1007,7 +1008,7 @@ return false; #else if (!unmask_details_.offer_fido_opt_in && - unmask_details_.fido_request_options.has_value()) { + !unmask_details_.fido_request_options.empty()) { // Server instructed the client to not offer fido because the client is // already opted in. This can be verified with the presence of request // options in the server response. @@ -1285,7 +1286,7 @@ // GetUnmaskDetails to determine whether the card can be enrolled into // FIDO. StartAuthenticationFlow(IsFidoAuthEnabled( - /*fido_auth_offered=*/response.fido_request_options.has_value() || + /*fido_auth_offered=*/!response.fido_request_options.empty() || unmask_details_.unmask_auth_method == AutofillClient::UnmaskAuthMethod::kFido)); break; @@ -1361,7 +1362,7 @@ /*show_confirmation_before_closing=*/false, /*no_interactive_authentication_callback=*/base::OnceClosure()); StartAuthenticationFlow( - IsFidoAuthEnabled(response_details.fido_request_options.has_value())); + IsFidoAuthEnabled(!response_details.fido_request_options.empty())); return; }
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h index ff73cd6f..6cbc49d 100644 --- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h +++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
@@ -44,8 +44,7 @@ cvc = std::u16string(s); return *this; } - CvcAuthenticationResponse& with_request_options( - std::optional<base::Value::Dict> v) { + CvcAuthenticationResponse& with_request_options(base::Value::Dict v) { request_options = std::move(v); return *this; } @@ -56,9 +55,9 @@ bool did_succeed = false; raw_ptr<const CreditCard> card = nullptr; // TODO(crbug.com/40927733): Remove CVC. - std::u16string cvc = std::u16string(); - std::optional<base::Value::Dict> request_options; - std::string card_authorization_token = std::string(); + std::u16string cvc; + base::Value::Dict request_options; + std::string card_authorization_token; }; class Requester { public:
diff --git a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.cc b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.cc index ad7d204b..48793000 100644 --- a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.cc +++ b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.cc
@@ -23,10 +23,10 @@ result = other.result; error_dialog_context = other.error_dialog_context; card = other.card; - if (other.fido_request_options.has_value()) { - fido_request_options = other.fido_request_options->Clone(); + if (other.fido_request_options.empty()) { + fido_request_options.clear(); } else { - fido_request_options.reset(); + fido_request_options = other.fido_request_options.Clone(); } context_token = other.context_token; return *this; @@ -141,9 +141,9 @@ // The Payments server indicates further authentication is required. response.result = RiskBasedAuthenticationResponse::Result::kAuthenticationRequired; - if (response_details.fido_request_options.has_value()) { + if (!response_details.fido_request_options.empty()) { response.fido_request_options = - response_details.fido_request_options->Clone(); + response_details.fido_request_options.Clone(); } response.context_token = response_details.context_token;
diff --git a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h index 1252c414..34181ec7 100644 --- a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h +++ b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h
@@ -72,7 +72,7 @@ // The items below will be set when the server response was successful and // the card's real pan was not returned from the server side. // FIDO request options will be present only when FIDO is available. - std::optional<base::Value::Dict> fido_request_options; + base::Value::Dict fido_request_options; // Stores the latest version of the context token, passed between Payments // calls and unmodified by Chrome. std::string context_token;
diff --git a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator_unittest.cc index 1aa6e481..d2adfbe 100644 --- a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator_unittest.cc
@@ -233,8 +233,8 @@ Result::kAuthenticationRequired); EXPECT_FALSE( requester_->risk_based_authentication_response().card.has_value()); - EXPECT_TRUE(requester_->risk_based_authentication_response() - .fido_request_options.has_value()); + EXPECT_FALSE(requester_->risk_based_authentication_response() + .fido_request_options.empty()); // Expect the metrics are logged correctly. histogram_tester.ExpectUniqueSample(
diff --git a/components/autofill/core/browser/payments/payments_network_interface.cc b/components/autofill/core/browser/payments/payments_network_interface.cc index 1e59ad5e..521c006 100644 --- a/components/autofill/core/browser/payments/payments_network_interface.cc +++ b/components/autofill/core/browser/payments/payments_network_interface.cc
@@ -55,10 +55,10 @@ const PaymentsNetworkInterface::UnmaskDetails& other) { unmask_auth_method = other.unmask_auth_method; offer_fido_opt_in = other.offer_fido_opt_in; - if (other.fido_request_options.has_value()) { - fido_request_options = other.fido_request_options->Clone(); + if (other.fido_request_options.empty()) { + fido_request_options.clear(); } else { - fido_request_options.reset(); + fido_request_options = other.fido_request_options.Clone(); } fido_eligible_card_ids = other.fido_eligible_card_ids; return *this; @@ -125,10 +125,10 @@ dcvv = other.dcvv; expiration_month = other.expiration_month; expiration_year = other.expiration_year; - if (other.fido_request_options.has_value()) { - fido_request_options = other.fido_request_options->Clone(); + if (other.fido_request_options.empty()) { + fido_request_options.clear(); } else { - fido_request_options.reset(); + fido_request_options = other.fido_request_options.Clone(); } card_authorization_token = other.card_authorization_token; card_unmask_challenge_options = other.card_unmask_challenge_options;
diff --git a/components/autofill/core/browser/payments/payments_network_interface.h b/components/autofill/core/browser/payments/payments_network_interface.h index 0ece929..34b3943e 100644 --- a/components/autofill/core/browser/payments/payments_network_interface.h +++ b/components/autofill/core/browser/payments/payments_network_interface.h
@@ -97,7 +97,7 @@ bool offer_fido_opt_in = false; // Public Key Credential Request Options required for authentication. // https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialrequestoptions - std::optional<base::Value::Dict> fido_request_options; + base::Value::Dict fido_request_options; // Set of credit cards ids that are eligible for FIDO Authentication. std::set<std::string> fido_eligible_card_ids; }; @@ -170,7 +170,7 @@ std::string expiration_year; // Challenge required for authorizing user for FIDO authentication for // future card unmasking. - std::optional<base::Value::Dict> fido_request_options; + base::Value::Dict fido_request_options; // An opaque token used to logically chain consecutive UnmaskCard and // OptChange calls together. std::string card_authorization_token;
diff --git a/components/autofill/core/browser/payments/payments_network_interface_unittest.cc b/components/autofill/core/browser/payments/payments_network_interface_unittest.cc index 378b2a3a..e986a6d8 100644 --- a/components/autofill/core/browser/payments/payments_network_interface_unittest.cc +++ b/components/autofill/core/browser/payments/payments_network_interface_unittest.cc
@@ -710,9 +710,9 @@ EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ("fake_context_token", unmask_response_details()->context_token); // Verify the FIDO request challenge is correctly parsed. - EXPECT_EQ("fake_fido_challenge", - *unmask_response_details()->fido_request_options->FindString( - "challenge")); + EXPECT_EQ( + "fake_fido_challenge", + *unmask_response_details()->fido_request_options.FindString("challenge")); // Verify the three challenge options are two sms challenge options and one // cvc challenge option, and fields can be correctly parsed. ASSERT_EQ(3u, @@ -767,9 +767,9 @@ EXPECT_EQ(AutofillClient::PaymentsRpcResult::kSuccess, result_); EXPECT_EQ("fake_context_token", unmask_response_details()->context_token); // Verify the FIDO request challenge is correctly parsed. - EXPECT_EQ("fake_fido_challenge", - *unmask_response_details()->fido_request_options->FindString( - "challenge")); + EXPECT_EQ( + "fake_fido_challenge", + *unmask_response_details()->fido_request_options.FindString("challenge")); // Verify that the unknow new challenge option type won't break the parsing. // We ignore the unknown new type, and only return the supported challenge // option.
diff --git a/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc b/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc index 770fdba..7601a4e 100644 --- a/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc +++ b/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc
@@ -548,7 +548,7 @@ bool UnmaskCardRequest::CanPerformVirtualCardAuth() { return !response_details_.context_token.empty() && - (response_details_.fido_request_options.has_value() || + (!response_details_.fido_request_options.empty() || !response_details_.card_unmask_challenge_options.empty() || !response_details_.flow_status.empty()); }
diff --git a/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc index 7323db2..29cce0f 100644 --- a/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc +++ b/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc
@@ -157,7 +157,7 @@ EXPECT_EQ("fake_context_token", response_details.context_token); // Verify the FIDO request challenge is correctly parsed. EXPECT_EQ("fake_fido_challenge", - *response_details.fido_request_options->FindString("challenge")); + *response_details.fido_request_options.FindString("challenge")); // Verify that the response is considered complete. EXPECT_TRUE(GetRequest()->IsResponseComplete()); @@ -315,7 +315,7 @@ EXPECT_EQ("fake_context_token", response_details.context_token); // Verify the FIDO request challenge is correctly parsed. EXPECT_EQ("fake_fido_challenge", - *response_details.fido_request_options->FindString("challenge")); + *response_details.fido_request_options.FindString("challenge")); // Verify the six (or seven, if 3DS is enabled) challenge options are two SMS // OTP challenge options, two CVC challenge options, two email OTP challenge
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn index c2137e8..cbe34bb 100644 --- a/components/autofill/core/common/BUILD.gn +++ b/components/autofill/core/common/BUILD.gn
@@ -21,8 +21,6 @@ "autofill_internals/logging_scope.h", "autofill_l10n_util.cc", "autofill_l10n_util.h", - "autofill_payments_features.cc", - "autofill_payments_features.h", "autofill_prefs.cc", "autofill_prefs.h", "autofill_regex_constants.h", @@ -94,6 +92,8 @@ sources = [ "autofill_features.cc", "autofill_features.h", + "autofill_payments_features.cc", + "autofill_payments_features.h", ] deps = [
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc index 7e523e9..9e8d09b 100644 --- a/components/autofill/core/common/autofill_payments_features.cc +++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -8,8 +8,6 @@ namespace autofill::features { -// Features - // When enabled, Android N+ devices will be supported for FIDO authentication. BASE_FEATURE(kAutofillEnableAndroidNKeyForFidoAuthentication, "AutofillEnableAndroidNKeyForFidoAuthentication",
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h index 6f782e3..b80e5930 100644 --- a/components/autofill/core/common/autofill_payments_features.h +++ b/components/autofill/core/common/autofill_payments_features.h
@@ -5,68 +5,97 @@ #ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PAYMENTS_FEATURES_H_ #define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PAYMENTS_FEATURES_H_ +#include "base/component_export.h" #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" #include "build/build_config.h" -namespace autofill { -namespace features { +namespace autofill::features { // All features in alphabetical order. +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableAndroidNKeyForFidoAuthentication); -BASE_DECLARE_FEATURE(kAutofillEnableCardArtImage); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableCardArtImage); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableCardArtServerSideStretching); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableCardBenefitsForAmericanExpress); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableCardBenefitsForCapitalOne); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableCardBenefitsSync); -BASE_DECLARE_FEATURE(kAutofillEnableCardProductName); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableCardProductName); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableCvcStorageAndFilling); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableFIDOProgressDialog); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableFpanRiskBasedAuthentication); #if BUILDFLAG(IS_ANDROID) -BASE_DECLARE_FEATURE(kAutofillEnableLocalIban); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableLocalIban); #endif +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableMerchantDomainInUnmaskCardRequest); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableMovingGPayLogoToTheRightOnDesktop); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableMovingGPayLogoToTheRightOnClank); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableNewCardArtAndNetworkImages); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableOffersInClankKeyboardAccessory); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnablePrefetchingRiskDataForRetrieval); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableRemadeDownstreamMetrics); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableSaveCardLoadingAndConfirmation); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableSaveCardLocalSaveFallback); -BASE_DECLARE_FEATURE(kAutofillEnableServerIban); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableServerIban); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableStickyManualFallbackForCards); #if BUILDFLAG(IS_ANDROID) +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableSyncingOfPixBankAccounts); #endif +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableVcn3dsAuthentication); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableVcnEnrollLoadingAndConfirmation); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableVcnGrayOutForMerchantOptOut); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableVirtualCardEnrollMetricsLogger); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableVerveCardSupport); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableVirtualCardMetadata); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillParseVcnCardOnFileStandaloneCvcFields); #if BUILDFLAG(IS_ANDROID) +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillSkipAndroidBottomSheetForIban); #endif +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUpdateChromeSettingsLinkToGPayWeb); -BASE_DECLARE_FEATURE(kAutofillUpstream); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUpstream); #if BUILDFLAG(IS_IOS) +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUseTwoDotsForLastFourDigits); -BASE_DECLARE_FEATURE(kAutofillEnableVirtualCards); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableVirtualCards); #endif // Return whether a [No thanks] button and new messaging is shown in the save // card bubbles. This will be called only on desktop platforms. +COMPONENT_EXPORT(AUTOFILL) bool ShouldShowImprovedUserConsentForCreditCardSave(); -} // namespace features -} // namespace autofill +} // namespace autofill::features #endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PAYMENTS_FEATURES_H_
diff --git a/components/commerce_strings.grdp b/components/commerce_strings.grdp index 06c100d..1db60df 100644 --- a/components/commerce_strings.grdp +++ b/components/commerce_strings.grdp
@@ -540,4 +540,7 @@ <message name="IDS_PRODUCT_SPECIFICATIONS_DELETE" translateable="false" desc="The title of the menu item for deleting the product specification list."> Delete product specification list </message> + <message name="IDS_PRODUCT_SPECIFICATIONS_REMOVE_COLUMN" translateable="false" desc="The title of the menu item for removing a column in the product specification list."> + Remove column + </message> </grit-part>
diff --git a/components/compose/core/browser/compose_metrics.h b/components/compose/core/browser/compose_metrics.h index bfcc19e..c8b2761b 100644 --- a/components/compose/core/browser/compose_metrics.h +++ b/components/compose/core/browser/compose_metrics.h
@@ -208,6 +208,26 @@ kMaxValue = kRequestError, }; +// The output metric for the proactive nudge segmentation model. Represents what +// effect the nudge had on the user's engagement. Stored as +// "Compose.ProactiveNudge.DerivedEngagement". +enum class ProactiveNudgeDerivedEngagement { + // The user didn't interact with the nudge. + kIgnored, + // The user disabled the nudge on this site using the three-dot menu. + kNudgeDisabledOnSingleSite, + // The user disabled the nudge on all sites using the three-dot menu. + kNudgeDisabledOnAllSites, + // User clicked the nudge, but didn't press generate in Compose. + kOpenedComposeMinimalUse, + // User clicked the nudge, pressed generate at least once, but didn't accept + // the suggestion. + kGeneratedComposeSuggestion, + // User clicked, pressed generate, and accepted a suggestion. + kAcceptedComposeSuggestion, + kMaxValue = kAcceptedComposeSuggestion, +}; + // Struct containing event and logging information for an individual // |ComposeSession|. struct ComposeSessionEvents {
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index b8e93830..9c235677 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -376,6 +376,7 @@ "java/src/org/chromium/net/impl/CronetEngineBase.java", "java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java", "java/src/org/chromium/net/impl/CronetExceptionImpl.java", + "java/src/org/chromium/net/impl/CronetMetrics.java", "java/src/org/chromium/net/impl/NetworkExceptionImpl.java", "java/src/org/chromium/net/impl/Preconditions.java", "java/src/org/chromium/net/impl/QuicExceptionImpl.java", @@ -506,7 +507,6 @@ "java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java", "java/src/org/chromium/net/impl/CronetBidirectionalStream.java", "java/src/org/chromium/net/impl/CronetLibraryLoader.java", - "java/src/org/chromium/net/impl/CronetMetrics.java", "java/src/org/chromium/net/impl/CronetRequestCommon.java", "java/src/org/chromium/net/impl/CronetUploadDataStream.java", "java/src/org/chromium/net/impl/CronetUrlRequest.java",
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamCallbackWrapper.java b/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamCallbackWrapper.java index 22c99c73..2643f94 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamCallbackWrapper.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamCallbackWrapper.java
@@ -13,6 +13,9 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresExtension; +import org.chromium.net.CronetException; +import org.chromium.net.RequestFinishedInfo; + import java.nio.ByteBuffer; import java.util.Objects; @@ -83,7 +86,17 @@ android.net.http.UrlResponseInfo urlResponseInfo) { AndroidUrlResponseInfoWrapper specializedResponseInfo = AndroidUrlResponseInfoWrapper.createForBidirectionalStream(urlResponseInfo); - mBackend.onSucceeded(mWrappedStream, specializedResponseInfo); + try { + mBackend.onSucceeded(mWrappedStream, specializedResponseInfo); + } finally { + // In a scenario where this throws, the side effect is that it will be propagated to + // CronetUrlRequest as an error in the callback and mess with the FinalUserCallbackThrew + // metrics. Because we catch most the exceptions, this side effect is negligible enough + // to + // not try to figure out a workaround. + mWrappedStream.maybeReportMetrics( + RequestFinishedInfo.SUCCEEDED, specializedResponseInfo, null); + } } @Override @@ -93,10 +106,15 @@ HttpException e) { AndroidUrlResponseInfoWrapper specializedResponseInfo = AndroidUrlResponseInfoWrapper.createForBidirectionalStream(urlResponseInfo); - mBackend.onFailed( - mWrappedStream, - specializedResponseInfo, - CronetExceptionTranslationUtils.translateCheckedAndroidCronetException(e)); + CronetException exception = + CronetExceptionTranslationUtils.translateCheckedAndroidCronetException(e); + try { + mBackend.onFailed(mWrappedStream, specializedResponseInfo, exception); + } finally { + // See comment in onSucceeded. + mWrappedStream.maybeReportMetrics( + RequestFinishedInfo.FAILED, specializedResponseInfo, exception); + } } @Override @@ -105,7 +123,13 @@ @Nullable android.net.http.UrlResponseInfo urlResponseInfo) { AndroidUrlResponseInfoWrapper specializedResponseInfo = AndroidUrlResponseInfoWrapper.createForBidirectionalStream(urlResponseInfo); - mBackend.onCanceled(mWrappedStream, specializedResponseInfo); + try { + mBackend.onCanceled(mWrappedStream, specializedResponseInfo); + } finally { + // See comment in onSucceeded. + mWrappedStream.maybeReportMetrics( + RequestFinishedInfo.CANCELED, specializedResponseInfo, null); + } } void setStream(AndroidBidirectionalStreamWrapper stream) {
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamWrapper.java b/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamWrapper.java index fe10826ca..d9593dc3 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamWrapper.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/AndroidBidirectionalStreamWrapper.java
@@ -9,14 +9,30 @@ import androidx.annotation.RequiresExtension; +import org.chromium.net.CronetEngine; +import org.chromium.net.CronetException; +import org.chromium.net.RequestFinishedInfo; +import org.chromium.net.RequestFinishedInfo.Listener; + import java.nio.ByteBuffer; +import java.util.Collection; @RequiresExtension(extension = EXT_API_LEVEL, version = EXT_VERSION) class AndroidBidirectionalStreamWrapper extends org.chromium.net.ExperimentalBidirectionalStream { private final android.net.http.BidirectionalStream mBackend; + private final AndroidHttpEngineWrapper mEngine; + private final String mInitialUrl; + private final Collection<Object> mAnnotations; - private AndroidBidirectionalStreamWrapper(android.net.http.BidirectionalStream backend) { + AndroidBidirectionalStreamWrapper( + android.net.http.BidirectionalStream backend, + AndroidHttpEngineWrapper engine, + String url, + Collection<Object> annotations) { this.mBackend = backend; + this.mEngine = engine; + this.mInitialUrl = url; + this.mAnnotations = annotations; } @Override @@ -58,10 +74,36 @@ */ static AndroidBidirectionalStreamWrapper createAndAddToCallback( android.net.http.BidirectionalStream backend, - AndroidBidirectionalStreamCallbackWrapper callback) { + AndroidBidirectionalStreamCallbackWrapper callback, + AndroidHttpEngineWrapper engine, + String url, + Collection<Object> annotations) { AndroidBidirectionalStreamWrapper wrappedStream = - new AndroidBidirectionalStreamWrapper(backend); + new AndroidBidirectionalStreamWrapper(backend, engine, url, annotations); callback.setStream(wrappedStream); return wrappedStream; } + + /** + * HttpEngine does not support {@link CronetEngine#addRequestFinishedListener(Listener)}). To + * preserve compatibility with Cronet users who use that method, we reimplement the + * functionality with a placeholder CronetMetric object. This reimplementation allows for {@link + * RequestFinishedInfo.Listener#onRequestFinished(RequestFinishedInfo)} to be called so as not + * to unknowingly block users who might be depending on that API call. + */ + void maybeReportMetrics( + @RequestFinishedInfoImpl.FinishedReason int finishedReason, + AndroidUrlResponseInfoWrapper responseInfo, + CronetException exception) { + final RequestFinishedInfo requestInfo = + new RequestFinishedInfoImpl( + mInitialUrl, + mAnnotations, + new CronetMetrics( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, false, -1, -1), + finishedReason, + responseInfo, + exception); + mEngine.reportRequestFinished(requestInfo, null); + } }
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineWrapper.java b/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineWrapper.java index 0e65ce2..6c70d26 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineWrapper.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/AndroidHttpEngineWrapper.java
@@ -10,6 +10,7 @@ import android.net.Network; import android.net.http.HttpEngine; import android.os.Process; +import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.RequiresExtension; @@ -28,18 +29,25 @@ import java.net.URLStreamHandlerFactory; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; @RequiresExtension(extension = EXT_API_LEVEL, version = EXT_VERSION) class AndroidHttpEngineWrapper extends CronetEngineBase { + private static final String TAG = "HttpEngineWrapper"; private final HttpEngine mBackend; private final int mThreadPriority; // The thread that priority has been set on. private Thread mPriorityThread; + private final Map< + RequestFinishedInfo.Listener, VersionSafeCallbacks.RequestFinishedInfoListener> + mFinishedListenerMap = Collections.synchronizedMap(new HashMap<>()); public AndroidHttpEngineWrapper(HttpEngine backend, int threadPriority) { mBackend = backend; @@ -117,6 +125,45 @@ } @Override + public void addRequestFinishedListener(RequestFinishedInfo.Listener listener) { + mFinishedListenerMap.put( + listener, new VersionSafeCallbacks.RequestFinishedInfoListener(listener)); + } + + @Override + public void removeRequestFinishedListener(RequestFinishedInfo.Listener listener) { + mFinishedListenerMap.remove(listener); + } + + void reportRequestFinished( + RequestFinishedInfo requestInfo, + VersionSafeCallbacks.RequestFinishedInfoListener extraRequestListener) { + ArrayList<VersionSafeCallbacks.RequestFinishedInfoListener> currentListeners = + new ArrayList<>(); + synchronized (mFinishedListenerMap) { + currentListeners.addAll(mFinishedListenerMap.values()); + } + if (extraRequestListener != null) { + currentListeners.add(extraRequestListener); + } + for (final VersionSafeCallbacks.RequestFinishedInfoListener listener : currentListeners) { + try { + listener.getExecutor() + .execute( + () -> { + try { + listener.onRequestFinished(requestInfo); + } catch (Exception e) { + Log.e(TAG, "Exception thrown from observation task", e); + } + }); + } catch (RejectedExecutionException failException) { + Log.e(TAG, "Exception posting task to executor", failException); + } + } + } + + @Override public org.chromium.net.ExperimentalBidirectionalStream createBidirectionalStream( String url, BidirectionalStream.Callback callback, @@ -125,7 +172,7 @@ List<Entry<String, String>> requestHeaders, @StreamPriority int priority, boolean delayRequestHeadersUntilFirstFlush, - Collection<Object> requestAnnotations /* not in HttpEngine */, + Collection<Object> requestAnnotations, boolean trafficStatsTagSet, int trafficStatsTag, boolean trafficStatsUidSet, @@ -151,7 +198,7 @@ } return AndroidBidirectionalStreamWrapper.createAndAddToCallback( - streamBuilder.build(), wrappedCallback); + streamBuilder.build(), wrappedCallback, this, url, requestAnnotations); } @Override @@ -160,7 +207,7 @@ UrlRequest.Callback callback, Executor executor, @RequestPriority int priority, - Collection<Object> requestAnnotations /* not in HttpEngine */, + Collection<Object> requestAnnotations, boolean disableCache, boolean disableConnectionMigration /* not in HttpEngine */, boolean allowDirectExecutor, @@ -168,7 +215,7 @@ int trafficStatsTag, boolean trafficStatsUidSet, int trafficStatsUid, - @Nullable RequestFinishedInfo.Listener requestFinishedListener /* not in HttpEngine */, + @Nullable RequestFinishedInfo.Listener requestFinishedListener, @Idempotency int idempotency /* not in HttpEngine */, long networkHandle, String method, @@ -201,7 +248,12 @@ } return AndroidUrlRequestWrapper.createAndAddToCallback( - requestBuilder.build(), wrappedCallback); + requestBuilder.build(), + wrappedCallback, + this, + url, + requestAnnotations, + requestFinishedListener); } private Network getNetwork(long networkHandle) {
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestCallbackWrapper.java b/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestCallbackWrapper.java index 15051b97..10d699f 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestCallbackWrapper.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestCallbackWrapper.java
@@ -13,6 +13,9 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresExtension; +import org.chromium.net.CronetException; +import org.chromium.net.RequestFinishedInfo; + import java.nio.ByteBuffer; import java.util.Objects; @@ -83,7 +86,17 @@ android.net.http.UrlRequest request, android.net.http.UrlResponseInfo info) { AndroidUrlResponseInfoWrapper specializedResponseInfo = AndroidUrlResponseInfoWrapper.createForUrlRequest(info); - mBackend.onSucceeded(mWrappedRequest, specializedResponseInfo); + try { + mBackend.onSucceeded(mWrappedRequest, specializedResponseInfo); + } finally { + // In a scenario where this throws, the side effect is that it will be propagated to + // CronetUrlRequest as an error in the callback and mess with the FinalUserCallbackThrew + // metrics. Because we catch most the exceptions, this side effect is negligible enough + // to + // not try to figure out a workaround. + mWrappedRequest.maybeReportMetrics( + RequestFinishedInfo.SUCCEEDED, specializedResponseInfo, null); + } } @Override @@ -93,10 +106,15 @@ HttpException error) { AndroidUrlResponseInfoWrapper specializedResponseInfo = AndroidUrlResponseInfoWrapper.createForUrlRequest(info); - mBackend.onFailed( - mWrappedRequest, - specializedResponseInfo, - CronetExceptionTranslationUtils.translateCheckedAndroidCronetException(error)); + CronetException translatedException = + CronetExceptionTranslationUtils.translateCheckedAndroidCronetException(error); + try { + mBackend.onFailed(mWrappedRequest, specializedResponseInfo, translatedException); + } finally { + // See comment in onSucceeded. + mWrappedRequest.maybeReportMetrics( + RequestFinishedInfo.FAILED, specializedResponseInfo, translatedException); + } } @Override @@ -105,7 +123,13 @@ @Nullable android.net.http.UrlResponseInfo info) { AndroidUrlResponseInfoWrapper specializedResponseInfo = AndroidUrlResponseInfoWrapper.createForUrlRequest(info); - mBackend.onCanceled(mWrappedRequest, specializedResponseInfo); + try { + mBackend.onCanceled(mWrappedRequest, specializedResponseInfo); + } finally { + // See comment in onSucceeded. + mWrappedRequest.maybeReportMetrics( + RequestFinishedInfo.CANCELED, specializedResponseInfo, null); + } } void setRequest(AndroidUrlRequestWrapper request) {
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestWrapper.java b/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestWrapper.java index 2c67875..b2e11bb 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestWrapper.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/AndroidUrlRequestWrapper.java
@@ -9,14 +9,37 @@ import androidx.annotation.RequiresExtension; +import org.chromium.net.CronetEngine; +import org.chromium.net.CronetException; +import org.chromium.net.RequestFinishedInfo; +import org.chromium.net.RequestFinishedInfo.Listener; + import java.nio.ByteBuffer; +import java.util.Collection; @RequiresExtension(extension = EXT_API_LEVEL, version = EXT_VERSION) class AndroidUrlRequestWrapper extends org.chromium.net.ExperimentalUrlRequest { private final android.net.http.UrlRequest mBackend; + private final AndroidHttpEngineWrapper mEngine; + private final String mInitialUrl; + private final Collection<Object> mAnnotations; + private final VersionSafeCallbacks.RequestFinishedInfoListener mRequestFinishedInfoListener; - AndroidUrlRequestWrapper(android.net.http.UrlRequest backend) { + AndroidUrlRequestWrapper( + android.net.http.UrlRequest backend, + AndroidHttpEngineWrapper engine, + String url, + Collection<Object> annotations, + RequestFinishedInfo.Listener requestFinishedInfoListener) { this.mBackend = backend; + this.mEngine = engine; + this.mInitialUrl = url; + this.mAnnotations = annotations; + this.mRequestFinishedInfoListener = + requestFinishedInfoListener == null + ? null + : new VersionSafeCallbacks.RequestFinishedInfoListener( + requestFinishedInfoListener); } @Override @@ -57,9 +80,39 @@ * @return the wrapped request */ static AndroidUrlRequestWrapper createAndAddToCallback( - android.net.http.UrlRequest backend, AndroidUrlRequestCallbackWrapper callback) { - AndroidUrlRequestWrapper wrappedRequest = new AndroidUrlRequestWrapper(backend); + android.net.http.UrlRequest backend, + AndroidUrlRequestCallbackWrapper callback, + AndroidHttpEngineWrapper engine, + String url, + Collection<Object> annotations, + RequestFinishedInfo.Listener requestFinishedInfoListener) { + AndroidUrlRequestWrapper wrappedRequest = + new AndroidUrlRequestWrapper( + backend, engine, url, annotations, requestFinishedInfoListener); callback.setRequest(wrappedRequest); return wrappedRequest; } + + /** + * HttpEngine does not support {@link CronetEngine#addRequestFinishedListener(Listener)}). To + * preserve compatibility with Cronet users who use that method, we reimplement the + * functionality with a placeholder CronetMetric object. This reimplementation allows for {@link + * RequestFinishedInfo.Listener#onRequestFinished(RequestFinishedInfo)} to be called so as not + * to unknowingly block users who might be depending on that API call. + */ + void maybeReportMetrics( + @RequestFinishedInfoImpl.FinishedReason int finishedReason, + AndroidUrlResponseInfoWrapper responseInfo, + CronetException exception) { + final RequestFinishedInfo requestInfo = + new RequestFinishedInfoImpl( + mInitialUrl, + mAnnotations, + new CronetMetrics( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, false, -1, -1), + finishedReason, + responseInfo, + exception); + mEngine.reportRequestFinished(requestInfo, mRequestFinishedInfoListener); + } }
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java index 35d482d1..770f55f 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java
@@ -971,10 +971,9 @@ final RequestFinishedInfo requestInfo, RefCountDelegate inflightCallbackCount, VersionSafeCallbacks.RequestFinishedInfoListener extraRequestFinishedInfoListener) { - List<VersionSafeCallbacks.RequestFinishedInfoListener> currentListeners; + List<VersionSafeCallbacks.RequestFinishedInfoListener> currentListeners = new ArrayList<>(); synchronized (mFinishedListenerLock) { - if (mFinishedListenerMap.isEmpty() && extraRequestFinishedInfoListener == null) return; - currentListeners = new ArrayList<>(mFinishedListenerMap.values()); + currentListeners.addAll(mFinishedListenerMap.values()); } if (extraRequestFinishedInfoListener != null) { currentListeners.add(extraRequestFinishedInfoListener);
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java index 706658c..22d7bdd 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java
@@ -98,6 +98,7 @@ @Test @SmallTest public void testSimplePost() throws Exception { + CronetImplementation implementationUnderTest = mTestRule.implementationUnderTest(); String path = "/simple.txt"; String quicURL = QuicTestServer.getServerURL() + path; TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCallback(); @@ -124,9 +125,11 @@ requestFinishedListener.blockUntilDone(); Date endTime = new Date(); RequestFinishedInfo finishedInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(finishedInfo, quicURL, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + implementationUnderTest, finishedInfo, quicURL, startTime, endTime); assertThat(finishedInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkHasConnectTiming(finishedInfo.getMetrics(), startTime, endTime, true); + MetricsTestUtil.checkHasConnectTiming( + implementationUnderTest, finishedInfo.getMetrics(), startTime, endTime, true); assertThat(finishedInfo.getAnnotations()).containsExactly("request annotation", this); assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); assertThat(callback.mResponseAsString)
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java index a867020..1bd6ddd 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamTest.java
@@ -327,10 +327,8 @@ @Test @SmallTest - @IgnoreFor( - implementations = {CronetImplementation.AOSP_PLATFORM}, - reason = "RequedFinishedListener is not available in AOSP") public void testPostWithFinishedListener() throws Exception { + CronetImplementation implementationUnderTest = mTestRule.implementationUnderTest(); String url = Http2TestServer.getEchoStreamUrl(); TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCallback(); callback.addWriteData("Test String".getBytes()); @@ -355,9 +353,11 @@ requestFinishedListener.blockUntilDone(); Date endTime = new Date(); RequestFinishedInfo finishedInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(finishedInfo, url, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + implementationUnderTest, finishedInfo, url, startTime, endTime); assertThat(finishedInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkHasConnectTiming(finishedInfo.getMetrics(), startTime, endTime, true); + MetricsTestUtil.checkHasConnectTiming( + implementationUnderTest, finishedInfo.getMetrics(), startTime, endTime, true); assertThat(finishedInfo.getAnnotations()).containsExactly("request annotation", this); assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); assertThat(callback.mResponseAsString).isEqualTo("Test String1234567890woot!"); @@ -1316,11 +1316,6 @@ /** Checks that the buffer is updated correctly, when starting at an offset. */ @Test @SmallTest - @IgnoreFor( - implementations = {CronetImplementation.AOSP_PLATFORM}, - reason = - "crbug.com/1494845: Relies on finished listener synchronization which isn't" - + " available in AOSP") public void testSimpleGetBufferUpdates() throws Exception { TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); mCronetEngine.addRequestFinishedListener(requestFinishedListener); @@ -1494,22 +1489,29 @@ if (failureStep != ResponseStep.ON_STREAM_READY) { assertThat(callback.getResponseInfo()).isNotNull(); } - // Check metrics information. - if (failureStep == ResponseStep.ON_RESPONSE_STARTED - || failureStep == ResponseStep.ON_READ_COMPLETED - || failureStep == ResponseStep.ON_TRAILERS) { - // For steps after response headers are received, there will be - // connect timing metrics. - MetricsTestUtil.checkTimingMetrics(metrics, startTime, endTime); - MetricsTestUtil.checkHasConnectTiming(metrics, startTime, endTime, true); - assertThat(metrics.getSentByteCount()).isGreaterThan(0L); - assertThat(metrics.getReceivedByteCount()).isGreaterThan(0L); - } else if (failureStep == ResponseStep.ON_STREAM_READY) { - assertThat(metrics.getRequestStart()).isNotNull(); - MetricsTestUtil.assertAfter(metrics.getRequestStart(), startTime); - assertThat(metrics.getRequestEnd()).isNotNull(); - MetricsTestUtil.assertAfter(endTime, metrics.getRequestEnd()); - MetricsTestUtil.assertAfter(metrics.getRequestEnd(), metrics.getRequestStart()); + CronetImplementation implementationUnderTest = mTestRule.implementationUnderTest(); + // RequestFinishedInfoListener HttpEngineWrapper implementation has placeholder ie null + // metrics. Don't bother checking timing metrics for AOSP whether it passes or not. + if (implementationUnderTest != CronetImplementation.AOSP_PLATFORM) { + // Check metrics information. + if (failureStep == ResponseStep.ON_RESPONSE_STARTED + || failureStep == ResponseStep.ON_READ_COMPLETED + || failureStep == ResponseStep.ON_TRAILERS) { + // For steps after response headers are received, there will be + // connect timing metrics. + MetricsTestUtil.checkTimingMetrics( + implementationUnderTest, metrics, startTime, endTime); + MetricsTestUtil.checkHasConnectTiming( + implementationUnderTest, metrics, startTime, endTime, true); + assertThat(metrics.getSentByteCount()).isGreaterThan(0L); + assertThat(metrics.getReceivedByteCount()).isGreaterThan(0L); + } else if (failureStep == ResponseStep.ON_STREAM_READY) { + assertThat(metrics.getRequestStart()).isNotNull(); + MetricsTestUtil.assertAfter(metrics.getRequestStart(), startTime); + assertThat(metrics.getRequestEnd()).isNotNull(); + MetricsTestUtil.assertAfter(endTime, metrics.getRequestEnd()); + MetricsTestUtil.assertAfter(metrics.getRequestEnd(), metrics.getRequestStart()); + } } assertThat(callback.mError != null).isEqualTo(expectError); assertThat(callback.mOnErrorCalled).isEqualTo(expectError);
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java index 219c309..92bd66a 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -1073,7 +1073,9 @@ @SmallTest @IgnoreFor( implementations = {CronetImplementation.FALLBACK, CronetImplementation.AOSP_PLATFORM}, - reason = "Request finished listeners are only supported by native Cronet") + reason = + "Request finished listeners not supported in Fallback, Active request count not" + + " supported by AOSP.") public void testGetActiveRequestCountOnRequestFinishedListener() throws Exception { ExperimentalCronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); @@ -1098,7 +1100,9 @@ @SmallTest @IgnoreFor( implementations = {CronetImplementation.FALLBACK, CronetImplementation.AOSP_PLATFORM}, - reason = "Request finished listeners are only supported by native Cronet") + reason = + "Request finished listeners not supported in Fallback, Active request count not" + + " supported by AOSP.") public void testGetActiveRequestCountOnThrowingRequestFinishedListener() throws Exception { ExperimentalCronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); @@ -1124,7 +1128,9 @@ @SmallTest @IgnoreFor( implementations = {CronetImplementation.FALLBACK, CronetImplementation.AOSP_PLATFORM}, - reason = "Request finished listeners are only supported by native Cronet") + reason = + "Request finished listeners not supported in Fallback, Active request count not" + + " supported by AOSP.") public void testGetActiveRequestCountOnThrowingEngineRequestFinishedListener() throws Exception { ExperimentalCronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); @@ -1149,7 +1155,9 @@ @SmallTest @IgnoreFor( implementations = {CronetImplementation.FALLBACK, CronetImplementation.AOSP_PLATFORM}, - reason = "Request finished listeners are only supported by native Cronet") + reason = + "Request finished listeners not supported in Fallback, Active request count not" + + " supported by AOSP.") public void testGetActiveRequestCountOnEngineRequestFinishedListener() throws Exception { ExperimentalCronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener();
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/MetricsTestUtil.java b/components/cronet/android/test/javatests/src/org/chromium/net/MetricsTestUtil.java index 7e39d582..ac50ec0b 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/MetricsTestUtil.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/MetricsTestUtil.java
@@ -7,6 +7,8 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import org.chromium.net.CronetTestRule.CronetImplementation; + import java.util.Date; import java.util.LinkedList; import java.util.NoSuchElementException; @@ -47,14 +49,21 @@ } /** - * Check existence of all the timing metrics that apply to most test requests, - * except those that come from net::LoadTimingInfo::ConnectTiming. - * Also check some timing differences, focusing on things we can't check with asserts in the - * CronetMetrics constructor. - * Don't check push times here. + * Check existence of all the timing metrics that apply to most test requests, except those that + * come from net::LoadTimingInfo::ConnectTiming. Also check some timing differences, focusing on + * things we can't check with asserts in the CronetMetrics constructor. Don't check push times + * here. */ public static void checkTimingMetrics( - RequestFinishedInfo.Metrics metrics, Date startTime, Date endTime) { + CronetImplementation implementationUnderTest, + RequestFinishedInfo.Metrics metrics, + Date startTime, + Date endTime) { + if (implementationUnderTest == CronetImplementation.AOSP_PLATFORM) { + // RequestFinishedInfoListener HttpEngineWrapper implementation has placeholder ie null + // metrics. Don't bother checking timing metrics for AOSP whether it passes or not. + return; + } assertThat(metrics.getRequestStart()).isNotNull(); assertAfter(metrics.getRequestStart(), startTime); assertThat(metrics.getSendingStart()).isNotNull(); @@ -73,7 +82,16 @@ * except SSL times in the case of non-https requests. */ public static void checkHasConnectTiming( - RequestFinishedInfo.Metrics metrics, Date startTime, Date endTime, boolean isSsl) { + CronetImplementation implementationUnderTest, + RequestFinishedInfo.Metrics metrics, + Date startTime, + Date endTime, + boolean isSsl) { + if (implementationUnderTest == CronetImplementation.AOSP_PLATFORM) { + // RequestFinishedInfoListener HttpEngineWrapper implementation has placeholder ie null + // metrics. Don't bother checking timing metrics for AOSP whether it passes or not. + return; + } assertThat(metrics.getDnsStart()).isNotNull(); assertAfter(metrics.getDnsStart(), startTime); assertThat(metrics.getDnsEnd()).isNotNull(); @@ -94,7 +112,14 @@ } /** Check that the timing metrics from net::LoadTimingInfo::ConnectTiming don't exist. */ - public static void checkNoConnectTiming(RequestFinishedInfo.Metrics metrics) { + public static void checkNoConnectTiming( + CronetImplementation implementationUnderTest, RequestFinishedInfo.Metrics metrics) { + if (implementationUnderTest == CronetImplementation.AOSP_PLATFORM) { + // RequestFinishedInfoListener HttpEngineWrapper implementation has placeholder ie null + // metrics. Although the checks below would pass, generally, don't bother checking + // timing metrics for AOSP whether it passes or not. + return; + } assertThat(metrics.getDnsStart()).isNull(); assertThat(metrics.getDnsEnd()).isNull(); assertThat(metrics.getSslStart()).isNull(); @@ -103,9 +128,15 @@ assertThat(metrics.getConnectEnd()).isNull(); } - /** Check that RequestFinishedInfo looks the way it should look for a normal successful request. */ + /** + * Check that RequestFinishedInfo looks the way it should look for a normal successful request. + */ public static void checkRequestFinishedInfo( - RequestFinishedInfo info, String url, Date startTime, Date endTime) { + CronetImplementation implementationUnderTest, + RequestFinishedInfo info, + String url, + Date startTime, + Date endTime) { assertWithMessage("RequestFinishedInfo.Listener must be called").that(info).isNotNull(); assertThat(info.getUrl()).isEqualTo(url); assertThat(info.getResponseInfo()).isNotNull(); @@ -114,15 +145,20 @@ assertWithMessage("RequestFinishedInfo.getMetrics() must not be null") .that(metrics) .isNotNull(); - // Check old (deprecated) timing metrics - assertThat(metrics.getTotalTimeMs()).isAtLeast(0L); - assertThat(metrics.getTotalTimeMs()).isAtLeast(metrics.getTtfbMs()); - // Check new timing metrics - checkTimingMetrics(metrics, startTime, endTime); - assertThat(metrics.getPushStart()).isNull(); - assertThat(metrics.getPushEnd()).isNull(); - // Check data use metrics - assertThat(metrics.getSentByteCount()).isGreaterThan(0L); - assertThat(metrics.getReceivedByteCount()).isGreaterThan(0L); + + // RequestFinishedInfoListener HttpEngineWrapper implementation has placeholder ie null + // metrics. Don't bother checking timing metrics for AOSP whether it passes or not. + if (implementationUnderTest != CronetImplementation.AOSP_PLATFORM) { + // Check old (deprecated) timing metrics + assertThat(metrics.getTotalTimeMs()).isAtLeast(0L); + assertThat(metrics.getTotalTimeMs()).isAtLeast(metrics.getTtfbMs()); + // Check new timing metrics + checkTimingMetrics(implementationUnderTest, metrics, startTime, endTime); + assertThat(metrics.getPushStart()).isNull(); + assertThat(metrics.getPushEnd()).isNull(); + // Check data use metrics + assertThat(metrics.getSentByteCount()).isGreaterThan(0L); + assertThat(metrics.getReceivedByteCount()).isGreaterThan(0L); + } } }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java index 1aff795..b3f3ac9d9 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java
@@ -249,6 +249,7 @@ @SmallTest public void testMetricsWithQuic() throws Exception { ExperimentalCronetEngine cronetEngine = mTestRule.getTestFramework().getEngine(); + CronetImplementation implementationUnderTest = mTestRule.implementationUnderTest(); TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); cronetEngine.addRequestFinishedListener(requestFinishedListener); @@ -267,9 +268,11 @@ assertIsQuic(callback.getResponseInfoWithChecks()); RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, quicURL, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + implementationUnderTest, requestInfo, quicURL, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, true); + MetricsTestUtil.checkHasConnectTiming( + implementationUnderTest, requestInfo.getMetrics(), startTime, endTime, true); // Second request should use the same connection and not have ConnectTiming numbers callback = new TestUrlRequestCallback(); @@ -286,9 +289,10 @@ assertIsQuic(callback.getResponseInfoWithChecks()); requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, quicURL, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + implementationUnderTest, requestInfo, quicURL, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkNoConnectTiming(requestInfo.getMetrics()); + MetricsTestUtil.checkNoConnectTiming(implementationUnderTest, requestInfo.getMetrics()); cronetEngine.shutdown(); }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java index c4963d4f..1cee9e6 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java
@@ -38,12 +38,13 @@ @DoNotBatch(reason = "crbug/1459563") @RunWith(AndroidJUnit4.class) @IgnoreFor( - implementations = {CronetImplementation.FALLBACK, CronetImplementation.AOSP_PLATFORM}, - reason = "Fallback and AOSP implementations do not support RequestFinishedListeners") + implementations = {CronetImplementation.FALLBACK}, + reason = "Fallback implementation does not support RequestFinishedListener.") public class RequestFinishedInfoTest { @Rule public final CronetTestRule mTestRule = CronetTestRule.withAutomaticEngineStartup(); private String mUrl; + private CronetImplementation mImplementationUnderTest; // A subclass of TestRequestFinishedListener to additionally assert that UrlRequest.Callback's // terminal callbacks have been invoked at the time of onRequestFinished(). @@ -64,12 +65,12 @@ super.onRequestFinished(requestInfo); } } - ; @Before public void setUp() throws Exception { NativeTestServer.startNativeTestServer(mTestRule.getTestFramework().getContext()); mUrl = NativeTestServer.getFileURL("/echo?status=200"); + mImplementationUnderTest = mTestRule.implementationUnderTest(); } @After @@ -135,9 +136,11 @@ Date endTime = new Date(); RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, requestInfo, mUrl, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); + MetricsTestUtil.checkHasConnectTiming( + mImplementationUnderTest, requestInfo.getMetrics(), startTime, endTime, false); assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); } @@ -172,9 +175,11 @@ Date endTime = new Date(); RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, requestInfo, mUrl, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); + MetricsTestUtil.checkHasConnectTiming( + mImplementationUnderTest, requestInfo.getMetrics(), startTime, endTime, false); assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); } @@ -207,15 +212,21 @@ RequestFinishedInfo firstRequestInfo = firstListener.getRequestInfo(); RequestFinishedInfo secondRequestInfo = secondListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(firstRequestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, firstRequestInfo, mUrl, startTime, endTime); assertThat(firstRequestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); MetricsTestUtil.checkHasConnectTiming( - firstRequestInfo.getMetrics(), startTime, endTime, false); + mImplementationUnderTest, firstRequestInfo.getMetrics(), startTime, endTime, false); - MetricsTestUtil.checkRequestFinishedInfo(secondRequestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, secondRequestInfo, mUrl, startTime, endTime); assertThat(secondRequestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); MetricsTestUtil.checkHasConnectTiming( - secondRequestInfo.getMetrics(), startTime, endTime, false); + mImplementationUnderTest, + secondRequestInfo.getMetrics(), + startTime, + endTime, + false); assertThat(firstRequestInfo.getAnnotations()).containsExactly("request annotation", this); assertThat(secondRequestInfo.getAnnotations()).containsExactly("request annotation", this); @@ -259,22 +270,28 @@ assertWithMessage("RequestFinishedInfo.getMetrics() must not be null") .that(metrics) .isNotNull(); - // The failure is occasionally fast enough that time reported is 0, so just check for null - assertThat(metrics.getTotalTimeMs()).isNotNull(); - assertThat(metrics.getTtfbMs()).isNull(); - // Check the timing metrics - assertThat(metrics.getRequestStart()).isNotNull(); - MetricsTestUtil.assertAfter(metrics.getRequestStart(), startTime); - MetricsTestUtil.checkNoConnectTiming(metrics); - assertThat(metrics.getSendingStart()).isNull(); - assertThat(metrics.getSendingEnd()).isNull(); - assertThat(metrics.getResponseStart()).isNull(); - assertThat(metrics.getRequestEnd()).isNotNull(); - MetricsTestUtil.assertAfter(endTime, metrics.getRequestEnd()); - MetricsTestUtil.assertAfter(metrics.getRequestEnd(), metrics.getRequestStart()); - assertThat(metrics.getSentByteCount()).isEqualTo(0); - assertThat(metrics.getReceivedByteCount()).isEqualTo(0); + // RequestFinishedInfoListener HttpEngineWrapper implementation has placeholder ie null + // metrics. Don't bother checking timing metrics for AOSP whether it passes or not. + if (mImplementationUnderTest != CronetImplementation.AOSP_PLATFORM) { + // The failure is occasionally fast enough that time reported is 0, so just check for + // null + assertThat(metrics.getTotalTimeMs()).isNotNull(); + assertThat(metrics.getTtfbMs()).isNull(); + + // Check the timing metrics + assertThat(metrics.getRequestStart()).isNotNull(); + MetricsTestUtil.assertAfter(metrics.getRequestStart(), startTime); + MetricsTestUtil.checkNoConnectTiming(mImplementationUnderTest, metrics); + assertThat(metrics.getSendingStart()).isNull(); + assertThat(metrics.getSendingEnd()).isNull(); + assertThat(metrics.getResponseStart()).isNull(); + assertThat(metrics.getRequestEnd()).isNotNull(); + MetricsTestUtil.assertAfter(endTime, metrics.getRequestEnd()); + MetricsTestUtil.assertAfter(metrics.getRequestEnd(), metrics.getRequestStart()); + assertThat(metrics.getSentByteCount()).isEqualTo(0); + assertThat(metrics.getReceivedByteCount()).isEqualTo(0); + } } @Test @@ -401,9 +418,11 @@ Date endTime = new Date(); RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, requestInfo, mUrl, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.CANCELED); - MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); + MetricsTestUtil.checkHasConnectTiming( + mImplementationUnderTest, requestInfo.getMetrics(), startTime, endTime, false); assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); } @@ -437,7 +456,13 @@ // Empty headers are invalid and will cause start() to throw an exception. UrlRequest request = urlRequestBuilder.addHeader("", "").build(); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, request::start); - assertThat(e).hasMessageThat().isEqualTo("Invalid header with headername: "); + if (mImplementationUnderTest == CronetImplementation.AOSP_PLATFORM + && !mTestRule.isRunningInAOSP()) { + // TODO(b/307234565): Remove check once chromium Android 14 emulator has latest changes. + assertThat(e).hasMessageThat().isEqualTo("Invalid header ="); + } else { + assertThat(e).hasMessageThat().isEqualTo("Invalid header with headername: "); + } } @Test @@ -491,8 +516,8 @@ assertThat(metrics.getResponseStart()).isEqualTo(new Date(responseStart)); assertThat(metrics.getRequestEnd()).isEqualTo(new Date(requestEnd)); assertThat(metrics.getSocketReused()).isEqualTo(socketReused); - assertThat((long) metrics.getSentByteCount()).isEqualTo(sentByteCount); - assertThat((long) metrics.getReceivedByteCount()).isEqualTo(receivedByteCount); + assertThat(metrics.getSentByteCount()).isEqualTo(sentByteCount); + assertThat(metrics.getReceivedByteCount()).isEqualTo(receivedByteCount); } @Test @@ -523,9 +548,11 @@ Date endTime = new Date(); RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, requestInfo, mUrl, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); + MetricsTestUtil.checkHasConnectTiming( + mImplementationUnderTest, requestInfo.getMetrics(), startTime, endTime, false); assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); } @@ -562,9 +589,11 @@ requestFinishedListener.blockUntilDone(); Date endTime = new Date(); RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, requestInfo, mUrl, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.SUCCEEDED); - MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); + MetricsTestUtil.checkHasConnectTiming( + mImplementationUnderTest, requestInfo.getMetrics(), startTime, endTime, false); // Check that annotation got updated in onSucceeded() callback. assertThat(requestInfo.getAnnotations()).containsExactly(requestAnnotation); assertThat(requestAnnotation.get()).isTrue(); @@ -684,9 +713,11 @@ Date endTime = new Date(); RequestFinishedInfo requestInfo = requestFinishedListener.getRequestInfo(); - MetricsTestUtil.checkRequestFinishedInfo(requestInfo, mUrl, startTime, endTime); + MetricsTestUtil.checkRequestFinishedInfo( + mImplementationUnderTest, requestInfo, mUrl, startTime, endTime); assertThat(requestInfo.getFinishedReason()).isEqualTo(RequestFinishedInfo.CANCELED); - MetricsTestUtil.checkHasConnectTiming(requestInfo.getMetrics(), startTime, endTime, false); + MetricsTestUtil.checkHasConnectTiming( + mImplementationUnderTest, requestInfo.getMetrics(), startTime, endTime, false); assertThat(requestInfo.getAnnotations()).containsExactly("request annotation", this); }
diff --git a/components/data_sharing/BUILD.gn b/components/data_sharing/BUILD.gn index 2e28c21..fe4d5c1 100644 --- a/components/data_sharing/BUILD.gn +++ b/components/data_sharing/BUILD.gn
@@ -4,6 +4,11 @@ import("//build/buildflag_header.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + group("unit_tests") { testonly = true @@ -36,3 +41,16 @@ "//url", ] } + +if (is_android) { + android_library("test_support_java") { + sources = [ "test_support/android/java/src/org/chromium/components/data_sharing/TestDataSharingService.java" ] + deps = [ + "//base:base_java", + "//components/data_sharing/public:public_java", + "//third_party/androidx:androidx_annotation_annotation_java", + "//third_party/jni_zero:jni_zero_java", + "//url:gurl_java", + ] + } +}
diff --git a/components/data_sharing/internal/BUILD.gn b/components/data_sharing/internal/BUILD.gn index ee9159fa..ab0711d 100644 --- a/components/data_sharing/internal/BUILD.gn +++ b/components/data_sharing/internal/BUILD.gn
@@ -48,13 +48,18 @@ if (is_android) { sources += [ + "android/data_sharing_conversion_bridge.cc", + "android/data_sharing_conversion_bridge.h", "android/data_sharing_network_loader_android.cc", "android/data_sharing_network_loader_android.h", "android/data_sharing_service_android.cc", "android/data_sharing_service_android.h", ] - deps += [ ":jni_headers" ] + deps += [ + ":jni_headers", + "//components/data_sharing/public:jni_headers", + ] } } @@ -68,11 +73,16 @@ "data_sharing_network_loader_impl_unittest.cc", "data_sharing_service_impl_unittest.cc", "empty_data_sharing_service_unittest.cc", + "fake_data_sharing_sdk_delegate.cc", + "fake_data_sharing_sdk_delegate.h", "group_data_proto_utils_unittest.cc", ] if (is_android) { - sources += [ "android/data_sharing_network_loader_android_unittest.cc" ] + sources += [ + "android/data_sharing_network_loader_android_unittest.cc", + "android/data_sharing_service_android_unittest.cc", + ] } deps = [ @@ -90,6 +100,8 @@ if (is_android) { deps += [ + ":native_test_helper_java", + ":test_jni_headers", "//components/data_sharing:test_support", "//url", ] @@ -102,10 +114,15 @@ "//chrome/android:chrome_all_java", "//components:*", ] - srcjar_deps = [ ":jni_headers" ] + srcjar_deps = [ + ":jni_headers", + "//components/data_sharing/public:jni_headers", + ] sources = [ + "android/java/src/org/chromium/components/data_sharing/DataSharingConversionBridge.java", "android/java/src/org/chromium/components/data_sharing/DataSharingNetworkLoaderImpl.java", "android/java/src/org/chromium/components/data_sharing/DataSharingServiceImpl.java", + "android/java/src/org/chromium/components/data_sharing/ObserverBridge.java", ] deps = [ @@ -125,11 +142,29 @@ ] sources = [ + "android/java/src/org/chromium/components/data_sharing/DataSharingConversionBridge.java", "android/java/src/org/chromium/components/data_sharing/DataSharingNetworkLoaderImpl.java", "android/java/src/org/chromium/components/data_sharing/DataSharingServiceImpl.java", + "android/java/src/org/chromium/components/data_sharing/ObserverBridge.java", ] } + android_library("native_test_helper_java") { + srcjar_deps = [ ":test_jni_headers" ] + testonly = true + sources = [ "android/java/src/org/chromium/components/data_sharing/TestServiceObserver.java" ] + deps = [ + "//base:base_java", + "//components/data_sharing/public:public_java", + "//third_party/jni_zero:jni_zero_java", + ] + } + + generate_jni("test_jni_headers") { + testonly = true + sources = [ "android/java/src/org/chromium/components/data_sharing/TestServiceObserver.java" ] + } + robolectric_library("data_sharing_junit_tests") { sources = [ "android/java/src/org/chromium/components/data_sharing/DataSharingNetworkLoaderImplTest.java" ]
diff --git a/components/data_sharing/internal/android/data_sharing_conversion_bridge.cc b/components/data_sharing/internal/android/data_sharing_conversion_bridge.cc new file mode 100644 index 0000000..c47ae53 --- /dev/null +++ b/components/data_sharing/internal/android/data_sharing_conversion_bridge.cc
@@ -0,0 +1,102 @@ +// 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/data_sharing/internal/android/data_sharing_conversion_bridge.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "components/data_sharing/internal/jni_headers/DataSharingConversionBridge_jni.h" +#include "components/data_sharing/public/group_data.h" +#include "components/data_sharing/public/jni_headers/GroupData_jni.h" +#include "components/data_sharing/public/jni_headers/GroupMember_jni.h" +#include "url/android/gurl_android.h" + +using base::android::AttachCurrentThread; +using base::android::ConvertUTF8ToJavaString; +using base::android::ScopedJavaLocalRef; +using base::android::ToTypedJavaArrayOfObjects; + +namespace data_sharing { + +// static +ScopedJavaLocalRef<jobject> DataSharingConversionBridge::CreateJavaGroupMember( + JNIEnv* env, + const GroupMember& member) { + return Java_GroupMember_createGroupMember( + env, ConvertUTF8ToJavaString(env, member.gaia_id), + ConvertUTF8ToJavaString(env, member.display_name), + ConvertUTF8ToJavaString(env, member.email), static_cast<int>(member.role), + url::GURLAndroid::FromNativeGURL(env, member.avatar_url)); +} + +// static +ScopedJavaLocalRef<jobject> DataSharingConversionBridge::CreateJavaGroupData( + JNIEnv* env, + const GroupData& group_data) { + std::vector<ScopedJavaLocalRef<jobject>> j_members; + j_members.reserve(group_data.members.size()); + for (const GroupMember& member : group_data.members) { + j_members.push_back(CreateJavaGroupMember(env, member)); + } + return Java_GroupData_createGroupData( + env, ConvertUTF8ToJavaString(env, group_data.group_id), + ConvertUTF8ToJavaString(env, group_data.display_name), + ToTypedJavaArrayOfObjects( + env, base::make_span(j_members), + org_chromium_components_data_1sharing_GroupMember_clazz(env))); +} + +// static +ScopedJavaLocalRef<jobject> +DataSharingConversionBridge::CreateGroupDataOrFailureOutcome( + JNIEnv* env, + const DataSharingService::GroupDataOrFailureOutcome& data) { + ScopedJavaLocalRef<jobject> j_group_data; + DataSharingService::PeopleGroupActionFailure failure = + DataSharingService::PeopleGroupActionFailure::kUnknown; + if (data.has_value()) { + j_group_data = CreateJavaGroupData(env, data.value()); + } else { + failure = data.error(); + } + return Java_DataSharingConversionBridge_createGroupDataOrFailureOutcome( + env, j_group_data, static_cast<int>(failure)); +} + +// static +ScopedJavaLocalRef<jobject> +DataSharingConversionBridge::CreateGroupDataSetOrFailureOutcome( + JNIEnv* env, + const DataSharingService::GroupsDataSetOrFailureOutcome& data) { + std::vector<ScopedJavaLocalRef<jobject>> j_groups_data; + DataSharingService::PeopleGroupActionFailure failure = + DataSharingService::PeopleGroupActionFailure::kUnknown; + if (data.has_value()) { + for (const GroupData& group : data.value()) { + j_groups_data.push_back(CreateJavaGroupData(env, group)); + } + } else { + failure = data.error(); + } + ScopedJavaLocalRef<jobjectArray> j_group_array; + if (!j_groups_data.empty()) { + j_group_array = ToTypedJavaArrayOfObjects( + env, base::make_span(j_groups_data), + org_chromium_components_data_1sharing_GroupData_clazz(env)); + } + return Java_DataSharingConversionBridge_createGroupDataSetOrFailureOutcome( + env, j_group_array, static_cast<int>(failure)); +} + +// static +ScopedJavaLocalRef<jobject> +DataSharingConversionBridge::CreatePeopleGroupActionOutcome(JNIEnv* env, + int value) { + return Java_DataSharingConversionBridge_createPeopleGroupActionOutcome( + AttachCurrentThread(), value); +} + +} // namespace data_sharing
diff --git a/components/data_sharing/internal/android/data_sharing_conversion_bridge.h b/components/data_sharing/internal/android/data_sharing_conversion_bridge.h new file mode 100644 index 0000000..ca753b8 --- /dev/null +++ b/components/data_sharing/internal/android/data_sharing_conversion_bridge.h
@@ -0,0 +1,55 @@ +// 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_DATA_SHARING_INTERNAL_ANDROID_DATA_SHARING_CONVERSION_BRIDGE_H_ +#define COMPONENTS_DATA_SHARING_INTERNAL_ANDROID_DATA_SHARING_CONVERSION_BRIDGE_H_ + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "components/data_sharing/public/data_sharing_service.h" +#include "components/data_sharing/public/group_data.h" + +using base::android::ScopedJavaLocalRef; + +namespace data_sharing { + +// Utility for JNI conversion of the data types used by the service. +class DataSharingConversionBridge { + public: + // Creates an object of org.chromium.components.data_sharing.GroupMember. + static ScopedJavaLocalRef<jobject> CreateJavaGroupMember( + JNIEnv* env, + const GroupMember& member); + + // Creates an object of org.chromium.components.data_sharing.GroupData. + static ScopedJavaLocalRef<jobject> CreateJavaGroupData( + JNIEnv* env, + const GroupData& result); + + // Creates an object of + // org.chromium.components.data_sharing.DataSharingService. + // GroupDataOrFailureOutcome. + static ScopedJavaLocalRef<jobject> CreateGroupDataOrFailureOutcome( + JNIEnv* env, + const DataSharingService::GroupDataOrFailureOutcome& data); + + // Creates an object of + // org.chromium.components.data_sharing.DataSharingService. + // GroupsDataSetOrFailureOutcome. + static ScopedJavaLocalRef<jobject> CreateGroupDataSetOrFailureOutcome( + JNIEnv* env, + const DataSharingService::GroupsDataSetOrFailureOutcome& data); + + // Creates an Integer object that identifies the generated enum + // PeopleGroupActionOutcome. The object is useful since Java Callback does not + // support primitive type int. + static ScopedJavaLocalRef<jobject> CreatePeopleGroupActionOutcome(JNIEnv* env, + int value); +}; + +} // namespace data_sharing + +#endif // COMPONENTS_DATA_SHARING_INTERNAL_ANDROID_DATA_SHARING_CONVERSION_BRIDGE_H_
diff --git a/components/data_sharing/internal/android/data_sharing_service_android.cc b/components/data_sharing/internal/android/data_sharing_service_android.cc index 9dcd1896..c0b0397 100644 --- a/components/data_sharing/internal/android/data_sharing_service_android.cc +++ b/components/data_sharing/internal/android/data_sharing_service_android.cc
@@ -5,14 +5,24 @@ #include "components/data_sharing/internal/android/data_sharing_service_android.h" #include <memory> +#include <string> +#include "base/android/callback_android.h" +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/scoped_observation.h" +#include "components/data_sharing/internal/android/data_sharing_conversion_bridge.h" #include "components/data_sharing/internal/android/data_sharing_network_loader_android.h" #include "components/data_sharing/internal/jni_headers/DataSharingServiceImpl_jni.h" +#include "components/data_sharing/internal/jni_headers/ObserverBridge_jni.h" #include "components/data_sharing/public/data_sharing_service.h" using base::android::AttachCurrentThread; +using base::android::ConvertJavaStringToUTF8; +using base::android::ConvertUTF8ToJavaString; using base::android::JavaParamRef; +using base::android::RunObjectCallbackAndroid; using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; @@ -21,8 +31,93 @@ const char kDataSharingServiceBridgeKey[] = "data_sharing_service_bridge"; +void RunGroupsDataSetOrFailureOutcomeCallback( + const JavaRef<jobject>& j_callback, + const DataSharingService::GroupsDataSetOrFailureOutcome& result) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> j_result = + DataSharingConversionBridge::CreateGroupDataSetOrFailureOutcome(env, + result); + RunObjectCallbackAndroid(j_callback, j_result); +} + +void RunGroupDataOrFailureOutcomeCallback( + const JavaRef<jobject>& j_callback, + const DataSharingService::GroupDataOrFailureOutcome& result) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> j_result = + DataSharingConversionBridge::CreateGroupDataOrFailureOutcome(env, result); + RunObjectCallbackAndroid(j_callback, j_result); +} + +void RunPeopleGroupActionOutcomeCallback( + const JavaRef<jobject>& j_callback, + DataSharingService::PeopleGroupActionOutcome result) { + ScopedJavaLocalRef<jobject> j_result = + DataSharingConversionBridge::CreatePeopleGroupActionOutcome( + AttachCurrentThread(), static_cast<int>(result)); + RunObjectCallbackAndroid(j_callback, j_result); +} + } // namespace +// Native counterpart of Java ObserverBridge. Observes the native service and +// sends notifications to the Java bridge. +class DataSharingServiceAndroid::GroupDataObserverBridge + : public DataSharingService::Observer { + public: + GroupDataObserverBridge( + DataSharingService* data_sharing_service, + DataSharingServiceAndroid* data_sharing_service_android); + ~GroupDataObserverBridge() override; + + GroupDataObserverBridge(const GroupDataObserverBridge&) = delete; + GroupDataObserverBridge& operator=(const GroupDataObserverBridge&) = delete; + + // DataSharingService::Observer impl: + void OnGroupChanged(const GroupData& group_data) override; + void OnGroupAdded(const GroupData& group_data) override; + void OnGroupRemoved(const std::string& group_id) override; + + private: + ScopedJavaLocalRef<jobject> java_obj_; + base::ScopedObservation<DataSharingService, DataSharingService::Observer> + scoped_obs_{this}; +}; + +DataSharingServiceAndroid::GroupDataObserverBridge::GroupDataObserverBridge( + DataSharingService* data_sharing_service, + DataSharingServiceAndroid* data_sharing_service_android) { + java_obj_ = data_sharing_service_android->GetJavaObserverBridge(); + scoped_obs_.Observe(data_sharing_service); +} + +DataSharingServiceAndroid::GroupDataObserverBridge::~GroupDataObserverBridge() = + default; + +void DataSharingServiceAndroid::GroupDataObserverBridge::OnGroupChanged( + const GroupData& group_data) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> j_group = + DataSharingConversionBridge::CreateJavaGroupData(env, group_data); + Java_ObserverBridge_onGroupChanged(env, java_obj_, j_group); +} + +void DataSharingServiceAndroid::GroupDataObserverBridge::OnGroupAdded( + const GroupData& group_data) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> j_group = + DataSharingConversionBridge::CreateJavaGroupData(env, group_data); + Java_ObserverBridge_onGroupAdded(env, java_obj_, j_group); +} + +void DataSharingServiceAndroid::GroupDataObserverBridge::OnGroupRemoved( + const std::string& group_id) { + JNIEnv* env = AttachCurrentThread(); + Java_ObserverBridge_onGroupRemoved(env, java_obj_, + ConvertUTF8ToJavaString(env, group_id)); +} + // This function is declared in data_sharing_service.h and // should be linked in to any binary using // DataSharingService::GetJavaObject. @@ -50,6 +145,8 @@ java_obj_.Reset(env, Java_DataSharingServiceImpl_create( env, reinterpret_cast<int64_t>(this)) .obj()); + observer_bridge_ = + std::make_unique<GroupDataObserverBridge>(data_sharing_service, this); } DataSharingServiceAndroid::~DataSharingServiceAndroid() { @@ -57,6 +154,68 @@ Java_DataSharingServiceImpl_clearNativePtr(env, java_obj_); } +void DataSharingServiceAndroid::ReadAllGroups( + JNIEnv* env, + const JavaParamRef<jobject>& j_callback) { + data_sharing_service_->ReadAllGroups( + base::BindOnce(&RunGroupsDataSetOrFailureOutcomeCallback, + ScopedJavaGlobalRef<jobject>(j_callback))); +} + +void DataSharingServiceAndroid::ReadGroup( + JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jobject>& j_callback) { + data_sharing_service_->ReadGroup( + ConvertJavaStringToUTF8(env, group_id), + base::BindOnce(&RunGroupDataOrFailureOutcomeCallback, + ScopedJavaGlobalRef<jobject>(j_callback))); +} + +void DataSharingServiceAndroid::CreateGroup( + JNIEnv* env, + const JavaParamRef<jstring>& group_name, + const JavaParamRef<jobject>& j_callback) { + data_sharing_service_->CreateGroup( + ConvertJavaStringToUTF8(env, group_name), + base::BindOnce(&RunGroupDataOrFailureOutcomeCallback, + ScopedJavaGlobalRef<jobject>(j_callback))); +} + +void DataSharingServiceAndroid::DeleteGroup( + JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jobject>& j_callback) { + data_sharing_service_->DeleteGroup( + ConvertJavaStringToUTF8(env, group_id), + base::BindOnce(&RunPeopleGroupActionOutcomeCallback, + ScopedJavaGlobalRef<jobject>(j_callback))); +} + +void DataSharingServiceAndroid::InviteMember( + JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jstring>& invitee_email, + const JavaParamRef<jobject>& j_callback) { + data_sharing_service_->InviteMember( + ConvertJavaStringToUTF8(env, group_id), + ConvertJavaStringToUTF8(env, invitee_email), + base::BindOnce(&RunPeopleGroupActionOutcomeCallback, + ScopedJavaGlobalRef<jobject>(j_callback))); +} + +void DataSharingServiceAndroid::RemoveMember( + JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jstring>& member_email, + const JavaParamRef<jobject>& j_callback) { + data_sharing_service_->RemoveMember( + ConvertJavaStringToUTF8(env, group_id), + ConvertJavaStringToUTF8(env, member_email), + base::BindOnce(&RunPeopleGroupActionOutcomeCallback, + ScopedJavaGlobalRef<jobject>(j_callback))); +} + bool DataSharingServiceAndroid::IsEmptyService( JNIEnv* env, const JavaParamRef<jobject>& jcaller) { @@ -72,4 +231,9 @@ return ScopedJavaLocalRef<jobject>(java_obj_); } +ScopedJavaLocalRef<jobject> DataSharingServiceAndroid::GetJavaObserverBridge() { + JNIEnv* env = base::android::AttachCurrentThread(); + return Java_DataSharingServiceImpl_getObserverBridge(env, GetJavaObject()); +} + } // namespace data_sharing
diff --git a/components/data_sharing/internal/android/data_sharing_service_android.h b/components/data_sharing/internal/android/data_sharing_service_android.h index 721ecbe..a3b5a7a 100644 --- a/components/data_sharing/internal/android/data_sharing_service_android.h +++ b/components/data_sharing/internal/android/data_sharing_service_android.h
@@ -26,12 +26,39 @@ explicit DataSharingServiceAndroid(DataSharingService* service); ~DataSharingServiceAndroid() override; + // DataSharingService Java API methods, implemented by native service: + void ReadAllGroups(JNIEnv* env, const JavaParamRef<jobject>& j_callback); + void ReadGroup(JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jobject>& j_callback); + void CreateGroup(JNIEnv* env, + const JavaParamRef<jstring>& group_name, + const JavaParamRef<jobject>& j_callback); + void DeleteGroup(JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jobject>& j_callback); + void InviteMember(JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jstring>& invitee_email, + const JavaParamRef<jobject>& j_callback); + void RemoveMember(JNIEnv* env, + const JavaParamRef<jstring>& group_id, + const JavaParamRef<jstring>& member_email, + const JavaParamRef<jobject>& j_callback); bool IsEmptyService(JNIEnv* env, const JavaParamRef<jobject>& j_caller); ScopedJavaLocalRef<jobject> GetNetworkLoader(JNIEnv* env); + // Returns the DataSharingServiceImpl java object. ScopedJavaLocalRef<jobject> GetJavaObject(); + // Returns the observer that routes the notifications to Java observers. The + // returned object is of type: + // org.chromium.components.data_sharing.ObserverBridge. + ScopedJavaLocalRef<jobject> GetJavaObserverBridge(); + private: + class GroupDataObserverBridge; + // A reference to the Java counterpart of this class. See // DataSharingServiceImpl.java. ScopedJavaGlobalRef<jobject> java_obj_; @@ -40,6 +67,8 @@ raw_ptr<DataSharingService> data_sharing_service_; std::unique_ptr<DataSharingNetworkLoaderAndroid> network_loader_; + + std::unique_ptr<GroupDataObserverBridge> observer_bridge_; }; } // namespace data_sharing
diff --git a/components/data_sharing/internal/android/data_sharing_service_android_unittest.cc b/components/data_sharing/internal/android/data_sharing_service_android_unittest.cc new file mode 100644 index 0000000..32cdf5be --- /dev/null +++ b/components/data_sharing/internal/android/data_sharing_service_android_unittest.cc
@@ -0,0 +1,273 @@ +// 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/data_sharing/internal/android/data_sharing_service_android.h" + +#include "base/android/jni_android.h" +#include "base/functional/callback_forward.h" +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "components/data_sharing/internal/data_sharing_service_impl.h" +#include "components/data_sharing/internal/fake_data_sharing_sdk_delegate.h" +#include "components/data_sharing/internal/test_jni_headers/TestServiceObserver_jni.h" +#include "components/data_sharing/public/data_sharing_service.h" +#include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/sync/protocol/model_type_state.pb.h" +#include "components/sync/test/model_type_store_test_util.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" +#include "third_party/abseil-cpp/absl/status/status.h" + +namespace data_sharing { + +using ::base::android::AttachCurrentThread; +using ::base::android::ScopedJavaLocalRef; + +// Java observer for testing, counter part of TestServiceObserver. +// On each observation increments a counter and runs the callback. +class TestJavaObserver { + public: + TestJavaObserver(DataSharingService* service, base::OnceClosure callback) + : service_(DataSharingService::GetJavaObject(service)), + java_obj_(Java_TestServiceObserver_createAndAdd( + AttachCurrentThread(), + service_, + reinterpret_cast<long>(this))), + callback_(std::move(callback)) {} + ~TestJavaObserver() { + Java_TestServiceObserver_destroy(AttachCurrentThread(), java_obj_, + service_); + } + + int GetGroupChangeCount() { + return Java_TestServiceObserver_getOnGroupChangeCount(AttachCurrentThread(), + java_obj_); + } + int GetGroupAddedCount() { + return Java_TestServiceObserver_getOnGroupAddedCount(AttachCurrentThread(), + java_obj_); + } + int GetGroupRemovedCount() { + return Java_TestServiceObserver_getOnGroupRemovedCount( + AttachCurrentThread(), java_obj_); + } + + void ResetCallback(base::OnceClosure callback) { + callback_ = std::move(callback); + } + + void OnObserverNotify() { std::move(callback_).Run(); } + + private: + ScopedJavaLocalRef<jobject> service_; + ScopedJavaLocalRef<jobject> java_obj_; + + base::OnceClosure callback_; +}; + +// Implements TestServiceObserver.onObserverNotify static method. +void JNI_TestServiceObserver_OnObserverNotify(JNIEnv* env, jlong observer_ptr) { + reinterpret_cast<TestJavaObserver*>(observer_ptr)->OnObserverNotify(); +} + +namespace { + +sync_pb::CollaborationGroupSpecifics MakeCollaborationGroupSpecifics( + const std::string& id) { + sync_pb::CollaborationGroupSpecifics result; + result.set_collaboration_id(id); + result.set_last_updated_timestamp_millis_since_unix_epoch( + base::Time::Now().InMillisecondsSinceUnixEpoch()); + return result; +} + +syncer::EntityData EntityDataFromSpecifics( + const sync_pb::CollaborationGroupSpecifics& specifics) { + syncer::EntityData entity_data; + *entity_data.specifics.mutable_collaboration_group() = specifics; + entity_data.name = specifics.collaboration_id(); + return entity_data; +} + +std::unique_ptr<syncer::EntityChange> EntityChangeAddFromSpecifics( + const sync_pb::CollaborationGroupSpecifics& specifics) { + return syncer::EntityChange::CreateAdd(specifics.collaboration_id(), + EntityDataFromSpecifics(specifics)); +} + +std::unique_ptr<syncer::EntityChange> EntityChangeUpdateFromSpecifics( + const sync_pb::CollaborationGroupSpecifics& specifics) { + return syncer::EntityChange::CreateUpdate(specifics.collaboration_id(), + EntityDataFromSpecifics(specifics)); +} + +std::unique_ptr<syncer::EntityChange> EntityChangeDeleteFromSpecifics( + const sync_pb::CollaborationGroupSpecifics& specifics) { + return syncer::EntityChange::CreateDelete(specifics.collaboration_id()); +} + +} // namespace + +class DataSharingServiceAndroidTest : public testing::Test { + public: + DataSharingServiceAndroidTest() = default; + + ~DataSharingServiceAndroidTest() override = default; + + void SetUp() override { + Test::SetUp(); + scoped_refptr<network::SharedURLLoaderFactory> test_url_loader_factory = + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_); + + std::unique_ptr<FakeDataSharingSDKDelegate> sdk_delegate = + std::make_unique<FakeDataSharingSDKDelegate>(); + not_owned_sdk_delegate_ = sdk_delegate.get(); + + data_sharing_service_ = std::make_unique<DataSharingServiceImpl>( + std::move(test_url_loader_factory), + identity_test_env_.identity_manager(), + syncer::ModelTypeStoreTestUtil::FactoryForInMemoryStoreForTest(), + version_info::Channel::UNKNOWN, std::move(sdk_delegate), + /*ui_delegate=*/nullptr); + data_sharing_service_android_ = std::make_unique<DataSharingServiceAndroid>( + data_sharing_service_.get()); + } + + void TearDown() override { + data_sharing_service_android_.reset(); + not_owned_sdk_delegate_ = nullptr; + data_sharing_service_.reset(); + } + + // Creates group and returns ID. + // Mimics initial sync for collaboration group datatype, this should trigger + // OnGroupAdded() notification. + std::string CreateGroup() { + const std::string display_name = "display_name"; + const std::string group_id = + not_owned_sdk_delegate_->AddGroupAndReturnId(display_name); + + auto* collaboration_group_bridge = + data_sharing_service_->GetCollaborationGroupSyncBridgeForTesting(); + + syncer::EntityChangeList entity_changes; + entity_changes.push_back(EntityChangeAddFromSpecifics( + MakeCollaborationGroupSpecifics(group_id))); + + collaboration_group_bridge->MergeFullSyncData( + collaboration_group_bridge->CreateMetadataChangeList(), + std::move(entity_changes)); + return group_id; + } + + // Removes the group with `group_id`, which would trigger the OnGroupRemoved() + // notification. + void RemoveGroup(const std::string& group_id) { + auto* collaboration_group_bridge = + data_sharing_service_->GetCollaborationGroupSyncBridgeForTesting(); + not_owned_sdk_delegate_->RemoveGroup(group_id); + syncer::EntityChangeList entity_changes; + entity_changes.push_back(EntityChangeDeleteFromSpecifics( + MakeCollaborationGroupSpecifics(group_id))); + + collaboration_group_bridge->ApplyIncrementalSyncChanges( + collaboration_group_bridge->CreateMetadataChangeList(), + std::move(entity_changes)); + } + + // Updates the group with `group_id` with a different name, which wuld trigger + // the OnGroupUpdated() notification. + void UpdateGroup(const std::string& group_id) { + const std::string new_display_name = "new_display_name"; + auto* collaboration_group_bridge = + data_sharing_service_->GetCollaborationGroupSyncBridgeForTesting(); + not_owned_sdk_delegate_->UpdateGroup(group_id, new_display_name); + syncer::EntityChangeList entity_changes; + entity_changes.push_back(EntityChangeUpdateFromSpecifics( + MakeCollaborationGroupSpecifics(group_id))); + + collaboration_group_bridge->ApplyIncrementalSyncChanges( + collaboration_group_bridge->CreateMetadataChangeList(), + std::move(entity_changes)); + } + + protected: + base::test::TaskEnvironment task_environment_; + signin::IdentityTestEnvironment identity_test_env_; + network::TestURLLoaderFactory test_url_loader_factory_; + std::unique_ptr<DataSharingServiceImpl> data_sharing_service_; + std::unique_ptr<DataSharingServiceAndroid> data_sharing_service_android_; + raw_ptr<FakeDataSharingSDKDelegate> not_owned_sdk_delegate_; +}; + +TEST_F(DataSharingServiceAndroidTest, GroupAddedObservation) { + base::RunLoop run_loop; + TestJavaObserver observer(data_sharing_service_.get(), + run_loop.QuitClosure()); + + EXPECT_EQ(observer.GetGroupChangeCount(), 0); + EXPECT_EQ(observer.GetGroupAddedCount(), 0); + EXPECT_EQ(observer.GetGroupRemovedCount(), 0); + + CreateGroup(); + + run_loop.Run(); + + EXPECT_EQ(observer.GetGroupChangeCount(), 0); + EXPECT_EQ(observer.GetGroupAddedCount(), 1); + EXPECT_EQ(observer.GetGroupRemovedCount(), 0); +} + +TEST_F(DataSharingServiceAndroidTest, GroupRemovedObservation) { + base::RunLoop run_loop; + TestJavaObserver observer(data_sharing_service_.get(), + run_loop.QuitClosure()); + EXPECT_EQ(observer.GetGroupChangeCount(), 0); + EXPECT_EQ(observer.GetGroupAddedCount(), 0); + EXPECT_EQ(observer.GetGroupRemovedCount(), 0); + + std::string group_id = CreateGroup(); + + run_loop.Run(); + EXPECT_EQ(observer.GetGroupChangeCount(), 0); + EXPECT_EQ(observer.GetGroupAddedCount(), 1); + EXPECT_EQ(observer.GetGroupRemovedCount(), 0); + + base::RunLoop wait_for_remove; + observer.ResetCallback(wait_for_remove.QuitClosure()); + + RemoveGroup(group_id); + + wait_for_remove.Run(); + EXPECT_EQ(observer.GetGroupChangeCount(), 0); + EXPECT_EQ(observer.GetGroupAddedCount(), 1); + EXPECT_EQ(observer.GetGroupRemovedCount(), 1); +} + +TEST_F(DataSharingServiceAndroidTest, GroupChangeObservation) { + base::RunLoop run_loop; + TestJavaObserver observer(data_sharing_service_.get(), + run_loop.QuitClosure()); + EXPECT_EQ(observer.GetGroupChangeCount(), 0); + EXPECT_EQ(observer.GetGroupAddedCount(), 0); + EXPECT_EQ(observer.GetGroupRemovedCount(), 0); + + std::string group_id = CreateGroup(); + + run_loop.Run(); + EXPECT_EQ(observer.GetGroupChangeCount(), 0); + EXPECT_EQ(observer.GetGroupAddedCount(), 1); + EXPECT_EQ(observer.GetGroupRemovedCount(), 0); + + base::RunLoop wait_for_update; + observer.ResetCallback(wait_for_update.QuitClosure()); + + UpdateGroup(group_id); + + wait_for_update.Run(); +} + +} // namespace data_sharing
diff --git a/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/DataSharingConversionBridge.java b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/DataSharingConversionBridge.java new file mode 100644 index 0000000..c4322568 --- /dev/null +++ b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/DataSharingConversionBridge.java
@@ -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. + +package org.chromium.components.data_sharing; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; + +import java.util.List; + +/** Conversion utility for misc types needed in the JNI layer for the service. */ +@JNINamespace("data_sharing") +public class DataSharingConversionBridge { + + @CalledByNative + private static DataSharingService.GroupDataOrFailureOutcome createGroupDataOrFailureOutcome( + GroupData groupData, int failureOutcome) { + return new DataSharingService.GroupDataOrFailureOutcome(groupData, failureOutcome); + } + + @CalledByNative + private static DataSharingService.GroupsDataSetOrFailureOutcome + createGroupDataSetOrFailureOutcome(GroupData[] groupDataSet, int failureOutcome) { + List<GroupData> list = groupDataSet == null ? null : List.of(groupDataSet); + return new DataSharingService.GroupsDataSetOrFailureOutcome(list, failureOutcome); + } + + @CalledByNative + public static Integer createPeopleGroupActionOutcome(int value) { + return value; + } +}
diff --git a/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/DataSharingServiceImpl.java b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/DataSharingServiceImpl.java index 5465e9f..70bfbb0 100644 --- a/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/DataSharingServiceImpl.java +++ b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/DataSharingServiceImpl.java
@@ -8,6 +8,7 @@ import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.base.Callback; import org.chromium.base.UserDataHost; /** @@ -20,6 +21,8 @@ private final UserDataHost mUserDataHost = new UserDataHost(); + private final ObserverBridge mObserverBridge = new ObserverBridge(); + @CalledByNative private static DataSharingServiceImpl create(long nativePtr) { return new DataSharingServiceImpl(nativePtr); @@ -29,6 +32,51 @@ mNativePtr = nativePtr; } + @CalledByNative + private ObserverBridge getObserverBridge() { + return mObserverBridge; + } + + @Override + public void addObserver(Observer observer) { + mObserverBridge.addObserver(observer); + } + + @Override + public void removeObserver(Observer observer) { + mObserverBridge.removeObserver(observer); + } + + @Override + public void readAllGroups(Callback<GroupsDataSetOrFailureOutcome> callback) { + DataSharingServiceImplJni.get().readAllGroups(mNativePtr, callback); + } + + @Override + public void readGroup(String groupId, Callback<GroupDataOrFailureOutcome> callback) { + DataSharingServiceImplJni.get().readGroup(mNativePtr, groupId, callback); + } + + @Override + public void createGroup(String groupName, Callback<GroupDataOrFailureOutcome> callback) { + DataSharingServiceImplJni.get().createGroup(mNativePtr, groupName, callback); + } + + @Override + public void deleteGroup(String groupId, Callback<Integer> callback) { + DataSharingServiceImplJni.get().deleteGroup(mNativePtr, groupId, callback); + } + + @Override + public void inviteMember(String groupId, String inviteeEmail, Callback<Integer> callback) { + DataSharingServiceImplJni.get().inviteMember(mNativePtr, groupId, inviteeEmail, callback); + } + + @Override + public void removeMember(String groupId, String memberEmail, Callback<Integer> callback) { + DataSharingServiceImplJni.get().removeMember(mNativePtr, groupId, memberEmail, callback); + } + @Override public boolean isEmptyService() { return DataSharingServiceImplJni.get().isEmptyService(mNativePtr, this); @@ -52,6 +100,35 @@ @NativeMethods interface Natives { + void readAllGroups( + long nativeDataSharingServiceAndroid, + Callback<GroupsDataSetOrFailureOutcome> callback); + + void readGroup( + long nativeDataSharingServiceAndroid, + String groupId, + Callback<GroupDataOrFailureOutcome> callback); + + void createGroup( + long nativeDataSharingServiceAndroid, + String groupName, + Callback<GroupDataOrFailureOutcome> callback); + + void deleteGroup( + long nativeDataSharingServiceAndroid, String groupId, Callback<Integer> callback); + + void inviteMember( + long nativeDataSharingServiceAndroid, + String groupId, + String inviteeEmail, + Callback<Integer> callback); + + void removeMember( + long nativeDataSharingServiceAndroid, + String groupId, + String memberEmail, + Callback<Integer> callback); + boolean isEmptyService(long nativeDataSharingServiceAndroid, DataSharingServiceImpl caller); DataSharingNetworkLoader getNetworkLoader(long nativeDataSharingServiceAndroid);
diff --git a/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/ObserverBridge.java b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/ObserverBridge.java new file mode 100644 index 0000000..bd553f7 --- /dev/null +++ b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/ObserverBridge.java
@@ -0,0 +1,57 @@ +// 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. + +package org.chromium.components.data_sharing; + +import org.jni_zero.CalledByNative; + +import org.chromium.base.ObserverList; + +/** + * A wrapper for DataSharingService.Observer + * + * <p>Hosts all the Java observers of the service. Receives all the notifications from the native + * counterpart GroupDataObserverBridge and then notifies all the Java observers. NOTE: This observer + * is not registered to the Java DataSharingService, this implements the DataSharingService.Observer + * only for readability. The native observer is registered to the native service. + */ +public class ObserverBridge implements DataSharingService.Observer { + ObserverList<DataSharingService.Observer> mJavaObservers = new ObserverList<>(); + + public ObserverBridge() {} + + /** Add a new observer. Each observer can be added only once */ + public void addObserver(DataSharingService.Observer observer) { + mJavaObservers.addObserver(observer); + } + + /** Remove an added observer. Ignores if an observer is not in the list. */ + public void removeObserver(DataSharingService.Observer observer) { + mJavaObservers.removeObserver(observer); + } + + @CalledByNative + @Override + public void onGroupChanged(GroupData groupData) { + for (DataSharingService.Observer javaObserver : mJavaObservers) { + javaObserver.onGroupChanged(groupData); + } + } + + @CalledByNative + @Override + public void onGroupAdded(GroupData groupData) { + for (DataSharingService.Observer javaObserver : mJavaObservers) { + javaObserver.onGroupAdded(groupData); + } + } + + @CalledByNative + @Override + public void onGroupRemoved(String groupId) { + for (DataSharingService.Observer javaObserver : mJavaObservers) { + javaObserver.onGroupRemoved(groupId); + } + } +}
diff --git a/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/TestServiceObserver.java b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/TestServiceObserver.java new file mode 100644 index 0000000..a16130f --- /dev/null +++ b/components/data_sharing/internal/android/java/src/org/chromium/components/data_sharing/TestServiceObserver.java
@@ -0,0 +1,80 @@ +// 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. + +package org.chromium.components.data_sharing; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; +import org.jni_zero.NativeMethods; + +/** + * Test observer that registers itself to the Java service, and sends notification to the native + * test. + * + * <p>See data_sharing_service_android_unittest.cc for usage. + */ +@JNINamespace("data_sharing") +public class TestServiceObserver implements DataSharingService.Observer { + private final long mNativePtr; + private int mOnGroupChangeCount; + private int mOnGroupAddedCount; + private int mOnGroupRemovedCount; + + public TestServiceObserver(long nativePtr) { + this.mNativePtr = nativePtr; + this.mOnGroupChangeCount = 0; + this.mOnGroupAddedCount = 0; + this.mOnGroupRemovedCount = 0; + } + + @CalledByNative + public static TestServiceObserver createAndAdd(DataSharingService service, long nativePtr) { + TestServiceObserver obs = new TestServiceObserver(nativePtr); + service.addObserver(obs); + return obs; + } + + @CalledByNative + public void destroy(DataSharingService service) { + service.removeObserver(this); + } + + @CalledByNative + private int getOnGroupChangeCount() { + return mOnGroupChangeCount; + } + + @CalledByNative + private int getOnGroupAddedCount() { + return mOnGroupAddedCount; + } + + @CalledByNative + private int getOnGroupRemovedCount() { + return mOnGroupRemovedCount; + } + + @Override + public void onGroupChanged(GroupData groupData) { + mOnGroupChangeCount++; + TestServiceObserverJni.get().onObserverNotify(mNativePtr); + } + + @Override + public void onGroupAdded(GroupData groupData) { + mOnGroupAddedCount++; + TestServiceObserverJni.get().onObserverNotify(mNativePtr); + } + + @Override + public void onGroupRemoved(String groupId) { + mOnGroupRemovedCount++; + TestServiceObserverJni.get().onObserverNotify(mNativePtr); + } + + @NativeMethods + interface Natives { + void onObserverNotify(long observerPtr); + } +}
diff --git a/components/data_sharing/internal/data_sharing_service_impl.cc b/components/data_sharing/internal/data_sharing_service_impl.cc index e30ed6c..15e06fe6 100644 --- a/components/data_sharing/internal/data_sharing_service_impl.cc +++ b/components/data_sharing/internal/data_sharing_service_impl.cc
@@ -66,6 +66,8 @@ return DataSharingService::PeopleGroupActionOutcome::kSuccess; } switch (StatusToPeopleGroupActionFailure(status)) { + case DataSharingService::PeopleGroupActionFailure::kUnknown: + return DataSharingService::PeopleGroupActionOutcome::kUnknown; case DataSharingService::PeopleGroupActionFailure::kPersistentFailure: return DataSharingService::PeopleGroupActionOutcome::kPersistentFailure; case DataSharingService::PeopleGroupActionFailure::kTransientFailure:
diff --git a/components/data_sharing/internal/data_sharing_service_impl_unittest.cc b/components/data_sharing/internal/data_sharing_service_impl_unittest.cc index e8a249d..384e1a5a 100644 --- a/components/data_sharing/internal/data_sharing_service_impl_unittest.cc +++ b/components/data_sharing/internal/data_sharing_service_impl_unittest.cc
@@ -7,12 +7,12 @@ #include <memory> #include "base/memory/raw_ptr.h" -#include "base/task/single_thread_task_runner.h" #include "base/test/bind.h" #include "base/test/gmock_callback_support.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "base/version_info/channel.h" +#include "components/data_sharing/internal/fake_data_sharing_sdk_delegate.h" #include "components/data_sharing/public/data_sharing_sdk_delegate.h" #include "components/data_sharing/public/data_sharing_service.h" #include "components/data_sharing/public/data_sharing_ui_delegate.h" @@ -85,179 +85,6 @@ MOCK_METHOD(void, OnGroupRemoved, (const std::string&), (override)); }; -class FakeDataSharingSDKDelegate : public DataSharingSDKDelegate { - public: - FakeDataSharingSDKDelegate() = default; - ~FakeDataSharingSDKDelegate() override = default; - - // Convenience methods for testing. - std::optional<data_sharing_pb::GroupData> GetGroup( - const std::string& group_id) { - auto it = groups_.find(group_id); - if (it != groups_.end()) { - return it->second; - } - return std::nullopt; - } - - void RemoveGroup(const std::string& group_id) { groups_.erase(group_id); } - - void UpdateGroup(const std::string& group_id, - const std::string& new_display_name) { - auto it = groups_.find(group_id); - ASSERT_TRUE(it != groups_.end()); - - it->second.set_display_name(new_display_name); - } - - std::string AddGroupAndReturnId(const std::string& display_name) { - data_sharing_pb::GroupData group_data; - group_data.set_group_id(base::NumberToString(next_group_id_++)); - group_data.set_display_name(display_name); - groups_[group_data.group_id()] = group_data; - return group_data.group_id(); - } - - void AddMember(const std::string& group_id, - const std::string& member_gaia_id) { - auto group_it = groups_.find(group_id); - ASSERT_TRUE(group_it != groups_.end()); - - data_sharing_pb::GroupMember member; - member.set_gaia_id(member_gaia_id); - *group_it->second.add_members() = member; - } - - void AddAccount(const std::string& email, const std::string& gaia_id) { - email_to_gaia_id_[email] = gaia_id; - } - - // DataSharingSDKDelegate implementation. - void CreateGroup( - const data_sharing_pb::CreateGroupParams& params, - base::OnceCallback< - void(const base::expected<data_sharing_pb::CreateGroupResult, - absl::Status>&)> callback) override { - std::string group_id = AddGroupAndReturnId(params.display_name()); - - data_sharing_pb::CreateGroupResult result; - *result.mutable_group_data() = groups_[group_id]; - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), result)); - } - - void ReadGroups(const data_sharing_pb::ReadGroupsParams& params, - base::OnceCallback<void( - const base::expected<data_sharing_pb::ReadGroupsResult, - absl::Status>&)> callback) override { - data_sharing_pb::ReadGroupsResult result; - for (const auto& group_id : params.group_ids()) { - if (groups_.find(group_id) != groups_.end()) { - *result.add_group_data() = groups_[group_id]; - } - } - - if (result.group_data().empty()) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), base::unexpected(absl::Status( - absl::StatusCode::kNotFound, - "Groups not found")))); - return; - } - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), result)); - } - - void AddMember( - const data_sharing_pb::AddMemberParams& params, - base::OnceCallback<void(const absl::Status&)> callback) override { - auto group_it = groups_.find(params.group_id()); - absl::Status status = absl::OkStatus(); - if (group_it != groups_.end()) { - data_sharing_pb::GroupMember member; - member.set_gaia_id(params.member_gaia_id()); - *group_it->second.add_members() = member; - } else { - status = absl::Status(absl::StatusCode::kNotFound, "Group not found"); - } - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), status)); - } - - void RemoveMember( - const data_sharing_pb::RemoveMemberParams& params, - base::OnceCallback<void(const absl::Status&)> callback) override { - auto group_it = groups_.find(params.group_id()); - if (group_it == groups_.end()) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - absl::Status(absl::StatusCode::kNotFound, - "Group not found"))); - return; - } - - absl::Status status = absl::OkStatus(); - auto* group_members = group_it->second.mutable_members(); - auto member_it = - std::find_if(group_members->begin(), group_members->end(), - [¶ms](const data_sharing_pb::GroupMember& member) { - return member.gaia_id() == params.member_gaia_id(); - }); - if (member_it != group_members->end()) { - group_members->erase(member_it); - } else { - status = absl::Status(absl::StatusCode::kNotFound, "Member not found"); - } - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), status)); - } - - void DeleteGroup( - const data_sharing_pb::DeleteGroupParams& params, - base::OnceCallback<void(const absl::Status&)> callback) override { - absl::Status status = absl::OkStatus(); - if (groups_.find(params.group_id()) != groups_.end()) { - groups_.erase(params.group_id()); - } else { - status = absl::Status(absl::StatusCode::kNotFound, "Group not found"); - } - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), status)); - } - - void LookupGaiaIdByEmail( - const data_sharing_pb::LookupGaiaIdByEmailParams& params, - base::OnceCallback< - void(const base::expected<data_sharing_pb::LookupGaiaIdByEmailResult, - absl::Status>&)> callback) override { - auto it = email_to_gaia_id_.find(params.email()); - if (it != email_to_gaia_id_.end()) { - data_sharing_pb::LookupGaiaIdByEmailResult result; - result.set_gaia_id(it->second); - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), result)); - return; - } - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), - base::unexpected(absl::Status( - absl::StatusCode::kNotFound, "Account not found")))); - } - - private: - std::map<std::string, data_sharing_pb::GroupData> groups_; - std::map<std::string, std::string> email_to_gaia_id_; - int next_group_id_ = 0; -}; } // namespace
diff --git a/components/data_sharing/internal/fake_data_sharing_sdk_delegate.cc b/components/data_sharing/internal/fake_data_sharing_sdk_delegate.cc new file mode 100644 index 0000000..dab75f9 --- /dev/null +++ b/components/data_sharing/internal/fake_data_sharing_sdk_delegate.cc
@@ -0,0 +1,184 @@ +// 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/data_sharing/internal/fake_data_sharing_sdk_delegate.h" + +#include "base/strings/string_number_conversions.h" +#include "base/task/single_thread_task_runner.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/status/status.h" + +namespace data_sharing { + +FakeDataSharingSDKDelegate::FakeDataSharingSDKDelegate() = default; +FakeDataSharingSDKDelegate::~FakeDataSharingSDKDelegate() = default; + +std::optional<data_sharing_pb::GroupData> FakeDataSharingSDKDelegate::GetGroup( + const std::string& group_id) { + auto it = groups_.find(group_id); + if (it != groups_.end()) { + return it->second; + } + return std::nullopt; +} + +void FakeDataSharingSDKDelegate::RemoveGroup(const std::string& group_id) { + groups_.erase(group_id); +} + +void FakeDataSharingSDKDelegate::UpdateGroup( + const std::string& group_id, + const std::string& new_display_name) { + auto it = groups_.find(group_id); + ASSERT_TRUE(it != groups_.end()); + + it->second.set_display_name(new_display_name); +} + +std::string FakeDataSharingSDKDelegate::AddGroupAndReturnId( + const std::string& display_name) { + data_sharing_pb::GroupData group_data; + group_data.set_group_id(base::NumberToString(next_group_id_++)); + group_data.set_display_name(display_name); + groups_[group_data.group_id()] = group_data; + return group_data.group_id(); +} + +void FakeDataSharingSDKDelegate::AddMember(const std::string& group_id, + const std::string& member_gaia_id) { + auto group_it = groups_.find(group_id); + ASSERT_TRUE(group_it != groups_.end()); + + data_sharing_pb::GroupMember member; + member.set_gaia_id(member_gaia_id); + *group_it->second.add_members() = member; +} + +void FakeDataSharingSDKDelegate::AddAccount(const std::string& email, + const std::string& gaia_id) { + email_to_gaia_id_[email] = gaia_id; +} + +void FakeDataSharingSDKDelegate::CreateGroup( + const data_sharing_pb::CreateGroupParams& params, + base::OnceCallback< + void(const base::expected<data_sharing_pb::CreateGroupResult, + absl::Status>&)> callback) { + std::string group_id = AddGroupAndReturnId(params.display_name()); + + data_sharing_pb::CreateGroupResult result; + *result.mutable_group_data() = groups_[group_id]; + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result)); +} + +void FakeDataSharingSDKDelegate::ReadGroups( + const data_sharing_pb::ReadGroupsParams& params, + base::OnceCallback<void( + const base::expected<data_sharing_pb::ReadGroupsResult, absl::Status>&)> + callback) { + data_sharing_pb::ReadGroupsResult result; + for (const auto& group_id : params.group_ids()) { + if (groups_.find(group_id) != groups_.end()) { + *result.add_group_data() = groups_[group_id]; + } + } + + if (result.group_data().empty()) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), + base::unexpected(absl::Status( + absl::StatusCode::kNotFound, "Groups not found")))); + return; + } + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result)); +} + +void FakeDataSharingSDKDelegate::AddMember( + const data_sharing_pb::AddMemberParams& params, + base::OnceCallback<void(const absl::Status&)> callback) { + auto group_it = groups_.find(params.group_id()); + absl::Status status = absl::OkStatus(); + if (group_it != groups_.end()) { + data_sharing_pb::GroupMember member; + member.set_gaia_id(params.member_gaia_id()); + *group_it->second.add_members() = member; + } else { + status = absl::Status(absl::StatusCode::kNotFound, "Group not found"); + } + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), status)); +} + +void FakeDataSharingSDKDelegate::RemoveMember( + const data_sharing_pb::RemoveMemberParams& params, + base::OnceCallback<void(const absl::Status&)> callback) { + auto group_it = groups_.find(params.group_id()); + if (group_it == groups_.end()) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + absl::Status(absl::StatusCode::kNotFound, + "Group not found"))); + return; + } + + absl::Status status = absl::OkStatus(); + auto* group_members = group_it->second.mutable_members(); + auto member_it = + std::find_if(group_members->begin(), group_members->end(), + [¶ms](const data_sharing_pb::GroupMember& member) { + return member.gaia_id() == params.member_gaia_id(); + }); + if (member_it != group_members->end()) { + group_members->erase(member_it); + } else { + status = absl::Status(absl::StatusCode::kNotFound, "Member not found"); + } + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), status)); +} + +void FakeDataSharingSDKDelegate::DeleteGroup( + const data_sharing_pb::DeleteGroupParams& params, + base::OnceCallback<void(const absl::Status&)> callback) { + absl::Status status = absl::OkStatus(); + if (groups_.find(params.group_id()) != groups_.end()) { + groups_.erase(params.group_id()); + } else { + status = absl::Status(absl::StatusCode::kNotFound, "Group not found"); + } + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), status)); +} + +void FakeDataSharingSDKDelegate::LookupGaiaIdByEmail( + const data_sharing_pb::LookupGaiaIdByEmailParams& params, + base::OnceCallback< + void(const base::expected<data_sharing_pb::LookupGaiaIdByEmailResult, + absl::Status>&)> callback) { + auto it = email_to_gaia_id_.find(params.email()); + if (it != email_to_gaia_id_.end()) { + data_sharing_pb::LookupGaiaIdByEmailResult result; + result.set_gaia_id(it->second); + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result)); + return; + } + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), + base::unexpected(absl::Status(absl::StatusCode::kNotFound, + "Account not found")))); +} + +} // namespace data_sharing
diff --git a/components/data_sharing/internal/fake_data_sharing_sdk_delegate.h b/components/data_sharing/internal/fake_data_sharing_sdk_delegate.h new file mode 100644 index 0000000..5b5d75e4 --- /dev/null +++ b/components/data_sharing/internal/fake_data_sharing_sdk_delegate.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 COMPONENTS_DATA_SHARING_INTERNAL_FAKE_DATA_SHARING_SDK_DELEGATE_H_ +#define COMPONENTS_DATA_SHARING_INTERNAL_FAKE_DATA_SHARING_SDK_DELEGATE_H_ + +#include <string> + +#include "components/data_sharing/public/data_sharing_sdk_delegate.h" + +namespace data_sharing { + +// Implementation of DataSharingSDKDelegate for unit tests that holds the group +// info in-memory. +class FakeDataSharingSDKDelegate : public DataSharingSDKDelegate { + public: + FakeDataSharingSDKDelegate(); + ~FakeDataSharingSDKDelegate() override; + + // Convenience methods for testing. + std::optional<data_sharing_pb::GroupData> GetGroup( + const std::string& group_id); + + void RemoveGroup(const std::string& group_id); + + void UpdateGroup(const std::string& group_id, + const std::string& new_display_name); + + std::string AddGroupAndReturnId(const std::string& display_name); + + void AddMember(const std::string& group_id, + const std::string& member_gaia_id); + + void AddAccount(const std::string& email, const std::string& gaia_id); + + // DataSharingSDKDelegate impl: + void CreateGroup(const data_sharing_pb::CreateGroupParams& params, + base::OnceCallback<void( + const base::expected<data_sharing_pb::CreateGroupResult, + absl::Status>&)> callback) override; + void ReadGroups(const data_sharing_pb::ReadGroupsParams& params, + base::OnceCallback<void( + const base::expected<data_sharing_pb::ReadGroupsResult, + absl::Status>&)> callback) override; + void AddMember( + const data_sharing_pb::AddMemberParams& params, + base::OnceCallback<void(const absl::Status&)> callback) override; + void RemoveMember( + const data_sharing_pb::RemoveMemberParams& params, + base::OnceCallback<void(const absl::Status&)> callback) override; + void DeleteGroup( + const data_sharing_pb::DeleteGroupParams& params, + base::OnceCallback<void(const absl::Status&)> callback) override; + void LookupGaiaIdByEmail( + const data_sharing_pb::LookupGaiaIdByEmailParams& params, + base::OnceCallback< + void(const base::expected<data_sharing_pb::LookupGaiaIdByEmailResult, + absl::Status>&)> callback) override; + + private: + std::map<std::string, data_sharing_pb::GroupData> groups_; + std::map<std::string, std::string> email_to_gaia_id_; + int next_group_id_ = 0; +}; + +} // namespace data_sharing + +#endif // COMPONENTS_DATA_SHARING_INTERNAL_FAKE_DATA_SHARING_SDK_DELEGATE_H_
diff --git a/components/data_sharing/public/BUILD.gn b/components/data_sharing/public/BUILD.gn index 4d3df068..065cf78 100644 --- a/components/data_sharing/public/BUILD.gn +++ b/components/data_sharing/public/BUILD.gn
@@ -36,6 +36,8 @@ "android/java/src/org/chromium/components/data_sharing/DataSharingNetworkLoader.java", "android/java/src/org/chromium/components/data_sharing/DataSharingService.java", "android/java/src/org/chromium/components/data_sharing/DataSharingUIDelegate.java", + "android/java/src/org/chromium/components/data_sharing/GroupData.java", + "android/java/src/org/chromium/components/data_sharing/GroupMember.java", "android/java/src/org/chromium/components/data_sharing/configs/AvatarConfig.java", "android/java/src/org/chromium/components/data_sharing/configs/GroupMemberConfig.java", "android/java/src/org/chromium/components/data_sharing/configs/MemberPickerConfig.java", @@ -48,5 +50,21 @@ "//third_party/jni_zero:jni_zero_java", "//url:gurl_java", ] + + srcjar_deps = [ ":enums_java" ] + } + + java_cpp_enum("enums_java") { + sources = [ + "data_sharing_service.h", + "group_data.h", + ] + } + + generate_jni("jni_headers") { + sources = [ + "android/java/src/org/chromium/components/data_sharing/GroupData.java", + "android/java/src/org/chromium/components/data_sharing/GroupMember.java", + ] } }
diff --git a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/DataSharingService.java b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/DataSharingService.java index 80c5552e..67d9a20 100644 --- a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/DataSharingService.java +++ b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/DataSharingService.java
@@ -4,13 +4,139 @@ package org.chromium.components.data_sharing; +import org.chromium.base.Callback; import org.chromium.base.UserDataHost; +import java.util.List; + /** * DataSharingService is the core class for managing data sharing. It represents a native * DataSharingService object in Java. */ public interface DataSharingService { + /** Result that contains group data and an outcome of the action that was requested. */ + public static class GroupDataOrFailureOutcome { + /** + * The group data requested. + * + * <p>Can be null if the action failed. Please check `actionFailure` for more info. + */ + public final GroupData groupData; + + /** Result of the action, UNKNOWN if the action was successful. */ + public final @PeopleGroupActionFailure int actionFailure; + + GroupDataOrFailureOutcome(GroupData groupData, int actionFailure) { + this.groupData = groupData; + this.actionFailure = actionFailure; + } + } + + /** Result that contains a set of groups and an outcome of the action that was requested. */ + public static class GroupsDataSetOrFailureOutcome { + /** + * The list of groups requested. + * + * <p>The list if null if the request failed. Group IDs cannot be repeated in the list. + */ + public final List<GroupData> groupDataSet; + + /** Result of the action */ + public final @PeopleGroupActionFailure int actionFailure; + + GroupsDataSetOrFailureOutcome(List<GroupData> groupDataSet, int actionFailure) { + this.groupDataSet = groupDataSet; + this.actionFailure = actionFailure; + } + } + + /** Observer to listen to the updates on any of the groups. */ + interface Observer { + /** A group was updated where the current user continues to be a member of. */ + void onGroupChanged(GroupData groupData); + + /** The user either created a new group or has been invited to the existing one. */ + void onGroupAdded(GroupData groupData); + + /** Either group has been deleted or user has been removed from the group. */ + void onGroupRemoved(String groupId); + } + + /** + * Add an observer to the service. + * + * <p>An observer should not be added to the same list more than once. + * + * @param observer The observer to add. + */ + void addObserver(Observer observer); + + /** + * Remove an observer from the service, if it is in the list. + * + * @param observer The observer to remove. + */ + void removeObserver(Observer observer); + + /** + * Refresh and read all the group data the user is part of. + * + * <p>Refresh data if necessary. The result is ordered by group ID. + * + * @param callback On success passes to the `callback` a set of all groups known to the client. + */ + void readAllGroups(Callback<GroupsDataSetOrFailureOutcome> callback); + + /** + * Refresh and read the requested group data. + * + * <p>Refresh data if necessary. + * + * @param groupId The group ID to read data from. + * @param callback The GroupData is returned by callback. + */ + void readGroup(String groupId, Callback<GroupDataOrFailureOutcome> callback); + + /** + * Attempt to create a new group. + * + * @param groupName The name of the group to be created. + * @param callback Return a created group data on success. + */ + void createGroup(String groupName, Callback<GroupDataOrFailureOutcome> callback); + + /** + * Attempt to delete a group. + * + * @param groupID The group ID to delete. + * @param callback The deletion result as PeopleGroupActionOutcome. + */ + void deleteGroup(String groupId, Callback</*PeopleGroupActionOutcome*/ Integer> callback); + + /** + * Attempt to invite a new user to the group. + * + * @param groupID The group ID to add to. + * @param inviteeEmail The email of the member to add. + * @param callback The invite result as PeopleGroupActionOutcome. + */ + void inviteMember( + String groupId, + String inviteeEmail, + Callback</*PeopleGroupActionOutcome*/ Integer> callback); + + /** + * Attempts to remove a user from the group. + * + * @param groupID The group ID to remove from. + * @param membeEmail The email of the member to remove. + * @param callback The removal result as PeopleGroupActionOutcome. + */ + void removeMember( + String groupId, + String memberEmail, + Callback</*PeopleGroupActionOutcome*/ Integer> callback); + /** * Whether the service is an empty implementation. This is here because the Chromium build * disables RTTI, and we need to be able to verify that we are using an empty service from the
diff --git a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/GroupData.java b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/GroupData.java new file mode 100644 index 0000000..df36132 --- /dev/null +++ b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/GroupData.java
@@ -0,0 +1,30 @@ +// 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. + +package org.chromium.components.data_sharing; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; + +import java.util.List; + +/** Information about a group. */ +@JNINamespace("data_sharing") +public class GroupData { + public final String groupId; + public final String displayName; + public final List<GroupMember> members; + + GroupData(String groupId, String displayName, GroupMember[] members) { + this.groupId = groupId; + this.displayName = displayName; + this.members = members == null ? null : List.of(members); + } + + @CalledByNative + private static GroupData createGroupData( + String groupId, String displayName, GroupMember[] members) { + return new GroupData(groupId, displayName, members); + } +}
diff --git a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/GroupMember.java b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/GroupMember.java new file mode 100644 index 0000000..68f90c00 --- /dev/null +++ b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/GroupMember.java
@@ -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. + +package org.chromium.components.data_sharing; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; + +import org.chromium.components.data_sharing.member_role.MemberRole; +import org.chromium.url.GURL; + +/** Information about a member of a group. */ +@JNINamespace("data_sharing") +public class GroupMember { + public final String gaiaId; + public final String displayName; + public final String email; + public final @MemberRole int role; + public final GURL avatarUrl; + + GroupMember(String gaiaId, String displayName, String email, int role, GURL avatarUrl) { + this.gaiaId = gaiaId; + this.displayName = displayName; + this.email = email; + this.role = role; + this.avatarUrl = avatarUrl; + } + + @CalledByNative + private static GroupMember createGroupMember( + String gaiaId, String displayName, String email, int role, GURL avatarUrl) { + return new GroupMember(gaiaId, displayName, email, role, avatarUrl); + } +}
diff --git a/components/data_sharing/public/data_sharing_service.h b/components/data_sharing/public/data_sharing_service.h index fe80276..010238e 100644 --- a/components/data_sharing/public/data_sharing_service.h +++ b/components/data_sharing/public/data_sharing_service.h
@@ -5,6 +5,8 @@ #ifndef COMPONENTS_DATA_SHARING_PUBLIC_DATA_SHARING_SERVICE_H_ #define COMPONENTS_DATA_SHARING_PUBLIC_DATA_SHARING_SERVICE_H_ +#include <string> + #include "base/functional/callback_forward.h" #include "base/observer_list_types.h" #include "base/supports_user_data.h" @@ -38,12 +40,21 @@ virtual void OnGroupRemoved(const std::string& group_id) {} }; - enum class PeopleGroupActionFailure { kTransientFailure, kPersistentFailure }; + // GENERATED_JAVA_ENUM_PACKAGE: ( + // org.chromium.components.data_sharing) + enum class PeopleGroupActionFailure { + kUnknown = 0, + kTransientFailure = 1, + kPersistentFailure = 2 + }; + // GENERATED_JAVA_ENUM_PACKAGE: ( + // org.chromium.components.data_sharing) enum class PeopleGroupActionOutcome { - kSuccess, - kTransientFailure, - kPersistentFailure + kUnknown = 0, + kSuccess = 1, + kTransientFailure = 2, + kPersistentFailure = 3 }; using GroupDataOrFailureOutcome =
diff --git a/components/data_sharing/public/group_data.h b/components/data_sharing/public/group_data.h index a62d4f7..57efeb3 100644 --- a/components/data_sharing/public/group_data.h +++ b/components/data_sharing/public/group_data.h
@@ -11,7 +11,9 @@ namespace data_sharing { -enum class MemberRole { kUnknown, kOwner, kMember, kInvitee }; +// GENERATED_JAVA_ENUM_PACKAGE: ( +// org.chromium.components.data_sharing.member_role) +enum class MemberRole { kUnknown = 0, kOwner = 1, kMember = 2, kInvitee = 3 }; struct GroupMember { GroupMember();
diff --git a/components/data_sharing/test_support/android/java/src/org/chromium/components/data_sharing/TestDataSharingService.java b/components/data_sharing/test_support/android/java/src/org/chromium/components/data_sharing/TestDataSharingService.java new file mode 100644 index 0000000..1db6dc44 --- /dev/null +++ b/components/data_sharing/test_support/android/java/src/org/chromium/components/data_sharing/TestDataSharingService.java
@@ -0,0 +1,81 @@ +// 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. + +package org.chromium.components.data_sharing; + +import org.chromium.base.Callback; +import org.chromium.base.ObserverList; +import org.chromium.base.UserDataHost; + +/** Data sharing service impl for testing. */ +public class TestDataSharingService implements DataSharingService { + + ObserverList<DataSharingService.Observer> mJavaObservers = new ObserverList<>(); + + public TestDataSharingService() {} + + @Override + public void addObserver(Observer observer) { + mJavaObservers.addObserver(observer); + } + + @Override + public void removeObserver(Observer observer) { + mJavaObservers.removeObserver(observer); + } + + @Override + public void readAllGroups(Callback<GroupsDataSetOrFailureOutcome> callback) { + Callback.runNullSafe( + callback, + new DataSharingService.GroupsDataSetOrFailureOutcome( + null, PeopleGroupActionFailure.PERSISTENT_FAILURE)); + } + + @Override + public void readGroup(String groupId, Callback<GroupDataOrFailureOutcome> callback) { + Callback.runNullSafe( + callback, + new DataSharingService.GroupDataOrFailureOutcome( + null, PeopleGroupActionFailure.PERSISTENT_FAILURE)); + } + + @Override + public void createGroup(String groupName, Callback<GroupDataOrFailureOutcome> callback) { + Callback.runNullSafe( + callback, + new DataSharingService.GroupDataOrFailureOutcome( + null, PeopleGroupActionFailure.PERSISTENT_FAILURE)); + } + + @Override + public void deleteGroup(String groupId, Callback<Integer> callback) { + Callback.runNullSafe(callback, PeopleGroupActionOutcome.PERSISTENT_FAILURE); + } + + @Override + public void inviteMember(String groupId, String inviteeEmail, Callback<Integer> callback) { + Callback.runNullSafe(callback, PeopleGroupActionOutcome.PERSISTENT_FAILURE); + } + + @Override + public void removeMember(String groupId, String memberEmail, Callback<Integer> callback) { + Callback.runNullSafe(callback, PeopleGroupActionOutcome.PERSISTENT_FAILURE); + } + + @Override + public boolean isEmptyService() { + return true; + } + + @Override + public DataSharingNetworkLoader getNetworkLoader() { + return null; + } + + @Override + public UserDataHost getUserDataHost() { + return null; + } +}
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index ac4d832..f61a9b6 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -79,12 +79,6 @@ namespace exo { namespace { -bool IsRadiiUniform(const gfx::RoundedCornersF& radii) { - return radii.upper_left() == radii.upper_right() && - radii.lower_left() == radii.lower_right() && - radii.upper_left() == radii.lower_left(); -} - // The accelerator keys used to close ShellSurfaces. const struct { ui::KeyboardCode keycode; @@ -182,7 +176,6 @@ window_radii.value_or(shadow_radii.value_or(gfx::RoundedCornersF())); // TODO(crbug.com/40256581): Support variable window radii. - DCHECK(IsRadiiUniform(radii)); corner_radius = radii.upper_left(); } @@ -2160,11 +2153,9 @@ // TODO(crbug.com/40256581): Revisit once all the clients have migrated. shadow_radii = shadow_corners_radii_dp_.value_or( window_corners_radii_dp_.value_or(gfx::RoundedCornersF())); - - // TODO(crbug.com/40256581): Support shadow with variable radius corners. - DCHECK(IsRadiiUniform(shadow_radii)); } + // TODO(crbug.com/40256581): Support shadow with variable radius corners. shadow->SetRoundedCornerRadius(shadow_radii.upper_left()); }
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc index 7b823fa..37095bc8 100644 --- a/components/exo/wayland/zaura_shell.cc +++ b/components/exo/wayland/zaura_shell.cc
@@ -32,6 +32,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/ui/base/chromeos_ui_constants.h" #include "chromeos/ui/base/window_properties.h" #include "chromeos/ui/base/window_state_type.h" #include "chromeos/ui/frame/multitask_menu/float_controller_base.h" @@ -1287,7 +1288,9 @@ if (wl_resource_get_version(aura_shell_resource_) >= ZAURA_SHELL_WINDOW_CORNERS_RADII_SINCE_VERSION) { const int window_corner_radius = - chromeos::features::RoundedWindowsRadius(); + chromeos::features::IsRoundedWindowsEnabled() + ? chromeos::features::RoundedWindowsRadius() + : chromeos::kTopCornerRadiusWhenRestored; zaura_shell_send_window_corners_radii( aura_shell_resource_, window_corner_radius, window_corner_radius,
diff --git a/components/history_embeddings/passage_embeddings_service_controller.cc b/components/history_embeddings/passage_embeddings_service_controller.cc index 83fc0d2..f47d50ed 100644 --- a/components/history_embeddings/passage_embeddings_service_controller.cc +++ b/components/history_embeddings/passage_embeddings_service_controller.cc
@@ -4,6 +4,7 @@ #include "components/history_embeddings/passage_embeddings_service_controller.h" +#include "base/metrics/histogram_functions.h" #include "base/task/thread_pool.h" #include "components/history_embeddings/vector_database.h" #include "components/optimization_guide/core/optimization_guide_util.h" @@ -27,6 +28,24 @@ return params; } +class ScopedEmbeddingsModelInfoStatusLogger { + public: + ScopedEmbeddingsModelInfoStatusLogger() = default; + ~ScopedEmbeddingsModelInfoStatusLogger() { + CHECK_NE(history_embeddings::EmbeddingsModelInfoStatus::kUnknown, status_); + base::UmaHistogramEnumeration("History.Embeddings.Embedder.ModelInfoStatus", + status_); + } + + void set_status(history_embeddings::EmbeddingsModelInfoStatus status) { + status_ = status; + } + + private: + history_embeddings::EmbeddingsModelInfoStatus status_ = + history_embeddings::EmbeddingsModelInfoStatus::kUnknown; +}; + } // namespace namespace history_embeddings { @@ -36,7 +55,6 @@ PassageEmbeddingsServiceController::~PassageEmbeddingsServiceController() = default; -// TODO(b/338650221): Add histograms for bad model info. bool PassageEmbeddingsServiceController::MaybeUpdateModelPaths( base::optional_ref<const optimization_guide::ModelInfo> model_info) { // Reset everything, so if the model info is invalid, the service controller @@ -46,7 +64,9 @@ model_metadata_ = std::nullopt; ResetRemotes(); - if (!model_info.has_value() || !model_info->GetModelMetadata()) { + ScopedEmbeddingsModelInfoStatusLogger logger; + if (!model_info.has_value()) { + logger.set_status(EmbeddingsModelInfoStatus::kEmpty); return false; } @@ -54,16 +74,22 @@ base::flat_set<base::FilePath> additional_files = model_info->GetAdditionalFiles(); if (additional_files.size() != 1u) { + logger.set_status(EmbeddingsModelInfoStatus::kInvalidAdditionalFiles); return false; } // Check validity of model metadata. const std::optional<optimization_guide::proto::Any>& metadata = model_info->GetModelMetadata(); + if (!metadata) { + logger.set_status(EmbeddingsModelInfoStatus::kNoMetadata); + return false; + } std::optional<history_embeddings::proto::PassageEmbeddingsModelMetadata> embeddings_metadata = optimization_guide::ParsedAnyMetadata< history_embeddings::proto::PassageEmbeddingsModelMetadata>(*metadata); if (!embeddings_metadata) { + logger.set_status(EmbeddingsModelInfoStatus::kInvalidMetadata); return false; } @@ -74,6 +100,7 @@ CHECK(!embeddings_model_path_.empty()); CHECK(!sp_model_path_.empty()); + logger.set_status(EmbeddingsModelInfoStatus::kValid); return true; }
diff --git a/components/history_embeddings/passage_embeddings_service_controller.h b/components/history_embeddings/passage_embeddings_service_controller.h index 3291288..13f634f4 100644 --- a/components/history_embeddings/passage_embeddings_service_controller.h +++ b/components/history_embeddings/passage_embeddings_service_controller.h
@@ -13,6 +13,29 @@ namespace history_embeddings { +enum class EmbeddingsModelInfoStatus { + kUnknown = 0, + + // Model info is valid. + kValid = 1, + + // Model info is empty. + kEmpty = 2, + + // Model info does not contain model metadata. + kNoMetadata = 3, + + // Model info has invalid metadata. + kInvalidMetadata = 4, + + // Model info has invalid additional files. + kInvalidAdditionalFiles = 5, + + // This must be kept in sync with EmbeddingsModelInfoStatus in + // history/enums.xml + kMaxValue = kInvalidAdditionalFiles, +}; + class PassageEmbeddingsServiceController { public: PassageEmbeddingsServiceController();
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index 751be9a..a10e3bac 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -1942,11 +1942,9 @@ // would be scored independently with their partial signals. internal_result_.DeduplicateMatches(input_, template_url_service_); - size_t eligible_matches_count = - base::ranges::count_if(internal_result_.matches_, [](const auto& match) { - return match.IsUrlScoringEligible() && - !AutocompleteMatch::IsSearchType(match.type); - }); + size_t eligible_matches_count = base::ranges::count_if( + internal_result_.matches_, + [](const auto& match) { return match.IsUrlScoringEligible(); }); if (eligible_matches_count == 0) return; @@ -1965,10 +1963,6 @@ RecordScoringSignalCoverageForProvider(match_itr->scoring_signals.value(), match_itr->provider.get()); - if (AutocompleteMatch::IsSearchType(match_itr->type)) { - continue; - } - // Verify the eligible match or one of its duplicates has an expected type. DCHECK(match_itr->MatchOrDuplicateMeets([](const auto& match) { return AutocompleteScoringSignalsAnnotator::IsEligibleMatch(match); @@ -2191,6 +2185,8 @@ // This is needed in order to ensure that the relevance score assignment logic // can properly break ties when two (or more) URL suggestions have the same ML // score. + // TODO(crbug.com/40062540): Replace `Sort` with `DeduplicateMatches` for + // better stability of matches. internal_result_.Sort(input_, template_url_service_, old_result.default_match_to_preserve); @@ -2211,10 +2207,6 @@ RecordScoringSignalCoverageForProvider(match.scoring_signals.value(), match.provider.get()); - if (AutocompleteMatch::IsSearchType(match.type)) { - continue; - } - batch_scoring_signals.push_back(&match.scoring_signals.value()); scored_positions.push_back(i); } @@ -2276,8 +2268,7 @@ const auto& match = internal_result_.matches_[i]; if (!match.IsUrlScoringEligible() || (match.type == AutocompleteMatchType::DOCUMENT_SUGGESTION && - match.relevance == 0) || - AutocompleteMatch::IsSearchType(match.type)) { + match.relevance == 0)) { continue; } scores_pool.push_back(match.relevance);
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index 7018dc6..575f538 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -1453,7 +1453,8 @@ bool AutocompleteMatch::IsUrlScoringEligible() const { return scoring_signals.has_value() && - type != AutocompleteMatchType::URL_WHAT_YOU_TYPED; + type != AutocompleteMatchType::URL_WHAT_YOU_TYPED && + !force_skip_ml_scoring && !AutocompleteMatch::IsSearchType(type); } bool AutocompleteMatch::IsTrendSuggestion() const { @@ -1693,6 +1694,17 @@ duplicate_match.rich_autocompletion_triggered; } + // If either one of the matches is ineligible for ML scoring, then ensure that + // the final match is marked as ineligible for ML scoring. Search suggestions + // are guaranteed to be excluded from ML scoring at this time, so there's no + // need to set `force_skip_ml_scoring` for those matches. + if (base::FeatureList::IsEnabled(omnibox::kEnableForceSkipMlScoring) && + (!IsUrlScoringEligible() || !duplicate_match.IsUrlScoringEligible()) && + !AutocompleteMatch::IsSearchType(type)) { + force_skip_ml_scoring = true; + RecordAdditionalInfo("force skip ml scoring", "true"); + } + // Merge scoring signals from duplicate match for ML model scoring and // training. if (OmniboxFieldTrial::IsPopulatingUrlScoringSignalsEnabled()) {
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h index d7658d8..a516ff3b 100644 --- a/components/omnibox/browser/autocomplete_match.h +++ b/components/omnibox/browser/autocomplete_match.h
@@ -916,6 +916,12 @@ // Signals for ML scoring. std::optional<ScoringSignals> scoring_signals; + // A flag that's set during the de-duplication process in order to forcibly + // exclude this match from ML scoring (e.g. this match is ML-eligible, but one + // of the matches in `duplicate_matches` is not). Furthermore, when this flag + // is set, ML scoring signals will NOT be logged for this particular match. + bool force_skip_ml_scoring = false; + // A flag to mark whether this would've been excluded from the "original" list // of matches. Traditionally, providers limit the number of suggestions they // provide to the top N most relevant matches. When ML scoring is enabled,
diff --git a/components/omnibox/browser/omnibox_metrics_provider.cc b/components/omnibox/browser/omnibox_metrics_provider.cc index f935a5d..95cb4b02 100644 --- a/components/omnibox/browser/omnibox_metrics_provider.cc +++ b/components/omnibox/browser/omnibox_metrics_provider.cc
@@ -226,10 +226,10 @@ suggestion->set_is_keyword_suggestion(match.from_keyword); // Scoring signals are not logged for search suggestions or in incognito - // mode. + // mode or when the `force_skip_ml_scoring` flag as been set. if (OmniboxFieldTrial::IsReportingUrlScoringSignalsEnabled() && !AutocompleteMatch::IsSearchType(match.type) && !log.is_incognito && - match.scoring_signals) { + !match.force_skip_ml_scoring && match.scoring_signals) { suggestion->mutable_scoring_signals()->CopyFrom(*match.scoring_signals); } }
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index a18878f..12a4246 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -447,6 +447,12 @@ "UrlScoringModel", enabled_by_default_desktop_only); +// If enabled, skips ML scoring for those autocomplete matches which were +// constructed by deduping an ML-eligible and ML-ineligible match. +BASE_FEATURE(kEnableForceSkipMlScoring, + "EnableForceSkipMlScoring", + base::FEATURE_ENABLED_BY_DEFAULT); + // Actions in Suggest is a data-driven feature; it's considered enabled when the // data is available. // The feature flag below helps us tune feature behaviors.
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h index d71a0e7..1d5acbd 100644 --- a/components/omnibox/common/omnibox_features.h +++ b/components/omnibox/common/omnibox_features.h
@@ -128,6 +128,7 @@ BASE_DECLARE_FEATURE(kMlUrlScoring); BASE_DECLARE_FEATURE(kMlUrlSearchBlending); BASE_DECLARE_FEATURE(kUrlScoringModel); +BASE_DECLARE_FEATURE(kEnableForceSkipMlScoring); // Actions in Suggest - Action Chips for Entity Suggestions. // Data driven feature; flag helps tune behavior.
diff --git a/components/optimization_guide/core/model_execution/model_execution_features.cc b/components/optimization_guide/core/model_execution/model_execution_features.cc index cb2da51..5900f9f 100644 --- a/components/optimization_guide/core/model_execution/model_execution_features.cc +++ b/components/optimization_guide/core/model_execution/model_execution_features.cc
@@ -47,7 +47,7 @@ BASE_FEATURE(kModelAdaptationCompose, "ModelAdaptationCompose", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kOnDeviceModelTestFeature, "OnDeviceModelTestFeature",
diff --git a/components/optimization_guide/core/model_execution/model_execution_manager_unittest.cc b/components/optimization_guide/core/model_execution/model_execution_manager_unittest.cc index a866313..b4d8c35 100644 --- a/components/optimization_guide/core/model_execution/model_execution_manager_unittest.cc +++ b/components/optimization_guide/core/model_execution/model_execution_manager_unittest.cc
@@ -11,6 +11,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/test/test.pb.h" +#include "components/optimization_guide/core/model_execution/model_execution_features.h" #include "components/optimization_guide/core/model_execution/on_device_model_access_controller.h" #include "components/optimization_guide/core/model_execution/on_device_model_service_controller.h" #include "components/optimization_guide/core/optimization_guide_constants.h" @@ -109,7 +110,9 @@ class ModelExecutionManagerTest : public testing::Test { public: ModelExecutionManagerTest() { - scoped_feature_list_.InitAndDisableFeature(features::kTextSafetyClassifier); + scoped_feature_list_.InitWithFeatures( + {}, {features::kTextSafetyClassifier, + features::internal::kModelAdaptationCompose}); } ~ModelExecutionManagerTest() override = default; @@ -660,7 +663,9 @@ : public ModelExecutionManagerTest { public: ModelExecutionManagerSafetyEnabledTest() { - scoped_feature_list_.InitAndEnableFeature(features::kTextSafetyClassifier); + scoped_feature_list_.InitWithFeatures( + {features::kTextSafetyClassifier}, + {features::internal::kModelAdaptationCompose}); } private:
diff --git a/components/optimization_guide/core/model_execution/model_execution_util.cc b/components/optimization_guide/core/model_execution/model_execution_util.cc index e18502d..0f8fcf8 100644 --- a/components/optimization_guide/core/model_execution/model_execution_util.cc +++ b/components/optimization_guide/core/model_execution/model_execution_util.cc
@@ -14,8 +14,6 @@ namespace optimization_guide { -const char kModelOverrideSeparator[] = "|"; - // Helper method matches feature to corresponding FeatureTypeMap to set // LogAiDataRequest's request data. void SetExecutionRequest( @@ -79,48 +77,6 @@ kGenAILocalFoundationalModelEnterprisePolicySettings)); } -std::optional<on_device_model::AdaptationAssetPaths> -GetOnDeviceModelAdaptationOverride(proto::ModelExecutionFeature feature) { - auto adaptations_override_switch = - switches::GetOnDeviceModelAdaptationsOverride(); - if (!adaptations_override_switch) { - return std::nullopt; - } - - for (const auto& adaptation_override : - base::SplitString(*adaptations_override_switch, ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { - std::vector<std::string> override_parts = - base::SplitString(adaptation_override, kModelOverrideSeparator, - base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - if (override_parts.size() != 2 && override_parts.size() != 3) { - // Input is malformed. - DLOG(ERROR) << "Invalid string format provided to the on-device model " - "adaptations override"; - return std::nullopt; - } - proto::ModelExecutionFeature this_feature; - if (!proto::ModelExecutionFeature_Parse(override_parts[0], &this_feature)) { - DLOG(ERROR) << "Invalid optimization target provided to the on-device " - "model adaptations override"; - return std::nullopt; - } - if (feature != this_feature) { - continue; - } - on_device_model::AdaptationAssetPaths adaptation_asset; - adaptation_asset.weights = *StringToFilePath(override_parts[1]); - if (!adaptation_asset.weights.IsAbsolute()) { - DLOG(ERROR) - << "Provided model adaptations weights file path must be absolute " - << adaptation_asset.weights; - return std::nullopt; - } - return adaptation_asset; - } - return std::nullopt; -} - OnDeviceModelLoadResult ConvertToOnDeviceModelLoadResult( on_device_model::mojom::LoadModelResult result) { switch (result) {
diff --git a/components/optimization_guide/core/model_execution/model_execution_util.h b/components/optimization_guide/core/model_execution/model_execution_util.h index 286d8dd..c66ca9c3 100644 --- a/components/optimization_guide/core/model_execution/model_execution_util.h +++ b/components/optimization_guide/core/model_execution/model_execution_util.h
@@ -13,7 +13,6 @@ #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/proto/model_quality_service.pb.h" #include "components/optimization_guide/proto/on_device_model_execution_config.pb.h" -#include "services/on_device_model/public/cpp/model_assets.h" #include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" namespace optimization_guide { @@ -73,12 +72,6 @@ GetGenAILocalFoundationalModelEnterprisePolicySettings( PrefService* local_state); -// Returns the model adaptation override from the command line. The override can -// be specified as feature|weigths_path|model_pb_path, where the paths are all -// absolute. model_pb_path is optional. -std::optional<on_device_model::AdaptationAssetPaths> -GetOnDeviceModelAdaptationOverride(proto::ModelExecutionFeature feature); - OnDeviceModelLoadResult ConvertToOnDeviceModelLoadResult( on_device_model::mojom::LoadModelResult result);
diff --git a/components/optimization_guide/core/model_execution/on_device_model_adaptation_loader.cc b/components/optimization_guide/core/model_execution/on_device_model_adaptation_loader.cc index 23843cc..3ccf44a 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_adaptation_loader.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_adaptation_loader.cc
@@ -104,14 +104,6 @@ background_task_runner_(base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT})) { CHECK(features::internal::IsOnDeviceModelAdaptationEnabled(feature_)); - if (const auto adaptations_override = GetOnDeviceModelAdaptationOverride( - ToModelExecutionFeatureProto(feature_))) { - // Do not register with model provider or component state manager, when - // override is provided. - model_provider_ = nullptr; - on_load_fn_.Run(nullptr); - return; - } component_state_manager_observation_.Observe( on_device_component_state_manager.get()); }
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc index 3928580..20be0e3 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
@@ -98,7 +98,7 @@ {"on_device_model_topk", "1"}, {"on_device_model_temperature", "0"}}}, {features::kTextSafetyClassifier, {}}}, - {}); + {features::internal::kModelAdaptationCompose}); prefs::RegisterLocalStatePrefs(pref_service_.registry()); // Fake the requirements to install the model. @@ -2698,9 +2698,6 @@ .on_device_model_service_response() .has_repeats()); histogram_tester.ExpectUniqueSample( - "OptimizationGuide.ModelExecution.OnDeviceResponseHasRepeats.Compose", - true, 1); - histogram_tester.ExpectUniqueSample( "OptimizationGuide.ModelExecution.OnDeviceExecuteModelResult.Compose", ExecuteModelResult::kResponseHadRepeats, 1); }
diff --git a/components/optimization_guide/core/model_execution/session_impl.cc b/components/optimization_guide/core/model_execution/session_impl.cc index eeacc5bc..4271623 100644 --- a/components/optimization_guide/core/model_execution/session_impl.cc +++ b/components/optimization_guide/core/model_execution/session_impl.cc
@@ -524,8 +524,6 @@ // If a repeat is detected, halt the response, and cancel/finish early. on_device_state_->receiver.reset(); logged_response->set_has_repeats(true); - LogResponseHasRepeats(feature_, true); - if (features::GetOnDeviceModelRetractRepeats()) { logged_response->set_status( proto::ON_DEVICE_MODEL_SERVICE_RESPONSE_STATUS_RETRACTED); @@ -554,6 +552,10 @@ // Stop timer, just in case we didn't already via OnResponse(). on_device_state_->timer_for_first_response.Stop(); + proto::OnDeviceModelServiceResponse* logged_response = + on_device_state_->MutableLoggedResponse(); + LogResponseHasRepeats(feature_, logged_response->has_repeats()); + base::TimeDelta time_to_completion = base::TimeTicks::Now() - on_device_state_->start; base::UmaHistogramMediumTimes( @@ -561,7 +563,7 @@ {"OptimizationGuide.ModelExecution.OnDeviceResponseCompleteTime.", GetStringNameForModelExecutionFeature(feature_)}), time_to_completion); - on_device_state_->MutableLoggedResponse()->set_time_to_completion_millis( + logged_response->set_time_to_completion_millis( time_to_completion.InMilliseconds()); on_device_state_->opts.model_client->OnResponseCompleted(); @@ -748,12 +750,6 @@ return; } - if (!on_device_state_->MutableLoggedResponse()->has_repeats()) { - // Log completed responses with no repeats to calculate percentage of - // responses that have repeats. - LogResponseHasRepeats(feature_, false); - } - if (features::ShouldUseTextSafetyRemoteFallbackForEligibleFeatures()) { RunTextSafetyRemoteFallbackAndCompletionCallback(std::move(*output)); return;
diff --git a/components/optimization_guide/core/model_quality/OWNERS b/components/optimization_guide/core/model_quality/OWNERS index 37e07883..d2b6e744 100644 --- a/components/optimization_guide/core/model_quality/OWNERS +++ b/components/optimization_guide/core/model_quality/OWNERS
@@ -1,2 +1,3 @@ +curranmax@chromium.org spelchat@chromium.org -sreejakshetty@chromium.org \ No newline at end of file +sreejakshetty@chromium.org
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index 62b2a33..32d26d73 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -162,7 +162,7 @@ // Whether to download the text safety classifier model. BASE_FEATURE(kTextSafetyClassifier, "TextSafetyClassifier", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Whether the text safety remote fallback should be used. BASE_FEATURE(kTextSafetyRemoteFallback,
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index 48f79882..1a0b4b8 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -1255,15 +1255,34 @@ } void PrintRenderFrameHelper::PrintRequestedPages() { + PrintRequestedPagesInternal(/*already_notified_frame=*/false); +} + +void PrintRenderFrameHelper::PrintRequestedPagesInternal( + bool already_notified_frame) { ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr()); - if (ipc_nesting_level_ > kAllowedIpcDepthForPrint) + if (ipc_nesting_level_ > kAllowedIpcDepthForPrint) { return; + } blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); - frame->DispatchBeforePrintEvent(/*print_client=*/nullptr); - // Don't print if the RenderFrame is gone. - if (render_frame_gone_) - return; + + if (!already_notified_frame) { + frame->DispatchBeforePrintEvent(/*print_client=*/nullptr); + // Don't print if the RenderFrame is gone. + if (render_frame_gone_) { + return; + } + + is_loading_ = frame->WillPrintSoon(); + if (is_loading_) { + on_stop_loading_closure_ = base::BindOnce( + &PrintRenderFrameHelper::PrintRequestedPagesInternal, + weak_ptr_factory_.GetWeakPtr(), /*already_notified_frame=*/true); + SetupOnStopLoadingTimeout(); + return; + } + } // If we are printing a frame with an internal PDF plugin element, find the // plugin node and print that instead. @@ -2523,6 +2542,15 @@ DCHECK(ret); } +void PrintRenderFrameHelper::SetupOnStopLoadingTimeout() { + static constexpr base::TimeDelta kLoadEventTimeout = base::Seconds(2); + base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PrintRenderFrameHelper::DidFinishLoadForPrinting, + weak_ptr_factory_.GetWeakPtr()), + kLoadEventTimeout); +} + #if BUILDFLAG(ENABLE_PRINT_PREVIEW) void PrintRenderFrameHelper::ShowScriptedPrintPreview() { if (is_scripted_preview_delayed_) { @@ -2532,19 +2560,6 @@ } } -void PrintRenderFrameHelper::WaitForLoad(PrintPreviewRequestType type) { - static constexpr base::TimeDelta kLoadEventTimeout = base::Seconds(2); - - on_stop_loading_closure_ = - base::BindOnce(&PrintRenderFrameHelper::RequestPrintPreview, - weak_ptr_factory_.GetWeakPtr(), type, true); - base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&PrintRenderFrameHelper::DidFinishLoadForPrinting, - weak_ptr_factory_.GetWeakPtr()), - kLoadEventTimeout); -} - void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type, bool already_notified_frame) { auto weak_this = weak_ptr_factory_.GetWeakPtr(); @@ -2555,6 +2570,19 @@ } is_loading_ = print_preview_context_.source_frame()->WillPrintSoon(); + if (is_loading_) { + // Wait for DidStopLoading, for two reasons: + // * To give the document time to finish loading any pending resources + // that are desired for printing. + // * Plugins may not know the correct `is_modifiable` value until they + // are fully loaded, which occurs when DidStopLoading() is called. + // Defer showing the preview until then. + on_stop_loading_closure_ = + base::BindOnce(&PrintRenderFrameHelper::RequestPrintPreview, + weak_ptr_factory_.GetWeakPtr(), type, true); + SetupOnStopLoadingTimeout(); + return; + } } #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -2578,16 +2606,6 @@ // loaded. RecordDebugEvent(DebugEvent::kRequestPrintPreviewScripted); is_scripted_preview_delayed_ = true; - if (is_loading_) { - // Wait for DidStopLoading, for two reasons: - // * To give the document time to finish loading any pending resources - /// that are desired for printing. - // * Plugins may not know the correct|is_modifiable| value until they - // are fully loaded, which occurs when DidStopLoading() is called. - // Defer showing the preview until then. - WaitForLoad(type); - return; - } base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(&PrintRenderFrameHelper::ShowScriptedPrintPreview, @@ -2618,12 +2636,6 @@ case PrintPreviewRequestType::kUserInitiatedEntireFrame: { RecordDebugEvent( DebugEvent::kRequestPrintPreviewUserInitiatedEntireFrame); - // See comment under PRINT_PREVIEW_SCRIPTED. - if (is_loading_) { - WaitForLoad(type); - return; - } - break; } case PrintPreviewRequestType::kUserInitiatedSelection: { @@ -2636,12 +2648,6 @@ case PrintPreviewRequestType::kUserInitiatedContextNode: { RecordDebugEvent( DebugEvent::kRequestPrintPreviewUserInitiatedContextNode); - // See comment under PRINT_PREVIEW_SCRIPTED. - if (is_loading_) { - WaitForLoad(type); - return; - } - params->webnode_only = true; break; }
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h index cc65c4ac5..14de0297 100644 --- a/components/printing/renderer/print_render_frame_helper.h +++ b/components/printing/renderer/print_render_frame_helper.h
@@ -624,7 +624,8 @@ int count_ = 0; }; - void WaitForLoad(PrintPreviewRequestType type); + void SetupOnStopLoadingTimeout(); + void PrintRequestedPagesInternal(bool already_notified_frame); ScriptingThrottler scripting_throttler_;
diff --git a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc index e3a379f..7d39d0b 100644 --- a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc
@@ -823,8 +823,8 @@ std::string SerializeReportType(ClientPhishingRequest::ReportType report_type) { switch (report_type) { - case ClientPhishingRequest::UNKNOWN: - return "UNKNOWN"; + case ClientPhishingRequest::REPORT_TYPE_UNSPECIFIED: + return "REPORT_TYPE_UNSPECIFIED"; case ClientPhishingRequest::FULL_REPORT: return "FULL_REPORT"; case ClientPhishingRequest::SAMPLE_REPORT:
diff --git a/components/safe_browsing/core/common/proto/csd.proto b/components/safe_browsing/core/common/proto/csd.proto index 56cfc21..e74ca68a 100644 --- a/components/safe_browsing/core/common/proto/csd.proto +++ b/components/safe_browsing/core/common/proto/csd.proto
@@ -256,7 +256,7 @@ optional ImageFeatureEmbedding image_feature_embedding = 29; enum ReportType { - UNKNOWN = 0; + REPORT_TYPE_UNSPECIFIED = 0; // Normal/full ping to Safe Browsing containing all the fields in the // ClientPhishingRequest. FULL_REPORT = 1;
diff --git a/components/services/storage/public/cpp/filesystem/BUILD.gn b/components/services/storage/public/cpp/filesystem/BUILD.gn index 84608110..36e1dbec 100644 --- a/components/services/storage/public/cpp/filesystem/BUILD.gn +++ b/components/services/storage/public/cpp/filesystem/BUILD.gn
@@ -21,6 +21,8 @@ "//mojo/public/cpp/bindings", ] + deps = [ "//components/crash/core/common:crash_key" ] + defines = [ "IS_STORAGE_SERVICE_FILESYSTEM_SUPPORT_IMPL" ] }
diff --git a/components/services/storage/public/cpp/filesystem/DEPS b/components/services/storage/public/cpp/filesystem/DEPS new file mode 100644 index 0000000..64556717 --- /dev/null +++ b/components/services/storage/public/cpp/filesystem/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + # TODO(crbug.com/340398745): remove after fixing. + "+components/crash/core/common/crash_key.h", +]
diff --git a/components/services/storage/public/cpp/filesystem/filesystem_impl.cc b/components/services/storage/public/cpp/filesystem/filesystem_impl.cc index 7a311d7..1dc39c322 100644 --- a/components/services/storage/public/cpp/filesystem/filesystem_impl.cc +++ b/components/services/storage/public/cpp/filesystem/filesystem_impl.cc
@@ -4,12 +4,13 @@ #include "components/services/storage/public/cpp/filesystem/filesystem_impl.h" -#include <set> +#include <map> #include <vector> #include "base/check.h" #include "base/containers/contains.h" #include "base/debug/dump_without_crashing.h" +#include "base/debug/stack_trace.h" #include "base/files/file.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" @@ -19,6 +20,7 @@ #include "base/synchronization/lock.h" #include "base/types/expected_macros.h" #include "build/build_config.h" +#include "components/crash/core/common/crash_key.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #if BUILDFLAG(IS_WIN) @@ -41,7 +43,20 @@ bool AddLock(const base::FilePath& path) { DCHECK(path.IsAbsolute()); base::AutoLock lock(lock_); - auto result = lock_paths_.insert(path.NormalizePathSeparators()); + auto result = lock_paths_.insert(std::make_pair( + path.NormalizePathSeparators(), base::debug::StackTrace())); + + // TODO(crbug.com/340398745): resolve this mystery and remove this + // block, or even replace it with a CHECK. + if (!result.second) { + static crash_reporter::CrashKeyString<1024> trace_key( + "crbug/340398745/existing_lock_stack"); + crash_reporter::SetCrashKeyStringToStackTrace(&trace_key, + result.first->second); + base::debug::DumpWithoutCrashing(); + trace_key.Clear(); + } + return result.second; } @@ -54,7 +69,8 @@ private: base::Lock lock_; - std::set<base::FilePath> lock_paths_ GUARDED_BY(lock_); + std::map<base::FilePath, base::debug::StackTrace> lock_paths_ + GUARDED_BY(lock_); }; // Get the global singleton instance of LockTable. This returned object is @@ -269,9 +285,6 @@ return base::unexpected(file.error_details()); if (!GetLockTable().AddLock(path)) { - // TODO(crbug.com/340398745): resolve this mystery and remove this line, or - // even replace it with a CHECK. - base::debug::DumpWithoutCrashing(); return base::unexpected(base::File::FILE_ERROR_IN_USE); }
diff --git a/components/speech/BUILD.gn b/components/speech/BUILD.gn index 2be48280..842b24f 100644 --- a/components/speech/BUILD.gn +++ b/components/speech/BUILD.gn
@@ -18,6 +18,17 @@ "upstream_loader_client.h", ] + if (!is_android) { + sources += [ + "endpointer/endpointer.cc", + "endpointer/endpointer.h", + "endpointer/energy_endpointer.cc", + "endpointer/energy_endpointer.h", + "endpointer/energy_endpointer_params.cc", + "endpointer/energy_endpointer_params.h", + ] + } + public_deps = [ "//base" ] deps = [ "//mojo/public/cpp/bindings", @@ -31,7 +42,16 @@ source_set("unit_tests") { testonly = true - sources = [ "chunked_byte_buffer_unittest.cc" ] + sources = [ + "chunked_byte_buffer_unittest.cc", + ] + + if (!is_android) { + sources += [ + "endpointer/endpointer_unittest.cc", + ] + } + deps = [ ":speech", "//testing/gtest",
diff --git a/content/browser/speech/endpointer/endpointer.cc b/components/speech/endpointer/endpointer.cc similarity index 89% rename from content/browser/speech/endpointer/endpointer.cc rename to components/speech/endpointer/endpointer.cc index 32d767fe..7d9518ad 100644 --- a/content/browser/speech/endpointer/endpointer.cc +++ b/components/speech/endpointer/endpointer.cc
@@ -1,8 +1,8 @@ -// Copyright 2012 The Chromium Authors +// 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 "content/browser/speech/endpointer/endpointer.h" +#include "components/speech/endpointer/endpointer.h" #include "base/time/time.h" #include "components/speech/audio_buffer.h" @@ -10,9 +10,9 @@ namespace { const int64_t kMicrosecondsPerSecond = base::Time::kMicrosecondsPerSecond; const int kFrameRate = 50; // 1 frame = 20ms of audio. -} +} // namespace -namespace content { +namespace speech { Endpointer::Endpointer(int sample_rate) : speech_input_possibly_complete_silence_length_us_(-1), @@ -61,7 +61,7 @@ waiting_for_speech_complete_timeout_ = false; speech_previously_detected_ = false; speech_input_complete_ = false; - audio_frame_time_us_ = 0; // Reset time for packets sent to endpointer. + audio_frame_time_us_ = 0; // Reset time for packets sent to endpointer. speech_end_time_us_ = -1; speech_start_time_us_ = -1; } @@ -99,10 +99,8 @@ int sample_index = 0; while (sample_index + frame_size_ <= num_samples) { // Have the endpointer process the frame. - energy_endpointer_.ProcessAudioFrame(audio_frame_time_us_, - audio_data + sample_index, - frame_size_, - rms_out); + energy_endpointer_.ProcessAudioFrame( + audio_frame_time_us_, audio_data + sample_index, frame_size_, rms_out); sample_index += frame_size_; audio_frame_time_us_ += (frame_size_ * kMicrosecondsPerSecond) / sample_rate_; @@ -133,7 +131,7 @@ // Speech possibly complete timeout. if ((waiting_for_speech_possibly_complete_timeout_) && (ep_time - speech_end_time_us_ > - speech_input_possibly_complete_silence_length_us_)) { + speech_input_possibly_complete_silence_length_us_)) { waiting_for_speech_possibly_complete_timeout_ = false; } if (waiting_for_speech_complete_timeout_) { @@ -149,8 +147,7 @@ requested_silence_length = long_speech_input_complete_silence_length_us_; } else { - requested_silence_length = - speech_input_complete_silence_length_us_; + requested_silence_length = speech_input_complete_silence_length_us_; } // Speech complete timeout. @@ -165,4 +162,4 @@ return ep_status; } -} // namespace content +} // namespace speech
diff --git a/content/browser/speech/endpointer/endpointer.h b/components/speech/endpointer/endpointer.h similarity index 89% rename from content/browser/speech/endpointer/endpointer.h rename to components/speech/endpointer/endpointer.h index 7695d5ec..db54ea0 100644 --- a/content/browser/speech/endpointer/endpointer.h +++ b/components/speech/endpointer/endpointer.h
@@ -1,19 +1,18 @@ -// Copyright 2012 The Chromium Authors +// 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 CONTENT_BROWSER_SPEECH_ENDPOINTER_ENDPOINTER_H_ -#define CONTENT_BROWSER_SPEECH_ENDPOINTER_ENDPOINTER_H_ +#ifndef COMPONENTS_SPEECH_ENDPOINTER_ENDPOINTER_H_ +#define COMPONENTS_SPEECH_ENDPOINTER_ENDPOINTER_H_ #include <stdint.h> -#include "content/browser/speech/endpointer/energy_endpointer.h" -#include "content/common/content_export.h" +#include "components/speech/endpointer/energy_endpointer.h" class EpStatus; class AudioChunk; -namespace content { +namespace speech { // A simple interface to the underlying energy-endpointer implementation, this // class lets callers provide audio as being recorded and let them poll to find @@ -43,7 +42,7 @@ // The timeout length is speech_input_complete_silence_length until // long_speech_length, when it changes to // long_speech_input_complete_silence_length. -class CONTENT_EXPORT Endpointer { +class Endpointer { public: explicit Endpointer(int sample_rate); @@ -70,9 +69,7 @@ // Returns true if the endpointer detected reasonable audio levels above // background noise which could be user speech, false if not. - bool DidStartReceivingSpeech() const { - return speech_previously_detected_; - } + bool DidStartReceivingSpeech() const { return speech_previously_detected_; } bool IsEstimatingEnvironment() const { return energy_endpointer_.estimating_environment(); @@ -94,9 +91,7 @@ long_speech_length_us_ = time_us; } - bool speech_input_complete() const { - return speech_input_complete_; - } + bool speech_input_complete() const { return speech_input_complete_; } // RMS background noise level in dB. float NoiseLevelDb() const { return energy_endpointer_.GetNoiseLevelDb(); } @@ -148,6 +143,6 @@ int32_t frame_size_; }; -} // namespace content +} // namespace speech -#endif // CONTENT_BROWSER_SPEECH_ENDPOINTER_ENDPOINTER_H_ +#endif // COMPONENTS_SPEECH_ENDPOINTER_ENDPOINTER_H_
diff --git a/content/browser/speech/endpointer/endpointer_unittest.cc b/components/speech/endpointer/endpointer_unittest.cc similarity index 92% rename from content/browser/speech/endpointer/endpointer_unittest.cc rename to components/speech/endpointer/endpointer_unittest.cc index c00a161e..0f7c2cd 100644 --- a/content/browser/speech/endpointer/endpointer_unittest.cc +++ b/components/speech/endpointer/endpointer_unittest.cc
@@ -1,25 +1,26 @@ -// Copyright 2012 The Chromium Authors +// 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/speech/endpointer/endpointer.h" + #include <stdint.h> #include "base/memory/raw_ptr.h" #include "components/speech/audio_buffer.h" -#include "content/browser/speech/endpointer/endpointer.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -const int kFrameRate = 50; // 20 ms long frames for AMR encoding. +const int kFrameRate = 50; // 20 ms long frames for AMR encoding. const int kSampleRate = 8000; // 8 k samples per second for AMR encoding. // At 8 sample per second a 20 ms frame is 160 samples, which corrsponds // to the AMR codec. const int kFrameSize = kSampleRate / kFrameRate; // 160 samples. static_assert(kFrameSize == 160, "invalid frame size"); -} +} // namespace -namespace content { +namespace speech { class FrameProcessor { public: @@ -51,7 +52,7 @@ // Create random samples. for (int i = 0; i < kFrameSize; ++i) { float randNum = static_cast<float>(rand() - (RAND_MAX / 2)) / - static_cast<float>(RAND_MAX); + static_cast<float>(RAND_MAX); samples[i] = static_cast<int16_t>(gain * randNum); } @@ -59,12 +60,15 @@ time += static_cast<int64_t>(kFrameSize * (1e6 / kSampleRate)); // Log the status. - if (20 == frame_count) + if (20 == frame_count) { EXPECT_EQ(EP_PRE_SPEECH, ep_status); - if (70 == frame_count) + } + if (70 == frame_count) { EXPECT_EQ(EP_SPEECH_PRESENT, ep_status); - if (120 == frame_count) + } + if (120 == frame_count) { EXPECT_EQ(EP_PRE_SPEECH, ep_status); + } } } @@ -154,4 +158,4 @@ endpointer.EndSession(); } -} // namespace content +} // namespace speech
diff --git a/content/browser/speech/endpointer/energy_endpointer.cc b/components/speech/endpointer/energy_endpointer.cc similarity index 87% rename from content/browser/speech/endpointer/energy_endpointer.cc rename to components/speech/endpointer/energy_endpointer.cc index ec72e2b7..f8dba53 100644 --- a/content/browser/speech/endpointer/energy_endpointer.cc +++ b/components/speech/endpointer/energy_endpointer.cc
@@ -1,4 +1,4 @@ -// Copyright 2012 The Chromium Authors +// 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. // @@ -6,7 +6,7 @@ // based of, see // https://wiki.corp.google.com/twiki/bin/view/Main/ChromeGoogleCodeXRef -#include "content/browser/speech/endpointer/energy_endpointer.h" +#include "components/speech/endpointer/energy_endpointer.h" #include <math.h> #include <stddef.h> @@ -35,14 +35,15 @@ } float GetDecibel(float value) { - if (value > 1.0e-100) + if (value > 1.0e-100) { return 20 * log10(value); + } return -2000.0; } } // namespace -namespace content { +namespace speech { // Stores threshold-crossing histories for making decisions about the speech // state. @@ -80,7 +81,7 @@ void EnergyEndpointer::HistoryRing::SetRing(int size, bool initial_state) { insertion_index_ = 0; decision_points_.clear(); - DecisionPoint init = { -1, initial_state }; + DecisionPoint init = {-1, initial_state}; decision_points_.resize(size, init); } @@ -92,33 +93,39 @@ int64_t EnergyEndpointer::HistoryRing::EndTime() const { int ind = insertion_index_ - 1; - if (ind < 0) + if (ind < 0) { ind = decision_points_.size() - 1; + } return decision_points_[ind].time_us; } float EnergyEndpointer::HistoryRing::RingSum(float duration_sec) { - if (decision_points_.empty()) + if (decision_points_.empty()) { return 0.0; + } int64_t sum_us = 0; int ind = insertion_index_ - 1; - if (ind < 0) + if (ind < 0) { ind = decision_points_.size() - 1; + } int64_t end_us = decision_points_[ind].time_us; bool is_on = decision_points_[ind].decision; int64_t start_us = end_us - static_cast<int64_t>(0.5 + (1.0e6 * duration_sec)); - if (start_us < 0) + if (start_us < 0) { start_us = 0; + } size_t n_summed = 1; // n points ==> (n-1) intervals while ((decision_points_[ind].time_us > start_us) && (n_summed < decision_points_.size())) { --ind; - if (ind < 0) + if (ind < 0) { ind = decision_points_.size() - 1; - if (is_on) + } + if (is_on) { sum_us += end_us - decision_points_[ind].time_us; + } is_on = decision_points_[ind].decision; end_us = decision_points_[ind].time_us; n_summed++; @@ -142,11 +149,9 @@ rms_adapt_(0), start_lag_(0), end_lag_(0), - user_input_start_time_us_(0) { -} + user_input_start_time_us_(0) {} -EnergyEndpointer::~EnergyEndpointer() { -} +EnergyEndpointer::~EnergyEndpointer() {} int EnergyEndpointer::TimeToFrame(float time) const { return static_cast<int32_t>(0.5 + (time / params_.frame_period())); @@ -181,16 +186,19 @@ // depends upon ep_frame_period being set correctly in the factory // that did this instantiation. max_window_dur_ = params_.onset_window(); - if (params_.speech_on_window() > max_window_dur_) + if (params_.speech_on_window() > max_window_dur_) { max_window_dur_ = params_.speech_on_window(); - if (params_.offset_window() > max_window_dur_) + } + if (params_.offset_window() > max_window_dur_) { max_window_dur_ = params_.offset_window(); + } Restart(true); - offset_confirm_dur_sec_ = params_.offset_window() - - params_.offset_confirm_dur(); - if (offset_confirm_dur_sec_ < 0.0) + offset_confirm_dur_sec_ = + params_.offset_window() - params_.offset_confirm_dur(); + if (offset_confirm_dur_sec_ < 0.0) { offset_confirm_dur_sec_ = 0.0; + } user_input_start_time_us_ = 0; @@ -208,10 +216,10 @@ frame_counter_ = 0; // Used for rapid initial update of levels. sample_rate_ = params_.sample_rate(); - start_lag_ = static_cast<int>(sample_rate_ / - params_.max_fundamental_frequency()); - end_lag_ = static_cast<int>(sample_rate_ / - params_.min_fundamental_frequency()); + start_lag_ = + static_cast<int>(sample_rate_ / params_.max_fundamental_frequency()); + end_lag_ = + static_cast<int>(sample_rate_ / params_.min_fundamental_frequency()); } void EnergyEndpointer::StartSession() { @@ -268,8 +276,9 @@ if (tsum > params_.onset_confirm_dur()) { status_ = EP_SPEECH_PRESENT; } else { // If signal is not maintained, drop back to pre-speech. - if (tsum <= params_.onset_detect_dur()) + if (tsum <= params_.onset_detect_dur()) { status_ = EP_PRE_SPEECH; + } } break; } @@ -279,8 +288,9 @@ // smaller residency time in the on_ring, than was required to // enter the SPEECH_PERSENT state. float on_time = history_->RingSum(params_.speech_on_window()); - if (on_time < params_.on_maintain_dur()) + if (on_time < params_.on_maintain_dur()) { status_ = EP_POSSIBLE_OFFSET; + } break; } @@ -293,8 +303,9 @@ status_ = EP_PRE_SPEECH; // Automatically reset for next utterance. } else { // If speech picks up again we allow return to SPEECH_PRESENT. if (history_->RingSum(params_.speech_on_window()) >= - params_.on_maintain_dur()) + params_.on_maintain_dur()) { status_ = EP_SPEECH_PRESENT; + } } break; @@ -320,23 +331,25 @@ } else { rms_adapt_ = (0.95f * rms_adapt_) + (0.05f * rms); } - float target_threshold = 0.3f * rms_adapt_ + noise_level_; - decision_threshold_ = (.90f * decision_threshold_) + - (0.10f * target_threshold); + float target_threshold = 0.3f * rms_adapt_ + noise_level_; + decision_threshold_ = + (.90f * decision_threshold_) + (0.10f * target_threshold); } } // Set a floor - if (decision_threshold_ < params_.min_decision_threshold()) + if (decision_threshold_ < params_.min_decision_threshold()) { decision_threshold_ = params_.min_decision_threshold(); + } } // Update speech and noise levels. UpdateLevels(rms); ++frame_counter_; - if (rms_out) + if (rms_out) { *rms_out = GetDecibel(rms); + } } float EnergyEndpointer::GetNoiseLevelDb() const { @@ -350,7 +363,7 @@ // Alpha increases from 0 to (k-1)/k where k is the number of time // steps in the initial adaptation period. float alpha = static_cast<float>(frame_counter_) / - static_cast<float>(fast_update_frames_); + static_cast<float>(fast_update_frames_); noise_level_ = (alpha * noise_level_) + ((1 - alpha) * rms); DVLOG(1) << "FAST UPDATE, frame_counter_ " << frame_counter_ << ", fast_update_frames_ " << fast_update_frames_; @@ -358,16 +371,18 @@ // Update Noise level. The noise level adapts quickly downward, but // slowly upward. The noise_level_ parameter is not currently used // for threshold adaptation. It is used for UI feedback. - if (noise_level_ < rms) + if (noise_level_ < rms) { noise_level_ = (0.999f * noise_level_) + (0.001f * rms); - else + } else { noise_level_ = (0.95f * noise_level_) + (0.05f * rms); + } } if (estimating_environment_ || (frame_counter_ < fast_update_frames_)) { - decision_threshold_ = noise_level_ * 2; // 6dB above noise level. + decision_threshold_ = noise_level_ * 2; // 6dB above noise level. // Set a floor - if (decision_threshold_ < params_.min_decision_threshold()) + if (decision_threshold_ < params_.min_decision_threshold()) { decision_threshold_ = params_.min_decision_threshold(); + } } } @@ -376,4 +391,4 @@ return status_; } -} // namespace content +} // namespace speech
diff --git a/content/browser/speech/endpointer/energy_endpointer.h b/components/speech/endpointer/energy_endpointer.h similarity index 89% rename from content/browser/speech/endpointer/energy_endpointer.h rename to components/speech/endpointer/energy_endpointer.h index 9f869a3..bbea6a9 100644 --- a/content/browser/speech/endpointer/energy_endpointer.h +++ b/components/speech/endpointer/energy_endpointer.h
@@ -1,4 +1,4 @@ -// Copyright 2012 The Chromium Authors +// 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. @@ -34,18 +34,17 @@ // accept. The false accepts can be ignored by setting // ep_contamination_rejection_period. -#ifndef CONTENT_BROWSER_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_H_ -#define CONTENT_BROWSER_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_H_ +#ifndef COMPONENTS_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_H_ +#define COMPONENTS_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_H_ #include <stdint.h> #include <memory> #include <vector> -#include "content/browser/speech/endpointer/energy_endpointer_params.h" -#include "content/common/content_export.h" +#include "components/speech/endpointer/energy_endpointer_params.h" -namespace content { +namespace speech { // Endpointer status codes enum EpStatus { @@ -56,7 +55,7 @@ EP_POST_SPEECH, }; -class CONTENT_EXPORT EnergyEndpointer { +class EnergyEndpointer { public: // The default construction MUST be followed by Init(), before any // other use can be made of the instance. @@ -94,9 +93,7 @@ // corresponding to the most recently computed frame. EpStatus Status(int64_t* status_time_us) const; - bool estimating_environment() const { - return estimating_environment_; - } + bool estimating_environment() const { return estimating_environment_; } // Returns estimated noise level in dB. float GetNoiseLevelDb() const; @@ -116,7 +113,7 @@ // the 'time' (in seconds). int TimeToFrame(float time) const; - EpStatus status_; // The current state of this instance. + EpStatus status_; // The current state of this instance. float offset_confirm_dur_sec_; // max on time allowed to confirm POST_SPEECH int64_t endpointer_time_us_; // Time of the most recently received audio frame. @@ -125,7 +122,7 @@ int64_t frame_counter_; // Number of frames seen. Used for initial adaptation. float max_window_dur_; // Largest search window size (seconds) - float sample_rate_; // Sampling rate. + float sample_rate_; // Sampling rate. // Ring buffers to hold the speech activity history. std::unique_ptr<HistoryRing> history_; @@ -157,6 +154,6 @@ int64_t user_input_start_time_us_; }; -} // namespace content +} // namespace speech -#endif // CONTENT_BROWSER_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_H_ +#endif // COMPONENTS_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_H_
diff --git a/content/browser/speech/endpointer/energy_endpointer_params.cc b/components/speech/endpointer/energy_endpointer_params.cc similarity index 91% rename from content/browser/speech/endpointer/energy_endpointer_params.cc rename to components/speech/endpointer/energy_endpointer_params.cc index d9b70f29..21194c41 100644 --- a/content/browser/speech/endpointer/energy_endpointer_params.cc +++ b/components/speech/endpointer/energy_endpointer_params.cc
@@ -1,10 +1,10 @@ -// Copyright 2012 The Chromium Authors +// 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 "content/browser/speech/endpointer/energy_endpointer_params.h" +#include "components/speech/endpointer/energy_endpointer_params.h" -namespace content { +namespace speech { EnergyEndpointerParams::EnergyEndpointerParams() { SetDefaults(); @@ -50,4 +50,4 @@ contamination_rejection_period_ = source.contamination_rejection_period(); } -} // namespace content +} // namespace speech
diff --git a/content/browser/speech/endpointer/energy_endpointer_params.h b/components/speech/endpointer/energy_endpointer_params.h similarity index 79% rename from content/browser/speech/endpointer/energy_endpointer_params.h rename to components/speech/endpointer/energy_endpointer_params.h index bf13dd2..b5341c3 100644 --- a/content/browser/speech/endpointer/energy_endpointer_params.h +++ b/components/speech/endpointer/energy_endpointer_params.h
@@ -1,16 +1,14 @@ -// Copyright 2012 The Chromium Authors +// 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 CONTENT_BROWSER_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_PARAMS_H_ -#define CONTENT_BROWSER_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_PARAMS_H_ +#ifndef COMPONENTS_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_PARAMS_H_ +#define COMPONENTS_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_PARAMS_H_ -#include "content/common/content_export.h" - -namespace content { +namespace speech { // Input parameters for the EnergyEndpointer class. -class CONTENT_EXPORT EnergyEndpointerParams { +class EnergyEndpointerParams { public: EnergyEndpointerParams(); @@ -20,9 +18,7 @@ // Accessors and mutators float frame_period() const { return frame_period_; } - void set_frame_period(float frame_period) { - frame_period_ = frame_period; - } + void set_frame_period(float frame_period) { frame_period_ = frame_period; } float frame_duration() const { return frame_duration_; } void set_frame_duration(float frame_duration) { @@ -104,16 +100,16 @@ } private: - float frame_period_; // Frame period - float frame_duration_; // Window size - float onset_window_; // Interval scanned for onset activity - float speech_on_window_; // Inverval scanned for ongoing speech - float offset_window_; // Interval scanned for offset evidence - float offset_confirm_dur_; // Silence duration required to confirm offset - float decision_threshold_; // Initial rms detection threshold + float frame_period_; // Frame period + float frame_duration_; // Window size + float onset_window_; // Interval scanned for onset activity + float speech_on_window_; // Inverval scanned for ongoing speech + float offset_window_; // Interval scanned for offset evidence + float offset_confirm_dur_; // Silence duration required to confirm offset + float decision_threshold_; // Initial rms detection threshold float min_decision_threshold_; // Minimum rms detection threshold - float fast_update_dur_; // Period for initial estimation of levels. - float sample_rate_; // Expected sample rate. + float fast_update_dur_; // Period for initial estimation of levels. + float sample_rate_; // Expected sample rate. // Time to add on either side of endpoint threshold crossings float endpoint_margin_; @@ -132,6 +128,6 @@ float contamination_rejection_period_; }; -} // namespace content +} // namespace speech -#endif // CONTENT_BROWSER_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_PARAMS_H_ +#endif // COMPONENTS_SPEECH_ENDPOINTER_ENERGY_ENDPOINTER_PARAMS_H_
diff --git a/components/user_education/views/help_bubble_view.cc b/components/user_education/views/help_bubble_view.cc index 53ae95e..f3ee834 100644 --- a/components/user_education/views/help_bubble_view.cc +++ b/components/user_education/views/help_bubble_view.cc
@@ -1000,21 +1000,22 @@ #if BUILDFLAG(IS_LINUX) // Help bubbles anchored to menus may be clipped to their anchors' bounds, // resulting in visual errors, unless they use accelerated rendering. See - // crbug.com/1445770 for details. + // crbug.com/1445770 for details. This also applies to bubbles anchored to + // all accelerated windows below a certain size, especially those which are + // not top-level application windows (see crbug.com/340523110). // - // In Views, [nearly] all menus have a scroll container as their root view. - // Key off of this in order to minimize the number of widgets that are forced - // to be accelerated. Accelerated widgets are "desktop native" widgets and - // interact with the OS window activation system; this is, in turn, a problem - // for Linux because of known technical limitations around window activation. + // Because it is not possible to know exactly if a bubble will correctly fit + // in the bounds of its ancestor accelerator widget, due to things like + // anchor positioning and the possibility that a window size could change, + // make all Linux help bubbles accelerated. // - // See the following bug for more information regarding window activation - // issues in Weston, the windowing environment used on chrome's Wayland - // testbots: + // Note: accelerated widgets are "desktop native" widgets and interact with + // the OS window activation system; this is, in turn, a problem for Linux + // because of known technical limitations around window activation. See the + // following bug for more information regarding window activation issues in + // Weston, the windowing environment used on chrome's Wayland test-bots: // https://gitlab.freedesktop.org/wayland/weston/-/issues/669 - if (GetAnchorAsMenuItem(this) != nullptr) { - params->use_accelerated_widget_override = true; - } + params->use_accelerated_widget_override = true; #endif }
diff --git a/components/viz/service/display_embedder/compositor_gpu_thread.cc b/components/viz/service/display_embedder/compositor_gpu_thread.cc index 318ea52..a38c889 100644 --- a/components/viz/service/display_embedder/compositor_gpu_thread.cc +++ b/components/viz/service/display_embedder/compositor_gpu_thread.cc
@@ -22,7 +22,6 @@ #include "gpu/vulkan/buildflags.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" -#include "ui/gl/gl_features.h" #include "ui/gl/gl_surface_egl.h" #include "ui/gl/init/gl_factory.h" @@ -143,7 +142,13 @@ attribs.angle_context_virtualization_group_number = gl::AngleContextVirtualizationGroup::kDrDc; - attribs.can_skip_validation = !features::IsANGLEValidationEnabled(); + bool enable_angle_validation = features::IsANGLEValidationEnabled(); +#if DCHECK_IS_ON() + // Force validation on for all debug builds and testing + enable_angle_validation = true; +#endif + + attribs.can_skip_validation = !enable_angle_validation; // Compositor thread context doesn't need access textures and semaphores // created with other contexts.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 42ad9b4..cd93a04 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -456,11 +456,13 @@ "attribution_reporting/attribution_report_network_sender.cc", "attribution_reporting/attribution_report_network_sender.h", "attribution_reporting/attribution_report_sender.h", - "attribution_reporting/attribution_storage.h", - "attribution_reporting/attribution_storage_delegate.cc", - "attribution_reporting/attribution_storage_delegate.h", - "attribution_reporting/attribution_storage_delegate_impl.cc", - "attribution_reporting/attribution_storage_delegate_impl.h", + "attribution_reporting/attribution_resolver.h", + "attribution_reporting/attribution_resolver_delegate.cc", + "attribution_reporting/attribution_resolver_delegate.h", + "attribution_reporting/attribution_resolver_delegate_impl.cc", + "attribution_reporting/attribution_resolver_delegate_impl.h", + "attribution_reporting/attribution_resolver_impl.cc", + "attribution_reporting/attribution_resolver_impl.h", "attribution_reporting/attribution_storage_sql.cc", "attribution_reporting/attribution_storage_sql.h", "attribution_reporting/attribution_storage_sql_migrations.cc", @@ -2058,6 +2060,8 @@ "service_worker/url_loader_client_checker.h", "shared_storage/shared_storage_budget_charger.cc", "shared_storage/shared_storage_budget_charger.h", + "shared_storage/shared_storage_code_cache_host_proxy.cc", + "shared_storage/shared_storage_code_cache_host_proxy.h", "shared_storage/shared_storage_document_service_impl.cc", "shared_storage/shared_storage_document_service_impl.h", "shared_storage/shared_storage_event_params.cc", @@ -2068,7 +2072,6 @@ "shared_storage/shared_storage_render_thread_worklet_driver.h", "shared_storage/shared_storage_url_loader_factory_proxy.cc", "shared_storage/shared_storage_url_loader_factory_proxy.h", - "shared_storage/shared_storage_worklet_driver.h", "shared_storage/shared_storage_worklet_host.cc", "shared_storage/shared_storage_worklet_host.h", "shared_storage/shared_storage_worklet_host_manager.cc", @@ -3278,12 +3281,6 @@ "service_worker/service_worker_usb_delegate_observer.h", # Most speech code is non-Android. - "speech/endpointer/endpointer.cc", - "speech/endpointer/endpointer.h", - "speech/endpointer/energy_endpointer.cc", - "speech/endpointer/energy_endpointer.h", - "speech/endpointer/energy_endpointer_params.cc", - "speech/endpointer/energy_endpointer_params.h", "speech/network_speech_recognition_engine_impl.cc", "speech/network_speech_recognition_engine_impl.h", "speech/speech_recognition_engine.cc",
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 49ea5e6..ce900674 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -1277,7 +1277,6 @@ case ax::mojom::Action::kStitchChildTree: CHECK_NE(data.target_tree_id, ui::AXTreeIDUnknown()); CHECK_EQ(data.target_tree_id, manager()->GetTreeID()); - CHECK_NE(data.target_node_id, ui::kInvalidAXNodeID); CHECK_EQ(data.target_node_id, node()->id()); CHECK_NE(data.child_tree_id, ui::AXTreeIDUnknown()); CHECK_NE(data.child_tree_id, manager()->GetTreeID())
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc index 36dce71..09bef9ac 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -61,10 +61,10 @@ #include "content/browser/attribution_reporting/attribution_report_network_sender.h" #include "content/browser/attribution_reporting/attribution_report_sender.h" #include "content/browser/attribution_reporting/attribution_reporting.mojom.h" -#include "content/browser/attribution_reporting/attribution_storage.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate_impl.h" -#include "content/browser/attribution_reporting/attribution_storage_sql.h" +#include "content/browser/attribution_reporting/attribution_resolver.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate_impl.h" +#include "content/browser/attribution_reporting/attribution_resolver_impl.h" #include "content/browser/attribution_reporting/attribution_trigger.h" #include "content/browser/attribution_reporting/create_report_result.h" #include "content/browser/attribution_reporting/os_registration.h" @@ -127,21 +127,21 @@ const base::TimeDelta kPrivacySandboxAttestationsTimeout = base::Minutes(5); // This class consolidates logic regarding when to schedule the browser to send -// attribution reports. It talks directly to the `AttributionStorage` to help +// attribution reports. It talks directly to the `AttributionResolver` to help // make these decisions. // // While the class does not make large changes to the underlying database, it -// is responsible for notifying the `AttributionStorage` when the browser comes +// is responsible for notifying the `AttributionResolver` when the browser comes // back online, which mutates report times for some scheduled reports. class AttributionReportScheduler : public ReportSchedulerTimer::Delegate { public: AttributionReportScheduler( base::RepeatingClosure send_reports, base::RepeatingClosure on_reporting_paused_cb, - base::SequenceBound<AttributionStorage>& attribution_storage) + base::SequenceBound<AttributionResolver>& attribution_resolver) : send_reports_(std::move(send_reports)), on_reporting_paused_cb_(std::move(on_reporting_paused_cb)), - attribution_storage_(attribution_storage) {} + attribution_resolver_(attribution_resolver) {} ~AttributionReportScheduler() override = default; AttributionReportScheduler(const AttributionReportScheduler&) = delete; @@ -155,7 +155,7 @@ void GetNextReportTime( base::OnceCallback<void(std::optional<base::Time>)> callback, base::Time now) override { - attribution_storage_->AsyncCall(&AttributionStorage::GetNextReportTime) + attribution_resolver_->AsyncCall(&AttributionResolver::GetNextReportTime) .WithArgs(now) .Then(std::move(callback)); } @@ -170,8 +170,8 @@ // offline so they are not temporally joinable. We do this in storage to // avoid pulling an unbounded number of reports into memory, only to // immediately issue async storage calls to modify their report times. - attribution_storage_ - ->AsyncCall(&AttributionStorage::AdjustOfflineReportTimes) + attribution_resolver_ + ->AsyncCall(&AttributionResolver::AdjustOfflineReportTimes) .Then(std::move(maybe_set_timer_cb)); } @@ -179,7 +179,7 @@ base::RepeatingClosure send_reports_; base::RepeatingClosure on_reporting_paused_cb_; - const raw_ref<base::SequenceBound<AttributionStorage>> attribution_storage_; + const raw_ref<base::SequenceBound<AttributionResolver>> attribution_resolver_; }; bool IsStorageKeySessionOnly( @@ -417,14 +417,14 @@ } } -std::unique_ptr<AttributionStorageDelegate> MakeStorageDelegate( +std::unique_ptr<AttributionResolverDelegate> MakeResolverDelegate( bool debug_mode) { if (debug_mode) { - return std::make_unique<AttributionStorageDelegateImpl>( + return std::make_unique<AttributionResolverDelegateImpl>( AttributionNoiseMode::kNone, AttributionDelayMode::kNone); } - return std::make_unique<AttributionStorageDelegateImpl>( + return std::make_unique<AttributionResolverDelegateImpl>( AttributionNoiseMode::kDefault, AttributionDelayMode::kDefault); } @@ -513,17 +513,17 @@ const base::FilePath& user_data_directory, size_t max_pending_events, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, - std::unique_ptr<AttributionStorageDelegate> storage_delegate, + std::unique_ptr<AttributionResolverDelegate> resolver_delegate, std::unique_ptr<AttributionCookieChecker> cookie_checker, std::unique_ptr<AttributionReportSender> report_sender, std::unique_ptr<AttributionOsLevelManager> os_level_manager, StoragePartitionImpl* storage_partition, - scoped_refptr<base::UpdateableSequencedTaskRunner> storage_task_runner) { + scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner) { return base::WrapUnique(new AttributionManagerImpl( storage_partition, user_data_directory, max_pending_events, - std::move(special_storage_policy), std::move(storage_delegate), + std::move(special_storage_policy), std::move(resolver_delegate), std::move(cookie_checker), std::move(report_sender), - std::move(os_level_manager), std::move(storage_task_runner))); + std::move(os_level_manager), std::move(resolver_task_runner))); } AttributionManagerImpl::AttributionManagerImpl( @@ -537,8 +537,9 @@ // os registrations will include multiple items. /*max_pending_events=*/1000, std::move(special_storage_policy), - MakeStorageDelegate(base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAttributionReportingDebugMode)), + MakeResolverDelegate( + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAttributionReportingDebugMode)), std::make_unique<AttributionCookieCheckerImpl>(storage_partition), std::make_unique<AttributionReportNetworkSender>( storage_partition->GetURLLoaderFactoryForBrowserProcess()), @@ -559,19 +560,19 @@ const base::FilePath& user_data_directory, size_t max_pending_events, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, - std::unique_ptr<AttributionStorageDelegate> storage_delegate, + std::unique_ptr<AttributionResolverDelegate> resolver_delegate, std::unique_ptr<AttributionCookieChecker> cookie_checker, std::unique_ptr<AttributionReportSender> report_sender, std::unique_ptr<AttributionOsLevelManager> os_level_manager, - scoped_refptr<base::UpdateableSequencedTaskRunner> storage_task_runner) + scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner) : storage_partition_( raw_ref<StoragePartitionImpl>::from_ptr(storage_partition)), max_pending_events_(max_pending_events), - storage_task_runner_(std::move(storage_task_runner)), - attribution_storage_(base::SequenceBound<AttributionStorageSql>( - storage_task_runner_, + resolver_task_runner_(std::move(resolver_task_runner)), + attribution_resolver_(base::SequenceBound<AttributionResolverImpl>( + resolver_task_runner_, g_run_in_memory ? base::FilePath() : user_data_directory, - std::move(storage_delegate))), + std::move(resolver_delegate))), data_host_manager_( std::make_unique<AttributionDataHostManagerImpl>(this)), special_storage_policy_(std::move(special_storage_policy)), @@ -579,7 +580,7 @@ report_sender_(std::move(report_sender)), os_level_manager_(std::move(os_level_manager)) { DCHECK_GT(max_pending_events_, 0u); - DCHECK(storage_task_runner_); + DCHECK(resolver_task_runner_); DCHECK(cookie_checker_); DCHECK(report_sender_); DCHECK(os_level_manager_); @@ -694,7 +695,8 @@ std::exchange(trigger.registration().debug_key, std::nullopt); } - attribution_storage_.AsyncCall(&AttributionStorage::MaybeCreateAndStoreReport) + attribution_resolver_ + .AsyncCall(&AttributionResolver::MaybeCreateAndStoreReport) .WithArgs(std::move(trigger)) .Then(base::BindOnce(&AttributionManagerImpl::OnReportStored, weak_factory_.GetWeakPtr(), cleared_debug_key, @@ -842,7 +844,7 @@ std::exchange(source.registration().debug_key, std::nullopt); } - attribution_storage_.AsyncCall(&AttributionStorage::StoreSource) + attribution_resolver_.AsyncCall(&AttributionResolver::StoreSource) .WithArgs(std::move(source)) .Then(base::BindOnce(&AttributionManagerImpl::OnSourceStored, weak_factory_.GetWeakPtr(), cleared_debug_key)); @@ -944,7 +946,7 @@ OnUserVisibleTaskStarted(); const int kMaxSources = 1000; - attribution_storage_.AsyncCall(&AttributionStorage::GetActiveSources) + attribution_resolver_.AsyncCall(&AttributionResolver::GetActiveSources) .WithArgs(kMaxSources) .Then(std::move(callback).Then( base::BindOnce(&AttributionManagerImpl::OnUserVisibleTaskComplete, @@ -956,7 +958,7 @@ base::OnceCallback<void(std::vector<AttributionReport>)> callback) { OnUserVisibleTaskStarted(); - attribution_storage_.AsyncCall(&AttributionStorage::GetAttributionReports) + attribution_resolver_.AsyncCall(&AttributionResolver::GetAttributionReports) .WithArgs(/*max_report_time=*/base::Time::Max(), limit) .Then(std::move(callback).Then( base::BindOnce(&AttributionManagerImpl::OnUserVisibleTaskComplete, @@ -978,7 +980,7 @@ base::BindOnce(&AttributionManagerImpl::OnUserVisibleTaskComplete, weak_factory_.GetWeakPtr())); - attribution_storage_.AsyncCall(&AttributionStorage::GetReport) + attribution_resolver_.AsyncCall(&AttributionResolver::GetReport) .WithArgs(id) .Then(base::BindOnce(&AttributionManagerImpl::OnGetReportToSendFromWebUI, weak_factory_.GetWeakPtr(), std::move(done))); @@ -1017,7 +1019,7 @@ OnUserVisibleTaskStarted(); } - attribution_storage_.AsyncCall(&AttributionStorage::ClearData) + attribution_resolver_.AsyncCall(&AttributionResolver::ClearData) .WithArgs(delete_begin, delete_end, std::move(filter), delete_rate_limit_data) .Then(std::move(done).Then( @@ -1029,7 +1031,7 @@ void AttributionManagerImpl::OnUserVisibleTaskStarted() { // When a user-visible task is queued or running, we use a higher priority. ++num_pending_user_visible_tasks_; - storage_task_runner_->UpdatePriority(base::TaskPriority::USER_VISIBLE); + resolver_task_runner_->UpdatePriority(base::TaskPriority::USER_VISIBLE); } void AttributionManagerImpl::OnUserVisibleTaskComplete() { @@ -1038,7 +1040,7 @@ // No more user-visible tasks, so we can reset the priority. if (num_pending_user_visible_tasks_ == 0) { - storage_task_runner_->UpdatePriority(base::TaskPriority::BEST_EFFORT); + resolver_task_runner_->UpdatePriority(base::TaskPriority::BEST_EFFORT); } } @@ -1053,7 +1055,7 @@ void AttributionManagerImpl::GetAllDataKeys( base::OnceCallback<void(std::set<DataKey>)> callback) { OnUserVisibleTaskStarted(); - attribution_storage_.AsyncCall(&AttributionStorage::GetAllDataKeys) + attribution_resolver_.AsyncCall(&AttributionResolver::GetAllDataKeys) .Then(std::move(callback).Then( base::BindOnce(&AttributionManagerImpl::OnUserVisibleTaskComplete, weak_factory_.GetWeakPtr()))); @@ -1073,7 +1075,7 @@ OnUserVisibleTaskStarted(); - attribution_storage_.AsyncCall(&AttributionStorage::DeleteByDataKey) + attribution_resolver_.AsyncCall(&AttributionResolver::DeleteByDataKey) .WithArgs(data_key) .Then(std::move(callback).Then(base::BindOnce( &AttributionManagerImpl::OnClearDataComplete, @@ -1089,7 +1091,7 @@ // // TODO(apaseltiner): Consider limiting the number of reports being sent at // once, to avoid pulling an arbitrary number of reports into memory. - attribution_storage_.AsyncCall(&AttributionStorage::GetAttributionReports) + attribution_resolver_.AsyncCall(&AttributionResolver::GetAttributionReports) .WithArgs(/*max_report_time=*/base::Time::Now(), /*limit=*/-1) .Then(base::BindOnce(&AttributionManagerImpl::SendReports, weak_factory_.GetWeakPtr())); @@ -1236,8 +1238,8 @@ new_report_time); if (new_report_time) { - attribution_storage_ - .AsyncCall(&AttributionStorage::UpdateReportForSendFailure) + attribution_resolver_ + .AsyncCall(&AttributionResolver::UpdateReportForSendFailure) .WithArgs(report.id(), *new_report_time) .Then(std::move(then)); @@ -1248,7 +1250,7 @@ NotifyReportSent(/*is_debug_report=*/false, report, info); - attribution_storage_.AsyncCall(&AttributionStorage::DeleteReport) + attribution_resolver_.AsyncCall(&AttributionResolver::DeleteReport) .WithArgs(report.id()) .Then(std::move(then)); @@ -1632,8 +1634,8 @@ // TODO(apaseltiner): Observers should be notified when the debug mode changes // so they can re-query its value. - attribution_storage_.AsyncCall(&AttributionStorage::SetDelegate) - .WithArgs(MakeStorageDelegate(debug_mode)) + attribution_resolver_.AsyncCall(&AttributionResolver::SetDelegate) + .WithArgs(MakeResolverDelegate(debug_mode)) .Then(std::move(done)); } @@ -1698,7 +1700,7 @@ base::BindRepeating( &AttributionManagerImpl::RecordPendingAggregatableReportsTimings, base::Unretained(this)), - attribution_storage_)); + attribution_resolver_)); PrepareNextEvent(); PrepareNextOsEvent();
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.h b/content/browser/attribution_reporting/attribution_manager_impl.h index 9320cf4e..9f41f236 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.h +++ b/content/browser/attribution_reporting/attribution_manager_impl.h
@@ -61,8 +61,8 @@ class AttributionDataHostManager; class AttributionDebugReport; class AttributionOsLevelManager; -class AttributionStorage; -class AttributionStorageDelegate; +class AttributionResolver; +class AttributionResolverDelegate; class CreateReportResult; class StoragePartitionImpl; class StoreSourceResult; @@ -104,12 +104,12 @@ const base::FilePath& user_data_directory, size_t max_pending_events, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, - std::unique_ptr<AttributionStorageDelegate> storage_delegate, + std::unique_ptr<AttributionResolverDelegate> resolver_delegate, std::unique_ptr<AttributionCookieChecker> cookie_checker, std::unique_ptr<AttributionReportSender> report_sender, std::unique_ptr<AttributionOsLevelManager> os_level_manager, StoragePartitionImpl* storage_partition, - scoped_refptr<base::UpdateableSequencedTaskRunner> storage_task_runner); + scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner); AttributionManagerImpl( StoragePartitionImpl* storage_partition, @@ -175,11 +175,11 @@ const base::FilePath& user_data_directory, size_t max_pending_events, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, - std::unique_ptr<AttributionStorageDelegate> storage_delegate, + std::unique_ptr<AttributionResolverDelegate> resolver_delegate, std::unique_ptr<AttributionCookieChecker> cookie_checker, std::unique_ptr<AttributionReportSender> report_sender, std::unique_ptr<AttributionOsLevelManager> os_level_manager, - scoped_refptr<base::UpdateableSequencedTaskRunner> storage_task_runner); + scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner); void MaybeEnqueueEvent(SourceOrTriggerRFH); void PrepareNextEvent(); @@ -282,17 +282,17 @@ // growth with adversarial input. size_t max_pending_events_; - // The task runner for all attribution reporting storage operations. + // The task runner for all operations on the resolver. // Updateable to allow for priority to be temporarily increased to // `USER_VISIBLE` when a user-visible storage task is queued or running. // Otherwise `BEST_EFFORT` is used. - scoped_refptr<base::UpdateableSequencedTaskRunner> storage_task_runner_; + scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner_; // How many user-visible storage tasks are queued or running currently, // i.e. have been posted but the reply has not been run. int num_pending_user_visible_tasks_ = 0; - base::SequenceBound<AttributionStorage> attribution_storage_; + base::SequenceBound<AttributionResolver> attribution_resolver_; std::unique_ptr<ReportSchedulerTimer> scheduler_timer_;
diff --git a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc index 33e5bc5..551327d 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
@@ -57,8 +57,8 @@ #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_report_sender.h" #include "content/browser/attribution_reporting/attribution_reporting.mojom.h" -#include "content/browser/attribution_reporting/attribution_storage.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" #include "content/browser/attribution_reporting/attribution_trigger.h" #include "content/browser/attribution_reporting/common_source_info.h" @@ -135,7 +135,7 @@ constexpr attribution_reporting::Registrar kRegistrar = attribution_reporting::Registrar::kWeb; -constexpr AttributionStorageDelegate::OfflineReportDelayConfig +constexpr AttributionResolverDelegate::OfflineReportDelayConfig kDefaultOfflineReportDelay{ .min = base::Minutes(0), .max = base::Minutes(1), @@ -191,7 +191,7 @@ } // Time after impression that a conversion can first be sent. See -// AttributionStorageDelegateImpl::GetReportTimeForConversion(). +// AttributionResolverDelegateImpl::GetReportTimeForConversion(). constexpr base::TimeDelta kFirstReportingWindow = base::Days(2); // Give impressions a sufficiently long expiry. @@ -817,7 +817,7 @@ // Simulate startup and ensure the report is sent before being expired. // Advance by the max offline report delay, per - // `AttributionStorageDelegate::GetOfflineReportDelayConfig()`. + // `AttributionResolverDelegate::GetOfflineReportDelayConfig()`. CreateManager(); EXPECT_CALL(*report_sender_, SendReport(_, /*is_debug_report=*/false, _)); @@ -996,7 +996,7 @@ } } -// This functionality is tested more thoroughly in the AttributionStorageSql +// This functionality is tested more thoroughly in the AttributionResolverImpl // unit tests. Here, just test to make sure the basic control flow is working. TEST_F(AttributionManagerImplTest, ClearDataFromBrowserOnly) { for (bool match_url : {true, false}) { @@ -1378,7 +1378,7 @@ // Ensure that the expired report is delayed based on the time the browser // started and the min and max offline report delays, per - // `AttributionStorageDelegate::GetOfflineReportDelayConfig()`. + // `AttributionResolverDelegate::GetOfflineReportDelayConfig()`. base::Time min_new_time = base::Time::Now(); EXPECT_THAT(StoredReports(), ElementsAre(ReportTimeIs( @@ -1834,7 +1834,7 @@ void ConfigureStorageDelegate( ConfigurableStorageDelegate& delegate) const override { delegate.set_offline_report_delay_config( - AttributionStorageDelegate::OfflineReportDelayConfig{ + AttributionResolverDelegate::OfflineReportDelayConfig{ .min = base::Minutes(1), .max = base::Minutes(1), }); @@ -1850,7 +1850,7 @@ // Deliberately avoid running tasks so that the connection change and time // advance can be "atomic", which is necessary because - // `AttributionStorage::AdjustOfflineReportTimes()` only adjusts times for + // `AttributionResolver::AdjustOfflineReportTimes()` only adjusts times for // reports that should have been sent before now. In other words, the call to // `AdjustOfflineReportTimes()` would have no effect if we used // `FastForwardBy()` here, and we wouldn't be able to detect it below.
diff --git a/content/browser/attribution_reporting/attribution_storage.h b/content/browser/attribution_reporting/attribution_resolver.h similarity index 80% rename from content/browser/attribution_reporting/attribution_storage.h rename to content/browser/attribution_reporting/attribution_resolver.h index 0429848..8266420c 100644 --- a/content/browser/attribution_reporting/attribution_storage.h +++ b/content/browser/attribution_reporting/attribution_resolver.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_H_ -#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_H_ +#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_H_ +#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_H_ #include <memory> #include <optional> @@ -21,7 +21,7 @@ namespace content { -class AttributionStorageDelegate; +class AttributionResolverDelegate; class AttributionTrigger; class CreateReportResult; class StorableSource; @@ -29,15 +29,15 @@ class StoredSource; // This class provides an interface for persisting attribution data to -// disk, and performing queries on it. AttributionStorage should initialize -// itself. Calls to a AttributionStorage instance that failed to initialize +// disk, and performing queries on it. AttributionResolver should initialize +// itself. Calls to a AttributionResolver instance that failed to initialize // properly should result in no-ops. -class AttributionStorage { +class AttributionResolver { public: - virtual ~AttributionStorage() = default; + virtual ~AttributionResolver() = default; // When adding a new method, also add it to - // AttributionStorageTest.StorageUsedAfterFailedInitilization_FailsSilently. + // AttributionResolverTest.StorageUsedAfterFailedInitilization_FailsSilently. // Add |source| to storage. Two sources are considered // matching when they share a <reporting origin, attribution destination> @@ -46,15 +46,14 @@ // Unconverted matching sources are not modified. virtual StoreSourceResult StoreSource(StorableSource source) = 0; - // Finds all stored sources matching a given `trigger`, and stores the + // Finds all stored sources matching a given `trigger`, and creates a // new associated report. Only active sources will receive new attributions. // Returns whether a new report has been scheduled/added to storage. virtual CreateReportResult MaybeCreateAndStoreReport(AttributionTrigger) = 0; // Returns all of the reports that should be sent before - // |max_report_time|. This call is logically const, and does not modify the - // underlying storage. |limit| limits the number of reports to return; use - // a negative number for no limit. Reports are shuffled before being returned. + // |max_report_time|. |limit| limits the number of reports to return; use + // a negative number for no limit. Reports are shuffled before being returned. This call is logically const and does not mutate reports. virtual std::vector<AttributionReport> GetAttributionReports( base::Time max_report_time, int limit = -1) = 0; @@ -63,7 +62,7 @@ virtual std::optional<base::Time> GetNextReportTime(base::Time time) = 0; // Returns the report with the given ID. This call is logically const, and - // does not modify the underlying storage. + // does not mutate reports. virtual std::optional<AttributionReport> GetReport(AttributionReport::Id) = 0; // Returns all active sources in storage. Active sources are all @@ -79,7 +78,7 @@ // in the event of an error. virtual std::set<AttributionDataModel::DataKey> GetAllDataKeys() = 0; - // Deletes all data in storage for storage keys matching the provided + // Deletes all data for storage keys matching the provided // reporting origin in the data key. virtual void DeleteByDataKey(const AttributionDataModel::DataKey&) = 0; @@ -96,7 +95,7 @@ // Adjusts the report time of all reports that should have been sent while the // browser was offline, according to - // `AttributionStorageDelegate::GetOfflineReportDelayConfig()`. If that + // `AttributionResolverDelegate::GetOfflineReportDelayConfig()`. If that // method returns null, no delay is applied. Otherwise, applies a random value // between `min_delay` and `max_delay`, both inclusive. Returns the new first // report time in storage, if any. @@ -118,9 +117,9 @@ StoragePartition::StorageKeyMatcherFunction filter, bool delete_rate_limit_data = true) = 0; - virtual void SetDelegate(std::unique_ptr<AttributionStorageDelegate>) = 0; + virtual void SetDelegate(std::unique_ptr<AttributionResolverDelegate>) = 0; }; } // namespace content -#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_H_ +#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_H_
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate.cc b/content/browser/attribution_reporting/attribution_resolver_delegate.cc similarity index 74% rename from content/browser/attribution_reporting/attribution_storage_delegate.cc rename to content/browser/attribution_reporting/attribution_resolver_delegate.cc index 804397b..b657ab3 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate.cc +++ b/content/browser/attribution_reporting/attribution_resolver_delegate.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" #include "base/check.h" #include "base/notreached.h" @@ -17,20 +17,20 @@ } // namespace -AttributionStorageDelegate::AttributionStorageDelegate( +AttributionResolverDelegate::AttributionResolverDelegate( const AttributionConfig& config) : config_(config) { DCHECK(config_.Validate()); } -AttributionStorageDelegate::~AttributionStorageDelegate() = default; +AttributionResolverDelegate::~AttributionResolverDelegate() = default; -int AttributionStorageDelegate::GetMaxSourcesPerOrigin() const { +int AttributionResolverDelegate::GetMaxSourcesPerOrigin() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return config_.max_sources_per_origin; } -int AttributionStorageDelegate::GetMaxReportsPerDestination( +int AttributionResolverDelegate::GetMaxReportsPerDestination( attribution_reporting::mojom::ReportType report_type) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); switch (report_type) { @@ -43,19 +43,19 @@ } } -int AttributionStorageDelegate::GetMaxDestinationsPerSourceSiteReportingSite() +int AttributionResolverDelegate::GetMaxDestinationsPerSourceSiteReportingSite() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return config_.max_destinations_per_source_site_reporting_site; } const AttributionConfig::RateLimitConfig& -AttributionStorageDelegate::GetRateLimits() const { +AttributionResolverDelegate::GetRateLimits() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return config_.rate_limit; } -double AttributionStorageDelegate::GetMaxChannelCapacity( +double AttributionResolverDelegate::GetMaxChannelCapacity( SourceType source_type) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); switch (source_type) { @@ -66,19 +66,19 @@ } } -absl::uint128 AttributionStorageDelegate::GetMaxTriggerStateCardinality() +absl::uint128 AttributionResolverDelegate::GetMaxTriggerStateCardinality() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return config_.event_level_limit.max_trigger_state_cardinality; } -int AttributionStorageDelegate::GetMaxAggregatableReportsPerSource() const { +int AttributionResolverDelegate::GetMaxAggregatableReportsPerSource() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return config_.aggregate_limit.max_aggregatable_reports_per_source; } AttributionConfig::DestinationRateLimit -AttributionStorageDelegate::GetDestinationRateLimit() const { +AttributionResolverDelegate::GetDestinationRateLimit() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return config_.destination_rate_limit; }
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate.h b/content/browser/attribution_reporting/attribution_resolver_delegate.h similarity index 88% rename from content/browser/attribution_reporting/attribution_storage_delegate.h rename to content/browser/attribution_reporting/attribution_resolver_delegate.h index f2df3ea..450435ff 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate.h +++ b/content/browser/attribution_reporting/attribution_resolver_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_DELEGATE_H_ -#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_DELEGATE_H_ +#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_DELEGATE_H_ +#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_DELEGATE_H_ #include <stdint.h> @@ -40,11 +40,11 @@ class AttributionReport; -// Storage delegate that can supplied to extend basic attribution storage +// Resolver delegate that can supplied to extend basic attribution storage // functionality like annotating reports. Users and subclasses must NOT assume // that the delegate has the same lifetime as the `AttributionManager` or -// `AttributionStorage` classes. -class CONTENT_EXPORT AttributionStorageDelegate { +// `AttributionResolver` classes. +class CONTENT_EXPORT AttributionResolverDelegate { public: // Both bounds are inclusive. struct OfflineReportDelayConfig { @@ -52,16 +52,16 @@ base::TimeDelta max; }; - explicit AttributionStorageDelegate(const AttributionConfig& config); + explicit AttributionResolverDelegate(const AttributionConfig& config); - virtual ~AttributionStorageDelegate(); + virtual ~AttributionResolverDelegate(); - AttributionStorageDelegate(const AttributionStorageDelegate&) = delete; - AttributionStorageDelegate& operator=(const AttributionStorageDelegate&) = + AttributionResolverDelegate(const AttributionResolverDelegate&) = delete; + AttributionResolverDelegate& operator=(const AttributionResolverDelegate&) = delete; - AttributionStorageDelegate(AttributionStorageDelegate&&) = delete; - AttributionStorageDelegate& operator=(AttributionStorageDelegate&&) = delete; + AttributionResolverDelegate(AttributionResolverDelegate&&) = delete; + AttributionResolverDelegate& operator=(AttributionResolverDelegate&&) = delete; // Returns the time an event-level report should be sent for a given trigger // time and its corresponding source. @@ -174,4 +174,4 @@ } // namespace content -#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_DELEGATE_H_ +#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_DELEGATE_H_
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc b/content/browser/attribution_reporting/attribution_resolver_delegate_impl.cc similarity index 82% rename from content/browser/attribution_reporting/attribution_storage_delegate_impl.cc rename to content/browser/attribution_reporting/attribution_resolver_delegate_impl.cc index 53924d5..706e73d 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc +++ b/content/browser/attribution_reporting/attribution_resolver_delegate_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/attribution_reporting/attribution_storage_delegate_impl.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate_impl.h" #include <stddef.h> #include <stdint.h> @@ -42,47 +42,47 @@ } // namespace // static -std::unique_ptr<AttributionStorageDelegate> -AttributionStorageDelegateImpl::CreateForTesting( +std::unique_ptr<AttributionResolverDelegate> +AttributionResolverDelegateImpl::CreateForTesting( AttributionNoiseMode noise_mode, AttributionDelayMode delay_mode, const AttributionConfig& config) { return base::WrapUnique( - new AttributionStorageDelegateImpl(noise_mode, delay_mode, config)); + new AttributionResolverDelegateImpl(noise_mode, delay_mode, config)); } -AttributionStorageDelegateImpl::AttributionStorageDelegateImpl( +AttributionResolverDelegateImpl::AttributionResolverDelegateImpl( AttributionNoiseMode noise_mode, AttributionDelayMode delay_mode) - : AttributionStorageDelegateImpl(noise_mode, + : AttributionResolverDelegateImpl(noise_mode, delay_mode, AttributionConfig()) {} -AttributionStorageDelegateImpl::AttributionStorageDelegateImpl( +AttributionResolverDelegateImpl::AttributionResolverDelegateImpl( AttributionNoiseMode noise_mode, AttributionDelayMode delay_mode, const AttributionConfig& config) - : AttributionStorageDelegate(config), + : AttributionResolverDelegate(config), noise_mode_(noise_mode), delay_mode_(delay_mode) { DETACH_FROM_SEQUENCE(sequence_checker_); } -AttributionStorageDelegateImpl::~AttributionStorageDelegateImpl() = default; +AttributionResolverDelegateImpl::~AttributionResolverDelegateImpl() = default; base::TimeDelta -AttributionStorageDelegateImpl::GetDeleteExpiredSourcesFrequency() const { +AttributionResolverDelegateImpl::GetDeleteExpiredSourcesFrequency() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return base::Minutes(5); } base::TimeDelta -AttributionStorageDelegateImpl::GetDeleteExpiredRateLimitsFrequency() const { +AttributionResolverDelegateImpl::GetDeleteExpiredRateLimitsFrequency() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return base::Minutes(5); } -base::Time AttributionStorageDelegateImpl::GetEventLevelReportTime( +base::Time AttributionResolverDelegateImpl::GetEventLevelReportTime( const attribution_reporting::EventReportWindows& event_report_windows, base::Time source_time, base::Time trigger_time) const { @@ -96,7 +96,7 @@ } } -base::Time AttributionStorageDelegateImpl::GetAggregatableReportTime( +base::Time AttributionResolverDelegateImpl::GetAggregatableReportTime( base::Time trigger_time) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -116,13 +116,13 @@ } } -base::Uuid AttributionStorageDelegateImpl::NewReportID() const { +base::Uuid AttributionResolverDelegateImpl::NewReportID() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return base::Uuid::GenerateRandomV4(); } -std::optional<AttributionStorageDelegate::OfflineReportDelayConfig> -AttributionStorageDelegateImpl::GetOfflineReportDelayConfig() const { +std::optional<AttributionResolverDelegate::OfflineReportDelayConfig> +AttributionResolverDelegateImpl::GetOfflineReportDelayConfig() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (noise_mode_ == AttributionNoiseMode::kDefault && @@ -142,7 +142,7 @@ return std::nullopt; } -void AttributionStorageDelegateImpl::ShuffleReports( +void AttributionResolverDelegateImpl::ShuffleReports( std::vector<AttributionReport>& reports) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -155,7 +155,7 @@ } } -void AttributionStorageDelegateImpl::ShuffleTriggerVerifications( +void AttributionResolverDelegateImpl::ShuffleTriggerVerifications( std::vector<network::TriggerVerification>& verifications) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -168,7 +168,7 @@ } } -double AttributionStorageDelegateImpl::GetRandomizedResponseRate( +double AttributionResolverDelegateImpl::GetRandomizedResponseRate( const attribution_reporting::TriggerSpecs& trigger_specs, attribution_reporting::MaxEventLevelReports max_event_level_reports, attribution_reporting::EventLevelEpsilon epsilon) const { @@ -177,8 +177,8 @@ GetNumStates(trigger_specs, max_event_level_reports), epsilon); } -AttributionStorageDelegate::GetRandomizedResponseResult -AttributionStorageDelegateImpl::GetRandomizedResponse( +AttributionResolverDelegate::GetRandomizedResponseResult +AttributionResolverDelegateImpl::GetRandomizedResponse( SourceType source_type, const attribution_reporting::TriggerSpecs& trigger_specs, attribution_reporting::MaxEventLevelReports max_event_level_reports, @@ -204,7 +204,7 @@ return response; } -bool AttributionStorageDelegateImpl:: +bool AttributionResolverDelegateImpl:: GenerateNullAggregatableReportForLookbackDay( int lookback_day, attribution_reporting::mojom::SourceRegistrationTimeConfig
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.h b/content/browser/attribution_reporting/attribution_resolver_delegate_impl.h similarity index 74% rename from content/browser/attribution_reporting/attribution_storage_delegate_impl.h rename to content/browser/attribution_reporting/attribution_resolver_delegate_impl.h index 582e8fa..3f3ba33 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.h +++ b/content/browser/attribution_reporting/attribution_resolver_delegate_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_DELEGATE_IMPL_H_ -#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_DELEGATE_IMPL_H_ +#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_DELEGATE_IMPL_H_ +#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_DELEGATE_IMPL_H_ #include <stdint.h> @@ -12,7 +12,7 @@ #include "base/thread_annotations.h" #include "components/attribution_reporting/source_type.mojom-forward.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" #include "content/common/content_export.h" namespace base { @@ -48,30 +48,30 @@ // Implementation of the storage delegate. This class handles assigning // report times to newly created reports. It -// also controls constants for AttributionStorage. This is owned by +// also controls constants for AttributionResolver. This is owned by // AttributionStorageSql, and should only be accessed on the attribution storage // task runner. -class CONTENT_EXPORT AttributionStorageDelegateImpl - : public AttributionStorageDelegate { +class CONTENT_EXPORT AttributionResolverDelegateImpl + : public AttributionResolverDelegate { public: - static std::unique_ptr<AttributionStorageDelegate> CreateForTesting( + static std::unique_ptr<AttributionResolverDelegate> CreateForTesting( AttributionNoiseMode noise_mode, AttributionDelayMode delay_mode, const AttributionConfig& config); - explicit AttributionStorageDelegateImpl( + explicit AttributionResolverDelegateImpl( AttributionNoiseMode noise_mode = AttributionNoiseMode::kDefault, AttributionDelayMode delay_mode = AttributionDelayMode::kDefault); - AttributionStorageDelegateImpl(const AttributionStorageDelegateImpl&) = + AttributionResolverDelegateImpl(const AttributionResolverDelegateImpl&) = delete; - AttributionStorageDelegateImpl& operator=( - const AttributionStorageDelegateImpl&) = delete; - AttributionStorageDelegateImpl(AttributionStorageDelegateImpl&&) = delete; - AttributionStorageDelegateImpl& operator=(AttributionStorageDelegateImpl&&) = + AttributionResolverDelegateImpl& operator=( + const AttributionResolverDelegateImpl&) = delete; + AttributionResolverDelegateImpl(AttributionResolverDelegateImpl&&) = delete; + AttributionResolverDelegateImpl& operator=(AttributionResolverDelegateImpl&&) = delete; - ~AttributionStorageDelegateImpl() override; + ~AttributionResolverDelegateImpl() override; - // AttributionStorageDelegate: + // AttributionResolverDelegate: base::Time GetEventLevelReportTime( const attribution_reporting::EventReportWindows& event_report_windows, base::Time source_time, @@ -100,7 +100,7 @@ const override; protected: - AttributionStorageDelegateImpl(AttributionNoiseMode noise_mode, + AttributionResolverDelegateImpl(AttributionNoiseMode noise_mode, AttributionDelayMode delay_mode, const AttributionConfig& config); @@ -111,4 +111,4 @@ } // namespace content -#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_DELEGATE_IMPL_H_ +#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_DELEGATE_IMPL_H_
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc b/content/browser/attribution_reporting/attribution_resolver_delegate_impl_unittest.cc similarity index 84% rename from content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc rename to content/browser/attribution_reporting/attribution_resolver_delegate_impl_unittest.cc index f030460..9bed2c6 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_resolver_delegate_impl_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/attribution_reporting/attribution_storage_delegate_impl.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate_impl.h" #include <stdint.h> @@ -36,30 +36,30 @@ // This is more comprehensively tested in // //components/attribution_reporting/event_report_windows_unittest.cc. -TEST(AttributionStorageDelegateImplTest, GetEventLevelReportTime) { +TEST(AttributionResolverDelegateImplTest, GetEventLevelReportTime) { constexpr base::Time kSourceTime; constexpr base::Time kTriggerTime = kSourceTime + base::Seconds(1); constexpr base::TimeDelta kEnd = base::Days(3); EXPECT_EQ(kSourceTime + kEnd, - AttributionStorageDelegateImpl().GetEventLevelReportTime( + AttributionResolverDelegateImpl().GetEventLevelReportTime( *EventReportWindows::Create(/*start_time=*/base::Seconds(0), /*end_times=*/{kEnd}), kSourceTime, kTriggerTime)); } -TEST(AttributionStorageDelegateImplTest, GetAggregatableReportTime) { +TEST(AttributionResolverDelegateImplTest, GetAggregatableReportTime) { base::Time trigger_time = base::Time::Now(); EXPECT_THAT( - AttributionStorageDelegateImpl().GetAggregatableReportTime(trigger_time), + AttributionResolverDelegateImpl().GetAggregatableReportTime(trigger_time), AllOf(Ge(trigger_time), Lt(trigger_time + base::Minutes(10)))); } -TEST(AttributionStorageDelegateImplTest, NewReportID_IsValidGUID) { - EXPECT_TRUE(AttributionStorageDelegateImpl().NewReportID().is_valid()); +TEST(AttributionResolverDelegateImplTest, NewReportID_IsValidGUID) { + EXPECT_TRUE(AttributionResolverDelegateImpl().NewReportID().is_valid()); } -TEST(AttributionStorageDelegateImplTest, +TEST(AttributionResolverDelegateImplTest, RandomizedResponse_NoNoiseModeReturnsRealRateAndNullResponse) { for (auto source_type : {SourceType::kNavigation, SourceType::kEvent}) { const auto source = @@ -72,7 +72,7 @@ : 1) .BuildStored(); - auto result = AttributionStorageDelegateImpl(AttributionNoiseMode::kNone) + auto result = AttributionResolverDelegateImpl(AttributionNoiseMode::kNone) .GetRandomizedResponse(source.common_info().source_type(), source.trigger_specs(), source.max_event_level_reports(), @@ -83,7 +83,7 @@ } } -TEST(AttributionStorageDelegateImplTest, +TEST(AttributionResolverDelegateImplTest, RandomizedResponse_ExceedsLimit_ReturnsError) { const struct { SourceType source_type; @@ -120,7 +120,7 @@ config.event_level_limit.max_event_info_gain = test_case.max_event_info_gain; - auto delegate = AttributionStorageDelegateImpl::CreateForTesting( + auto delegate = AttributionResolverDelegateImpl::CreateForTesting( AttributionNoiseMode::kDefault, AttributionDelayMode::kDefault, config); const auto source =
diff --git a/content/browser/attribution_reporting/attribution_resolver_impl.cc b/content/browser/attribution_reporting/attribution_resolver_impl.cc new file mode 100644 index 0000000..83f29c0e --- /dev/null +++ b/content/browser/attribution_reporting/attribution_resolver_impl.cc
@@ -0,0 +1,112 @@ +// 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 "content/browser/attribution_reporting/attribution_resolver_impl.h" + +#include <memory> + +#include "base/check.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" +#include "content/browser/attribution_reporting/attribution_storage_sql.h" +#include "content/browser/attribution_reporting/create_report_result.h" +#include "content/browser/attribution_reporting/storable_source.h" +#include "content/browser/attribution_reporting/store_source_result.h" + +namespace content { + +AttributionResolverImpl::AttributionResolverImpl( + const base::FilePath& user_data_directory, + std::unique_ptr<AttributionResolverDelegate> delegate) + : delegate_(std::move(delegate)), + storage_(user_data_directory, delegate_.get()) { + DCHECK(delegate_); +} + +AttributionResolverImpl::~AttributionResolverImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +StoreSourceResult AttributionResolverImpl::StoreSource(StorableSource source) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.StoreSource(std::move(source)); +} + +CreateReportResult AttributionResolverImpl::MaybeCreateAndStoreReport( + AttributionTrigger trigger) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.MaybeCreateAndStoreReport(std::move(trigger)); +} + +std::vector<AttributionReport> AttributionResolverImpl::GetAttributionReports( + base::Time max_report_time, + int limit) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.GetAttributionReports(max_report_time, limit); +} + +std::optional<base::Time> AttributionResolverImpl::GetNextReportTime( + base::Time time) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.GetNextReportTime(time); +} + +std::optional<AttributionReport> AttributionResolverImpl::GetReport( + AttributionReport::Id id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.GetReport(id); +} + +std::vector<StoredSource> AttributionResolverImpl::GetActiveSources(int limit) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.GetActiveSources(limit); +} + +std::set<AttributionDataModel::DataKey> +AttributionResolverImpl::GetAllDataKeys() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.GetAllDataKeys(); +} + +void AttributionResolverImpl::DeleteByDataKey( + const AttributionDataModel::DataKey& datakey) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + storage_.DeleteByDataKey(datakey); +} + +bool AttributionResolverImpl::DeleteReport(AttributionReport::Id report_id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.DeleteReport(report_id); +} + +bool AttributionResolverImpl::UpdateReportForSendFailure( + AttributionReport::Id report_id, + base::Time new_report_time) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.UpdateReportForSendFailure(report_id, new_report_time); +} + +std::optional<base::Time> AttributionResolverImpl::AdjustOfflineReportTimes() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return storage_.AdjustOfflineReportTimes(); +} + +void AttributionResolverImpl::ClearData( + base::Time delete_begin, + base::Time delete_end, + StoragePartition::StorageKeyMatcherFunction filter, + bool delete_rate_limit_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + storage_.ClearData(delete_begin, delete_end, std::move(filter), + delete_rate_limit_data); +} + +void AttributionResolverImpl::SetDelegate( + std::unique_ptr<AttributionResolverDelegate> delegate) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(delegate); + storage_.SetDelegate(delegate.get()); + delegate_ = std::move(delegate); +} + +} // namespace content
diff --git a/content/browser/attribution_reporting/attribution_resolver_impl.h b/content/browser/attribution_reporting/attribution_resolver_impl.h new file mode 100644 index 0000000..955af17 --- /dev/null +++ b/content/browser/attribution_reporting/attribution_resolver_impl.h
@@ -0,0 +1,88 @@ +// 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 CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_IMPL_H_ +#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_IMPL_H_ + +#include <stdint.h> + +#include <memory> +#include <optional> +#include <string> +#include <vector> + +#include "base/containers/enum_set.h" +#include "base/files/file_path.h" +#include "base/sequence_checker.h" +#include "base/thread_annotations.h" +#include "base/time/time.h" +#include "base/types/expected.h" +#include "content/browser/attribution_reporting/attribution_report.h" +#include "content/browser/attribution_reporting/attribution_resolver.h" +#include "content/browser/attribution_reporting/attribution_storage_sql.h" +#include "content/browser/attribution_reporting/attribution_trigger.h" +#include "content/browser/attribution_reporting/rate_limit_result.h" +#include "content/browser/attribution_reporting/stored_source.h" +#include "content/common/content_export.h" +#include "content/public/browser/attribution_data_model.h" +#include "content/public/browser/storage_partition.h" + +namespace content { + +class AttributionResolverDelegate; +class StorableSource; +struct AttributionInfo; + +// This class may be constructed on any sequence but must be accessed and +// destroyed on the same sequence. The sequence must outlive |this|. +class CONTENT_EXPORT AttributionResolverImpl : public AttributionResolver { + public: + AttributionResolverImpl( + const base::FilePath& user_data_directory, + std::unique_ptr<AttributionResolverDelegate> delegate); + AttributionResolverImpl(const AttributionResolverImpl&) = delete; + AttributionResolverImpl& operator=(const AttributionResolverImpl&) = delete; + AttributionResolverImpl(AttributionResolverImpl&&) = delete; + AttributionResolverImpl& operator=(AttributionResolverImpl&&) = delete; + ~AttributionResolverImpl() override; + + void set_ignore_errors_for_testing(bool ignore_for_testing) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + storage_.set_ignore_errors_for_testing(ignore_for_testing); + } + + private: + // AttributionResolver: + StoreSourceResult StoreSource(StorableSource source) override; + CreateReportResult MaybeCreateAndStoreReport( + AttributionTrigger trigger) override; + std::vector<AttributionReport> GetAttributionReports( + base::Time max_report_time, + int limit = -1) override; + std::optional<base::Time> GetNextReportTime(base::Time time) override; + std::optional<AttributionReport> GetReport(AttributionReport::Id) override; + std::vector<StoredSource> GetActiveSources(int limit = -1) override; + std::set<AttributionDataModel::DataKey> GetAllDataKeys() override; + void DeleteByDataKey(const AttributionDataModel::DataKey& datakey) override; + bool DeleteReport(AttributionReport::Id report_id) override; + bool UpdateReportForSendFailure(AttributionReport::Id report_id, + base::Time new_report_time) override; + std::optional<base::Time> AdjustOfflineReportTimes() override; + void ClearData(base::Time delete_begin, + base::Time delete_end, + StoragePartition::StorageKeyMatcherFunction filter, + bool delete_rate_limit_data) override; + void SetDelegate(std::unique_ptr<AttributionResolverDelegate>) override; + + std::unique_ptr<AttributionResolverDelegate> delegate_ + GUARDED_BY_CONTEXT(sequence_checker_); + + AttributionStorageSql storage_ GUARDED_BY_CONTEXT(sequence_checker_); + + SEQUENCE_CHECKER(sequence_checker_); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_RESOLVER_IMPL_H_
diff --git a/content/browser/attribution_reporting/attribution_storage_unittest.cc b/content/browser/attribution_reporting/attribution_resolver_unittest.cc similarity index 95% rename from content/browser/attribution_reporting/attribution_storage_unittest.cc rename to content/browser/attribution_reporting/attribution_resolver_unittest.cc index b3a645b8..f1648ac0 100644 --- a/content/browser/attribution_reporting/attribution_storage_unittest.cc +++ b/content/browser/attribution_reporting/attribution_resolver_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/attribution_reporting/attribution_storage.h" +#include "content/browser/attribution_reporting/attribution_resolver.h" #include <stdint.h> @@ -45,6 +45,7 @@ #include "components/attribution_reporting/trigger_registration.h" #include "content/browser/attribution_reporting/attribution_features.h" #include "content/browser/attribution_reporting/attribution_report.h" +#include "content/browser/attribution_reporting/attribution_resolver_impl.h" #include "content/browser/attribution_reporting/attribution_storage_sql.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" #include "content/browser/attribution_reporting/attribution_trigger.h" @@ -135,16 +136,16 @@ } // namespace -// Unit test suite for the AttributionStorage interface. All AttributionStorage +// Unit test suite for the AttributionResolver interface. All AttributionResolver // implementations (including fakes) should be able to re-use this test suite. -class AttributionStorageTest : public testing::Test { +class AttributionResolverTest : public testing::Test { public: - AttributionStorageTest() { + AttributionResolverTest() { EXPECT_TRUE(dir_.CreateUniqueTempDir()); auto delegate = std::make_unique<ConfigurableStorageDelegate>(); delegate->set_report_delay(kReportDelay); delegate_ = delegate.get(); - storage_ = std::make_unique<AttributionStorageSql>(dir_.GetPath(), + storage_ = std::make_unique<AttributionResolverImpl>(dir_.GetPath(), std::move(delegate)); } @@ -179,7 +180,7 @@ } } - AttributionStorage* storage() { return storage_.get(); } + AttributionResolver* storage() { return storage_.get(); } ConfigurableStorageDelegate* delegate() { return delegate_; } @@ -189,23 +190,23 @@ base::ScopedTempDir dir_; private: - std::unique_ptr<AttributionStorage> storage_; + std::unique_ptr<AttributionResolver> storage_; raw_ptr<ConfigurableStorageDelegate> delegate_; }; -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, StorageUsedAfterFailedInitilization_FailsSilently) { // We create a failed initialization by writing a dir to the database file // path. base::CreateDirectoryAndGetError( dir_.GetPath().Append(FILE_PATH_LITERAL("Conversions")), nullptr); - std::unique_ptr<AttributionStorage> storage = - std::make_unique<AttributionStorageSql>( + std::unique_ptr<AttributionResolver> storage = + std::make_unique<AttributionResolverImpl>( dir_.GetPath(), std::make_unique<ConfigurableStorageDelegate>()); - static_cast<AttributionStorageSql*>(storage.get()) + static_cast<AttributionResolverImpl*>(storage.get()) ->set_ignore_errors_for_testing(true); - // Test all public methods on AttributionStorage. + // Test all public methods on AttributionResolver. EXPECT_NO_FATAL_FAILURE(storage->StoreSource(SourceBuilder().Build())); EXPECT_EQ(AttributionTrigger::EventLevelResult::kInternalError, storage->MaybeCreateAndStoreReport(DefaultTrigger()) @@ -218,7 +219,7 @@ EXPECT_EQ(storage->AdjustOfflineReportTimes(), std::nullopt); } -TEST_F(AttributionStorageTest, ImpressionStoredAndRetrieved_ValuesIdentical) { +TEST_F(AttributionResolverTest, ImpressionStoredAndRetrieved_ValuesIdentical) { base::HistogramTester histograms; storage()->StoreSource(SourceBuilder().Build()); histograms.ExpectBucketCount("Conversions.DbVersionOnSourceStored", @@ -227,7 +228,7 @@ ElementsAre(SourceBuilder().BuildStored())); } -TEST_F(AttributionStorageTest, UniqueReportWindowsStored_ValuesIdentical) { +TEST_F(AttributionResolverTest, UniqueReportWindowsStored_ValuesIdentical) { base::Time source_time = base::Time::Now(); const auto kTriggerSpecs = @@ -250,7 +251,7 @@ source_time + base::Days(5))))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, GetWithNoMatchingImpressions_NoImpressionsReturned) { EXPECT_THAT( storage()->MaybeCreateAndStoreReport(DefaultTrigger()), @@ -262,20 +263,20 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Now()), IsEmpty()); } -TEST_F(AttributionStorageTest, GetWithMatchingImpression_ImpressionReturned) { +TEST_F(AttributionResolverTest, GetWithMatchingImpression_ImpressionReturned) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, MultipleImpressionsForConversion_OneConverts) { +TEST_F(AttributionResolverTest, MultipleImpressionsForConversion_OneConverts) { storage()->StoreSource(SourceBuilder().Build()); storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, CrossOriginSameDomainConversion_ImpressionConverted) { auto impression = SourceBuilder() @@ -293,7 +294,7 @@ .Build())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ImpressionWithMultipleDestinations_ImpressionConverted) { auto impression = SourceBuilder() .SetDestinationSites( @@ -312,7 +313,7 @@ .Build())); } -TEST_F(AttributionStorageTest, EventSourceImpressionsForConversion_Converts) { +TEST_F(AttributionResolverTest, EventSourceImpressionsForConversion_Converts) { storage()->StoreSource( SourceBuilder().SetSourceType(SourceType::kEvent).Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, @@ -322,7 +323,7 @@ ElementsAre(EventLevelDataIs(_))); } -TEST_F(AttributionStorageTest, ImpressionExpired_NoConversionsStored) { +TEST_F(AttributionResolverTest, ImpressionExpired_NoConversionsStored) { storage()->StoreSource( SourceBuilder().SetExpiry(base::Milliseconds(2)).Build()); task_environment_.FastForwardBy(base::Milliseconds(2)); @@ -331,7 +332,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AggregatableReportWindowPassed_NoReportGenerated) { storage()->StoreSource(TestAggregatableSourceProvider() .GetBuilder() @@ -348,7 +349,7 @@ AttributionTrigger::AggregatableResult::kReportWindowPassed))); } -TEST_F(AttributionStorageTest, ImpressionExpired_ConversionsStoredPrior) { +TEST_F(AttributionResolverTest, ImpressionExpired_ConversionsStoredPrior) { storage()->StoreSource( SourceBuilder().SetExpiry(base::Milliseconds(4)).Build()); @@ -363,7 +364,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ImpressionWithSetMaxConversions_ConversionReportStored) { storage()->StoreSource( SourceBuilder().SetMaxEventLevelReports(kMaxConversions + 1).Build()); @@ -386,7 +387,7 @@ DroppedEventLevelReportIs(Optional(TriggerDebugKeyIs(20u))))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ImpressionWithMaxConversionsSetToZero_NoReportGenerated) { storage()->StoreSource(SourceBuilder().SetMaxEventLevelReports(0).Build()); @@ -394,7 +395,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ImpressionReportWindowNotStarted_NoReportGenerated) { storage()->StoreSource( SourceBuilder() @@ -408,7 +409,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ImpressionReportWindowsPassed_NoReportGenerated) { storage()->StoreSource( SourceBuilder() @@ -424,7 +425,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, OneConversion_OneReportScheduled) { +TEST_F(AttributionResolverTest, OneConversion_OneReportScheduled) { auto conversion = DefaultTrigger(); storage()->StoreSource(SourceBuilder().Build()); @@ -440,7 +441,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Now()), SizeIs(1u)); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ConversionWithDifferentReportingOrigin_NoReportScheduled) { auto impression = SourceBuilder() .SetReportingOrigin(*SuitableOrigin::Deserialize( @@ -453,7 +454,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ConversionWithDifferentConversionOrigin_NoReportScheduled) { auto impression = SourceBuilder() @@ -467,7 +468,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } -TEST_F(AttributionStorageTest, ConversionReportDeleted_RemovedFromStorage) { +TEST_F(AttributionResolverTest, ConversionReportDeleted_RemovedFromStorage) { base::HistogramTester histograms; storage()->StoreSource(SourceBuilder().Build()); @@ -483,7 +484,7 @@ histograms.ExpectTotalCount("Conversions.DbVersionOnReportSentAndDeleted", 1); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ManyImpressionsWithManyConversions_OneImpressionAttributed) { const int kNumMultiTouchImpressions = 20; @@ -504,7 +505,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MultipleImpressionsForConversion_UnattributedImpressionsInactive) { storage()->StoreSource(SourceBuilder().Build()); @@ -526,7 +527,7 @@ // <reporting_origin, destination_origin> pair, all existing impressions for // that origin that have converted are marked ineligible for new conversions per // the multi-touch model. -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, NewImpressionForConvertedImpression_MarkedInactive) { storage()->StoreSource(SourceBuilder().SetSourceEventId(0).Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, @@ -553,7 +554,7 @@ ElementsAre(ReportSourceIs(SourceEventIdIs(1000u)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, NonMatchingImpressionForConvertedImpression_FirstRemainsActive) { auto reporting_origin = SuitableOrigin::Deserialize("https://reporter.test").value(); @@ -580,7 +581,7 @@ ReportOriginIs(reporting_origin))); } -TEST_F(AttributionStorageTest, ImpressionWithDeletedReport_RemainsActive) { +TEST_F(AttributionResolverTest, ImpressionWithDeletedReport_RemainsActive) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); @@ -594,7 +595,7 @@ } TEST_F( - AttributionStorageTest, + AttributionResolverTest, MultipleImpressionsForConversionAtDifferentTimes_OneImpressionAttributed) { storage()->StoreSource(SourceBuilder().Build()); storage()->StoreSource(SourceBuilder().Build()); @@ -614,7 +615,7 @@ ElementsAre(ReportSourceIs(SourceEventIdIs(10)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ImpressionsAtDifferentTimes_AttributedImpressionHasCorrectReportTime) { auto first_impression = SourceBuilder().Build(); storage()->StoreSource(first_impression); @@ -638,7 +639,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Now()), SizeIs(1)); } -TEST_F(AttributionStorageTest, GetAttributionReportsMultipleTimes_SameResult) { +TEST_F(AttributionResolverTest, GetAttributionReportsMultipleTimes_SameResult) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); @@ -653,7 +654,7 @@ EXPECT_EQ(first_call_reports, second_call_reports); } -TEST_F(AttributionStorageTest, ExceedsChannelCapacity_SupersedesRateLimits) { +TEST_F(AttributionResolverTest, ExceedsChannelCapacity_SupersedesRateLimits) { delegate()->set_max_sources_per_origin(1); EXPECT_EQ(storage()->StoreSource(SourceBuilder().Build()).status(), StorableSource::Result::kSuccess); @@ -663,7 +664,7 @@ StorableSource::Result::kExceedsMaxChannelCapacity); } -TEST_F(AttributionStorageTest, MaxImpressionsPerOrigin_LimitsStorage) { +TEST_F(AttributionResolverTest, MaxImpressionsPerOrigin_LimitsStorage) { delegate()->set_max_sources_per_origin(2); base::HistogramTester histograms; @@ -723,7 +724,7 @@ ElementsAre(SourceEventIdIs(5u), SourceEventIdIs(6u))); } -TEST_F(AttributionStorageTest, MaxImpressionsPerOrigin_PerOriginNotSite) { +TEST_F(AttributionResolverTest, MaxImpressionsPerOrigin_PerOriginNotSite) { delegate()->set_max_sources_per_origin(2); storage()->StoreSource(SourceBuilder() .SetSourceOrigin(*SuitableOrigin::Deserialize( @@ -772,7 +773,7 @@ // Regression test for https://crbug.com/1510433 in which expired sources // were erroneously counted during calculation of the sources-per-source-origin // limit check. -TEST_F(AttributionStorageTest, MaxImpressionsPerOrigin_ExpiredSourcesIgnored) { +TEST_F(AttributionResolverTest, MaxImpressionsPerOrigin_ExpiredSourcesIgnored) { delegate()->set_max_sources_per_origin(1); // Effectively prevent expired sources from being deleted/deactivated. @@ -809,7 +810,7 @@ ElementsAre(SourceEventIdIs(222u))); } -TEST_F(AttributionStorageTest, MaxEventLevelReportsPerDestination) { +TEST_F(AttributionResolverTest, MaxEventLevelReportsPerDestination) { SourceBuilder source_builder = TestAggregatableSourceProvider().GetBuilder(); delegate()->set_max_reports_per_destination( @@ -840,7 +841,7 @@ CreateReportMaxAggregatableReportsLimitIs(std::nullopt))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxEventLevelReportsPerDestination_MultipleDestinations) { SourceBuilder source_builder = TestAggregatableSourceProvider().GetBuilder(); @@ -888,7 +889,7 @@ CreateReportMaxAggregatableReportsLimitIs(std::nullopt))); } -TEST_F(AttributionStorageTest, MaxAggregatableReportsPerDestination) { +TEST_F(AttributionResolverTest, MaxAggregatableReportsPerDestination) { SourceBuilder source_builder = TestAggregatableSourceProvider().GetBuilder(); delegate()->set_max_reports_per_destination( @@ -919,7 +920,7 @@ CreateReportMaxAggregatableReportsLimitIs(1))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxAggregatableReportsPerDestination_MultipleDestinations) { SourceBuilder source_builder = TestAggregatableSourceProvider().GetBuilder(); @@ -967,7 +968,7 @@ CreateReportMaxAggregatableReportsLimitIs(1))); } -TEST_F(AttributionStorageTest, ClearDataWithNoMatch_NoDelete) { +TEST_F(AttributionResolverTest, ClearDataWithNoMatch_NoDelete) { base::Time now = base::Time::Now(); storage()->StoreSource(SourceBuilder(now).Build()); storage()->ClearData( @@ -976,7 +977,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, ClearData_SourceAndDestinationOriginsIrrelevant) { const auto origin = *SuitableOrigin::Deserialize("https://a.test"); @@ -997,7 +998,7 @@ EXPECT_EQ(storage()->GetAttributionReports(base::Time::Max()).size(), 1u); } -TEST_F(AttributionStorageTest, ClearDataOutsideRange_NoDelete) { +TEST_F(AttributionResolverTest, ClearDataOutsideRange_NoDelete) { base::Time now = base::Time::Now(); auto impression = SourceBuilder(now).Build(); storage()->StoreSource(impression); @@ -1008,7 +1009,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, ClearDataImpression) { +TEST_F(AttributionResolverTest, ClearDataImpression) { base::Time now = base::Time::Now(); { @@ -1022,7 +1023,7 @@ } } -TEST_F(AttributionStorageTest, ClearDataImpressionConversion) { +TEST_F(AttributionResolverTest, ClearDataImpressionConversion) { base::Time now = base::Time::Now(); auto impression = SourceBuilder(now).Build(); auto conversion = DefaultTrigger(); @@ -1038,7 +1039,7 @@ } // The null filter should match all origins. -TEST_F(AttributionStorageTest, ClearDataNullFilter) { +TEST_F(AttributionResolverTest, ClearDataNullFilter) { base::Time now = base::Time::Now(); for (int i = 0; i < 10; i++) { @@ -1082,7 +1083,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), SizeIs(5)); } -TEST_F(AttributionStorageTest, ClearDataWithImpressionOutsideRange) { +TEST_F(AttributionResolverTest, ClearDataWithImpressionOutsideRange) { base::Time start = base::Time::Now(); auto impression = SourceBuilder(start).SetExpiry(base::Days(30)).Build(); auto conversion = DefaultTrigger(); @@ -1098,7 +1099,7 @@ // Deletions with time range between the impression and conversion should not // delete anything, unless the time range intersects one of the events. -TEST_F(AttributionStorageTest, ClearDataRangeBetweenEvents) { +TEST_F(AttributionResolverTest, ClearDataRangeBetweenEvents) { base::Time start = base::Time::Now(); auto impression = SourceBuilder().SetExpiry(base::Days(30)).Build(); @@ -1119,7 +1120,7 @@ // Test that only a subset of impressions / conversions are deleted with // multiple impressions per conversion, if only a subset of impressions match. -TEST_F(AttributionStorageTest, ClearDataWithMultiTouch) { +TEST_F(AttributionResolverTest, ClearDataWithMultiTouch) { base::Time start = base::Time::Now(); auto impression1 = SourceBuilder(start).SetExpiry(base::Days(30)).Build(); storage()->StoreSource(impression1); @@ -1139,7 +1140,7 @@ } // The max time range with a null filter should delete everything. -TEST_F(AttributionStorageTest, DeleteAll) { +TEST_F(AttributionResolverTest, DeleteAll) { base::Time start = base::Time::Now(); for (int i = 0; i < 10; i++) { storage()->StoreSource( @@ -1162,7 +1163,7 @@ // Same as the above test, but uses base::Time() instead of base::Time::Min() // for delete_begin, which should yield the same behavior. -TEST_F(AttributionStorageTest, DeleteAllNullDeleteBegin) { +TEST_F(AttributionResolverTest, DeleteAllNullDeleteBegin) { base::Time start = base::Time::Now(); for (int i = 0; i < 10; i++) { storage()->StoreSource( @@ -1183,7 +1184,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } -TEST_F(AttributionStorageTest, MaxAttributionsBetweenSites) { +TEST_F(AttributionResolverTest, MaxAttributionsBetweenSites) { base::HistogramTester histogram_tester; delegate()->set_rate_limits([]() { @@ -1265,7 +1266,7 @@ base::Bucket(2, 1))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxAttributionReportsBetweenSites_IgnoresSourceType) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; @@ -1289,7 +1290,7 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, NeverAttributeImpression_EventLevelReportNotStored) { delegate()->set_randomized_response( std::vector<attribution_reporting::FakeEventLevelReport>{}); @@ -1312,7 +1313,7 @@ DefaultAggregatableHistogramContributions())))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AttributeFalseImpression_OtherSourceDeactivated) { storage()->StoreSource(SourceBuilder().SetSourceEventId(7).Build()); @@ -1333,7 +1334,7 @@ EXPECT_THAT(storage()->GetActiveSources(), ElementsAre(SourceEventIdIs(5u))); } -TEST_F(AttributionStorageTest, NeverAttributeImpression_RateLimitsChanged) { +TEST_F(AttributionResolverTest, NeverAttributeImpression_RateLimitsChanged) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; r.time_window = base::TimeDelta::Max(); @@ -1361,7 +1362,7 @@ AttributionTrigger::AggregatableResult::kSuccess))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, NeverAndTruthfullyAttributeImpressions_EventLevelReportNotStored) { TestAggregatableSourceProvider provider; @@ -1400,7 +1401,7 @@ AggregatableHistogramContributionsAre(contributions)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxDestinationsPerSource_ScopedToSourceSiteAndReportingSite) { delegate()->set_max_destinations_per_source_site_reporting_site(3); @@ -1449,7 +1450,7 @@ EXPECT_THAT(storage()->GetActiveSources(), SizeIs(6)); } -TEST_F(AttributionStorageTest, DestinationLimit_ApplyLimit) { +TEST_F(AttributionResolverTest, DestinationLimit_ApplyLimit) { delegate()->set_max_destinations_per_source_site_reporting_site(1); delegate()->set_delete_expired_sources_frequency(base::Milliseconds(10)); @@ -1504,7 +1505,7 @@ StorableSource::Result::kSuccess); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxAttributionDestinationsPerSource_AppliesToNavigationSources) { delegate()->set_max_destinations_per_source_site_reporting_site(1); storage()->StoreSource( @@ -1521,7 +1522,7 @@ EXPECT_THAT(storage()->GetActiveSources(), SizeIs(1)); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxAttributionDestinationsPerSource_CountsAllSourceTypes) { delegate()->set_max_destinations_per_source_site_reporting_site(1); storage()->StoreSource( @@ -1547,7 +1548,7 @@ EXPECT_THAT(storage()->GetActiveSources(), SizeIs(1)); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxAttributionDestinationsPerSource_CountsUnexpiredSources) { delegate()->set_max_destinations_per_source_site_reporting_site(1); delegate()->set_delete_expired_rate_limits_frequency(base::Milliseconds(10)); @@ -1583,7 +1584,7 @@ EXPECT_THAT(storage()->GetActiveSources(), SizeIs(1)); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaxAttributionDestinationsPerSource_SourceWithTooManyDestinations) { delegate()->set_max_destinations_per_source_site_reporting_site(1); @@ -1605,7 +1606,7 @@ EXPECT_THAT(storage()->GetActiveSources(), SizeIs(1)); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, HandleSource_DestinationThrottleReportingLimitReached) { // Current reporting limit for Destination Throttle int max_per_reporting_source_site = 50; @@ -1626,7 +1627,7 @@ StorableSource::Result::kDestinationReportingLimitReached); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, HandleSource_DestinationThrottleGlobalLimitReached) { // Current global limit for Destination Throttle int max_global_source_site = 200; @@ -1647,7 +1648,7 @@ StorableSource::Result::kDestinationGlobalLimitReached); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, HandleSource_DestinationThrottleBothLimitsReached) { int max_global_source_site = 200; for (int i = 0; i < max_global_source_site; i += 4) { @@ -1687,7 +1688,7 @@ StorableSource::Result::kDestinationBothLimitsReached); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MultipleImpressionsPerConversion_MostRecentAttributesForSamePriority) { storage()->StoreSource(SourceBuilder().SetSourceEventId(3).Build()); @@ -1706,7 +1707,7 @@ ElementsAre(ReportSourceIs(SourceEventIdIs(5u)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MultipleImpressionsPerConversion_HighestPriorityAttributes) { storage()->StoreSource( SourceBuilder().SetPriority(100).SetSourceEventId(3).Build()); @@ -1727,7 +1728,7 @@ ElementsAre(ReportSourceIs(SourceEventIdIs(5u)))); } -TEST_F(AttributionStorageTest, MultipleImpressions_CorrectDeactivation) { +TEST_F(AttributionResolverTest, MultipleImpressions_CorrectDeactivation) { storage()->StoreSource( SourceBuilder().SetSourceEventId(3).SetPriority(0).Build()); storage()->StoreSource( @@ -1743,7 +1744,7 @@ EXPECT_THAT(storage()->GetActiveSources(), ElementsAre(SourceEventIdIs(5u))); } -TEST_F(AttributionStorageTest, FalselyAttributeImpression_ReportStored) { +TEST_F(AttributionResolverTest, FalselyAttributeImpression_ReportStored) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; r.time_window = base::TimeDelta::Max(); @@ -1856,7 +1857,7 @@ expected_aggregatable_report)); } -TEST_F(AttributionStorageTest, StoreSource_ReturnsMinFakeReportTime) { +TEST_F(AttributionResolverTest, StoreSource_ReturnsMinFakeReportTime) { const base::Time now = base::Time::Now(); const struct { @@ -1899,7 +1900,7 @@ } } -TEST_F(AttributionStorageTest, TriggerPriority) { +TEST_F(AttributionResolverTest, TriggerPriority) { storage()->StoreSource(SourceBuilder() .SetSourceEventId(3) .SetPriority(0) @@ -1960,7 +1961,7 @@ // Regression test for erroneous use of report_time instead of // initial_report_time in event-level prioritization (http://crbug.com/1500598). -TEST_F(AttributionStorageTest, TriggerPriority_UsesOriginalReportTime) { +TEST_F(AttributionResolverTest, TriggerPriority_UsesOriginalReportTime) { delegate()->use_realistic_report_times(); storage()->StoreSource( @@ -2016,7 +2017,7 @@ Optional(ReportTimeIs(expected_first_report_time))))); } -TEST_F(AttributionStorageTest, TriggerPriority_Simple) { +TEST_F(AttributionResolverTest, TriggerPriority_Simple) { storage()->StoreSource(SourceBuilder().SetMaxEventLevelReports(1).Build()); int i = 0; @@ -2036,7 +2037,7 @@ ElementsAre(TriggerDebugKeyIs(9u))); } -TEST_F(AttributionStorageTest, TriggerPriority_SamePriorityDeletesMostRecent) { +TEST_F(AttributionResolverTest, TriggerPriority_SamePriorityDeletesMostRecent) { storage()->StoreSource(SourceBuilder().SetMaxEventLevelReports(2).Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, @@ -2069,7 +2070,7 @@ EventLevelDataIs(TriggerDataIs(5u)))); } -TEST_F(AttributionStorageTest, TriggerPriority_DeactivatesImpression) { +TEST_F(AttributionResolverTest, TriggerPriority_DeactivatesImpression) { storage()->StoreSource(SourceBuilder() .SetSourceEventId(3) .SetPriority(0) @@ -2111,7 +2112,7 @@ StoredSource::ActiveState::kReachedEventLevelAttributionLimit))); } -TEST_F(AttributionStorageTest, TriggerPriority_AttributionRateLimitAdjusted) { +TEST_F(AttributionResolverTest, TriggerPriority_AttributionRateLimitAdjusted) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; r.time_window = base::TimeDelta::Max(); @@ -2142,7 +2143,7 @@ ElementsAre(TriggerDebugKeyIs(1u), TriggerDebugKeyIs(2u))); } -TEST_F(AttributionStorageTest, DedupKey_Dedups) { +TEST_F(AttributionResolverTest, DedupKey_Dedups) { storage()->StoreSource( SourceBuilder() .SetDestinationSites( @@ -2220,7 +2221,7 @@ DedupKeysAre(ElementsAre(12)))); } -TEST_F(AttributionStorageTest, DedupKey_DedupsAfterConversionDeletion) { +TEST_F(AttributionResolverTest, DedupKey_DedupsAfterConversionDeletion) { storage()->StoreSource( SourceBuilder() .SetDestinationSites( @@ -2265,7 +2266,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Now()), IsEmpty()); } -TEST_F(AttributionStorageTest, AggregatableDedupKey_Dedups) { +TEST_F(AttributionResolverTest, AggregatableDedupKey_Dedups) { TestAggregatableSourceProvider provider; storage()->StoreSource( provider.GetBuilder() @@ -2346,7 +2347,7 @@ AggregatableDedupKeysAre(ElementsAre(12)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AggregatableDedupKey_DedupsAfterConversionDeletion) { storage()->StoreSource( TestAggregatableSourceProvider() @@ -2394,7 +2395,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Now()), IsEmpty()); } -TEST_F(AttributionStorageTest, DedupKey_AggregatableReportNotDedups) { +TEST_F(AttributionResolverTest, DedupKey_AggregatableReportNotDedups) { storage()->StoreSource( TestAggregatableSourceProvider() .GetBuilder() @@ -2427,7 +2428,7 @@ result.aggregatable_status()); } -TEST_F(AttributionStorageTest, AggregatableDedupKey_EventLevelReportNotDedups) { +TEST_F(AttributionResolverTest, AggregatableDedupKey_EventLevelReportNotDedups) { storage()->StoreSource( TestAggregatableSourceProvider() .GetBuilder() @@ -2460,7 +2461,7 @@ result.aggregatable_status()); } -TEST_F(AttributionStorageTest, AggregatableDedupKeysFiltering) { +TEST_F(AttributionResolverTest, AggregatableDedupKeysFiltering) { const auto origin = *SuitableOrigin::Deserialize("https://r.test"); std::vector<attribution_reporting::AggregatableTriggerData> @@ -2624,7 +2625,7 @@ } } -TEST_F(AttributionStorageTest, GetAttributionReports_SetsPriority) { +TEST_F(AttributionResolverTest, GetAttributionReports_SetsPriority) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport( @@ -2634,7 +2635,7 @@ ElementsAre(EventLevelDataIs(TriggerPriorityIs(13)))); } -TEST_F(AttributionStorageTest, NoIDReuse_Impression) { +TEST_F(AttributionResolverTest, NoIDReuse_Impression) { storage()->StoreSource(SourceBuilder().Build()); auto sources = storage()->GetActiveSources(); const StoredSource::Id id1 = sources.front().source_id(); @@ -2650,7 +2651,7 @@ EXPECT_NE(id1, id2); } -TEST_F(AttributionStorageTest, NoIDReuse_Conversion) { +TEST_F(AttributionResolverTest, NoIDReuse_Conversion) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); @@ -2672,7 +2673,7 @@ EXPECT_NE(id1, id2); } -TEST_F(AttributionStorageTest, UpdateReportForSendFailure) { +TEST_F(AttributionResolverTest, UpdateReportForSendFailure) { storage()->StoreSource(TestAggregatableSourceProvider().GetBuilder().Build()); EXPECT_THAT(storage()->MaybeCreateAndStoreReport( DefaultAggregatableTriggerBuilder().Build()), @@ -2709,7 +2710,7 @@ AllOf(FailedSendAttemptsIs(1), ReportTimeIs(new_report_time)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaybeCreateAndStoreEventLevelReport_ReturnsDeactivatedSources) { storage()->StoreSource( SourceBuilder().SetMaxEventLevelReports(kMaxConversions).Build()); @@ -2744,7 +2745,7 @@ StoredSource::ActiveState::kReachedEventLevelAttributionLimit))); } -TEST_F(AttributionStorageTest, ReportID_RoundTrips) { +TEST_F(AttributionResolverTest, ReportID_RoundTrips) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); @@ -2755,11 +2756,11 @@ EXPECT_EQ(DefaultExternalReportID(), actual_reports[0].external_report_id()); } -TEST_F(AttributionStorageTest, AdjustOfflineReportTimes) { +TEST_F(AttributionResolverTest, AdjustOfflineReportTimes) { EXPECT_EQ(storage()->AdjustOfflineReportTimes(), std::nullopt); delegate()->set_offline_report_delay_config( - AttributionStorageDelegate::OfflineReportDelayConfig{ + AttributionResolverDelegate::OfflineReportDelayConfig{ .min = base::Hours(1), .max = base::Hours(1)}); EXPECT_EQ(storage()->AdjustOfflineReportTimes(), std::nullopt); @@ -2802,9 +2803,9 @@ InitialReportTimeIs(original_report_time)))); } -TEST_F(AttributionStorageTest, AdjustOfflineReportTimes_Range) { +TEST_F(AttributionResolverTest, AdjustOfflineReportTimes_Range) { delegate()->set_offline_report_delay_config( - AttributionStorageDelegate::OfflineReportDelayConfig{ + AttributionResolverDelegate::OfflineReportDelayConfig{ .min = base::Hours(1), .max = base::Hours(3)}); storage()->StoreSource(TestAggregatableSourceProvider().GetBuilder().Build()); @@ -2836,7 +2837,7 @@ InitialReportTimeIs(original_report_time)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AdjustOfflineReportTimes_ReturnsMinReportTimeWithoutDelay) { delegate()->set_offline_report_delay_config(std::nullopt); @@ -2854,7 +2855,7 @@ reports.front().report_time()); } -TEST_F(AttributionStorageTest, GetNextEventReportTime) { +TEST_F(AttributionResolverTest, GetNextEventReportTime) { const auto origin_a = *SuitableOrigin::Deserialize("https://a.example/"); const auto origin_b = *SuitableOrigin::Deserialize("https://b.example/"); @@ -2883,7 +2884,7 @@ EXPECT_EQ(storage()->GetNextReportTime(report_time_b), std::nullopt); } -TEST_F(AttributionStorageTest, GetAttributionReports_Shuffles) { +TEST_F(AttributionResolverTest, GetAttributionReports_Shuffles) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport( @@ -2910,7 +2911,7 @@ EventLevelDataIs(TriggerDataIs(3)))); } -TEST_F(AttributionStorageTest, GetAttributionReportsExceedLimit_Shuffles) { +TEST_F(AttributionResolverTest, GetAttributionReportsExceedLimit_Shuffles) { storage()->StoreSource(TestAggregatableSourceProvider().GetBuilder().Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport( @@ -2947,7 +2948,7 @@ EventLevelDataIs(TriggerDataIs(3)))); } -TEST_F(AttributionStorageTest, GetAttributionDataKeysSet) { +TEST_F(AttributionResolverTest, GetAttributionDataKeysSet) { auto expected_1 = AttributionDataModel::DataKey( url::Origin::Create(GURL("https://a.r.test"))); auto expected_2 = AttributionDataModel::DataKey( @@ -2980,13 +2981,13 @@ EXPECT_THAT(storage()->GetAllDataKeys(), ElementsAre(expected_1, expected_2)); } -TEST_F(AttributionStorageTest, SourceDebugKey_RoundTrips) { +TEST_F(AttributionResolverTest, SourceDebugKey_RoundTrips) { storage()->StoreSource( SourceBuilder().SetDebugKey(33).SetDebugCookieSet(true).Build()); EXPECT_THAT(storage()->GetActiveSources(), ElementsAre(SourceDebugKeyIs(33))); } -TEST_F(AttributionStorageTest, TriggerDebugKey_RoundTrips) { +TEST_F(AttributionResolverTest, TriggerDebugKey_RoundTrips) { storage()->StoreSource( SourceBuilder().SetDebugKey(22).SetDebugCookieSet(true).Build()); EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, @@ -2998,7 +2999,7 @@ TriggerDebugKeyIs(33)))); } -TEST_F(AttributionStorageTest, AttributionAggregationKeys_RoundTrips) { +TEST_F(AttributionResolverTest, AttributionAggregationKeys_RoundTrips) { auto aggregation_keys = attribution_reporting::AggregationKeys::FromKeys({{"key", 345}}); ASSERT_TRUE(aggregation_keys.has_value()); @@ -3008,7 +3009,7 @@ ElementsAre(AggregationKeysAre(*aggregation_keys))); } -TEST_F(AttributionStorageTest, MaybeCreateAndStoreReport_ReturnsNewReport) { +TEST_F(AttributionResolverTest, MaybeCreateAndStoreReport_ReturnsNewReport) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_THAT(storage()->MaybeCreateAndStoreReport(TriggerBuilder().Build()), AllOf(CreateReportEventLevelStatusIs( @@ -3019,7 +3020,7 @@ // This is tested more thoroughly by the `RateLimitTable` unit tests. Here just // ensure that the rate limits are consulted at all. -TEST_F(AttributionStorageTest, MaxReportingOriginsPerSource) { +TEST_F(AttributionResolverTest, MaxReportingOriginsPerSource) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; r.time_window = base::TimeDelta::Max(); @@ -3065,7 +3066,7 @@ // This is tested more thoroughly by the `RateLimitTable` unit tests. Here just // ensure that the rate limits are consulted at all and the rate limit is shared // between event-level and aggregatable reports. -TEST_F(AttributionStorageTest, MaxReportingOriginsPerAttribution) { +TEST_F(AttributionResolverTest, MaxReportingOriginsPerAttribution) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; r.time_window = base::TimeDelta::Max(); @@ -3127,13 +3128,13 @@ UnorderedElementsAre(TriggerDebugKeyIs(1), TriggerDebugKeyIs(2))); } -TEST_F(AttributionStorageTest, SourceBudgetValueRetrieved) { +TEST_F(AttributionResolverTest, SourceBudgetValueRetrieved) { storage()->StoreSource(SourceBuilder().Build()); EXPECT_THAT(storage()->GetActiveSources(), ElementsAre(AggregatableBudgetConsumedIs(0))); } -TEST_F(AttributionStorageTest, MaxAggregatableBudgetPerSource) { +TEST_F(AttributionResolverTest, MaxAggregatableBudgetPerSource) { auto provider = TestAggregatableSourceProvider(/*size=*/2); storage()->StoreSource(provider.GetBuilder().Build()); @@ -3184,7 +3185,7 @@ AttributionTrigger::AggregatableResult::kSuccess)); } -TEST_F(AttributionStorageTest, BudgetConsumedAfterTriggerIsRetrieved) { +TEST_F(AttributionResolverTest, BudgetConsumedAfterTriggerIsRetrieved) { auto provider = TestAggregatableSourceProvider(/*size=*/1); storage()->StoreSource(provider.GetBuilder().Build()); @@ -3198,7 +3199,7 @@ ElementsAre(AggregatableBudgetConsumedIs(2))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, GetAttributionReports_SetsRandomizedTriggerRate) { delegate()->set_randomized_response_rate(0.1); @@ -3227,7 +3228,7 @@ RandomizedResponseRateIs(0.1))))); } -TEST_F(AttributionStorageTest, RandomizedResponseRatePerSourceUsed) { +TEST_F(AttributionResolverTest, RandomizedResponseRatePerSourceUsed) { delegate()->set_randomized_response_rate(0.1); storage()->StoreSource(SourceBuilder().Build()); delegate()->set_randomized_response_rate(0.2); @@ -3240,7 +3241,7 @@ // Will return minimum of next event-level report and next aggregatable report // time if both present. -TEST_F(AttributionStorageTest, GetNextReportTime) { +TEST_F(AttributionResolverTest, GetNextReportTime) { EXPECT_EQ(storage()->GetNextReportTime(base::Time::Min()), std::nullopt); storage()->StoreSource(TestAggregatableSourceProvider() @@ -3283,7 +3284,7 @@ EXPECT_EQ(storage()->GetNextReportTime(report_time_c), std::nullopt); } -TEST_F(AttributionStorageTest, TriggerDataSanitized) { +TEST_F(AttributionResolverTest, TriggerDataSanitized) { const auto origin1 = *SuitableOrigin::Deserialize("https://r1.test"); const auto origin2 = *SuitableOrigin::Deserialize("https://r2.test"); @@ -3309,7 +3310,7 @@ EventLevelDataIs(TriggerDataIs(1))))); } -TEST_F(AttributionStorageTest, SourceFilterData_RoundTrips) { +TEST_F(AttributionResolverTest, SourceFilterData_RoundTrips) { storage()->StoreSource(SourceBuilder() .SetFilterData(AttributionFilterData()) .SetSourceType(SourceType::kNavigation) @@ -3328,7 +3329,7 @@ SourceFilterDataIs(filter_data))); } -TEST_F(AttributionStorageTest, NoMatchingTriggerData_ReturnsError) { +TEST_F(AttributionResolverTest, NoMatchingTriggerData_ReturnsError) { const auto origin = *SuitableOrigin::Deserialize("https://r.test"); storage()->StoreSource(SourceBuilder() @@ -3360,7 +3361,7 @@ ElementsAre(DedupKeysAre(IsEmpty()))); } -TEST_F(AttributionStorageTest, MatchingTriggerData_UsesCorrectData) { +TEST_F(AttributionResolverTest, MatchingTriggerData_UsesCorrectData) { const auto origin = *SuitableOrigin::Deserialize("https://r.test"); storage()->StoreSource( @@ -3436,7 +3437,7 @@ ElementsAre(DedupKeysAre(ElementsAre(33)))); } -TEST_F(AttributionStorageTest, TopLevelTriggerFiltering) { +TEST_F(AttributionResolverTest, TopLevelTriggerFiltering) { const auto origin = *SuitableOrigin::Deserialize("https://r.test"); std::vector<attribution_reporting::EventTriggerData> event_triggers = { @@ -3545,7 +3546,7 @@ kNoMatchingSourceFilterData))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AggregatableAttributionNoMatchingSources_NoSourcesReturned) { EXPECT_THAT( storage()->MaybeCreateAndStoreReport( @@ -3557,7 +3558,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AggregatableAttributionNoAggregationKeys_NoContributions) { storage()->StoreSource(SourceBuilder().Build()); @@ -3576,7 +3577,7 @@ NewAggregatableReportIs(Eq(std::nullopt)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AggregatableAttributionValues_NoMatchingFilters_NoContributions) { storage()->StoreSource( SourceBuilder() @@ -3599,7 +3600,7 @@ AttributionTrigger::AggregatableResult::kNoHistograms); } -TEST_F(AttributionStorageTest, AggregatableAttribution_ReportsScheduled) { +TEST_F(AttributionResolverTest, AggregatableAttribution_ReportsScheduled) { auto source_builder = TestAggregatableSourceProvider().GetBuilder(); storage()->StoreSource(source_builder.Build()); @@ -3633,7 +3634,7 @@ } TEST_F( - AttributionStorageTest, + AttributionResolverTest, MaybeCreateAndStoreAggregatableReport_reachedEventLevelAttributionLimit) { storage()->StoreSource(TestAggregatableSourceProvider() .GetBuilder() @@ -3686,7 +3687,7 @@ StoredSource::ActiveState::kReachedEventLevelAttributionLimit))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AggregatableTriggerDataOrValuesNotSet_Registered) { storage()->StoreSource( SourceBuilder() @@ -3710,7 +3711,7 @@ AttributionTrigger::AggregatableResult::kSuccess); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, PrioritizationConsidersAttributedAndUnattributedSources) { storage()->StoreSource( SourceBuilder().SetSourceEventId(3).SetPriority(10).Build()); @@ -3729,7 +3730,7 @@ ReportSourceIs(SourceEventIdIs(3)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, MaybeCreateAndStoreEventLevelReport_DeactivatesUnattributedSources) { storage()->StoreSource( SourceBuilder().SetSourceEventId(3).SetPriority(1).Build()); @@ -3752,7 +3753,7 @@ ReportSourceIs(SourceEventIdIs(7)))); } -TEST_F(AttributionStorageTest, AggregationCoordinator_RoundTrip) { +TEST_F(AttributionResolverTest, AggregationCoordinator_RoundTrip) { base::test::ScopedFeatureList scoped_feature_list( ::aggregation_service::kAggregationServiceMultipleCloudProviders); @@ -3775,7 +3776,7 @@ AggregationCoordinatorOriginIs(coordinator_origin)))); } -TEST_F(AttributionStorageTest, MaxAttributions_BoundedBySourceTimeWindow) { +TEST_F(AttributionResolverTest, MaxAttributions_BoundedBySourceTimeWindow) { constexpr base::TimeDelta kTimeWindow = base::Days(1); delegate()->set_rate_limits([kTimeWindow]() { AttributionConfig::RateLimitConfig r; @@ -3803,7 +3804,7 @@ MaybeCreateAndStoreEventLevelReport(trigger)); } -TEST_F(AttributionStorageTest, NoEventTriggerData_NotRegisteredReturned) { +TEST_F(AttributionResolverTest, NoEventTriggerData_NotRegisteredReturned) { EXPECT_THAT( storage()->MaybeCreateAndStoreReport( DefaultAggregatableTriggerBuilder().Build( @@ -3817,7 +3818,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } -TEST_F(AttributionStorageTest, StoreNullAggregatableReport) { +TEST_F(AttributionResolverTest, StoreNullAggregatableReport) { base::Time now = base::Time::Now(); base::Time report_time = now + kReportDelay; base::Time fake_source_time = now; @@ -3842,7 +3843,7 @@ ElementsAre(expected_report)); } -TEST_F(AttributionStorageTest, NoAggregatableData_NoNullReport) { +TEST_F(AttributionResolverTest, NoAggregatableData_NoNullReport) { delegate()->set_null_aggregatable_reports_lookback_days({0}); auto result = storage()->MaybeCreateAndStoreReport(DefaultTrigger()); delegate()->set_null_aggregatable_reports_lookback_days({}); @@ -3851,7 +3852,7 @@ EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } -TEST_F(AttributionStorageTest, BothRealAndNullAggregatableReports) { +TEST_F(AttributionResolverTest, BothRealAndNullAggregatableReports) { base::Time now = base::Time::Now(); SourceBuilder builder = TestAggregatableSourceProvider().GetBuilder(now); @@ -3888,7 +3889,7 @@ UnorderedElementsAre(expected_aggregatable_report, expected_null_report)); } -TEST_F(AttributionStorageTest, SourceRegistrationTimeConfig_RoundTrip) { +TEST_F(AttributionResolverTest, SourceRegistrationTimeConfig_RoundTrip) { for (auto config : base::EnumSet<attribution_reporting::mojom::SourceRegistrationTimeConfig, attribution_reporting::mojom:: @@ -3911,7 +3912,7 @@ } } -TEST_F(AttributionStorageTest, MaximumAggregatableReportsPerSource) { +TEST_F(AttributionResolverTest, MaximumAggregatableReportsPerSource) { auto source = TestAggregatableSourceProvider().GetBuilder().Build(); storage()->StoreSource(source); AttributionTrigger trigger = DefaultAggregatableTriggerBuilder().Build(); @@ -3923,7 +3924,7 @@ MaybeCreateAndStoreAggregatableReport(trigger)); } -TEST_F(AttributionStorageTest, MaxSourceReportingOriginsPerSite) { +TEST_F(AttributionResolverTest, MaxSourceReportingOriginsPerSite) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; r.max_reporting_origins_per_source_reporting_site = 1; @@ -3966,7 +3967,7 @@ EXPECT_THAT(storage()->GetActiveSources(), SizeIs(4)); } -TEST_F(AttributionStorageTest, TriggerDataMatching) { +TEST_F(AttributionResolverTest, TriggerDataMatching) { const struct { const char* desc; TriggerDataMatching trigger_data_matching; @@ -4014,7 +4015,7 @@ } } -TEST_F(AttributionStorageTest, EventLevelDedupBeforeWindowCheck) { +TEST_F(AttributionResolverTest, EventLevelDedupBeforeWindowCheck) { storage()->StoreSource( SourceBuilder() .SetTriggerSpecs( @@ -4036,7 +4037,7 @@ TriggerBuilder().SetDedupKey(11).Build())); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AttributionAggregatableReportWithTriggerContextId_RoundTrip) { storage()->StoreSource(TestAggregatableSourceProvider().GetBuilder().Build()); @@ -4062,7 +4063,7 @@ ReportTimeIs(report_time)))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, NullAggregatableReportWithTriggerContextId_RoundTrip) { base::Time now = base::Time::Now(); base::Time report_time = now; @@ -4086,7 +4087,7 @@ } // TODO(crbug.com/40941848): Support multiple trigger specs instead of just 1. -TEST_F(AttributionStorageTest, RejectsMultipleTriggerSpecs) { +TEST_F(AttributionResolverTest, RejectsMultipleTriggerSpecs) { auto source = SourceBuilder().Build(); source.registration().trigger_specs = *TriggerSpecs::Create(/*trigger_data_indices=*/{{0, 0}}, @@ -4100,7 +4101,7 @@ // Regression test for https://crbug.com/331100922. TEST_F( - AttributionStorageTest, + AttributionResolverTest, FakeSourceCreateAggregatableReport_EffectiveDestinationAttributionRateLimitRecord) { delegate()->set_rate_limits([]() { AttributionConfig::RateLimitConfig r; @@ -4161,7 +4162,7 @@ AttributionTrigger::AggregatableResult::kSuccess))); } -TEST_F(AttributionStorageTest, +TEST_F(AttributionResolverTest, AttributedTriggerIncludeSourceRegistrationTime_NullAggregatableReports) { SourceBuilder builder = TestAggregatableSourceProvider().GetBuilder(); storage()->StoreSource(builder.Build()); @@ -4201,7 +4202,7 @@ } TEST_F( - AttributionStorageTest, + AttributionResolverTest, UnattributedTriggerIncludeSourceRegistrationTime_NullAggregatableReports) { const base::Time now = base::Time::Now(); @@ -4241,7 +4242,7 @@ } TEST_F( - AttributionStorageTest, + AttributionResolverTest, AttributedTriggerExcludeSourceRegistrationTime_NoNullAggregatableReport) { SourceBuilder builder = TestAggregatableSourceProvider().GetBuilder(); storage()->StoreSource(builder.Build()); @@ -4265,7 +4266,7 @@ } TEST_F( - AttributionStorageTest, + AttributionResolverTest, UnattributedTriggerExcludeSourceRegistrationTime_NullAggregatableReport) { const base::Time now = base::Time::Now();
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc index 34c8e09..43ee168 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -61,7 +61,7 @@ #include "content/browser/attribution_reporting/attribution_info.h" #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_reporting.pb.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" #include "content/browser/attribution_reporting/attribution_storage_sql_migrations.h" #include "content/browser/attribution_reporting/attribution_trigger.h" #include "content/browser/attribution_reporting/common_source_info.h" @@ -465,13 +465,13 @@ AttributionStorageSql::AttributionStorageSql( const base::FilePath& user_data_directory, - std::unique_ptr<AttributionStorageDelegate> delegate) + AttributionResolverDelegate* delegate) : path_to_database_(user_data_directory.empty() ? base::FilePath() : DatabasePath(user_data_directory)), db_(sql::DatabaseOptions{.page_size = 4096, .cache_size = 32}), - delegate_(std::move(delegate)), - rate_limit_table_(delegate_.get()) { + delegate_(delegate), + rate_limit_table_(delegate_) { DCHECK(delegate_); db_.set_histogram_tag("Conversions"); @@ -3292,12 +3292,11 @@ /*delete_rate_limit_data=*/true); } -void AttributionStorageSql::SetDelegate( - std::unique_ptr<AttributionStorageDelegate> delegate) { +void AttributionStorageSql::SetDelegate(AttributionResolverDelegate* delegate) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(delegate); rate_limit_table_.SetDelegate(*delegate); - delegate_ = std::move(delegate); + delegate_ = delegate; } } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.h b/content/browser/attribution_reporting/attribution_storage_sql.h index aa7641c..ee2c854d 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.h +++ b/content/browser/attribution_reporting/attribution_storage_sql.h
@@ -19,7 +19,7 @@ #include "base/time/time.h" #include "base/types/expected.h" #include "content/browser/attribution_reporting/attribution_report.h" -#include "content/browser/attribution_reporting/attribution_storage.h" +#include "content/browser/attribution_reporting/attribution_resolver.h" #include "content/browser/attribution_reporting/attribution_trigger.h" #include "content/browser/attribution_reporting/rate_limit_table.h" #include "content/browser/attribution_reporting/stored_source.h" @@ -35,17 +35,17 @@ namespace content { -class AttributionStorageDelegate; +class AttributionResolverDelegate; class StorableSource; class StoreSourceResult; struct AttributionInfo; enum class RateLimitResult : int; -// Provides an implementation of AttributionStorage that is backed by SQLite. +// Provides an implementation of storage that is backed by SQLite. // This class may be constructed on any sequence but must be accessed and // destroyed on the same sequence. The sequence must outlive |this|. -class CONTENT_EXPORT AttributionStorageSql : public AttributionStorage { +class CONTENT_EXPORT AttributionStorageSql { public: // Version number of the database. static constexpr int kCurrentVersionNumber = 59; @@ -64,12 +64,12 @@ // If `user_data_directory` is empty, the DB is created in memory and no data // is persisted to disk. AttributionStorageSql(const base::FilePath& user_data_directory, - std::unique_ptr<AttributionStorageDelegate> delegate); + AttributionResolverDelegate* delegate); AttributionStorageSql(const AttributionStorageSql&) = delete; AttributionStorageSql& operator=(const AttributionStorageSql&) = delete; AttributionStorageSql(AttributionStorageSql&&) = delete; AttributionStorageSql& operator=(AttributionStorageSql&&) = delete; - ~AttributionStorageSql() override; + ~AttributionStorageSql(); void set_ignore_errors_for_testing(bool ignore_for_testing) { ignore_errors_for_testing_ = ignore_for_testing; @@ -128,6 +128,26 @@ // Deletes corrupt sources/reports if `deletion_counts` is not `nullptr`. void VerifyReports(DeletionCounts* deletion_counts); + StoreSourceResult StoreSource(StorableSource source); + CreateReportResult MaybeCreateAndStoreReport(AttributionTrigger); + std::vector<AttributionReport> GetAttributionReports( + base::Time max_report_time, + int limit = -1); + std::optional<base::Time> GetNextReportTime(base::Time time); + std::optional<AttributionReport> GetReport(AttributionReport::Id); + std::vector<StoredSource> GetActiveSources(int limit = -1); + std::set<AttributionDataModel::DataKey> GetAllDataKeys(); + void DeleteByDataKey(const AttributionDataModel::DataKey& datakey); + bool DeleteReport(AttributionReport::Id report_id); + bool UpdateReportForSendFailure(AttributionReport::Id report_id, + base::Time new_report_time); + std::optional<base::Time> AdjustOfflineReportTimes(); + void ClearData(base::Time delete_begin, + base::Time delete_end, + StoragePartition::StorageKeyMatcherFunction filter, + bool delete_rate_limit_data); + void SetDelegate(AttributionResolverDelegate*); + private: using ReportCorruptionStatusSet = base::EnumSet<ReportCorruptionStatus, @@ -156,27 +176,6 @@ kIgnoreIfAbsent, }; - // AttributionStorage: - StoreSourceResult StoreSource(StorableSource source) override; - CreateReportResult MaybeCreateAndStoreReport(AttributionTrigger) override; - std::vector<AttributionReport> GetAttributionReports( - base::Time max_report_time, - int limit = -1) override; - std::optional<base::Time> GetNextReportTime(base::Time time) override; - std::optional<AttributionReport> GetReport(AttributionReport::Id) override; - std::vector<StoredSource> GetActiveSources(int limit = -1) override; - std::set<AttributionDataModel::DataKey> GetAllDataKeys() override; - void DeleteByDataKey(const AttributionDataModel::DataKey& datakey) override; - bool DeleteReport(AttributionReport::Id report_id) override; - bool UpdateReportForSendFailure(AttributionReport::Id report_id, - base::Time new_report_time) override; - std::optional<base::Time> AdjustOfflineReportTimes() override; - void ClearData(base::Time delete_begin, - base::Time delete_end, - StoragePartition::StorageKeyMatcherFunction filter, - bool delete_rate_limit_data) override; - void SetDelegate(std::unique_ptr<AttributionStorageDelegate>) override; - void ClearAllDataAllTime(bool delete_rate_limit_data) VALID_CONTEXT_REQUIRED(sequence_checker_); @@ -426,7 +425,7 @@ sql::Database db_ GUARDED_BY_CONTEXT(sequence_checker_); - std::unique_ptr<AttributionStorageDelegate> delegate_ + raw_ptr<AttributionResolverDelegate> delegate_ GUARDED_BY_CONTEXT(sequence_checker_); // Table which stores timestamps of sent reports, and checks if new reports
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc index 4dcd85f..caa1686b 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc
@@ -16,7 +16,8 @@ #include "base/test/metrics/histogram_tester.h" #include "base/time/time.h" #include "content/browser/attribution_reporting/attribution_reporting.pb.h" -#include "content/browser/attribution_reporting/attribution_storage.h" +#include "content/browser/attribution_reporting/attribution_resolver.h" +#include "content/browser/attribution_reporting/attribution_resolver_impl.h" #include "content/browser/attribution_reporting/attribution_storage_sql.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" #include "content/browser/attribution_reporting/store_source_result.h" @@ -56,13 +57,13 @@ void SetUp() override { ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); } void MigrateDatabase() { - AttributionStorageSql storage( + AttributionResolverImpl storage( temp_directory_.GetPath(), std::make_unique<ConfigurableStorageDelegate>()); // We need to run an operation on storage to force the lazy initialization. std::ignore = - static_cast<AttributionStorage*>(&storage)->GetAttributionReports( + static_cast<AttributionResolver*>(&storage)->GetAttributionReports( base::Time::Min()); } @@ -133,13 +134,13 @@ TEST_F(AttributionStorageSqlMigrationsTest, MigrateEmptyToCurrent) { base::HistogramTester histograms; { - AttributionStorageSql storage( + AttributionResolverImpl storage( temp_directory_.GetPath(), std::make_unique<ConfigurableStorageDelegate>()); // We need to perform an operation that is non-trivial on an empty database // to force initialization. - static_cast<AttributionStorage*>(&storage)->StoreSource( + static_cast<AttributionResolver*>(&storage)->StoreSource( SourceBuilder(base::Time::Min()).Build()); } @@ -400,14 +401,14 @@ ASSERT_TRUE(db.Open(DbPath())); } { - AttributionStorageSql storage( + AttributionResolverImpl storage( temp_directory_.GetPath(), std::make_unique<ConfigurableStorageDelegate>()); // Store a valid report to verify corruption deletion. - static_cast<AttributionStorage*>(&storage)->StoreSource( + static_cast<AttributionResolver*>(&storage)->StoreSource( SourceBuilder().Build()); - static_cast<AttributionStorage*>(&storage)->MaybeCreateAndStoreReport( + static_cast<AttributionResolver*>(&storage)->MaybeCreateAndStoreReport( DefaultTrigger()); } MigrateDatabase();
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc index 743f2afa..b10b432 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc
@@ -11,7 +11,8 @@ #include "base/files/scoped_temp_dir.h" #include "base/strings/string_util.h" #include "base/test/gmock_expected_support.h" -#include "content/browser/attribution_reporting/attribution_storage_sql.h" +#include "content/browser/attribution_reporting/attribution_resolver.h" +#include "content/browser/attribution_reporting/attribution_resolver_impl.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" #include "content/browser/attribution_reporting/sql_queries.h" #include "content/browser/attribution_reporting/sql_query_plan_test_util.h" @@ -35,8 +36,8 @@ ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); { - std::unique_ptr<AttributionStorage> storage = - std::make_unique<AttributionStorageSql>( + std::unique_ptr<AttributionResolver> storage = + std::make_unique<AttributionResolverImpl>( temp_directory_.GetPath(), std::make_unique<ConfigurableStorageDelegate>());
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc index 34b8086..efeed791 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
@@ -48,6 +48,7 @@ #include "content/browser/attribution_reporting/attribution_features.h" #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_reporting.pb.h" +#include "content/browser/attribution_reporting/attribution_resolver_impl.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" #include "content/browser/attribution_reporting/attribution_trigger.h" #include "content/browser/attribution_reporting/sql_utils.h" @@ -270,7 +271,7 @@ CloseDatabase(); auto delegate = std::make_unique<ConfigurableStorageDelegate>(); delegate_ = delegate.get(); - storage_ = std::make_unique<AttributionStorageSql>( + storage_ = std::make_unique<AttributionResolverImpl>( temp_directory_.GetPath(), std::move(delegate)); } @@ -304,7 +305,7 @@ return temp_directory_.GetPath().Append(FILE_PATH_LITERAL("Conversions")); } - AttributionStorage* storage() { return storage_.get(); } + AttributionResolver* storage() { return storage_.get(); } ConfigurableStorageDelegate* delegate() { return delegate_; } @@ -393,7 +394,7 @@ base::ScopedTempDir temp_directory_; private: - std::unique_ptr<AttributionStorage> storage_; + std::unique_ptr<AttributionResolver> storage_; raw_ptr<ConfigurableStorageDelegate> delegate_ = nullptr; }; @@ -1085,12 +1086,12 @@ TEST_F(AttributionStorageSqlTest, CantOpenDb_FailsSilentlyInRelease) { base::CreateDirectoryAndGetError(db_path(), nullptr); - auto sql_storage = std::make_unique<AttributionStorageSql>( + auto sql_storage = std::make_unique<AttributionResolverImpl>( temp_directory_.GetPath(), std::make_unique<ConfigurableStorageDelegate>()); sql_storage->set_ignore_errors_for_testing(true); - std::unique_ptr<AttributionStorage> storage = std::move(sql_storage); + std::unique_ptr<AttributionResolver> storage = std::move(sql_storage); // These calls should be no-ops. storage->StoreSource(SourceBuilder().Build()); @@ -1101,8 +1102,8 @@ TEST_F(AttributionStorageSqlTest, DatabaseDirDoesExist_CreateDirAndOpenDB) { // Give the storage layer a database directory that doesn't exist. - std::unique_ptr<AttributionStorage> storage = - std::make_unique<AttributionStorageSql>( + std::unique_ptr<AttributionResolver> storage = + std::make_unique<AttributionResolverImpl>( temp_directory_.GetPath().Append( FILE_PATH_LITERAL("ConversionFolder/")), std::make_unique<ConfigurableStorageDelegate>());
diff --git a/content/browser/attribution_reporting/interop/runner.cc b/content/browser/attribution_reporting/interop/runner.cc index c7cb0a9..8977865 100644 --- a/content/browser/attribution_reporting/interop/runner.cc +++ b/content/browser/attribution_reporting/interop/runner.cc
@@ -58,7 +58,7 @@ #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_report_network_sender.h" #include "content/browser/attribution_reporting/attribution_reporting.mojom.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate_impl.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate_impl.h" #include "content/browser/attribution_reporting/attribution_suitable_context.h" #include "content/browser/attribution_reporting/interop/parser.h" #include "content/browser/storage_partition_impl.h" @@ -163,12 +163,12 @@ base::flat_set<base::Time> debug_cookie_set_; }; -class ControllableStorageDelegate : public AttributionStorageDelegateImpl { +class ControllableStorageDelegate : public AttributionResolverDelegateImpl { public: explicit ControllableStorageDelegate(AttributionInteropRun& run) - : AttributionStorageDelegateImpl(AttributionNoiseMode::kNone, - AttributionDelayMode::kDefault, - run.config.attribution_config) { + : AttributionResolverDelegateImpl(AttributionNoiseMode::kNone, + AttributionDelayMode::kDefault, + run.config.attribution_config) { std::vector<std::pair<base::Time, RandomizedResponse>> responses; std::vector<std::pair<base::Time, base::flat_set<int>>> null_aggregatable_reports_days; @@ -203,7 +203,7 @@ delete; private: - // AttributionStorageDelegateImpl: + // AttributionResolverDelegateImpl: GetRandomizedResponseResult GetRandomizedResponse( const attribution_reporting::mojom::SourceType source_type, const attribution_reporting::TriggerSpecs& trigger_specs, @@ -213,7 +213,7 @@ ASSIGN_OR_RETURN( auto response_data, - AttributionStorageDelegateImpl::GetRandomizedResponse( + AttributionResolverDelegateImpl::GetRandomizedResponse( source_type, trigger_specs, max_event_level_reports, epsilon)); auto it = randomized_responses_.find(base::Time::Now()); @@ -242,7 +242,7 @@ source_registration_time_config) const override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - bool ret = AttributionStorageDelegateImpl:: + bool ret = AttributionResolverDelegateImpl:: GenerateNullAggregatableReportForLookbackDay( lookback_day, source_registration_time_config); auto it = null_aggregatable_reports_days_.find(base::Time::Now());
diff --git a/content/browser/attribution_reporting/rate_limit_table.cc b/content/browser/attribution_reporting/rate_limit_table.cc index f25146ed2..a67695c 100644 --- a/content/browser/attribution_reporting/rate_limit_table.cc +++ b/content/browser/attribution_reporting/rate_limit_table.cc
@@ -18,7 +18,7 @@ #include "components/attribution_reporting/suitable_origin.h" #include "content/browser/attribution_reporting/attribution_config.h" #include "content/browser/attribution_reporting/attribution_info.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" #include "content/browser/attribution_reporting/common_source_info.h" #include "content/browser/attribution_reporting/rate_limit_result.h" #include "content/browser/attribution_reporting/sql_queries.h" @@ -49,9 +49,9 @@ } // namespace -RateLimitTable::RateLimitTable(const AttributionStorageDelegate* delegate) - : delegate_(raw_ref<const AttributionStorageDelegate>::from_ptr(delegate)) { -} +RateLimitTable::RateLimitTable(const AttributionResolverDelegate* delegate) + : delegate_( + raw_ref<const AttributionResolverDelegate>::from_ptr(delegate)) {} RateLimitTable::~RateLimitTable() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -635,7 +635,7 @@ } } -void RateLimitTable::SetDelegate(const AttributionStorageDelegate& delegate) { +void RateLimitTable::SetDelegate(const AttributionResolverDelegate& delegate) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); delegate_ = delegate; }
diff --git a/content/browser/attribution_reporting/rate_limit_table.h b/content/browser/attribution_reporting/rate_limit_table.h index 5bf26af..8405601 100644 --- a/content/browser/attribution_reporting/rate_limit_table.h +++ b/content/browser/attribution_reporting/rate_limit_table.h
@@ -37,7 +37,7 @@ namespace content { struct AttributionInfo; -class AttributionStorageDelegate; +class AttributionResolverDelegate; class CommonSourceInfo; class StorableSource; @@ -70,7 +70,7 @@ kMaxValue = kError, }; - explicit RateLimitTable(const AttributionStorageDelegate*); + explicit RateLimitTable(const AttributionResolverDelegate*); RateLimitTable(const RateLimitTable&) = delete; RateLimitTable& operator=(const RateLimitTable&) = delete; RateLimitTable(RateLimitTable&&) = delete; @@ -145,7 +145,7 @@ void AppendRateLimitDataKeys(sql::Database* db, std::set<AttributionDataModel::DataKey>& keys); - void SetDelegate(const AttributionStorageDelegate&); + void SetDelegate(const AttributionResolverDelegate&); static constexpr int64_t kUnsetReportId = -1; @@ -179,7 +179,7 @@ [[nodiscard]] bool DeleteExpiredRateLimits(sql::Database* db) VALID_CONTEXT_REQUIRED(sequence_checker_); - raw_ref<const AttributionStorageDelegate> delegate_ + raw_ref<const AttributionResolverDelegate> delegate_ GUARDED_BY_CONTEXT(sequence_checker_); // Time at which `DeleteExpiredRateLimits()` was last called. Initialized to
diff --git a/content/browser/attribution_reporting/test/configurable_storage_delegate.cc b/content/browser/attribution_reporting/test/configurable_storage_delegate.cc index 6011724c..9a15f50 100644 --- a/content/browser/attribution_reporting/test/configurable_storage_delegate.cc +++ b/content/browser/attribution_reporting/test/configurable_storage_delegate.cc
@@ -24,14 +24,14 @@ #include "components/attribution_reporting/privacy_math.h" #include "content/browser/attribution_reporting/attribution_config.h" #include "content/browser/attribution_reporting/attribution_report.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" #include "services/network/public/cpp/trigger_verification.h" namespace content { ConfigurableStorageDelegate::ConfigurableStorageDelegate() - : AttributionStorageDelegate([]() { + : AttributionResolverDelegate([]() { AttributionConfig c; c.max_sources_per_origin = std::numeric_limits<int>::max(), c.max_destinations_per_source_site_reporting_site = @@ -98,7 +98,7 @@ return DefaultExternalReportID(); } -std::optional<AttributionStorageDelegate::OfflineReportDelayConfig> +std::optional<AttributionResolverDelegate::OfflineReportDelayConfig> ConfigurableStorageDelegate::GetOfflineReportDelayConfig() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return offline_report_delay_config_; @@ -129,7 +129,7 @@ return randomized_response_rate_; } -AttributionStorageDelegate::GetRandomizedResponseResult +AttributionResolverDelegate::GetRandomizedResponseResult ConfigurableStorageDelegate::GetRandomizedResponse( attribution_reporting::mojom::SourceType, const attribution_reporting::TriggerSpecs&,
diff --git a/content/browser/attribution_reporting/test/configurable_storage_delegate.h b/content/browser/attribution_reporting/test/configurable_storage_delegate.h index 7b481bf..bd8de17 100644 --- a/content/browser/attribution_reporting/test/configurable_storage_delegate.h +++ b/content/browser/attribution_reporting/test/configurable_storage_delegate.h
@@ -14,16 +14,16 @@ #include "components/attribution_reporting/privacy_math.h" #include "content/browser/attribution_reporting/attribution_config.h" #include "content/browser/attribution_reporting/attribution_report.h" -#include "content/browser/attribution_reporting/attribution_storage_delegate.h" +#include "content/browser/attribution_reporting/attribution_resolver_delegate.h" namespace content { -class ConfigurableStorageDelegate : public AttributionStorageDelegate { +class ConfigurableStorageDelegate : public AttributionResolverDelegate { public: ConfigurableStorageDelegate(); ~ConfigurableStorageDelegate() override; - // AttributionStorageDelegate: + // AttributionResolverDelegate: base::Time GetEventLevelReportTime( const attribution_reporting::EventReportWindows& event_report_windows, base::Time source_time,
diff --git a/content/browser/fenced_frame/fenced_frame_browsertest.cc b/content/browser/fenced_frame/fenced_frame_browsertest.cc index 891cecd7..79eb3f9 100644 --- a/content/browser/fenced_frame/fenced_frame_browsertest.cc +++ b/content/browser/fenced_frame/fenced_frame_browsertest.cc
@@ -7124,7 +7124,7 @@ .destination = {"a.test", "/set-header" "?Supports-Loading-Mode: fenced-frame" - "&Allow-Cross-Origin-Event-Reporting: true"}, + "&Allow-Cross-Origin-Event-Reporting: ?1"}, .report_event_result = Step::Result::kSuccess, }, { @@ -7158,7 +7158,7 @@ .destination = {"a.test", "/set-header" "?Supports-Loading-Mode: fenced-frame" - "&Allow-Cross-Origin-Event-Reporting: true"}, + "&Allow-Cross-Origin-Event-Reporting: ?1"}, .report_event_result = Step::Result::kSuccess, }, { @@ -7382,7 +7382,7 @@ .destination = {"a.test", "/set-header" "?Supports-Loading-Mode: fenced-frame" - "&Allow-Cross-Origin-Event-Reporting: true"}, + "&Allow-Cross-Origin-Event-Reporting: ?1"}, .report_event_result = Step::Result::kSuccess, }, { @@ -7408,7 +7408,7 @@ .destination = {"a.test", "/set-header" "?Supports-Loading-Mode: fenced-frame" - "&Allow-Cross-Origin-Event-Reporting: true"}, + "&Allow-Cross-Origin-Event-Reporting: ?1"}, .report_event_result = Step::Result::kSuccess, }, {
diff --git a/content/browser/indexed_db/indexed_db_bucket_context.cc b/content/browser/indexed_db/indexed_db_bucket_context.cc index 3eca4d1..ecf77bd 100644 --- a/content/browser/indexed_db/indexed_db_bucket_context.cc +++ b/content/browser/indexed_db/indexed_db_bucket_context.cc
@@ -20,6 +20,8 @@ #include "base/check_op.h" #include "base/compiler_specific.h" #include "base/containers/contains.h" +#include "base/debug/crash_logging.h" +#include "base/feature_list.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" @@ -1641,10 +1643,23 @@ constexpr static const int kNumOpenTries = 2; for (int i = 0; i < kNumOpenTries; ++i) { const bool is_first_attempt = i == 0; - std::tie(backing_store, status, data_loss_info, disk_full) = - OpenAndVerifyIndexedDBBackingStore(data_path_, database_path, blob_path, - lock_manager.get(), is_first_attempt, - create_if_missing); + { + SCOPED_CRASH_KEY_STRING256("crbug/340398745", "data_path", + data_path_.AsUTF8Unsafe()); + SCOPED_CRASH_KEY_BOOL("crbug/340398745", "first_attempt", + is_first_attempt); + SCOPED_CRASH_KEY_BOOL( + "crbug/340398745", "sharding", + base::FeatureList::IsEnabled(features::kIndexedDBShardBackingStores)); + SCOPED_CRASH_KEY_NUMBER("crbug/340398745", "store_open_count", + backing_store_open_count_); + + std::tie(backing_store, status, data_loss_info, disk_full) = + OpenAndVerifyIndexedDBBackingStore( + data_path_, database_path, blob_path, lock_manager.get(), + is_first_attempt, create_if_missing); + } + if (is_first_attempt) [[likely]] { first_try_status = status; } @@ -1711,6 +1726,7 @@ lock_manager_ = std::move(lock_manager); backing_store_ = std::move(backing_store); + backing_store_open_count_++; backing_store_->set_bucket_context(this); delegate().on_files_written.Run(/*flushed=*/true); return {leveldb::Status::OK(), IndexedDBDatabaseError(), data_loss_info};
diff --git a/content/browser/indexed_db/indexed_db_bucket_context.h b/content/browser/indexed_db/indexed_db_bucket_context.h index adced8fb..f7a866f3 100644 --- a/content/browser/indexed_db/indexed_db_bucket_context.h +++ b/content/browser/indexed_db/indexed_db_bucket_context.h
@@ -509,6 +509,9 @@ // True if there's already a task queued to call `RunTasks()`. bool task_run_queued_ = false; + // Debug field. TODO(crbug/340398745): remove. + size_t backing_store_open_count_ = 0; + mojo::ReceiverSet<blink::mojom::IDBFactory, ReceiverContext> receivers_; base::WeakPtrFactory<IndexedDBBucketContext> weak_factory_{this};
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index 26784f5c..425b3c0 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -455,6 +455,8 @@ rhs->no_vary_search_with_parse_error)); CHECK(mojo::Equals(adjusted_lhs->observe_browsing_topics, rhs->observe_browsing_topics)); + CHECK(mojo::Equals(adjusted_lhs->allow_cross_origin_event_reporting, + rhs->allow_cross_origin_event_reporting)); NOTREACHED_IN_MIGRATION() << "The parsed headers don't match, but we don't know which " "field does not match. Please add a DCHECK before this one "
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 8eb15fe..909f2f6 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -6076,14 +6076,9 @@ // cross-origin subframes to use their reporting metadata to send // `reportEvent()` beacons. The cross-origin subframes still require a // separate per-report opt-in. - { - std::string allow; - if (fenced_frame_properties_.has_value() && response() && - response()->headers->GetNormalizedHeader( - "Allow-Cross-Origin-Event-Reporting", &allow) && - allow == "true") { - fenced_frame_properties_->SetAllowCrossOriginEventReporting(); - } + if (fenced_frame_properties_.has_value() && response_head_ && + response_head_->parsed_headers->allow_cross_origin_event_reporting) { + fenced_frame_properties_->SetAllowCrossOriginEventReporting(); } // Create a view of the fenced frame properties from the perspective of the
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc index b5fbea93..16852fb 100644 --- a/content/browser/shared_storage/shared_storage_browsertest.cc +++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -1247,6 +1247,24 @@ bool ResolveSelectURLToConfig() override { return GetParam(); } + mojo_base::BigBuffer GetCodeCacheDataForUrl(RenderFrameHost* rfh, + const GURL& url) { + mojo::PendingRemote<blink::mojom::CodeCacheHost> pending_code_cache_host; + RenderFrameHostImpl::From(rfh)->CreateCodeCacheHost( + pending_code_cache_host.InitWithNewPipeAndPassReceiver()); + + mojo::Remote<blink::mojom::CodeCacheHost> inspecting_code_cache_host( + std::move(pending_code_cache_host)); + + base::test::TestFuture<base::Time, mojo_base::BigBuffer> code_cache_future; + inspecting_code_cache_host->FetchCachedCode( + blink::mojom::CodeCacheType::kJavascript, url, + code_cache_future.GetCallback()); + + auto [response_time, data] = code_cache_future.Take(); + return std::move(data); + } + ~SharedStorageBrowserTest() override = default; private: @@ -1434,6 +1452,63 @@ "a.test", "/shared_storage/simple_module.js"))}}); } +IN_PROC_BROWSER_TEST_P(SharedStorageBrowserTest, + AddModue_TheThirdTimeCompilesWithV8CodeCache) { + // The test assumes pages get deleted after navigation. To ensure this, + // disable back/forward cache. + content::DisableBackForwardCacheForTesting( + shell()->web_contents(), + content::BackForwardCache::TEST_REQUIRES_NO_CACHING); + + GURL url = https_server()->GetURL("a.test", kSimplePagePath); + GURL module_url = https_server()->GetURL( + "a.test", "/shared_storage/large_cacheable_script.js"); + + EXPECT_TRUE(NavigateToURL(shell(), url)); + + // Initially, the code cache has no data. + mojo_base::BigBuffer code_cache_data0 = GetCodeCacheDataForUrl( + shell()->web_contents()->GetPrimaryMainFrame(), module_url); + EXPECT_EQ(code_cache_data0.size(), 0u); + + EXPECT_TRUE(ExecJs(shell(), R"( + sharedStorage.worklet.addModule( + 'shared_storage/large_cacheable_script.js'); + )")); + + mojo_base::BigBuffer code_cache_data1 = GetCodeCacheDataForUrl( + shell()->web_contents()->GetPrimaryMainFrame(), module_url); + EXPECT_GT(code_cache_data1.size(), 0u); + + // After the first script loading, the code cache has some data. + EXPECT_TRUE(NavigateToURL(shell(), url)); + EXPECT_TRUE(ExecJs(shell(), R"( + sharedStorage.worklet.addModule( + 'shared_storage/large_cacheable_script.js'); + )")); + + // After the second script loading, the code cache has more data. This implies + // that the code cache wasn't used for the second compilation. This is + // expected, as we won't store the cached code entirely for first seen URLs. + mojo_base::BigBuffer code_cache_data2 = GetCodeCacheDataForUrl( + shell()->web_contents()->GetPrimaryMainFrame(), module_url); + EXPECT_GT(code_cache_data2.size(), code_cache_data1.size()); + + EXPECT_TRUE(NavigateToURL(shell(), url)); + EXPECT_TRUE(ExecJs(shell(), R"( + sharedStorage.worklet.addModule( + 'shared_storage/large_cacheable_script.js'); + )")); + + // After the third script loading, the code cache does not change. This + // implies that the code cache was used for the third compilation. + mojo_base::BigBuffer code_cache_data3 = GetCodeCacheDataForUrl( + shell()->web_contents()->GetPrimaryMainFrame(), module_url); + EXPECT_EQ(code_cache_data3.size(), code_cache_data2.size()); + EXPECT_TRUE(std::equal(code_cache_data3.begin(), code_cache_data3.end(), + code_cache_data2.begin())); +} + IN_PROC_BROWSER_TEST_P(SharedStorageBrowserTest, RunOperation_Success) { GURL url = https_server()->GetURL("a.test", kSimplePagePath); EXPECT_TRUE(NavigateToURL(shell(), url));
diff --git a/content/browser/shared_storage/shared_storage_code_cache_host_proxy.cc b/content/browser/shared_storage/shared_storage_code_cache_host_proxy.cc new file mode 100644 index 0000000..8d29a1f0 --- /dev/null +++ b/content/browser/shared_storage/shared_storage_code_cache_host_proxy.cc
@@ -0,0 +1,71 @@ +// 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 "content/browser/shared_storage/shared_storage_code_cache_host_proxy.h" + +#include "base/logging.h" + +namespace content { + +SharedStorageCodeCacheHostProxy::SharedStorageCodeCacheHostProxy( + mojo::PendingRemote<blink::mojom::CodeCacheHost> actual_code_cache_host, + mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver, + const GURL& script_url) + : actual_code_cache_host_(std::move(actual_code_cache_host)), + receiver_(this, std::move(receiver)), + script_url_(script_url) {} + +SharedStorageCodeCacheHostProxy::~SharedStorageCodeCacheHostProxy() = default; + +void SharedStorageCodeCacheHostProxy::DidGenerateCacheableMetadata( + blink::mojom::CodeCacheType cache_type, + const GURL& url, + base::Time expected_response_time, + mojo_base::BigBuffer data) { + // The only URL we expect to use the code cache is the worklet's script URL. + if (script_url_ != url) { + receiver_.ReportBadMessage("Unexpected request url"); + return; + } + actual_code_cache_host_->DidGenerateCacheableMetadata( + cache_type, url, expected_response_time, std::move(data)); +} + +void SharedStorageCodeCacheHostProxy::FetchCachedCode( + blink::mojom::CodeCacheType cache_type, + const GURL& url, + FetchCachedCodeCallback callback) { + // The only URL we expect to use the code cache is the worklet's script URL. + if (script_url_ != url) { + receiver_.ReportBadMessage("Unexpected request url"); + return; + } + actual_code_cache_host_->FetchCachedCode(cache_type, url, + std::move(callback)); +} + +void SharedStorageCodeCacheHostProxy::ClearCodeCacheEntry( + blink::mojom::CodeCacheType cache_type, + const GURL& url) { + // The only URL we expect to use the code cache is the worklet's script URL. + if (script_url_ != url) { + receiver_.ReportBadMessage("Unexpected request url"); + return; + } + actual_code_cache_host_->ClearCodeCacheEntry(cache_type, url); +} + +void SharedStorageCodeCacheHostProxy:: + DidGenerateCacheableMetadataInCacheStorage( + const GURL& url, + base::Time expected_response_time, + mojo_base::BigBuffer data, + const std::string& cache_storage_cache_name) { + // CacheStorage writes require a Service Worker context, which is inapplicable + // here for Shared Storage Worklets. Thus, this method should never invoke. + receiver_.ReportBadMessage( + "Unexpected call of DidGenerateCacheableMetadataInCacheStorage"); +} + +} // namespace content
diff --git a/content/browser/shared_storage/shared_storage_code_cache_host_proxy.h b/content/browser/shared_storage/shared_storage_code_cache_host_proxy.h new file mode 100644 index 0000000..c6ad7d4 --- /dev/null +++ b/content/browser/shared_storage/shared_storage_code_cache_host_proxy.h
@@ -0,0 +1,56 @@ +// 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 CONTENT_BROWSER_SHARED_STORAGE_SHARED_STORAGE_CODE_CACHE_HOST_PROXY_H_ +#define CONTENT_BROWSER_SHARED_STORAGE_SHARED_STORAGE_CODE_CACHE_HOST_PROXY_H_ + +#include "content/common/content_export.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom.h" +#include "url/gurl.h" + +namespace content { + +// Proxy CodeCacheHost, to limit the requests that a shared storage worklet can +// make. It also implicitly adds a scope -- requests are only allowed during the +// lifetime of `SharedStorageCodeCacheHostProxy`. +class CONTENT_EXPORT SharedStorageCodeCacheHostProxy + : public blink::mojom::CodeCacheHost { + public: + explicit SharedStorageCodeCacheHostProxy( + mojo::PendingRemote<blink::mojom::CodeCacheHost> actual_code_cache_host, + mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver, + const GURL& script_url); + ~SharedStorageCodeCacheHostProxy() override; + + void DidGenerateCacheableMetadata(blink::mojom::CodeCacheType cache_type, + const GURL& url, + base::Time expected_response_time, + mojo_base::BigBuffer data) override; + + void FetchCachedCode(blink::mojom::CodeCacheType cache_type, + const GURL& url, + FetchCachedCodeCallback callback) override; + + void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type, + const GURL& url) override; + + void DidGenerateCacheableMetadataInCacheStorage( + const GURL& url, + base::Time expected_response_time, + mojo_base::BigBuffer data, + const std::string& cache_storage_cache_name) override; + + private: + mojo::Remote<blink::mojom::CodeCacheHost> actual_code_cache_host_; + mojo::Receiver<blink::mojom::CodeCacheHost> receiver_; + const GURL script_url_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SHARED_STORAGE_SHARED_STORAGE_CODE_CACHE_HOST_PROXY_H_
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc index 94b343ff..624726c 100644 --- a/content/browser/shared_storage/shared_storage_worklet_host.cc +++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -26,6 +26,7 @@ #include "content/browser/private_aggregation/private_aggregation_manager.h" #include "content/browser/renderer_host/page_impl.h" #include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/shared_storage/shared_storage_code_cache_host_proxy.h" #include "content/browser/shared_storage/shared_storage_document_service_impl.h" #include "content/browser/shared_storage/shared_storage_render_thread_worklet_driver.h" #include "content/browser/shared_storage/shared_storage_url_loader_factory_proxy.h" @@ -1097,6 +1098,20 @@ blink::mojom::SharedStorageDocumentService::CreateWorkletCallback callback, bool success, const std::string& error_message) { + // After the initial script loading, accessing shared storage will be allowed. + // We want to disable the communication with network and with the cache, to + // prevent leaking shared storage data. + // + // Note: The last code cache message (i.e. `DidGenerateCacheableMetadata()`, + // if any) could race with this `OnAddModuleOnWorkletFinished()` callback, as + // they are from separate mojom channels. It could impact the utility (i.e. + // the generated code is not stored when the race happens). + // + // TODO(crbug.com/341690728): Measure how often the race happens, and + // rearchitect if necessary. + url_loader_factory_proxy_.reset(); + code_cache_host_proxy_.reset(); + std::move(callback).Run(success, error_message); DecrementPendingOperationsCount(); @@ -1312,11 +1327,24 @@ document_service_->render_frame_host().IsFeatureEnabled( blink::mojom::PermissionsPolicyFeature::kPrivateAggregation); + mojo::PendingRemote<blink::mojom::CodeCacheHost> actual_code_cache_host; + static_cast<RenderFrameHostImpl&>(document_service_->render_frame_host()) + .CreateCodeCacheHost( + actual_code_cache_host.InitWithNewPipeAndPassReceiver()); + + mojo::PendingRemote<blink::mojom::CodeCacheHost> proxied_code_cache_host; + + code_cache_host_proxy_ = std::make_unique<SharedStorageCodeCacheHostProxy>( + std::move(actual_code_cache_host), + proxied_code_cache_host.InitWithNewPipeAndPassReceiver(), + script_source_url_); + auto global_scope_creation_params = blink::mojom::WorkletGlobalScopeCreationParams::New( script_source_url_, shared_storage_origin_, origin_trial_features_, devtools_handle_->devtools_token(), devtools_handle_->BindNewPipeAndPassRemote(), + std::move(proxied_code_cache_host), devtools_handle_->wait_for_debugger()); driver_->StartWorkletService(
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.h b/content/browser/shared_storage/shared_storage_worklet_host.h index 5776768..327ddef 100644 --- a/content/browser/shared_storage/shared_storage_worklet_host.h +++ b/content/browser/shared_storage/shared_storage_worklet_host.h
@@ -33,6 +33,7 @@ class RenderProcessHost; class SharedStorageDocumentServiceImpl; class SharedStorageURLLoaderFactoryProxy; +class SharedStorageCodeCacheHostProxy; class SharedStorageWorkletDriver; class SharedStorageWorkletHostManager; class StoragePartitionImpl; @@ -341,6 +342,12 @@ // application/javascript request header; to enforce same-origin mode; etc. std::unique_ptr<SharedStorageURLLoaderFactoryProxy> url_loader_factory_proxy_; + // The proxy is used to limit the request that the worklet can make, e.g. to + // ensure the URL is not modified by a compromised worklet. This is reset + // after the script loading finishes, to prevent leaking the shared storage + // data after that. + std::unique_ptr<SharedStorageCodeCacheHostProxy> code_cache_host_proxy_; + base::WeakPtrFactory<SharedStorageWorkletHost> weak_ptr_factory_{this}; };
diff --git a/content/browser/speech/speech_recognizer_impl.h b/content/browser/speech/speech_recognizer_impl.h index 7e65764..617c279 100644 --- a/content/browser/speech/speech_recognizer_impl.h +++ b/content/browser/speech/speech_recognizer_impl.h
@@ -10,7 +10,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" -#include "content/browser/speech/endpointer/endpointer.h" +#include "components/speech/endpointer/endpointer.h" #include "content/browser/speech/speech_recognition_engine.h" #include "content/browser/speech/speech_recognizer.h" #include "content/common/content_export.h" @@ -172,7 +172,7 @@ raw_ptr<media::AudioSystem, DanglingUntriaged> audio_system_; std::unique_ptr<SpeechRecognitionEngine> recognition_engine_; - Endpointer endpointer_; + speech::Endpointer endpointer_; scoped_refptr<media::AudioCapturerSource> audio_capturer_source_; int num_samples_recorded_; float audio_level_;
diff --git a/content/renderer/accessibility/ax_action_target_factory.cc b/content/renderer/accessibility/ax_action_target_factory.cc index daf1bbd2..70f30d85 100644 --- a/content/renderer/accessibility/ax_action_target_factory.cc +++ b/content/renderer/accessibility/ax_action_target_factory.cc
@@ -8,6 +8,8 @@ #include "content/renderer/accessibility/blink_ax_action_target.h" #include "third_party/blink/public/web/web_ax_object.h" #include "third_party/blink/public/web/web_document.h" +#include "ui/accessibility/ax_enums.mojom-shared.h" +#include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/null_ax_action_target.h" namespace content { @@ -19,10 +21,13 @@ content::PluginAXTreeActionTargetAdapter* plugin_tree_adapter, ui::AXNodeID node_id, ax::mojom::Role role) { - CHECK(node_id == -1 || role == ax::mojom::Role::kNone) + if (node_id == ui::kInvalidAXNodeID && role == ax::mojom::Role::kUnknown) { + return std::make_unique<ui::NullAXActionTarget>(); + } + CHECK(node_id == ui::kInvalidAXNodeID || role == ax::mojom::Role::kUnknown) << "We cannot set both the `node_id` and the `role`"; blink::WebAXObject blink_target; - if (role != ax::mojom::Role::kNone) { + if (role != ax::mojom::Role::kUnknown) { blink_target = blink::WebAXObject::FromWebDocumentFirstWithRole(document, role); } else {
diff --git a/content/renderer/accessibility/ax_action_target_factory.h b/content/renderer/accessibility/ax_action_target_factory.h index fb9fcccdd..9547624 100644 --- a/content/renderer/accessibility/ax_action_target_factory.h +++ b/content/renderer/accessibility/ax_action_target_factory.h
@@ -32,7 +32,7 @@ const blink::WebDocument& document, content::PluginAXTreeActionTargetAdapter* plugin_tree_adapter, ui::AXNodeID node_id, - ax::mojom::Role role = ax::mojom::Role::kNone); + ax::mojom::Role role = ax::mojom::Role::kUnknown); }; } // namespace content
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index ac283ac6..3325f775f9 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -2360,10 +2360,10 @@ "../browser/attribution_reporting/attribution_manager_impl_unittest.cc", "../browser/attribution_reporting/attribution_report_network_sender_unittest.cc", "../browser/attribution_reporting/attribution_report_unittest.cc", - "../browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc", + "../browser/attribution_reporting/attribution_resolver_delegate_impl_unittest.cc", + "../browser/attribution_reporting/attribution_resolver_unittest.cc", "../browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc", "../browser/attribution_reporting/attribution_storage_sql_unittest.cc", - "../browser/attribution_reporting/attribution_storage_unittest.cc", "../browser/attribution_reporting/attribution_suitable_context_unittest.cc", "../browser/attribution_reporting/interop/interop_unittest.cc", "../browser/attribution_reporting/interop/parser_unittest.cc", @@ -3339,7 +3339,6 @@ "../browser/host_zoom_map_impl_unittest.cc", "../browser/picture_in_picture/document_picture_in_picture_navigation_throttle_unittest.cc", "../browser/serial/serial_unittest.cc", - "../browser/speech/endpointer/endpointer_unittest.cc", "../browser/speech/network_speech_recognition_engine_impl_unittest.cc", "../browser/speech/speech_recognizer_impl_unittest.cc", "../browser/tracing/tracing_ui_unittest.cc",
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist index df8f928..87ceb51 100644 --- a/content/test/content_test_bundle_data.filelist +++ b/content/test/content_test_bundle_data.filelist
@@ -7346,6 +7346,8 @@ data/shared_storage/erroneous_function_module.js data/shared_storage/erroneous_module.js data/shared_storage/getter_module.js +data/shared_storage/large_cacheable_script.js +data/shared_storage/large_cacheable_script.js.mock-http-headers data/shared_storage/module_with_custom_header.js data/shared_storage/module_with_custom_header.js.mock-http-headers data/shared_storage/page-with-non-shared-storage-writable-iframe.html
diff --git a/content/test/data/shared_storage/large_cacheable_script.js b/content/test/data/shared_storage/large_cacheable_script.js new file mode 100644 index 0000000..3af9dd2 --- /dev/null +++ b/content/test/data/shared_storage/large_cacheable_script.js
@@ -0,0 +1,17 @@ +// 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. + +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1; +a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;a=1;
diff --git a/content/test/data/shared_storage/large_cacheable_script.js.mock-http-headers b/content/test/data/shared_storage/large_cacheable_script.js.mock-http-headers new file mode 100644 index 0000000..beae210 --- /dev/null +++ b/content/test/data/shared_storage/large_cacheable_script.js.mock-http-headers
@@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Content-Type: text/javascript +Cache-Control: max-age=2592000
diff --git a/content/web_test/renderer/test_runner.cc b/content/web_test/renderer/test_runner.cc index 8fbf5061..6f475ee3 100644 --- a/content/web_test/renderer/test_runner.cc +++ b/content/web_test/renderer/test_runner.cc
@@ -2764,6 +2764,10 @@ web_test_runtime_flags_.is_printing(); } +bool TestRunner::IsPrinting() const { + return web_test_runtime_flags_.is_printing(); +} + #if BUILDFLAG(ENABLE_PRINTING) gfx::Size TestRunner::GetPrintingPageSize(blink::WebLocalFrame* frame) const { const int printing_width = web_test_runtime_flags_.printing_width();
diff --git a/content/web_test/renderer/test_runner.h b/content/web_test/renderer/test_runner.h index 3cf6d38..9b97c024 100644 --- a/content/web_test/renderer/test_runner.h +++ b/content/web_test/renderer/test_runner.h
@@ -129,6 +129,8 @@ // can be done locally in the renderer via DumpPixelsInRenderer(). bool CanDumpPixelsFromRenderer() const; + bool IsPrinting() const; + #if BUILDFLAG(ENABLE_PRINTING) // Returns the default page size to be used for printing. This is either the // size that was explicitly set via SetPrintingSize or the size of the frame
diff --git a/content/web_test/renderer/web_frame_test_proxy.cc b/content/web_test/renderer/web_frame_test_proxy.cc index eec6155..f5d4a7bb 100644 --- a/content/web_test/renderer/web_frame_test_proxy.cc +++ b/content/web_test/renderer/web_frame_test_proxy.cc
@@ -787,14 +787,24 @@ void WebFrameTestProxy::StartTest() { CHECK(!should_block_parsing_in_next_commit_); GetWebFrame()->FlushInputForTesting(base::BindOnce( - [](base::WeakPtr<RenderFrameImpl> render_frame) { - if (!render_frame || !render_frame->GetWebFrame()) { + [](base::WeakPtr<RenderFrameImpl> render_frame, + const TestRunner* test_runner) { + if (!render_frame) { return; } - render_frame->GetWebFrame()->ResumeParserForTesting(); + auto* web_frame = render_frame->GetWebFrame(); + if (!web_frame) { + return; + } + + web_frame->ResumeParserForTesting(); + + if (test_runner->IsPrinting()) { + web_frame->WillPrintSoon(); + } }, - GetWeakPtr())); + GetWeakPtr(), this->test_runner_)); } blink::FrameWidgetTestHelper*
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc index fa7ff8c..779a609 100644 --- a/gpu/config/gpu_finch_features.cc +++ b/gpu/config/gpu_finch_features.cc
@@ -175,6 +175,11 @@ "EnableMSAAOnNewIntelGPUs", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables the use of ANGLE validation for non-WebGL contexts. +BASE_FEATURE(kDefaultEnableANGLEValidation, + "DefaultEnableANGLEValidation", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enables canvas to free its resources by default when it's running in // the background. BASE_FEATURE(kCanvasContextLostInBackground, @@ -573,6 +578,11 @@ return IsDrDcEnabled() || IsUsingThreadSafeMediaForWebView(); } +bool IsANGLEValidationEnabled() { + return base::FeatureList::IsEnabled(kDefaultEnableANGLEValidation) && + UsePassthroughCommandDecoder(); +} + namespace { bool IsSkiaGraphiteSupportedByDevice(const base::CommandLine* command_line) { #if BUILDFLAG(IS_APPLE)
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h index e7fca776..e4a49f7 100644 --- a/gpu/config/gpu_finch_features.h +++ b/gpu/config/gpu_finch_features.h
@@ -43,6 +43,8 @@ GPU_EXPORT BASE_DECLARE_FEATURE(kEnableMSAAOnNewIntelGPUs); +GPU_EXPORT BASE_DECLARE_FEATURE(kDefaultEnableANGLEValidation); + GPU_EXPORT BASE_DECLARE_FEATURE(kCanvasContextLostInBackground); #if BUILDFLAG(IS_WIN) @@ -116,6 +118,7 @@ GPU_EXPORT bool IsUsingVulkan(); GPU_EXPORT bool IsDrDcEnabled(); GPU_EXPORT bool NeedThreadSafeAndroidMedia(); +GPU_EXPORT bool IsANGLEValidationEnabled(); GPU_EXPORT bool IsSkiaGraphiteEnabled(const base::CommandLine* command_line); GPU_EXPORT bool EnablePurgeGpuImageDecodeCache(); GPU_EXPORT bool EnablePruneOldTransferCacheEntries();
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc index 4b28124..271b10140 100644 --- a/gpu/ipc/service/gpu_channel_manager.cc +++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -914,6 +914,10 @@ gpu_driver_bug_workarounds_.use_virtualized_gl_contexts; bool enable_angle_validation = features::IsANGLEValidationEnabled(); +#if DCHECK_IS_ON() + // Force validation on for all debug builds and testing + enable_angle_validation = true; +#endif scoped_refptr<gl::GLShareGroup> share_group; bool use_passthrough_decoder = use_passthrough_cmd_decoder();
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index 7a12c5a..89a195a 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -267,16 +267,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 127.0.6490.0', + 'description': 'Run with ash-chrome version 127.0.6491.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6490.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v127.0.6490.0', - 'revision': 'version:127.0.6490.0', + 'location': 'lacros_version_skew_tests_v127.0.6491.0', + 'revision': 'version:127.0.6491.0', }, ], },
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index 5f4eadb5..c32a163 100644 --- a/infra/config/targets/lacros-version-skew-variants.json +++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@ { "LACROS_VERSION_SKEW_CANARY": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.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_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ] }
diff --git a/internal b/internal index 60b76f3..1ec6eaf 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 60b76f3502c88409b8190bc66362666ffe6dce81 +Subproject commit 1ec6eaf1463ef817385ef7fd9014c5e74ce4b91b
diff --git a/ios/chrome/browser/parcel_tracking/BUILD.gn b/ios/chrome/browser/parcel_tracking/BUILD.gn index b5aedf8..3706932 100644 --- a/ios/chrome/browser/parcel_tracking/BUILD.gn +++ b/ios/chrome/browser/parcel_tracking/BUILD.gn
@@ -44,6 +44,10 @@ sources = [ "parcel_tracking_step.h" ] } +source_set("opt_in_status") { + sources = [ "parcel_tracking_opt_in_status.h" ] +} + source_set("prefs") { sources = [ "parcel_tracking_prefs.h", @@ -62,6 +66,7 @@ ] deps = [ ":metrics", + ":opt_in_status", ":prefs", ":tracking_source", "//base",
diff --git a/ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h b/ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h new file mode 100644 index 0000000..95eaa80 --- /dev/null +++ b/ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h
@@ -0,0 +1,17 @@ +// 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 IOS_CHROME_BROWSER_PARCEL_TRACKING_PARCEL_TRACKING_OPT_IN_STATUS_H_ +#define IOS_CHROME_BROWSER_PARCEL_TRACKING_PARCEL_TRACKING_OPT_IN_STATUS_H_ + +// Enum for the different values of the parcel tracking opt-in status. +enum class IOSParcelTrackingOptInStatus { + kNeverTrack = 0, + kAlwaysTrack = 1, + kAskToTrack = 2, + kStatusNotSet = 3, + kMaxValue = kStatusNotSet, +}; + +#endif // IOS_CHROME_BROWSER_PARCEL_TRACKING_PARCEL_TRACKING_OPT_IN_STATUS_H_
diff --git a/ios/chrome/browser/parcel_tracking/parcel_tracking_util.h b/ios/chrome/browser/parcel_tracking/parcel_tracking_util.h index 8dcea2f6..b2d15f8f2 100644 --- a/ios/chrome/browser/parcel_tracking/parcel_tracking_util.h +++ b/ios/chrome/browser/parcel_tracking/parcel_tracking_util.h
@@ -17,13 +17,6 @@ @protocol ParcelTrackingOptInCommands; -// Enum for the different values of the parcel tracking opt-in status. -enum class IOSParcelTrackingOptInStatus { - kNeverTrack = 0, - kAlwaysTrack = 1, - kAskToTrack = 2, -}; - // Returns true if the parcel tracking feature is enabled. This returns true if // 1) the policy is not disabled for enterprise users and 2) the user's // permanent location is in the US.
diff --git a/ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.mm b/ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.mm index 98bb123..4239d4a2 100644 --- a/ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.mm +++ b/ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.mm
@@ -503,7 +503,7 @@ break; } - // If the Omaha response isn't recieved after `kOmahaNetworkWaitTime`, + // If the Omaha response isn't received after `kOmahaNetworkWaitTime`, // consider this an Omaha failure. task_runner_->PostDelayedTask( FROM_HERE,
diff --git a/ios/chrome/browser/shared/model/prefs/BUILD.gn b/ios/chrome/browser/shared/model/prefs/BUILD.gn index 93173085..f989cd2d 100644 --- a/ios/chrome/browser/shared/model/prefs/BUILD.gn +++ b/ios/chrome/browser/shared/model/prefs/BUILD.gn
@@ -89,6 +89,7 @@ "//ios/chrome/browser/net/model", "//ios/chrome/browser/ntp/model:set_up_list_prefs", "//ios/chrome/browser/ntp_tiles/model/tab_resumption:tab_resumption_prefs", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/parcel_tracking:prefs", "//ios/chrome/browser/photos/model:policy", "//ios/chrome/browser/policy/model:policy_util",
diff --git a/ios/chrome/browser/shared/model/prefs/DEPS b/ios/chrome/browser/shared/model/prefs/DEPS index 0247a0b..5ebd1ed 100644 --- a/ios/chrome/browser/shared/model/prefs/DEPS +++ b/ios/chrome/browser/shared/model/prefs/DEPS
@@ -15,6 +15,7 @@ "+ios/chrome/browser/photos/model/photos_policy.h", "+ios/chrome/browser/drive/model/drive_policy.h", "+ios/chrome/browser/web/model/annotations/annotations_util.h", + "+ios/chrome/browser/parcel_tracking", ] specific_include_rules = {
diff --git a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm index 172035fe..4b6bd388 100644 --- a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm +++ b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
@@ -79,6 +79,7 @@ #import "ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.h" #import "ios/chrome/browser/ntp/model/set_up_list_prefs.h" #import "ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/parcel_tracking/parcel_tracking_prefs.h" #import "ios/chrome/browser/photos/model/photos_policy.h" #import "ios/chrome/browser/policy/model/policy_util.h" @@ -716,7 +717,9 @@ // Preferences related to parcel tracking. registry->RegisterBooleanPref( prefs::kIosParcelTrackingOptInPromptDisplayLimitMet, false); - registry->RegisterIntegerPref(prefs::kIosParcelTrackingOptInStatus, 2); + registry->RegisterIntegerPref( + prefs::kIosParcelTrackingOptInStatus, + static_cast<int>(IOSParcelTrackingOptInStatus::kStatusNotSet)); registry->RegisterBooleanPref(prefs::kIosParcelTrackingOptInPromptSwipedDown, false);
diff --git a/ios/chrome/browser/shared/ui/util/property_animator_group.h b/ios/chrome/browser/shared/ui/util/property_animator_group.h index 7d878e85..3d4fe16 100644 --- a/ios/chrome/browser/shared/ui/util/property_animator_group.h +++ b/ios/chrome/browser/shared/ui/util/property_animator_group.h
@@ -13,7 +13,7 @@ // animators in a group. Since instances of this class conform to that protocol, // in most cases an animator group can be used where a single property animator // would be (provided that the call sites want a id<UIViewImplicitlyAnimating>). -// Protocol methods that mutate the reciever are sequentially appiled to all of +// Protocol methods that mutate the receiver are sequentially appiled to all of // the animators in the group (this include -startAnimation, -stopAnimation:, // and so on). -addAnimations:, -addCompletion:, and similar methods are just // applied to the first animator in the group. Methods (and property getters)
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 2ad6d1d6..c513934 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -86,6 +86,7 @@ "//ios/chrome/browser/overlays/model/public/web_content_area", "//ios/chrome/browser/overscroll_actions/model", "//ios/chrome/browser/parcel_tracking:infobar_delegate", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/parcel_tracking:parcel_tracking_step", "//ios/chrome/browser/parcel_tracking:prefs", "//ios/chrome/browser/parcel_tracking:tracking_source",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index de8da10..19e025e 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -55,6 +55,7 @@ #import "ios/chrome/browser/ntp/model/new_tab_page_tab_helper.h" #import "ios/chrome/browser/overscroll_actions/model/overscroll_actions_tab_helper.h" #import "ios/chrome/browser/parcel_tracking/parcel_tracking_infobar_delegate.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/parcel_tracking/parcel_tracking_step.h" #import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" #import "ios/chrome/browser/parcel_tracking/tracking_source.h" @@ -2701,6 +2702,7 @@ kAskedToTrackPackage]; break; case IOSParcelTrackingOptInStatus::kNeverTrack: + case IOSParcelTrackingOptInStatus::kStatusNotSet: // Do not display infobar. break; }
diff --git a/ios/chrome/browser/ui/parcel_tracking/BUILD.gn b/ios/chrome/browser/ui/parcel_tracking/BUILD.gn index 70a939d..8464b6d 100644 --- a/ios/chrome/browser/ui/parcel_tracking/BUILD.gn +++ b/ios/chrome/browser/ui/parcel_tracking/BUILD.gn
@@ -16,6 +16,7 @@ "//components/prefs", "//ios/chrome/browser/commerce/model:shopping_service", "//ios/chrome/browser/parcel_tracking:metrics", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/parcel_tracking:parcel_tracking_step", "//ios/chrome/browser/parcel_tracking:tracking_source", "//ios/chrome/browser/parcel_tracking:util", @@ -39,7 +40,7 @@ deps = [ "//base", "//ios/chrome/app/strings", - "//ios/chrome/browser/parcel_tracking:util", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/shared/ui/symbols", "//ios/chrome/browser/shared/ui/table_view/cells", "//ios/chrome/browser/ui/parcel_tracking/resources", @@ -61,6 +62,7 @@ "//base/test:test_support", "//components/prefs", "//ios/chrome/browser/parcel_tracking:metrics", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/parcel_tracking:util", "//ios/chrome/browser/shared/model/browser/test:test_support", "//ios/chrome/browser/shared/model/browser_state:test_support",
diff --git a/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator.mm b/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator.mm index 4622b73..f40194d0 100644 --- a/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator.mm +++ b/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator.mm
@@ -8,7 +8,7 @@ #import "base/metrics/histogram_functions.h" #import "components/prefs/pref_service.h" #import "ios/chrome/browser/parcel_tracking/metrics.h" -#import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
diff --git a/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator_unittest.mm b/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator_unittest.mm index 28a704c..a15e69b1 100644 --- a/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_coordinator_unittest.mm
@@ -9,7 +9,7 @@ #import "base/test/metrics/histogram_tester.h" #import "components/prefs/pref_service.h" #import "ios/chrome/browser/parcel_tracking/metrics.h" -#import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/shared/model/browser/test/test_browser.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
diff --git a/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_view_controller.mm b/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_view_controller.mm index 042f5ab..bb9c058 100644 --- a/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_view_controller.mm +++ b/ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_view_controller.mm
@@ -5,7 +5,7 @@ #import "ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_view_controller.h" #import "base/notreached.h" -#import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_item.h" #import "ios/chrome/browser/ui/parcel_tracking/parcel_tracking_opt_in_view_controller_delegate.h" @@ -115,6 +115,7 @@ [self.delegate askToTrackTapped]; break; case IOSParcelTrackingOptInStatus::kNeverTrack: + case IOSParcelTrackingOptInStatus::kStatusNotSet: NOTREACHED_IN_MIGRATION(); break; }
diff --git a/ios/chrome/browser/ui/settings/google_services/BUILD.gn b/ios/chrome/browser/ui/settings/google_services/BUILD.gn index 93eeeb4..c59c066 100644 --- a/ios/chrome/browser/ui/settings/google_services/BUILD.gn +++ b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
@@ -51,6 +51,7 @@ "//ios/chrome/app/strings", "//ios/chrome/browser/commerce/model:model", "//ios/chrome/browser/net/model:crurl", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/parcel_tracking:util", "//ios/chrome/browser/policy/model:policy_util", "//ios/chrome/browser/search_engines/model:template_url_service_factory", @@ -119,6 +120,7 @@ "//components/prefs", "//components/prefs/ios", "//ios/chrome/app/strings", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/parcel_tracking:util", "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser", @@ -280,7 +282,7 @@ "//components/variations:test_support", "//google_apis", "//ios/chrome/app/strings", - "//ios/chrome/browser/parcel_tracking:util", + "//ios/chrome/browser/parcel_tracking:opt_in_status", "//ios/chrome/browser/shared/model/application_context", "//ios/chrome/browser/shared/model/browser/test:test_support", "//ios/chrome/browser/shared/model/browser_state:test_support",
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm index fdc1240b..41901e3e 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm
@@ -15,6 +15,7 @@ #import "components/supervised_user/core/browser/supervised_user_preferences.h" #import "components/sync/service/sync_service.h" #import "components/unified_consent/pref_names.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" #import "ios/chrome/browser/policy/model/policy_util.h" #import "ios/chrome/browser/settings/model/sync/utils/sync_util.h" @@ -468,6 +469,7 @@ IDS_IOS_GOOGLE_SERVICES_SETTINGS_AUTO_TRACK_PACKAGES_ALL); break; case IOSParcelTrackingOptInStatus::kAskToTrack: + case IOSParcelTrackingOptInStatus::kStatusNotSet: currentOptInStatusString = l10n_util::GetNSString( IDS_IOS_PARCEL_TRACKING_OPT_IN_TERTIARY_ACTION); break;
diff --git a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator.mm index 80de38b..d6cc90f 100644 --- a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator.mm +++ b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator.mm
@@ -8,7 +8,7 @@ #import "components/prefs/pref_change_registrar.h" #import "components/prefs/pref_member.h" #import "components/prefs/pref_service.h" -#import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_model_consumer.h"
diff --git a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator_unittest.mm b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator_unittest.mm index 3a16a63f..ea26e715 100644 --- a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator_unittest.mm
@@ -5,7 +5,7 @@ #import "ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_mediator.h" #import "components/sync_preferences/testing_pref_service_syncable.h" -#import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/ui/list_model/list_model.h" @@ -56,7 +56,8 @@ TEST_F(ParcelTrackingSettingsMediatorUnittest, TestLoadModel) { mediator_.consumer = consumer_; - EXPECT_EQ(consumer_.latestStatus, IOSParcelTrackingOptInStatus::kAskToTrack); + EXPECT_EQ(consumer_.latestStatus, + IOSParcelTrackingOptInStatus::kStatusNotSet); [mediator_ disconnect]; }
diff --git a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller.mm b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller.mm index 4344b89..5cd9860 100644 --- a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller.mm +++ b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller.mm
@@ -4,7 +4,8 @@ #import "ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller.h" -#import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" +#import "base/notreached.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/shared/ui/list_model/list_model.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_detail_text_item.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.h" @@ -131,6 +132,15 @@ UITableViewCellAccessoryType desiredType = itemSetting == newState ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; + + // If the status is not explicitly set (default), then "Ask To Track" should + // be selected. kStatusNotSet and kAskToTrack have the same behavior and are + // only differentiated for metrics. + if (newState == IOSParcelTrackingOptInStatus::kStatusNotSet && + itemSetting == IOSParcelTrackingOptInStatus::kAskToTrack) { + desiredType = UITableViewCellAccessoryCheckmark; + } + if (item.accessoryType != desiredType) { item.accessoryType = desiredType; [modifiedItems addObject:item];
diff --git a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller_unittest.mm index e4a32bd..f527ffb 100644 --- a/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller_unittest.mm
@@ -4,7 +4,7 @@ #import "ios/chrome/browser/ui/settings/google_services/parcel_tracking_settings_view_controller.h" -#import "ios/chrome/browser/parcel_tracking/parcel_tracking_util.h" +#import "ios/chrome/browser/parcel_tracking/parcel_tracking_opt_in_status.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_detail_text_item.h" #import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h" #import "testing/platform_test.h"
diff --git a/ios/chrome/browser/ui/sharing/share_download_overlay_coordinator.mm b/ios/chrome/browser/ui/sharing/share_download_overlay_coordinator.mm index 1bfb80ca..caf4a88e 100644 --- a/ios/chrome/browser/ui/sharing/share_download_overlay_coordinator.mm +++ b/ios/chrome/browser/ui/sharing/share_download_overlay_coordinator.mm
@@ -19,7 +19,7 @@ } // namespace @interface ShareDownloadOverlayCoordinator () { - // Web state that will recieve the overlay view. + // Web state that will receive the overlay view. raw_ptr<web::WebState> _webState; }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/transitions/legacy_grid_transition_layout.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/transitions/legacy_grid_transition_layout.h index 98f59333..0f5ff58 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/transitions/legacy_grid_transition_layout.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/transitions/legacy_grid_transition_layout.h
@@ -86,7 +86,7 @@ center:(CGPoint)center size:(CGSize)size; -// Populate the `cell` view of the reciever by extracting snapshots from `view`, +// Populate the `cell` view of the receiver by extracting snapshots from `view`, // using `rect` to define (in `view`'s coordinates) the main tab view, with any // space above and below `rect` being the top and bottom tab views. - (void)populateWithSnapshotsFromView:(UIView*)view middleRect:(CGRect)rect;
diff --git a/ios/chrome/browser/ui/tabs/foreground_tab_animation_view.h b/ios/chrome/browser/ui/tabs/foreground_tab_animation_view.h index 82c146e..64159c1 100644 --- a/ios/chrome/browser/ui/tabs/foreground_tab_animation_view.h +++ b/ios/chrome/browser/ui/tabs/foreground_tab_animation_view.h
@@ -17,7 +17,7 @@ // Starts a New Tab animation in `parentView`, from `originPoint` with // a `completion` block. The new tab will scale up and move from the direction -// if `originPoint` to the center of the reciever. `originPoint` must be in +// if `originPoint` to the center of the receiver. `originPoint` must be in // UIWindow coordinates. - (void)animateFrom:(CGPoint)originPoint withCompletion:(void (^)())completion;
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.h b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.h index c82c663d..be2d28c7 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.h +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.h
@@ -156,7 +156,7 @@ // A PendingReceiver for `url_loader_factory_`, used during service // initialization. mojo::PendingReceiver<network::mojom::URLLoaderFactory> - url_loader_factory_pending_reciever_; + url_loader_factory_pending_receiver_; // A SharedURLLoaderFactory that wraps `url_loader_factory_`. scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm index 45dd42a6..70e8c426 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm
@@ -59,7 +59,7 @@ } // namespace SafeBrowsingServiceImpl::SafeBrowsingServiceImpl() { - url_loader_factory_pending_reciever_ = + url_loader_factory_pending_receiver_ = url_loader_factory_.BindNewPipeAndPassReceiver(); shared_url_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( @@ -103,7 +103,7 @@ url_loader_factory_params->process_id = network::mojom::kBrowserProcessId; url_loader_factory_params->is_orb_enabled = false; network_context_client_->CreateURLLoaderFactory( - std::move(url_loader_factory_pending_reciever_), + std::move(url_loader_factory_pending_receiver_), std::move(url_loader_factory_params)); // Watch for changes to the Safe Browsing opt-out preference.
diff --git a/ios/web/js_messaging/web_view_js_utils_unittest.mm b/ios/web/js_messaging/web_view_js_utils_unittest.mm index 96bdedd..f5512fa 100644 --- a/ios/web/js_messaging/web_view_js_utils_unittest.mm +++ b/ios/web/js_messaging/web_view_js_utils_unittest.mm
@@ -34,7 +34,7 @@ // Returns the WKFrameInfo instance for the main frame of `web_view`. WKFrameInfo* GetMainFrameWKFrameInfo(WKWebView* web_view) { - // Setup a message handler and recieve a message to obtain a WKFrameInfo + // Setup a message handler and receive a message to obtain a WKFrameInfo // instance. CRWFakeScriptMessageHandler* script_message_handler = [[CRWFakeScriptMessageHandler alloc] init];
diff --git a/media/gpu/av1_decoder.cc b/media/gpu/av1_decoder.cc index 5f0d608..434cc62 100644 --- a/media/gpu/av1_decoder.cc +++ b/media/gpu/av1_decoder.cc
@@ -5,14 +5,15 @@ #include "media/gpu/av1_decoder.h" #include <bitset> +#include <utility> -#include "base/functional/callback_helpers.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/ranges/algorithm.h" #include "media/base/limits.h" #include "media/base/media_switches.h" #include "media/gpu/av1_picture.h" +#include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #include "third_party/libgav1/src/src/decoder_state.h" #include "third_party/libgav1/src/src/gav1/status_code.h" #include "third_party/libgav1/src/src/utils/constants.h" @@ -250,15 +251,14 @@ return kRanOutOfStreamData; } while (parser_->HasData() || current_frame_header_) { - base::ScopedClosureRunner clear_current_frame( - base::BindOnce(&AV1Decoder::ClearCurrentFrame, base::Unretained(this))); + absl::Cleanup clear_current_frame = [this] { ClearCurrentFrame(); }; if (pending_pic_) { const AV1Accelerator::Status status = DecodeAndOutputPicture( std::move(pending_pic_), parser_->tile_buffers()); if (status == AV1Accelerator::Status::kFail) return kDecodeError; if (status == AV1Accelerator::Status::kTryAgain) { - clear_current_frame.ReplaceClosure(base::DoNothing()); + std::move(clear_current_frame).Cancel(); return kTryAgain; } // Continue so that we force |clear_current_frame| to run before moving @@ -368,7 +368,7 @@ profile_ = new_profile; bit_depth_ = new_bit_depth; picture_color_space_ = new_color_space; - clear_current_frame.ReplaceClosure(base::DoNothing()); + std::move(clear_current_frame).Cancel(); return kConfigChange; } } @@ -480,7 +480,7 @@ : accelerator_->CreateAV1Picture( frame_header.film_grain_params.apply_grain); if (!pic) { - clear_current_frame.ReplaceClosure(base::DoNothing()); + std::move(clear_current_frame).Cancel(); return kRanOutOfSurfaces; } @@ -501,7 +501,7 @@ if (status == AV1Accelerator::Status::kFail) return kDecodeError; if (status == AV1Accelerator::Status::kTryAgain) { - clear_current_frame.ReplaceClosure(base::DoNothing()); + std::move(clear_current_frame).Cancel(); return kTryAgain; } }
diff --git a/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc b/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc index 4c7bded..1489ace 100644 --- a/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc +++ b/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc
@@ -24,6 +24,7 @@ #include "media/gpu/v4l2/stateless/vp8_delegate.h" #include "media/gpu/v4l2/stateless/vp9_delegate.h" #include "media/gpu/v4l2/v4l2_status.h" +#include "third_party/abseil-cpp/absl/cleanup/cleanup.h" // Logging for the decoder is following this convention: // @@ -242,10 +243,11 @@ // In order to preserve the order of the callbacks between Decode() and // Reset(), we also trampoline |reset_cb|. - base::ScopedClosureRunner scoped_trampoline_reset_cb( - base::BindOnce(base::IgnoreResult(&base::SequencedTaskRunner::PostTask), - base::SequencedTaskRunner::GetCurrentDefault(), FROM_HERE, - std::move(reset_cb))); + absl::Cleanup scoped_trampoline_reset_cb = + [reset_cb = std::move(reset_cb)]() mutable { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, std::move(reset_cb)); + }; decoder_->Reset();
diff --git a/media/gpu/v4l2/v4l2_stateful_video_decoder.cc b/media/gpu/v4l2/v4l2_stateful_video_decoder.cc index b3b2813e..8d9d1a51 100644 --- a/media/gpu/v4l2/v4l2_stateful_video_decoder.cc +++ b/media/gpu/v4l2/v4l2_stateful_video_decoder.cc
@@ -13,7 +13,6 @@ #include "base/containers/contains.h" #include "base/containers/heap_array.h" #include "base/files/file_util.h" -#include "base/functional/callback_helpers.h" #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" @@ -30,6 +29,7 @@ #include "media/gpu/v4l2/v4l2_queue.h" #include "media/gpu/v4l2/v4l2_utils.h" #include "media/video/h264_parser.h" +#include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #include "ui/gfx/geometry/size.h" namespace { @@ -532,10 +532,11 @@ // In order to preserve the order of the callbacks between Decode() and // Reset(), we also trampoline |closure|. - base::ScopedClosureRunner scoped_trampoline_reset_cb( - base::BindOnce(base::IgnoreResult(&base::SequencedTaskRunner::PostTask), - base::SequencedTaskRunner::GetCurrentDefault(), FROM_HERE, - std::move(closure))); + absl::Cleanup scoped_trampoline_reset = [closure = + std::move(closure)]() mutable { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, std::move(closure)); + }; // Invalidate pointers from and cancel all hypothetical in-flight requests // to the WaitOnceForEvents() routine.
diff --git a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc index 1e4aad8..b692a37 100644 --- a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc
@@ -10,7 +10,6 @@ #include <utility> #include "base/functional/bind.h" -#include "base/functional/callback_helpers.h" #include "base/logging.h" #include "base/memory/shared_memory_mapping.h" #include "base/memory/unsafe_shared_memory_region.h" @@ -31,6 +30,7 @@ #include "media/gpu/vaapi/vaapi_jpeg_encoder.h" #include "media/gpu/vaapi/vaapi_utils.h" #include "media/parsers/jpeg_parser.h" +#include "third_party/abseil-cpp/absl/cleanup/cleanup.h" namespace media { @@ -316,8 +316,9 @@ notify_error_cb_.Run(task_id, PLATFORM_FAILURE); return; } - base::ScopedClosureRunner output_gmb_buffer_unmapper(base::BindOnce( - &gfx::GpuMemoryBuffer::Unmap, base::Unretained(output_gmb_buffer.get()))); + absl::Cleanup output_gmb_buffer_unmapper = [&output_gmb_buffer] { + output_gmb_buffer->Unmap(); + }; // Get the encoded output. DownloadFromVABuffer() is a blocking call. It // would wait until encoding is finished.
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc index 339067b..66a3fe6 100644 --- a/media/gpu/vaapi/vaapi_wrapper.cc +++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -56,6 +56,7 @@ // Auto-generated for dlopen libva libraries #include "media/gpu/vaapi/va_stubs.h" #include "media/media_buildflags.h" +#include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #include "third_party/libva_protected_content/va_protected_content.h" #include "third_party/libyuv/include/libyuv.h" #include "ui/gfx/buffer_format_util.h" @@ -1170,16 +1171,15 @@ vaCreateConfig(va_display, va_profile, entrypoint, &required_attribs[0], required_attribs.size(), &va_config_id); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVACreateConfig, false); - base::ScopedClosureRunner vaconfig_destroyer(base::BindOnce( - [](VADisplay display, VAConfigID id) { - if (id != VA_INVALID_ID) { - VAStatus va_res = vaDestroyConfig(display, id); - if (va_res != VA_STATUS_SUCCESS) - LOG(ERROR) << "vaDestroyConfig failed. VA error: " - << vaErrorStr(va_res); - } - }, - va_display, va_config_id)); + absl::Cleanup vaconfig_destroyer = [va_display, va_config_id] { + if (va_config_id != VA_INVALID_ID) { + VAStatus va_res = vaDestroyConfig(va_display, va_config_id); + if (va_res != VA_STATUS_SUCCESS) { + LOG(ERROR) << "vaDestroyConfig failed. VA error: " + << vaErrorStr(va_res); + } + } + }; #if BUILDFLAG(IS_CHROMEOS_ASH) // Nothing further to query for protected profile. @@ -1271,16 +1271,15 @@ va_res = vaCreateConfig(va_display, va_profile, entrypoint, nullptr, 0, &va_config_id); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVACreateConfig, false); - base::ScopedClosureRunner vaconfig_no_attribs_destroyer(base::BindOnce( - [](VADisplay display, VAConfigID id) { - if (id != VA_INVALID_ID) { - VAStatus va_res = vaDestroyConfig(display, id); - if (va_res != VA_STATUS_SUCCESS) - LOG(ERROR) << "vaDestroyConfig failed. VA error: " - << vaErrorStr(va_res); - } - }, - va_display, va_config_id)); + absl::Cleanup vaconfig_no_attribs_destroyer = [va_display, va_config_id] { + if (va_config_id != VA_INVALID_ID) { + VAStatus va_res = vaDestroyConfig(va_display, va_config_id); + if (va_res != VA_STATUS_SUCCESS) { + LOG(ERROR) << "vaDestroyConfig failed. VA error: " + << vaErrorStr(va_res); + } + } + }; profile_info->supported_internal_formats = {}; size_t max_num_config_attributes; if (!base::CheckedNumeric<int>(vaMaxNumConfigAttributes(va_display)) @@ -1319,7 +1318,7 @@ return is_any_profile_supported; } -void DestroyVAImage(VADisplay va_display, VAImage image) { +void DestroyVAImage(VADisplay va_display, const VAImage& image) { if (image.image_id != VA_INVALID_ID) vaDestroyImage(va_display, image.image_id); } @@ -1573,13 +1572,11 @@ } const VADisplay va_display = vaGetDisplayDRM(drm_fd_.get()); - base::ScopedClosureRunner va_display_cleaner_cb(base::BindOnce( - [](VADisplay va_display) { - if (vaDisplayIsValid(va_display)) { - vaTerminate(va_display); - } - }, - va_display)); + absl::Cleanup va_display_cleaner_cb = [va_display] { + if (vaDisplayIsValid(va_display)) { + vaTerminate(va_display); + } + }; if (!vaDisplayIsValid(va_display)) { LOG(ERROR) << "Could not get a valid VA display"; @@ -1632,7 +1629,7 @@ return false; } - std::ignore = va_display_cleaner_cb.Release(); + std::move(va_display_cleaner_cb).Cancel(); refcount_ = 1; va_display_ = va_display; implementation_type_ = implementation_type; @@ -2814,8 +2811,11 @@ VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVACreateImage, false); needs_va_put_image = true; } - base::ScopedClosureRunner vaimage_deleter( - base::BindOnce(&DestroyVAImage, va_display_, image)); + absl::Cleanup vaimage_deleter = + [this, &image]() EXCLUSIVE_LOCKS_REQUIRED(va_lock_.get()) { + VAAPI_CHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DestroyVAImage(va_display_, image); + }; if (image.format.fourcc != VA_FOURCC_NV12) { LOG(ERROR) << "Unsupported image format: " << image.format.fourcc; @@ -3121,20 +3121,22 @@ } #if BUILDFLAG(IS_CHROMEOS_ASH) - base::ScopedClosureRunner protected_session_detacher; if (va_protected_session_id != VA_INVALID_ID) { const VAStatus va_res = vaAttachProtectedSession( va_display_, va_context_id_, va_protected_session_id); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVAAttachProtectedSession, false); - // Note that we use a lambda expression to wrap vaDetachProtectedSession() - // because the function in |protected_session_detacher| must return void. - protected_session_detacher.ReplaceClosure(base::BindOnce( - [](VADisplay va_display, VAContextID va_context_id) { - vaDetachProtectedSession(va_display, va_context_id); - }, - va_display_, va_context_id_)); } + + absl::Cleanup protected_session_detacher = + [va_protected_session_id, this]() + EXCLUSIVE_LOCKS_REQUIRED(va_lock_.get()) { + if (va_protected_session_id == VA_INVALID_ID) { + return; + } + VAAPI_CHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + vaDetachProtectedSession(va_display_, va_context_id_); + }; #endif // BUILDFLAG(IS_CHROMEOS_ASH) TRACE_EVENT2("media,gpu", "VaapiWrapper::BlitSurface", "src_rect", @@ -3504,8 +3506,11 @@ MAYBE_ASSERT_ACQUIRED(va_lock_); DCHECK(IsValidVABufferType(va_buffer.type)); - base::ScopedClosureRunner pending_buffers_destroyer_on_failure(base::BindOnce( - &VaapiWrapper::DestroyPendingBuffers_Locked, base::Unretained(this))); + absl::Cleanup pending_buffers_destroyer_on_failure = + [this]() EXCLUSIVE_LOCKS_REQUIRED(va_lock_.get()) { + VAAPI_CHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DestroyPendingBuffers_Locked(); + }; unsigned int va_buffer_size; // We use a null |va_buffer|.data for testing: it signals that we want this // SubmitBuffer_Locked() call to fail. @@ -3529,7 +3534,7 @@ } pending_va_buffers_.push_back(buffer_id); - pending_buffers_destroyer_on_failure.ReplaceClosure(base::DoNothing()); + std::move(pending_buffers_destroyer_on_failure).Cancel(); return true; }
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 64fee2cc..0d880bc 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -326,6 +326,7 @@ auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()), http_server_properties_(std::make_unique<HttpServerProperties>()), ssl_data_(ASYNC, OK) { + SetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5, true); if (GetParam().priority_header_enabled) { feature_list_.InitAndEnableFeature(net::features::kPriorityHeader); } else { @@ -1778,16 +1779,25 @@ ConstructClientAckPacket(packet_num++, 3, 2)); mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientDataPacket(packet_num++, GetQpackDecoderStreamId(), false, + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite(SYNCHRONOUS, + client_maker_->MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + mock_quic_data.AddWrite(SYNCHRONOUS, + ConstructClientDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -3410,12 +3420,21 @@ 1, GetNthClientInitiatedBidirectionalStreamId(0), quic::QUIC_HEADERS_TOO_LARGE)); - quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeAckRstAndDataPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_HEADERS_TOO_LARGE, 1, 1, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckAndRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_HEADERS_TOO_LARGE, 1, 1, + /*include_stop_sending_if_v99=*/false)); + } else { + quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckRstAndDataPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_HEADERS_TOO_LARGE, 1, 1, GetQpackDecoderStreamId(), + false, StreamCancellationQpackDecoderInstruction(0))); + } quic_data.AddRead(ASYNC, OK); quic_data.AddSocketDataToFactory(&socket_factory_); @@ -3679,12 +3698,21 @@ ConstructServerRstPacket(3, GetNthClientInitiatedBidirectionalStreamId(1), quic::QUIC_HEADERS_TOO_LARGE)); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeAckRstAndDataPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_HEADERS_TOO_LARGE, 3, 2, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(1))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckAndRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_HEADERS_TOO_LARGE, 3, 2, + /*include_stop_sending_if_v99=*/false)); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckRstAndDataPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_HEADERS_TOO_LARGE, 3, 2, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(1))); + } mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED); @@ -4681,15 +4709,24 @@ ASYNC, ConstructServerResponseHeadersPacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false, GetResponseHeaders("425"))); - mock_quic_data.AddWrite( - SYNCHRONOUS, ConstructClientAckAndDataPacket( - packet_number++, GetQpackDecoderStreamId(), 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeRstPacket( - packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientAckDataAndRst( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, ConstructClientAckAndDataPacket( + packet_number++, GetQpackDecoderStreamId(), 1, 1, + false, StreamCancellationQpackDecoderInstruction(0))); + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); @@ -4763,15 +4800,24 @@ ASYNC, ConstructServerResponseHeadersPacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false, GetResponseHeaders("425"))); - mock_quic_data.AddWrite( - SYNCHRONOUS, ConstructClientAckAndDataPacket( - packet_number++, GetQpackDecoderStreamId(), 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeRstPacket( - packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientAckDataAndRst( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, ConstructClientAckAndDataPacket( + packet_number++, GetQpackDecoderStreamId(), 1, 1, + false, StreamCancellationQpackDecoderInstruction(0))); + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); @@ -4784,15 +4830,25 @@ ASYNC, ConstructServerResponseHeadersPacket( 2, GetNthClientInitiatedBidirectionalStreamId(1), false, GetResponseHeaders("425"))); - mock_quic_data.AddWrite( - SYNCHRONOUS, ConstructClientAckAndDataPacket( - packet_number++, GetQpackDecoderStreamId(), 2, 1, false, - StreamCancellationQpackDecoderInstruction(1, false))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeRstPacket( - packet_number++, GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientAckDataAndRst( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED, 2, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(1, false))); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientAckAndDataPacket( + packet_number++, GetQpackDecoderStreamId(), 2, 1, false, + StreamCancellationQpackDecoderInstruction(1, false))); + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED); @@ -4978,12 +5034,21 @@ ConstructServerRstPacket(2, GetNthClientInitiatedBidirectionalStreamId(0), quic::QUIC_STREAM_CANCELLED)); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeAckRstAndDataPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 2, 1, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckAndRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 2, 1, + /*include_stop_sending_if_v99=*/false)); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckRstAndDataPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 2, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data. mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -5047,12 +5112,21 @@ ConstructServerRstPacket(1, GetNthClientInitiatedBidirectionalStreamId(0), quic::QUIC_STREAM_CANCELLED)); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker_->MakeAckRstAndDataPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckAndRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, + /*include_stop_sending_if_v99=*/false)); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker_->MakeAckRstAndDataPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data. mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -6062,6 +6136,7 @@ ConfiguredProxyResolutionService::CreateDirect()), auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()), ssl_data_(ASYNC, OK) { + SetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5, true); FLAGS_quic_enable_http3_grease_randomness = false; } @@ -6594,19 +6669,30 @@ .AddWrite("response-ack", ConstructClientAckPacket(packet_num++, 3, 2)) .Sync(); - socket_data - .AddWrite("qpack-cancel", - ConstructClientDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))) - .Sync(); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data + .AddWrite("qpack-cancel-rst", + client_maker_->MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)) + .Sync(); + } else { + socket_data + .AddWrite("qpack-cancel", + ConstructClientDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))) + .Sync(); - socket_data - .AddWrite("rst", - ConstructClientRstPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)) - .Sync(); + socket_data + .AddWrite("rst", ConstructClientRstPacket( + packet_num++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)) + .Sync(); + } socket_factory_.AddSocketDataProvider(&socket_data); socket_factory_.AddSSLSocketDataProvider(&ssl_data_); @@ -6685,16 +6771,25 @@ ConstructClientAckPacket(packet_num++, 3, 2)); mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientDataPacket(packet_num++, GetQpackDecoderStreamId(), false, + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite(SYNCHRONOUS, + client_maker_->MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + mock_quic_data.AddWrite(SYNCHRONOUS, + ConstructClientDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -6932,19 +7027,30 @@ .AddWrite("response-ack", ConstructClientAckPacket(packet_num++, 3, 2)) .Sync(); - socket_data - .AddWrite("qpack-cancel", - ConstructClientDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))) - .Sync(); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data + .AddWrite("qpack-cancel-rst", + client_maker_->MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)) + .Sync(); + } else { + socket_data + .AddWrite("qpack-cancel", + ConstructClientDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))) + .Sync(); - socket_data - .AddWrite("rst", - ConstructClientRstPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)) - .Sync(); + socket_data + .AddWrite("rst", ConstructClientRstPacket( + packet_num++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)) + .Sync(); + } socket_factory_.AddSocketDataProvider(&socket_data); socket_factory_.AddSSLSocketDataProvider(&ssl_data_); @@ -7054,16 +7160,25 @@ ConstructClientAckPacket(write_packet_index++, 5, 4)); mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read - mock_quic_data.AddWrite( - SYNCHRONOUS, ConstructClientDataPacket( - write_packet_index++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite(SYNCHRONOUS, + client_maker_->MakeDataAndRstPacket( + write_packet_index++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, ConstructClientDataPacket( + write_packet_index++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(write_packet_index++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(write_packet_index++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -7197,25 +7312,41 @@ mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(packet_num++, 6, 5)); mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientDataPacket(packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); - mock_quic_data.AddWrite( - SYNCHRONOUS, ConstructClientDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(1, false))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite(SYNCHRONOUS, + client_maker_->MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_STREAM_CANCELLED)); + mock_quic_data.AddWrite( + SYNCHRONOUS, client_maker_->MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(1, false), + GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } else { + mock_quic_data.AddWrite(SYNCHRONOUS, + ConstructClientDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + mock_quic_data.AddWrite( + SYNCHRONOUS, ConstructClientDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(1, false))); + + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num++, + GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -7316,16 +7447,25 @@ mock_quic_data_1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read - mock_quic_data_1.AddWrite( - SYNCHRONOUS, ConstructClientDataPacket( - write_packet_index++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data_1.AddWrite( + SYNCHRONOUS, client_maker_->MakeDataAndRstPacket( + write_packet_index++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + mock_quic_data_1.AddWrite( + SYNCHRONOUS, ConstructClientDataPacket( + write_packet_index++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data_1.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(write_packet_index++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + mock_quic_data_1.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(write_packet_index++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data_1.AddSocketDataToFactory(&socket_factory_); @@ -7534,15 +7674,24 @@ ASYNC, ConstructServerResponseHeadersPacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false, GetResponseHeaders("200"))); - mock_quic_data.AddWrite( - SYNCHRONOUS, ConstructClientAckAndDataPacket( - packet_num++, GetQpackDecoderStreamId(), 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientAckDataAndRst( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, ConstructClientAckAndDataPacket( + packet_num++, GetQpackDecoderStreamId(), 1, 1, false, + StreamCancellationQpackDecoderInstruction(0))); + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num++, + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddWrite( SYNCHRONOUS, @@ -7588,15 +7737,24 @@ ConstructClientAckPacket(packet_num++, 4, 3)); mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read - mock_quic_data.AddWrite( - SYNCHRONOUS, ConstructClientDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(1, false))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, client_maker_->MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(1, false), + GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, ConstructClientDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(1, false))); + mock_quic_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num++, + GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddSocketDataToFactory(&socket_factory_); @@ -7872,18 +8030,27 @@ mock_quic_data.AddWrite(SYNCHRONOUS, client_maker.MakeAckPacket(packet_num++, 2, 1)); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /* fin = */ false, StreamCancellationQpackDecoderInstruction(0))); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite(SYNCHRONOUS, + client_maker.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /* fin = */ false, StreamCancellationQpackDecoderInstruction(0))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker.MakeRstPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, - /*include_stop_sending_if_v99=*/true)); + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, + /*include_stop_sending_if_v99=*/true)); + } mock_quic_data.AddWrite( SYNCHRONOUS, @@ -7911,15 +8078,25 @@ mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read - mock_quic_data.AddWrite( - SYNCHRONOUS, client_maker.MakeAckAndDataPacket( - packet_num++, GetQpackDecoderStreamId(), 3, 3, false, - StreamCancellationQpackDecoderInstruction(1, false))); - mock_quic_data.AddWrite( - SYNCHRONOUS, - client_maker.MakeRstPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker.MakeAckDataAndRst( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED, 3, 3, GetQpackDecoderStreamId(), + false, StreamCancellationQpackDecoderInstruction(1, false))); + } else { + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker.MakeAckAndDataPacket( + packet_num++, GetQpackDecoderStreamId(), 3, 3, false, + StreamCancellationQpackDecoderInstruction(1, false))); + mock_quic_data.AddWrite( + SYNCHRONOUS, + client_maker.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } mock_quic_data.AddSocketDataToFactory(&socket_factory_); mock_quic_data.GetSequencedSocketData()->set_busy_before_sync_reads(true);
diff --git a/net/quic/quic_session_pool_test.cc b/net/quic/quic_session_pool_test.cc index ae1c2ae..ef1b6bf 100644 --- a/net/quic/quic_session_pool_test.cc +++ b/net/quic/quic_session_pool_test.cc
@@ -386,15 +386,25 @@ socket_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeRetireConnectionIdPacket( packet_num++, /*sequence_number=*/0u)); - socket_data2.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -1731,13 +1741,22 @@ socket_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket( packet_num++, 50, /*unidirectional=*/false)); - socket_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data.AddWrite( - SYNCHRONOUS, client_maker_.MakeRstPacket(packet_num++, stream_id, - quic::QUIC_STREAM_CANCELLED)); + + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + stream_id, quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket(packet_num++, stream_id, + quic::QUIC_STREAM_CANCELLED)); + } socket_data.AddRead(ASYNC, server_maker_.MakeRstPacket( 1, stream_id, quic::QUIC_STREAM_CANCELLED)); socket_data.AddRead( @@ -2426,13 +2445,23 @@ int packet_num = 1; socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(packet_num++)); - socket_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num, quic::QUIC_STREAM_CANCELLED)); + + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num, quic::QUIC_STREAM_CANCELLED)); + } socket_data.AddSocketDataToFactory(socket_factory_.get()); RequestBuilder builder(this); @@ -2521,15 +2550,24 @@ ASYNC, ConstructOkResponsePacket( 2, GetNthClientInitiatedBidirectionalStreamId(0), false)); quic_data2.AddReadPauseForever(); - quic_data2.AddWrite(SYNCHRONOUS, - client_maker_.MakeAckAndDataPacket( - packet_num++, GetQpackDecoderStreamId(), 2, 2, false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckDataAndRst( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 2, 2, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + quic_data2.AddWrite( + SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( + packet_num++, GetQpackDecoderStreamId(), 2, 2, false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -2676,15 +2714,24 @@ /*smallest_received=*/1) .AddRetireConnectionIdFrame(/*sequence_number=*/0u) .Build()); - quic_data2.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -2971,15 +3018,24 @@ int packet_num = 1; socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(packet_num++)); - socket_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -3054,23 +3110,47 @@ failed_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(packet_num++)); // A RESET will be sent to the peer to cancel the non-migratable stream. - failed_socket_data.AddWrite( - SYNCHRONOUS, client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - failed_socket_data.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + failed_socket_data.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + failed_socket_data.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + failed_socket_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } failed_socket_data.AddSocketDataToFactory(socket_factory_.get()); // Set up second socket data provider that is used after migration. client_maker_.set_connection_id(cid_on_new_path); socket_data.AddReadPauseForever(); - socket_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeCombinedRetransmissionPacket( - {3, 1, 2}, packet_num++)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + auto packet_one_frames = client_maker_.CloneSavedFrames(1); // STREAM + auto packet_two_frames = + client_maker_.CloneSavedFrames(2); // STREAM, RST_STREAM + auto& packet = client_maker_.Packet(packet_num++); + for (size_t i = 1; i < packet_two_frames.size(); ++i) { + packet.AddFrame(packet_two_frames[i]); + } + for (auto& frame : packet_one_frames) { + packet.AddFrame(frame); + } + packet.AddFrame(packet_two_frames[0]); + socket_data.AddWrite(SYNCHRONOUS, packet.Build()); + } else { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeCombinedRetransmissionPacket( + {3, 1, 2}, packet_num++)); + } // Ping packet to send after migration. socket_data.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++)); @@ -3083,15 +3163,24 @@ int packet_num = 1; socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(packet_num++)); - socket_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket( - packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data.AddSocketDataToFactory(socket_factory_.get()); } @@ -3435,16 +3524,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_number++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_number++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_number++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Trigger connection migration. @@ -3571,16 +3669,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Add a new network and notify the stream factory of a new connected network. @@ -3682,15 +3789,24 @@ ASYNC, ConstructOkResponsePacket( 5, GetNthClientInitiatedBidirectionalStreamId(0), false)); quic_data2.AddReadPauseForever(); - quic_data2.AddWrite( - SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( - packet_number++, GetQpackDecoderStreamId(), 5, 1, false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckDataAndRst( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 5, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + quic_data2.AddWrite( + SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( + packet_number++, GetQpackDecoderStreamId(), 5, 1, + false, StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -3840,15 +3956,24 @@ ASYNC, ConstructOkResponsePacket( 2, GetNthClientInitiatedBidirectionalStreamId(0), false)); quic_data2.AddReadPauseForever(); - quic_data2.AddWrite( - SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( - packet_number++, GetQpackDecoderStreamId(), 2, 2, false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckDataAndRst( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 2, 2, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + quic_data2.AddWrite( + SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( + packet_number++, GetQpackDecoderStreamId(), 2, 2, + false, StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -4244,13 +4369,23 @@ 5, /*sequence_number=*/0u)); quic_data2.AddRead(ASYNC, server_maker_.MakeAckPacket(3, 5, 1)); quic_data2.AddReadPauseForever(); - quic_data2.AddWrite(ASYNC, client_maker_.MakeDataPacket( - 6, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite(ASYNC, - client_maker_.MakeRstPacket( - 7, GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + 6, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + quic_data2.AddWrite(ASYNC, + client_maker_.MakeDataPacket( + 6, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite(ASYNC, + client_maker_.MakeRstPacket( + 7, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -4531,15 +4666,24 @@ ConstructGetRequestPacket( packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), true)); - quic_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_number++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_number++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + quic_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_number++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -4629,15 +4773,24 @@ ConstructGetRequestPacket( packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), true)); - quic_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_number + 1, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number + 2, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_number + 1, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + quic_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_number + 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number + 2, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data1.AddSocketDataToFactory(socket_factory_.get()); // Set up the second socket data provider that is used for migration probing. @@ -5341,15 +5494,24 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); quic_data2.AddReadPauseForever(); - quic_data2.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data.AddSocketDataToFactory(socket_factory_.get()); quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -5487,16 +5649,25 @@ /*smallest_received=*/1) .AddRetireConnectionIdFrame(/*sequence_number=*/0u) .Build()); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_number++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_number++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_number++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -5978,15 +6149,24 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); quic_data.AddReadPauseForever(); - quic_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeAckAndDataPacket( - packet_num++, GetQpackDecoderStreamId(), 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckDataAndRst( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeAckAndDataPacket( + packet_num++, GetQpackDecoderStreamId(), 1, 1, false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data.AddSocketDataToFactory(socket_factory_.get()); // Set up second socket that will immediately return disconnected. @@ -6260,15 +6440,24 @@ ASYNC, ConstructOkResponsePacket( 2, GetNthClientInitiatedBidirectionalStreamId(0), false)); quic_data2.AddReadPauseForever(); - quic_data2.AddWrite(SYNCHRONOUS, - client_maker_.MakeAckAndDataPacket( - packet_num++, GetQpackDecoderStreamId(), 2, 2, false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckDataAndRst( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 2, 2, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + quic_data2.AddWrite( + SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( + packet_num++, GetQpackDecoderStreamId(), 2, 2, false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data2.AddSocketDataToFactory(socket_factory_.get()); @@ -6508,15 +6697,24 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); quic_data.AddReadPauseForever(); - quic_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeAckAndDataPacket( - packet_num++, GetQpackDecoderStreamId(), 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckDataAndRst( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeAckAndDataPacket( + packet_num++, GetQpackDecoderStreamId(), 1, 1, false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } quic_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -6706,15 +6904,24 @@ int packet_num = 1; socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(packet_num++)); - socket_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -6814,29 +7021,43 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(1, false), + GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); - socket_data1.AddWrite( - SYNCHRONOUS, client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /* fin = */ false, - StreamCancellationQpackDecoderInstruction(1, false))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_STREAM_CANCELLED, - /*include_stop_sending_if_v99=*/true)); - + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /* fin = */ false, + StreamCancellationQpackDecoderInstruction(1, false))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED, + /*include_stop_sending_if_v99=*/true)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request #1 and QuicHttpStream. @@ -7069,16 +7290,25 @@ /*largest_received=*/peer_packet_num - 1, /*smallest_received=*/1)); - quic_data3.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - quic_data3.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED, - /*include_stop_sending_if_v99=*/true)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + quic_data3.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + quic_data3.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + quic_data3.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, + /*include_stop_sending_if_v99=*/true)); + } quic_data3.AddSocketDataToFactory(socket_factory_.get()); // Fast forward to fire the migrate back timer and verify the session @@ -7306,15 +7536,24 @@ socket_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeRetireConnectionIdPacket( packet_num++, /*sequence_number=*/1u)); - socket_data2.AddWrite( - SYNCHRONOUS, client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), /*fin=*/false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data2.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), /*fin=*/false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data2.AddSocketDataToFactory(socket_factory_.get()); // Socket data for probing on the default network. @@ -7513,15 +7752,24 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data2.AddReadPauseForever(); - socket_data2.AddWrite( - SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( - packet_num++, GetQpackDecoderStreamId(), 1, 1, false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeAckDataAndRst( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + } else { + socket_data2.AddWrite( + SYNCHRONOUS, client_maker_.MakeAckAndDataPacket( + packet_num++, GetQpackDecoderStreamId(), 1, 1, false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request, should fail after the write of the CHLO fails. @@ -7636,16 +7884,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Send GET request on stream. This should cause a write error, which triggers @@ -7834,27 +8091,43 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); - socket_data1.AddWrite( - SYNCHRONOUS, client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(1, false))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(1), - quic::QUIC_STREAM_CANCELLED, - /*include_stop_sending_if_v99=*/true)); + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(1, false), + GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(1, false))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), + quic::QUIC_STREAM_CANCELLED, + /*include_stop_sending_if_v99=*/true)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -7991,16 +8264,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_number++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0, false))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataAndRstPacket( + packet_number++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0, false), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataPacket( + packet_number++, GetQpackDecoderStreamId(), + /*fin=*/false, + StreamCancellationQpackDecoderInstruction(0, false))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request #1 and QuicHttpStream. @@ -8148,16 +8430,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_number++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0, false))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_number++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataAndRstPacket( + packet_number++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0, false), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeDataPacket( + packet_number++, GetQpackDecoderStreamId(), + /*fin=*/false, + StreamCancellationQpackDecoderInstruction(0, false))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request #1 and QuicHttpStream. @@ -8658,16 +8949,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -8809,16 +9109,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -8976,16 +9285,25 @@ /*sequence_number=*/0u)); socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++)); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // On a DISCONNECTED notification, nothing happens. @@ -9105,16 +9423,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Send GET request on stream. @@ -9225,16 +9552,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); @@ -9350,16 +9686,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); @@ -9485,15 +9830,24 @@ 3, GetNthClientInitiatedBidirectionalStreamId(0), true, header + "hello!")); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -9643,15 +9997,24 @@ 3, GetNthClientInitiatedBidirectionalStreamId(0), true, header + "hello!")); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -9769,15 +10132,24 @@ 3, GetNthClientInitiatedBidirectionalStreamId(0), true, header + "hello!")); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -9890,15 +10262,24 @@ 3, GetNthClientInitiatedBidirectionalStreamId(0), true, header + "hello!")); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -10012,15 +10393,24 @@ 3, GetNthClientInitiatedBidirectionalStreamId(0), true, header + "hello!")); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -10135,15 +10525,24 @@ 3, GetNthClientInitiatedBidirectionalStreamId(0), true, header + "hello!")); socket_data1.AddReadPauseForever(); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -10439,16 +10838,25 @@ /*original_packet_numbers=*/{1, 2}, packet_num++)); socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetireConnectionIdPacket( packet_num++, /*sequence_number=*/0u)); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); scoped_mock_network_change_notifier_->mock_network_change_notifier() @@ -10981,16 +11389,25 @@ ASYNC, ConstructOkResponsePacket( 1, GetNthClientInitiatedBidirectionalStreamId(0), false)); socket_data2.AddReadPauseForever(); - socket_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), - /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); - socket_data2.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data2.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), + /*fin=*/false, StreamCancellationQpackDecoderInstruction(0))); + socket_data2.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data2.AddSocketDataToFactory(socket_factory_.get()); const uint8_t kTestIpAddress[] = {1, 2, 3, 4}; @@ -11051,13 +11468,22 @@ SYNCHRONOUS, ConstructGetRequestPacket( packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true)); - socket_data.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data.AddWrite( - SYNCHRONOUS, - ConstructClientRstPacket(packet_num++, quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data.AddWrite( + SYNCHRONOUS, + ConstructClientRstPacket(packet_num++, quic::QUIC_STREAM_CANCELLED)); + } socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -11192,15 +11618,24 @@ int packet_num = 1; socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(packet_num++)); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. @@ -11268,15 +11703,24 @@ int packet_num = 1; socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(packet_num++)); - socket_data1.AddWrite(SYNCHRONOUS, - client_maker_.MakeDataPacket( - packet_num++, GetQpackDecoderStreamId(), false, - StreamCancellationQpackDecoderInstruction(0))); - socket_data1.AddWrite( - SYNCHRONOUS, - client_maker_.MakeRstPacket(packet_num++, - GetNthClientInitiatedBidirectionalStreamId(0), - quic::QUIC_STREAM_CANCELLED)); + if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataAndRstPacket( + packet_num++, GetQpackDecoderStreamId(), + StreamCancellationQpackDecoderInstruction(0), + GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } else { + socket_data1.AddWrite(SYNCHRONOUS, + client_maker_.MakeDataPacket( + packet_num++, GetQpackDecoderStreamId(), false, + StreamCancellationQpackDecoderInstruction(0))); + socket_data1.AddWrite( + SYNCHRONOUS, + client_maker_.MakeRstPacket( + packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + } socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream.
diff --git a/net/quic/quic_session_pool_test_base.cc b/net/quic/quic_session_pool_test_base.cc index 00e4522..f3602dc 100644 --- a/net/quic/quic_session_pool_test_base.cc +++ b/net/quic/quic_session_pool_test_base.cc
@@ -159,6 +159,7 @@ &QuicSessionPoolTestBase::OnFailedOnDefaultNetwork, base::Unretained(this))), quic_params_(context_.params()) { + SetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5, true); enabled_features.push_back(features::kAsyncQuicSession); scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); FLAGS_quic_enable_http3_grease_randomness = false;
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc index dd60b06..850c3b3 100644 --- a/net/quic/quic_test_packet_maker.cc +++ b/net/quic/quic_test_packet_maker.cc
@@ -413,6 +413,12 @@ return builder.Build(); } +quic::QuicFrames QuicTestPacketMaker::CloneSavedFrames(uint64_t packet_number) { + DCHECK(connection_state_.save_packet_frames); + return CloneFrames( + connection_state_.saved_frames[quic::QuicPacketNumber(packet_number)]); +} + std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeCombinedRetransmissionPacket( const std::vector<uint64_t>& original_packet_numbers,
diff --git a/net/quic/quic_test_packet_maker.h b/net/quic/quic_test_packet_maker.h index 6951151..83a3e81 100644 --- a/net/quic/quic_test_packet_maker.h +++ b/net/quic/quic_test_packet_maker.h
@@ -90,6 +90,9 @@ // define the frames in the packet, and finish with its `Build` method. QuicTestPacketBuilder& Packet(uint64_t packet_number); + // Clone all frames from |packet_number|. + quic::QuicFrames CloneSavedFrames(uint64_t packet_number); + std::unique_ptr<quic::QuicReceivedPacket> MakeConnectivityProbingPacket( uint64_t packet_number);
diff --git a/services/accessibility/features/javascript/automation.js b/services/accessibility/features/javascript/automation.js index f9ed292..adbece8 100644 --- a/services/accessibility/features/javascript/automation.js +++ b/services/accessibility/features/javascript/automation.js
@@ -2194,6 +2194,7 @@ actionData.sourceExtensionId = ''; actionData.requestId = 0; actionData.targetNodeId = 0; + actionData.targetRole = ax.mojom.Role.kUnknown; actionData.flags = 0; actionData.action = ax.mojom.Action.kNone; actionData.anchorNodeId = 0;
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn index 10474ea..a62ce005 100644 --- a/services/network/public/cpp/BUILD.gn +++ b/services/network/public/cpp/BUILD.gn
@@ -76,6 +76,8 @@ "empty_url_loader_client.h", "features.cc", "features.h", + "fence_event_reporting_parser.cc", + "fence_event_reporting_parser.h", "header_util.cc", "header_util.h", "initiator_lock_compatibility.cc", @@ -581,6 +583,7 @@ "digitally_signed_mojom_traits_unittest.cc", "document_isolation_policy_parser_unittest.cc", "empty_url_loader_client_unittest.cc", + "fence_event_reporting_parser_unittest.cc", "file_enumeration_entry_mojom_traits_unittest.cc", "first_party_sets_mojom_traits_unittest.cc", "hash_value_mojom_traits_unittest.cc",
diff --git a/services/network/public/cpp/fence_event_reporting_parser.cc b/services/network/public/cpp/fence_event_reporting_parser.cc new file mode 100644 index 0000000..42f8c80 --- /dev/null +++ b/services/network/public/cpp/fence_event_reporting_parser.cc
@@ -0,0 +1,21 @@ +// 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 "services/network/public/cpp/fence_event_reporting_parser.h" + +#include "net/http/structured_headers.h" + +namespace network { + +bool ParseAllowCrossOriginEventReportingFromHeader( + const net::HttpResponseHeaders& headers) { + std::string header_value; + headers.GetNormalizedHeader("Allow-Cross-Origin-Event-Reporting", + &header_value); + std::optional<net::structured_headers::Item> item = + net::structured_headers::ParseBareItem(header_value); + return item && item->is_boolean() && item->GetBoolean(); +} + +} // namespace network
diff --git a/services/network/public/cpp/fence_event_reporting_parser.h b/services/network/public/cpp/fence_event_reporting_parser.h new file mode 100644 index 0000000..ca5a5f1f --- /dev/null +++ b/services/network/public/cpp/fence_event_reporting_parser.h
@@ -0,0 +1,23 @@ +// 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 SERVICES_NETWORK_PUBLIC_CPP_FENCE_EVENT_REPORTING_PARSER_H_ +#define SERVICES_NETWORK_PUBLIC_CPP_FENCE_EVENT_REPORTING_PARSER_H_ + +#include "base/component_export.h" +#include "net/http/http_response_headers.h" + +namespace network { + +// Parses the `Allow-Cross-Origin-Event-Reporting` response header. Returns true +// if the parsing succeeds and the parsed value is Boolean true; returns false +// otherwise. See: +// https://wicg.github.io/fenced-frame/#fenced-frame-config-cross-origin-reporting-allowed +COMPONENT_EXPORT(NETWORK_CPP) +bool ParseAllowCrossOriginEventReportingFromHeader( + const net::HttpResponseHeaders& headers); + +} // namespace network + +#endif // SERVICES_NETWORK_PUBLIC_CPP_FENCE_EVENT_REPORTING_PARSER_H_
diff --git a/services/network/public/cpp/fence_event_reporting_parser_unittest.cc b/services/network/public/cpp/fence_event_reporting_parser_unittest.cc new file mode 100644 index 0000000..3968abd --- /dev/null +++ b/services/network/public/cpp/fence_event_reporting_parser_unittest.cc
@@ -0,0 +1,68 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/fence_event_reporting_parser.h" + +#include "net/http/http_response_headers.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { + +TEST(FenceEventReportingParserTest, + ParseAllowCrossOriginEventReportingFromHeader_NoObserveTopicsHeader) { + scoped_refptr<net::HttpResponseHeaders> headers = + net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\r\n"); + EXPECT_FALSE(ParseAllowCrossOriginEventReportingFromHeader(*headers)); +} + +TEST( + FenceEventReportingParserTest, + ParseAllowCrossOriginEventReportingFromHeader_TrueValueObserveTopicsHeader) { + scoped_refptr<net::HttpResponseHeaders> headers = + net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\r\n" + "Allow-Cross-Origin-Event-Reporting: ?1\r\n"); + EXPECT_TRUE(ParseAllowCrossOriginEventReportingFromHeader(*headers)); +} + +TEST( + FenceEventReportingParserTest, + ParseAllowCrossOriginEventReportingFromHeader_FalseValueObserveTopicsHeader) { + scoped_refptr<net::HttpResponseHeaders> headers = + net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\r\n" + "Allow-Cross-Origin-Event-Reporting: ?0\r\n"); + EXPECT_FALSE(ParseAllowCrossOriginEventReportingFromHeader(*headers)); +} + +TEST( + FenceEventReportingParserTest, + ParseAllowCrossOriginEventReportingFromHeader_NotBooleanObserveTopicsHeader) { + scoped_refptr<net::HttpResponseHeaders> headers = + net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\r\n" + "Allow-Cross-Origin-Event-Reporting: 1\r\n"); + EXPECT_FALSE(ParseAllowCrossOriginEventReportingFromHeader(*headers)); +} + +TEST(FenceEventReportingParserTest, + ParseAllowCrossOriginEventReportingFromHeader_InvalidObserveTopicsHeader) { + scoped_refptr<net::HttpResponseHeaders> headers = + net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\r\n" + "Allow-Cross-Origin-Event-Reporting: !!!\r\n"); + EXPECT_FALSE(ParseAllowCrossOriginEventReportingFromHeader(*headers)); +} + +TEST(FenceEventReportingParserTest, + ParseAllowCrossOriginEventReportingFromHeader_InvalidNormalizedHeader) { + scoped_refptr<net::HttpResponseHeaders> headers = + net::HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\r\n" + "Allow-Cross-Origin-Event-Reporting: ?1\r\n" + "Allow-Cross-Origin-Event-Reporting: ?1\r\n"); + EXPECT_FALSE(ParseAllowCrossOriginEventReportingFromHeader(*headers)); +} + +} // namespace network
diff --git a/services/network/public/cpp/parsed_headers.cc b/services/network/public/cpp/parsed_headers.cc index a9861d16..26e96f7 100644 --- a/services/network/public/cpp/parsed_headers.cc +++ b/services/network/public/cpp/parsed_headers.cc
@@ -25,6 +25,7 @@ #include "services/network/public/cpp/cross_origin_opener_policy_parser.h" #include "services/network/public/cpp/document_isolation_policy_parser.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/fence_event_reporting_parser.h" #include "services/network/public/cpp/link_header_parser.h" #include "services/network/public/cpp/no_vary_search_header_parser.h" #include "services/network/public/cpp/origin_agent_cluster_parser.h" @@ -154,6 +155,9 @@ parsed_headers->observe_browsing_topics = ParseObserveBrowsingTopicsFromHeader(*headers); + parsed_headers->allow_cross_origin_event_reporting = + ParseAllowCrossOriginEventReportingFromHeader(*headers); + return parsed_headers; }
diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc index a002343..1543cf1 100644 --- a/services/network/public/cpp/simple_url_loader.cc +++ b/services/network/public/cpp/simple_url_loader.cc
@@ -283,6 +283,7 @@ int NetError() const override; const mojom::URLResponseHead* ResponseInfo() const override; + mojom::URLResponseHeadPtr TakeResponseInfo() override; const std::optional<URLLoaderCompletionStatus>& CompletionStatus() const override; const GURL& GetFinalURL() const override; @@ -1586,6 +1587,12 @@ return request_state_->response_info.get(); } +mojom::URLResponseHeadPtr SimpleURLLoaderImpl::TakeResponseInfo() { + // Should only be called once the request is complete. + DCHECK(request_state_->finished); + return std::move(request_state_->response_info); +} + const std::optional<URLLoaderCompletionStatus>& SimpleURLLoaderImpl::CompletionStatus() const { // Should only be called once the request is complete.
diff --git a/services/network/public/cpp/simple_url_loader.h b/services/network/public/cpp/simple_url_loader.h index 2d89684..7858419 100644 --- a/services/network/public/cpp/simple_url_loader.h +++ b/services/network/public/cpp/simple_url_loader.h
@@ -372,10 +372,15 @@ virtual int NetError() const = 0; // The URLResponseHead for the request. Will be nullptr if ResponseInfo - // was never received. May only be called once the loader has informed the - // caller of completion. + // was never received or if `TakeResponseInfo()` has been called. May only be + // called once the loader has informed the caller of completion. virtual const mojom::URLResponseHead* ResponseInfo() const = 0; + // The URLResponseHead for the request. Ownership is transferred to the + // caller. Will be nullptr if ResponseInfo was never received. May only be + // called once the loader has informed the caller of completion. + virtual mojom::URLResponseHeadPtr TakeResponseInfo() = 0; + // The URLLoaderCompletionStatus for the request. Will be nullopt if the // response never completed. May only be called once the loader has informed // the caller of completion.
diff --git a/services/network/public/mojom/parsed_headers.mojom b/services/network/public/mojom/parsed_headers.mojom index 597d0c5..6173c821 100644 --- a/services/network/public/mojom/parsed_headers.mojom +++ b/services/network/public/mojom/parsed_headers.mojom
@@ -145,5 +145,9 @@ // https://patcg-individual-drafts.github.io/topics/#the-observe-browsing-topics-http-response-header-header bool observe_browsing_topics; + // The parsed value of the Allow-Cross-Origin-Event-Reporting header. See: + // https://wicg.github.io/fenced-frame/#fenced-frame-config-cross-origin-reporting-allowed + bool allow_cross_origin_event_reporting; + // Please update `CheckParsedHeadersEquals` after adding new fields. };
diff --git a/services/passage_embeddings/passage_embeddings_service.cc b/services/passage_embeddings/passage_embeddings_service.cc index 7239aaa..851abdb 100644 --- a/services/passage_embeddings/passage_embeddings_service.cc +++ b/services/passage_embeddings/passage_embeddings_service.cc
@@ -16,7 +16,6 @@ PassageEmbeddingsService::~PassageEmbeddingsService() = default; -// TODO(b/338650221): Add histogram for whether model load succeeds or not. void PassageEmbeddingsService::LoadModels( mojom::PassageEmbeddingsLoadModelsParamsPtr params, mojo::PendingReceiver<mojom::PassageEmbedder> model,
diff --git a/services/webnn/features.gni b/services/webnn/features.gni index 4ff8844..b41cfc22 100644 --- a/services/webnn/features.gni +++ b/services/webnn/features.gni
@@ -5,7 +5,7 @@ import("//build/config/features.gni") declare_args() { - webnn_use_tflite = is_android || is_chromeos || is_linux + webnn_use_tflite = is_android || is_chromeos || is_linux || is_win # Enable logging of TFLite profiling information on MLGraph destruction. webnn_enable_tflite_profiler = false
diff --git a/services/webnn/webnn_context_provider_impl.cc b/services/webnn/webnn_context_provider_impl.cc index 33bdd35..b890e79 100644 --- a/services/webnn/webnn_context_provider_impl.cc +++ b/services/webnn/webnn_context_provider_impl.cc
@@ -86,6 +86,18 @@ } #endif +#if BUILDFLAG(IS_WIN) +bool ShouldCreateDmlContext(const mojom::CreateContextOptions& options) { + switch (options.device) { + case mojom::CreateContextOptions::Device::kCpu: + return false; + case mojom::CreateContextOptions::Device::kGpu: + case mojom::CreateContextOptions::Device::kNpu: + return true; + } +} +#endif // BUILDFLAG(IS_WIN) + } // namespace WebNNContextProviderImpl::WebNNContextProviderImpl( @@ -168,109 +180,97 @@ std::move(callback)); return; } -#if BUILDFLAG(WEBNN_USE_TFLITE) - // TODO: crbug.com/41486052 - Create the TFLite context using `options`. - // The remote sent to the renderer. mojo::PendingRemote<mojom::WebNNContext> blink_remote; + // The receiver bound to WebNNContextImpl. auto receiver = blink_remote.InitWithNewPipeAndPassReceiver(); + +#if BUILDFLAG(IS_WIN) + if (ShouldCreateDmlContext(*options)) { + DCHECK(gpu_feature_info_.IsInitialized()); + if (gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_WEBNN] != + gpu::kGpuFeatureStatusEnabled) { + std::move(callback).Run(ToError<mojom::CreateContextResult>( + mojom::Error::Code::kNotSupportedError, + "WebNN is not compatible with GPU.")); + LOG(ERROR) << "[WebNN] is not compatible with GPU."; + return; + } + + // Get the `Adapter` instance which is created for the adapter according to + // the device type. At the current stage, all `ContextImpl` share one + // instance for one device type. + base::expected<scoped_refptr<dml::Adapter>, mojom::ErrorPtr> + adapter_creation_result; + switch (options->device) { + case mojom::CreateContextOptions::Device::kCpu: + NOTREACHED_NORETURN(); + case mojom::CreateContextOptions::Device::kGpu: + adapter_creation_result = GetDmlGpuAdapter(shared_context_state_.get()); + break; + case mojom::CreateContextOptions::Device::kNpu: + adapter_creation_result = + dml::Adapter::GetNpuInstance(kMinDMLFeatureLevelForWebNN); + break; + } + if (!adapter_creation_result.has_value()) { + std::move(callback).Run(mojom::CreateContextResult::NewError( + std::move(adapter_creation_result.error()))); + return; + } + + scoped_refptr<dml::Adapter> adapter = adapter_creation_result.value(); + std::unique_ptr<dml::CommandRecorder> command_recorder = + dml::CommandRecorder::Create(adapter->command_queue(), + adapter->dml_device()); + if (!command_recorder) { + std::move(callback).Run(mojom::CreateContextResult::NewError( + dml::CreateError(mojom::Error::Code::kUnknownError, + "Failed to create a WebNN context."))); + LOG(ERROR) << "[WebNN] Failed to open the command recorder."; + return; + } + + auto* context_impl = + new dml::ContextImplDml(std::move(adapter), std::move(receiver), this, + std::move(command_recorder), gpu_feature_info_); + impls_.push_back(base::WrapUnique<WebNNContextImpl>(context_impl)); + std::move(callback).Run( + mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); + return; + } +#endif // BUILDFLAG(IS_WIN) + +#if BUILDFLAG(IS_MAC) + if (__builtin_available(macOS 14, *)) { + // TODO: crbug.com/41481333 - Create the CoreML context using `options`. + auto* context_impl = + new coreml::ContextImplCoreml(std::move(receiver), this); + impls_.push_back(base::WrapUnique<WebNNContextImpl>(context_impl)); + std::move(callback).Run( + mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); + return; + } +#endif // BUILDFLAG(IS_MAC) + +#if BUILDFLAG(WEBNN_USE_TFLITE) +// TODO: crbug.com/41486052 - Create the TFLite context using `options`. #if BUILDFLAG(IS_CHROMEOS) auto* context_impl = new tflite::ContextImplCrOS(std::move(receiver), this); #else auto* context_impl = new tflite::ContextImplTflite(std::move(receiver), this, std::move(options)); -#endif +#endif // BUILDFLAG(IS_CHROMEOS) impls_.push_back(base::WrapUnique<WebNNContextImpl>(context_impl)); std::move(callback).Run( mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); -#elif BUILDFLAG(IS_WIN) - // TODO: crbug.com/325612086 - Consider using TFLite to support CPU contexts - // on Windows. - if (options->device == mojom::CreateContextOptions::Device::kCpu) { - std::move(callback).Run(ToError<mojom::CreateContextResult>( - mojom::Error::Code::kNotSupportedError, - "The cpu device is not supported.")); - LOG(ERROR) << "[WebNN] Service is not supported on CPU on Windows."; - return; - } - - DCHECK(gpu_feature_info_.IsInitialized()); - if (gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_WEBNN] != - gpu::kGpuFeatureStatusEnabled) { - std::move(callback).Run(ToError<mojom::CreateContextResult>( - mojom::Error::Code::kNotSupportedError, - "WebNN is not compatible with GPU.")); - LOG(ERROR) << "[WebNN] is not compatible with GPU."; - return; - } - - // Get the `Adapter` instance which is created for the adapter according to - // the device type. At the current stage, all `ContextImplDml` share one - // instance for one device type. - base::expected<scoped_refptr<dml::Adapter>, mojom::ErrorPtr> - adapter_creation_result; - switch (options->device) { - case mojom::CreateContextOptions::Device::kCpu: - NOTREACHED_NORETURN(); - case mojom::CreateContextOptions::Device::kGpu: - adapter_creation_result = GetDmlGpuAdapter(shared_context_state_.get()); - break; - case mojom::CreateContextOptions::Device::kNpu: - adapter_creation_result = - dml::Adapter::GetNpuInstance(kMinDMLFeatureLevelForWebNN); - break; - } - if (!adapter_creation_result.has_value()) { - std::move(callback).Run(mojom::CreateContextResult::NewError( - std::move(adapter_creation_result.error()))); - return; - } - - scoped_refptr<dml::Adapter> adapter = adapter_creation_result.value(); - std::unique_ptr<dml::CommandRecorder> command_recorder = - dml::CommandRecorder::Create(adapter->command_queue(), - adapter->dml_device()); - if (!command_recorder) { - std::move(callback).Run(mojom::CreateContextResult::NewError( - dml::CreateError(mojom::Error::Code::kUnknownError, - "Failed to create a WebNN context."))); - LOG(ERROR) << "[WebNN] Failed to open the command recorder."; - return; - } - - // The remote sent to the renderer. - mojo::PendingRemote<mojom::WebNNContext> blink_remote; - // The receiver bound to WebNNContextImpl. - impls_.push_back(base::WrapUnique<WebNNContextImpl>(new dml::ContextImplDml( - std::move(adapter), blink_remote.InitWithNewPipeAndPassReceiver(), this, - std::move(command_recorder), gpu_feature_info_))); - std::move(callback).Run( - mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); -#elif BUILDFLAG(IS_MAC) - if (__builtin_available(macOS 14, *)) { - // The remote sent to the renderer. - mojo::PendingRemote<mojom::WebNNContext> blink_remote; - // The receiver bound to WebNNContextImpl. - // - // TODO: crbug.com/41481333 - Create the CoreML context using `options`. - impls_.push_back( - base::WrapUnique<WebNNContextImpl>(new coreml::ContextImplCoreml( - blink_remote.InitWithNewPipeAndPassReceiver(), this))); - std::move(callback).Run( - mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); - } else { - std::move(callback).Run(ToError<mojom::CreateContextResult>( - mojom::Error::Code::kNotSupportedError, - "WebNN Service is not supported on this platform.")); - LOG(ERROR) << "[WebNN] Service is not supported on this platform."; - } #else // TODO(crbug.com/40206287): Supporting WebNN Service on the platform. std::move(callback).Run(ToError<mojom::CreateContextResult>( mojom::Error::Code::kNotSupportedError, "WebNN Service is not supported on this platform.")); LOG(ERROR) << "[WebNN] Service is not supported on this platform."; -#endif +#endif // BUILDFLAG(WEBNN_USE_TFLITE) } } // namespace webnn
diff --git a/services/webnn/webnn_context_provider_impl_unittest.cc b/services/webnn/webnn_context_provider_impl_unittest.cc index b7a3555..2eada12 100644 --- a/services/webnn/webnn_context_provider_impl_unittest.cc +++ b/services/webnn/webnn_context_provider_impl_unittest.cc
@@ -79,8 +79,7 @@ #if BUILDFLAG(IS_WIN) -// The DirectML implementation does not support CPU execution. -TEST_F(WebNNContextProviderImplTest, CPUNotSupported) { +TEST_F(WebNNContextProviderImplTest, CPUIsSupported) { mojo::Remote<mojom::WebNNContextProvider> provider_remote; WebNNContextProviderImpl::CreateForTesting( @@ -94,10 +93,8 @@ /*thread_count_hint=*/0), future.GetCallback()); mojom::CreateContextResultPtr result = future.Take(); - ASSERT_TRUE(result->is_error()); - const mojom::ErrorPtr& create_context_error = result->get_error(); - EXPECT_EQ(create_context_error->code, mojom::Error::Code::kNotSupportedError); - EXPECT_EQ(create_context_error->message, "The cpu device is not supported."); + ASSERT_TRUE(result->is_context_remote()); + EXPECT_TRUE(result->get_context_remote().is_valid()); } // Checking for GPU compatibility is Windows-specific because only the DirectML
diff --git a/services/webnn/webnn_graph_impl_backend_test.cc b/services/webnn/webnn_graph_impl_backend_test.cc index b984a7c..05a99cf 100644 --- a/services/webnn/webnn_graph_impl_backend_test.cc +++ b/services/webnn/webnn_graph_impl_backend_test.cc
@@ -371,7 +371,8 @@ } #endif // BUILDFLAG(IS_MAC) -#if BUILDFLAG(WEBNN_USE_TFLITE) +// TODO(crbug.com/325612086): Parameterize these tests for different backends. +#if BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_WIN) class WebNNGraphImplBackendTest : public testing::Test { public: WebNNGraphImplBackendTest() @@ -420,7 +421,7 @@ GTEST_SKIP() << "Skipping test because the operator is not yet supported."; } } -#endif // BUILDFLAG(WEBNN_USE_TFLITE) +#endif // BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_WIN) template <typename T> struct ArgMinMaxTester {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index dc67232..c1f64c2 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5487,9 +5487,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5499,8 +5499,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -5643,9 +5643,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5655,8 +5655,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index c2ed94a1..1416d7d 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -19664,9 +19664,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19676,8 +19676,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -19820,9 +19820,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19832,8 +19832,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index f21ecfb1..6f5ba95 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -41840,9 +41840,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41851,8 +41851,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -41990,9 +41990,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -42001,8 +42001,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -43339,9 +43339,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43351,8 +43351,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -43495,9 +43495,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43507,8 +43507,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -44820,9 +44820,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44831,8 +44831,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -44970,9 +44970,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_v127.0.6490.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44981,8 +44981,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 24e13b9..9830c8a 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -15763,12 +15763,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_v127.0.6490.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15778,8 +15778,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": { @@ -15939,12 +15939,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_v127.0.6490.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 127.0.6490.0", + "description": "Run with ash-chrome version 127.0.6491.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15954,8 +15954,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v127.0.6490.0", - "revision": "version:127.0.6490.0" + "location": "lacros_version_skew_tests_v127.0.6491.0", + "revision": "version:127.0.6491.0" } ], "dimensions": {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 7a12c5a..89a195a 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -267,16 +267,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 127.0.6490.0', + 'description': 'Run with ash-chrome version 127.0.6491.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6490.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v127.0.6491.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v127.0.6490.0', - 'revision': 'version:127.0.6490.0', + 'location': 'lacros_version_skew_tests_v127.0.6491.0', + 'revision': 'version:127.0.6491.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index f5afae7..d9d6e98 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -4714,6 +4714,29 @@ ] } ], + "ComposeOnDeviceModel": [ + { + "platforms": [ + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "on_device_retract_unsafe_content": "false", + "on_device_text_safety_token_interval": "10" + }, + "enable_features": [ + "OptimizationGuideComposeOnDeviceEval", + "OptimizationGuideOnDeviceModel", + "TextSafetyClassifier" + ] + } + ] + } + ], "ComposeUiRefinement": [ { "platforms": [ @@ -17573,7 +17596,7 @@ { "name": "Enabled", "params": { - "SafetyCheckMagicStackAutorunHoursThreshold": "24" + "SafetyCheckMagicStackAutorunHoursThreshold": "720" }, "enable_features": [ "SafetyCheckMagicStack" @@ -19289,7 +19312,6 @@ "VisualQuerySuggestions" ], "disable_features": [ - "CompanionEnableNewBadgesInContextMenu", "SideSearch" ] } @@ -20279,27 +20301,6 @@ ] } ], - "TextSafetyClassifier": [ - { - "platforms": [ - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "on_device_retract_unsafe_content": "false", - "on_device_text_safety_token_interval": "10" - }, - "enable_features": [ - "TextSafetyClassifier" - ] - } - ] - } - ], "TheoraVideoCodec": [ { "platforms": [
diff --git a/third_party/blink/common/shared_storage/module_script_downloader.cc b/third_party/blink/common/shared_storage/module_script_downloader.cc index d698607..5755db0d 100644 --- a/third_party/blink/common/shared_storage/module_script_downloader.cc +++ b/third_party/blink/common/shared_storage/module_script_downloader.cc
@@ -133,7 +133,8 @@ net::ErrorToString(simple_url_loader->NetError()).c_str()); } std::move(module_script_downloader_callback_) - .Run(/*body=*/nullptr, error_message); + .Run(/*body=*/nullptr, error_message, + simple_url_loader->TakeResponseInfo()); return; } @@ -143,7 +144,8 @@ .Run(/*body=*/nullptr, base::StringPrintf( "Rejecting load of %s due to unexpected MIME type.", - source_url_.spec().c_str())); + source_url_.spec().c_str()), + simple_url_loader->TakeResponseInfo()); return; } @@ -152,13 +154,15 @@ .Run(/*body=*/nullptr, base::StringPrintf( "Rejecting load of %s due to unexpected charset.", - source_url_.spec().c_str())); + source_url_.spec().c_str()), + simple_url_loader->TakeResponseInfo()); return; } // All OK! std::move(module_script_downloader_callback_) - .Run(std::move(body), /*error_message=*/{}); + .Run(std::move(body), /*error_message=*/{}, + simple_url_loader->TakeResponseInfo()); } void ModuleScriptDownloader::OnRedirect( @@ -172,8 +176,10 @@ simple_url_loader_.reset(); std::move(module_script_downloader_callback_) - .Run(/*body=*/nullptr, base::StringPrintf("Unexpected redirect on %s.", - source_url_.spec().c_str())); + .Run(/*body=*/nullptr, + base::StringPrintf("Unexpected redirect on %s.", + source_url_.spec().c_str()), + nullptr); } } // namespace blink
diff --git a/third_party/blink/common/shared_storage/module_script_downloader_unittest.cc b/third_party/blink/common/shared_storage/module_script_downloader_unittest.cc index f5f81fe..df9c885142 100644 --- a/third_party/blink/common/shared_storage/module_script_downloader_unittest.cc +++ b/third_party/blink/common/shared_storage/module_script_downloader_unittest.cc
@@ -89,12 +89,15 @@ } protected: - void DownloadCompleteCallback(std::unique_ptr<std::string> body, - std::string error) { + void DownloadCompleteCallback( + std::unique_ptr<std::string> body, + std::string error, + network::mojom::URLResponseHeadPtr response_head) { DCHECK(!body_); DCHECK(run_loop_); body_ = std::move(body); error_ = std::move(error); + response_head_ = std::move(response_head); EXPECT_EQ(error_.empty(), !!body_); run_loop_->Quit(); } @@ -106,6 +109,7 @@ std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<std::string> body_; std::string error_; + network::mojom::URLResponseHeadPtr response_head_; network::TestURLLoaderFactory url_loader_factory_; }; @@ -113,12 +117,13 @@ TEST_F(ModuleScriptDownloaderTest, NetworkError) { network::URLLoaderCompletionStatus status; status.error_code = net::ERR_FAILED; - url_loader_factory_.AddResponse(url_, nullptr /* head */, kAsciiResponseBody, + url_loader_factory_.AddResponse(url_, /*head=*/nullptr, kAsciiResponseBody, status); EXPECT_FALSE(RunRequest()); EXPECT_EQ( "Failed to load https://url.test/script.js error = net::ERR_FAILED.", error_); + EXPECT_FALSE(response_head_); } // HTTP 404 responses are treated as failures. @@ -131,6 +136,8 @@ EXPECT_EQ( "Failed to load https://url.test/script.js HTTP status = 404 Not Found.", error_); + EXPECT_TRUE(response_head_); + EXPECT_EQ(response_head_->mime_type, kJavascriptMimeType); } // Redirect responses are treated as failures. @@ -149,6 +156,7 @@ kAsciiResponseBody, net::HTTP_OK, std::move(redirects)); EXPECT_FALSE(RunRequest()); EXPECT_EQ("Unexpected redirect on https://url.test/script.js.", error_); + EXPECT_FALSE(response_head_); } TEST_F(ModuleScriptDownloaderTest, Success) {
diff --git a/third_party/blink/public/common/shared_storage/module_script_downloader.h b/third_party/blink/public/common/shared_storage/module_script_downloader.h index 5dbab222..7090177 100644 --- a/third_party/blink/public/common/shared_storage/module_script_downloader.h +++ b/third_party/blink/public/common/shared_storage/module_script_downloader.h
@@ -9,6 +9,7 @@ #include "net/url_request/redirect_info.h" #include "services/network/public/mojom/url_loader_factory.mojom-forward.h" #include "services/network/public/mojom/url_response_head.mojom-forward.h" +#include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/blink/public/common/common_export.h" namespace network { @@ -21,10 +22,12 @@ // responses. class BLINK_COMMON_EXPORT ModuleScriptDownloader { public: - // Passes in nullptr on failure. Always invoked asynchronously. + // Passes in nullptr for `response_body` on failure. Always invoked + // asynchronously. using ModuleScriptDownloaderCallback = base::OnceCallback<void(std::unique_ptr<std::string> response_body, - std::string error_message)>; + std::string error_message, + network::mojom::URLResponseHeadPtr)>; // Starts loading the worklet module script on construction. Callback will be // invoked asynchronously once the data has been fetched or an error has
diff --git a/third_party/blink/public/mojom/worker/worklet_global_scope_creation_params.mojom b/third_party/blink/public/mojom/worker/worklet_global_scope_creation_params.mojom index 1aca7fe..0321d2c 100644 --- a/third_party/blink/public/mojom/worker/worklet_global_scope_creation_params.mojom +++ b/third_party/blink/public/mojom/worker/worklet_global_scope_creation_params.mojom
@@ -4,11 +4,12 @@ module blink.mojom; -import "third_party/blink/public/mojom/devtools/devtools_agent.mojom"; -import "third_party/blink/public/mojom/origin_trial_feature/origin_trial_feature.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; -import "url/mojom/url.mojom"; +import "third_party/blink/public/mojom/devtools/devtools_agent.mojom"; +import "third_party/blink/public/mojom/loader/code_cache.mojom"; +import "third_party/blink/public/mojom/origin_trial_feature/origin_trial_feature.mojom"; import "url/mojom/origin.mojom"; +import "url/mojom/url.mojom"; // Interface implemented in the browser for the worklets to forward // ready-for-inspection notification. @@ -31,5 +32,6 @@ array<OriginTrialFeature> origin_trial_features; mojo_base.mojom.UnguessableToken devtools_token; pending_remote<WorkletDevToolsHost> devtools_host; + pending_remote<CodeCacheHost> code_cache_host; bool wait_for_debugger; };
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc index bef437e..94d9327 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -667,7 +667,12 @@ classic_script->SourceUrl(), classic_script->StartPosition(), produce_cache_options); } - if (compile_options == v8::ScriptCompiler::kProduceCompileHints) { + + // `SharedStorageWorkletGlobalScope` has a out-of-process worklet + // architecture that does not have a `page` associated. + // TODO(crbug.com/340920456): Figure out what should be done here. + if (compile_options == v8::ScriptCompiler::kProduceCompileHints && + !execution_context->IsSharedStorageWorkletGlobalScope()) { CHECK(page); CHECK(frame); // We can produce both crowdsourced and local compile hints at the
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 600030c..01111bef 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3373,9 +3373,26 @@ loading_for_print_ = loading_for_print_ || view->LoadAllLazyLoadedIframes(); } + loading_for_print_ = + loading_for_print_ || InitiateStyleOrLayoutDependentLoadForPrint(); + return loading_for_print_; } +bool Document::InitiateStyleOrLayoutDependentLoadForPrint() { + if (auto* view = View()) { + view->AdjustMediaTypeForPrinting(true); + UpdateStyleAndLayout(DocumentUpdateReason::kPrinting); + + view->AdjustMediaTypeForPrinting(false); + UpdateStyleAndLayout(DocumentUpdateReason::kPrinting); + + return !ShouldComplete(); + } + + return false; +} + void Document::SetPrinting(PrintingState state) { bool was_printing = Printing(); printing_ = state;
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index cce9847..51f66da 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -2333,6 +2333,10 @@ ResizeObserver& GetLazyLoadedAutoSizedImgObserver(); + // Initiates data loading for print that is dependent on style or layout. + // Returns true if data loading has started. + bool InitiateStyleOrLayoutDependentLoadForPrint(); + // Mutable because the token is lazily-generated on demand if no token is // explicitly set. mutable std::optional<DocumentToken> token_;
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc index fa87ba2..bebe350 100644 --- a/third_party/blink/renderer/core/execution_context/execution_context.cc +++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -124,6 +124,13 @@ } DCHECK(execution_context->IsWorkletGlobalScope()); + + if (execution_context->IsSharedStorageWorkletGlobalScope()) { + auto* global_scope = + DynamicTo<WorkerOrWorkletGlobalScope>(execution_context); + return global_scope->GetCodeCacheHost(); + } + return nullptr; }
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc index 81eff71..10f8036 100644 --- a/third_party/blink/renderer/core/fetch/request.cc +++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -57,6 +57,7 @@ #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h" #include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h" #include "third_party/blink/renderer/platform/weborigin/referrer.h" +#include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/weborigin/security_policy.h" namespace blink { @@ -579,7 +580,7 @@ " in secure contexts."); return nullptr; } - if (origin->IsOpaque()) { + if (SecurityOrigin::Create(request->Url())->IsOpaque()) { exception_state.ThrowTypeError( "sharedStorageWritable: sharedStorage operations are not available" " for opaque origins.");
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc index 694bb3d4..0f401bb3 100644 --- a/third_party/blink/renderer/core/html/html_image_element.cc +++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -414,12 +414,6 @@ mojom::blink::ConsoleMessageLevel::kError, WebString::FromUTF8("sharedStorageWritable: sharedStorage operations " "are only available in secure contexts."))); - } else if (GetExecutionContext()->GetSecurityOrigin()->IsOpaque()) { - GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( - mojom::blink::ConsoleMessageSource::kOther, - mojom::blink::ConsoleMessageLevel::kError, - WebString::FromUTF8("sharedStorageWritable: sharedStorage operations " - "are not available for opaque origins."))); } else if (!params.new_value.IsNull()) { UseCounter::Count(GetDocument(), WebFeature::kSharedStorageAPI_Image_Attribute);
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index ab5c579..56196a6 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -936,9 +936,11 @@ OriginalStyleForLayoutObject(style_recalc_context); if (IsImageType() && !GetLayoutObject() && style && LayoutObjectIsNeeded(*style)) { - if (!image_loader_) + if (!image_loader_) { image_loader_ = MakeGarbageCollected<HTMLImageLoader>(this); - image_loader_->UpdateFromElement(); + } + image_loader_->UpdateFromElement(ImageLoader::kUpdateNormal, + /* force_blocking */ true); } return style; }
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index b555bd3..4bc6c0c 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -3657,7 +3657,7 @@ // these steps: if (EndedPlayback(LoopCondition::kIgnored)) { // If the media element has a loop attribute specified - if (Loop() && EarliestPossiblePosition() != CurrentPlaybackPosition()) { + if (Loop()) { // then seek to the earliest possible position of the media resource and // abort these steps. Seek(EarliestPossiblePosition());
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc index 5986a8a35..7fcc11e 100644 --- a/third_party/blink/renderer/core/loader/image_loader.cc +++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -528,10 +528,7 @@ RuntimeEnabledFeatures::SharedStorageAPIM118Enabled( GetElement()->GetExecutionContext()) && GetElement()->GetExecutionContext()->IsSecureContext() && - !GetElement() - ->GetExecutionContext() - ->GetSecurityOrigin() - ->IsOpaque(); + !SecurityOrigin::Create(url)->IsOpaque(); resource_request.SetSharedStorageWritableOptedIn( shared_storage_writable_opted_in); }
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc index 38422d6..4fec233 100644 --- a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
@@ -98,7 +98,10 @@ client_provided_global_scope_creation_params->devtools_token, /*worker_settings=*/nullptr, /*v8_cache_options=*/mojom::blink::V8CacheOptions::kDefault, - /*module_responses_map=*/nullptr); + /*module_responses_map=*/nullptr, + /*browser_interface_broker=*/mojo::NullRemote(), + std::move( + client_provided_global_scope_creation_params->code_cache_host)); auto devtools_params = std::make_unique<WorkerDevToolsParams>(); devtools_params->devtools_worker_token =
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 8c805e7..da3116a7 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -6853,9 +6853,6 @@ Scroll(action_data.action); return true; case ax::mojom::blink::Action::kStitchChildTree: - if (action_data.target_node_id == static_cast<int32_t>(AXID())) { - return false; - } if (action_data.child_tree_id == ui::AXTreeIDUnknown()) { return false; // No child tree ID provided.; }
diff --git a/third_party/blink/renderer/modules/exported/web_shared_storage_worklet_thread_impl.cc b/third_party/blink/renderer/modules/exported/web_shared_storage_worklet_thread_impl.cc index d42ba1a..fddb1f1 100644 --- a/third_party/blink/renderer/modules/exported/web_shared_storage_worklet_thread_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_shared_storage_worklet_thread_impl.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/exported/web_shared_storage_worklet_thread_impl.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom.h" #include "third_party/blink/public/mojom/origin_trial_feature/origin_trial_feature.mojom-shared.h" #include "third_party/blink/public/mojom/shared_storage/shared_storage_worklet_service.mojom-blink.h" #include "third_party/blink/public/mojom/worker/worklet_global_scope_creation_params.mojom-blink.h" @@ -26,6 +27,8 @@ global_scope_creation_params->devtools_token, CrossVariantMojoRemote<mojom::WorkletDevToolsHostInterfaceBase>( std::move(global_scope_creation_params->devtools_host)), + CrossVariantMojoRemote<mojom::CodeCacheHostInterfaceBase>( + std::move(global_scope_creation_params->code_cache_host)), global_scope_creation_params->wait_for_debugger); }
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc index 06632d0..d973a95 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
@@ -32,13 +32,16 @@ } void MediaControlTimeDisplayElement::SetCurrentValue(double time) { + if (current_value_ == time) { + return; + } current_value_ = time; String formatted_time = FormatTime(); setInnerText(formatted_time); } double MediaControlTimeDisplayElement::CurrentValue() const { - return current_value_; + return current_value_.value_or(0); } gfx::Size MediaControlTimeDisplayElement::GetSizeOrDefault() const { @@ -54,7 +57,7 @@ } String MediaControlTimeDisplayElement::FormatTime() const { - return MediaControlsSharedHelpers::FormatTime(current_value_); + return MediaControlsSharedHelpers::FormatTime(CurrentValue()); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h index 0735779..bcc9422 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h
@@ -30,7 +30,7 @@ private: void SetAriaLabel(); - double current_value_ = 0; + std::optional<double> current_value_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/ml/webnn/features.gni b/third_party/blink/renderer/modules/ml/webnn/features.gni index 54826759..a13d1158 100644 --- a/third_party/blink/renderer/modules/ml/webnn/features.gni +++ b/third_party/blink/renderer/modules/ml/webnn/features.gni
@@ -4,9 +4,6 @@ import("//build/config/chrome_build.gni") declare_args() { - # This enables building WebNN with XNNPACK. Currently only available for - # Windows and macOS on x64, x86 and arm64. - build_webnn_with_xnnpack = - (is_win || is_mac) && - (current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm64") + # This enables building WebNN with XNNPACK. + build_webnn_with_xnnpack = is_mac }
diff --git a/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc b/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc index c128325..034f4ea 100644 --- a/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc +++ b/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc
@@ -77,18 +77,15 @@ connection_->Init(std::move(connection_remote), std::move(connection_receiver)); - - resolver_->Resolve(connection_); #if BUILDFLAG(IS_ANDROID) PresentationMetrics::RecordPresentationConnectionResult(request_, true); #endif + + resolver_->Resolve(connection_); } void PresentationConnectionCallbacks::OnError( const mojom::blink::PresentationError& error) { - resolver_->Reject(CreatePresentationError( - resolver_->GetScriptState()->GetIsolate(), error)); - connection_ = nullptr; #if BUILDFLAG(IS_ANDROID) // These two error types are not recorded because it's likely that they don't // represent an actual error. @@ -99,6 +96,10 @@ PresentationMetrics::RecordPresentationConnectionResult(request_, false); } #endif + + resolver_->Reject(CreatePresentationError( + resolver_->GetScriptState()->GetIsolate(), error)); + connection_ = nullptr; } } // namespace blink
diff --git a/third_party/blink/renderer/modules/shared_storage/BUILD.gn b/third_party/blink/renderer/modules/shared_storage/BUILD.gn index ea8bcb69..ef7c52b 100644 --- a/third_party/blink/renderer/modules/shared_storage/BUILD.gn +++ b/third_party/blink/renderer/modules/shared_storage/BUILD.gn
@@ -37,6 +37,7 @@ deps = [ "//components/aggregation_service", + "//services/network/public/cpp", "//third_party/blink/renderer/modules/crypto:crypto", ]
diff --git a/third_party/blink/renderer/modules/shared_storage/DEPS b/third_party/blink/renderer/modules/shared_storage/DEPS index 062a227..a60297d 100644 --- a/third_party/blink/renderer/modules/shared_storage/DEPS +++ b/third_party/blink/renderer/modules/shared_storage/DEPS
@@ -7,6 +7,7 @@ "+third_party/blink/renderer/modules/crypto", "+third_party/blink/renderer/modules/v8", "+third_party/blink/renderer/core", + "+services/network/public/cpp", "+gin/converter.h", "+mojo/public/cpp/base/string16_mojom_traits.h", "+url",
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc index 46ea370..5818579 100644 --- a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc +++ b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc
@@ -15,6 +15,7 @@ #include "gin/converter.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" +#include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/url_loader_factory.mojom-blink.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "third_party/blink/public/common/features.h" @@ -23,6 +24,7 @@ #include "third_party/blink/public/mojom/private_aggregation/private_aggregation_host.mojom-blink.h" #include "third_party/blink/public/mojom/shared_storage/shared_storage_worklet_service.mojom-blink.h" #include "third_party/blink/public/platform/cross_variant_mojo_util.h" +#include "third_party/blink/public/platform/web_url_response.h" #include "third_party/blink/renderer/bindings/core/v8/idl_types.h" #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" #include "third_party/blink/renderer/bindings/core/v8/script_function.h" @@ -41,6 +43,8 @@ #include "third_party/blink/renderer/modules/shared_storage/shared_storage_operation_definition.h" #include "third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_thread.h" #include "third_party/blink/renderer/platform/bindings/callback_method_retriever.h" +#include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h" +#include "third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.h" #include "third_party/blink/renderer/platform/wtf/functional.h" #include "v8/include/v8-context.h" #include "v8/include/v8-isolate.h" @@ -356,6 +360,24 @@ WTF::BindOnce(&SharedStorageWorkletGlobalScope::OnModuleScriptDownloaded, WrapWeakPersistent(this), script_source_url, std::move(callback))); + + // Create a ResourceRequest and populate only the fields needed by + // `CodeCacheFetcher`. + // + // TODO(yaoxia): Move `code_cache_fetcher_` to `ModuleScriptDownloader` to + // avoid replicating the ResourceRequest here. This isn't viable today because + // `ModuleScriptDownloader` lives in blink/public/common, due to its use of + // `network::SimpleURLLoader`. + auto resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->url = GURL(script_source_url); + resource_request->destination = + network::mojom::RequestDestination::kSharedStorageWorklet; + + CHECK(GetCodeCacheHost()); + code_cache_fetcher_ = CodeCacheFetcher::TryCreateAndStart( + *resource_request, *GetCodeCacheHost(), + WTF::BindOnce(&SharedStorageWorkletGlobalScope::DidReceiveCachedCode, + WrapWeakPersistent(this))); } void SharedStorageWorkletGlobalScope::RunURLSelectionOperation( @@ -579,9 +601,31 @@ const KURL& script_source_url, mojom::blink::SharedStorageWorkletService::AddModuleCallback callback, std::unique_ptr<std::string> response_body, - std::string error_message) { + std::string error_message, + network::mojom::URLResponseHeadPtr response_head) { module_script_downloader_.reset(); + // If we haven't received the code cache data, defer handing the response. + if (code_cache_fetcher_ && code_cache_fetcher_->is_waiting()) { + handle_script_download_response_after_code_cache_response_ = WTF::BindOnce( + &SharedStorageWorkletGlobalScope::OnModuleScriptDownloaded, + WrapPersistent(this), script_source_url, std::move(callback), + std::move(response_body), std::move(error_message), + std::move(response_head)); + return; + } + + // Note: There's no need to check the `cached_metadata` param from + // `URLLoaderClient::OnReceiveResponse`. This param is only set for data + // fetched from ServiceWorker caches. Today, shared storage script fetch + // cannot be intercepted by service workers. + + std::optional<mojo_base::BigBuffer> cached_metadata = + (code_cache_fetcher_ && response_head) + ? code_cache_fetcher_->TakeCodeCacheForResponse(*response_head) + : std::nullopt; + code_cache_fetcher_.reset(); + mojom::blink::SharedStorageWorkletService::AddModuleCallback add_module_finished_callback = std::move(callback).Then(WTF::BindOnce( &SharedStorageWorkletGlobalScope::RecordAddModuleFinished, @@ -594,6 +638,7 @@ } DCHECK(error_message.empty()); + DCHECK(response_head); if (!ScriptController()) { std::move(add_module_finished_callback) @@ -601,16 +646,45 @@ return; } - ScriptState* script_state = ScriptController()->GetScriptState(); - DCHECK(script_state); + WebURLResponse response = + WebURLResponse::Create(script_source_url, *response_head.get(), + /*report_security_info=*/false, /*request_id=*/0); + + const ResourceResponse& resource_response = response.ToResourceResponse(); + + // Create a `ScriptCachedMetadataHandler` for http family URLs. This + // replicates the core logic from `ScriptResource::ResponseReceived`, + // simplified since shared storage doesn't require + // `ScriptCachedMetadataHandlerWithHashing` which is only used for certain + // schemes. + ScriptCachedMetadataHandler* cached_metadata_handler = nullptr; + + if (script_source_url.ProtocolIsInHTTPFamily()) { + std::unique_ptr<CachedMetadataSender> sender = CachedMetadataSender::Create( + resource_response, mojom::blink::CodeCacheType::kJavascript, + GetSecurityOrigin()); + + cached_metadata_handler = MakeGarbageCollected<ScriptCachedMetadataHandler>( + WTF::TextEncoding(response_head->charset.c_str()), std::move(sender)); + + if (cached_metadata) { + cached_metadata_handler->SetSerializedCachedMetadata( + std::move(*cached_metadata)); + } + } // TODO(crbug.com/1419253): Using a classic script with the custom script // loader is tentative. Eventually, this should migrate to the blink-worklet's // script loading infrastructure. - ClassicScript* worker_script = - ClassicScript::Create(String(*response_body), - /*source_url=*/script_source_url, - /*base_url=*/KURL(), ScriptFetchOptions()); + ClassicScript* worker_script = ClassicScript::Create( + String(*response_body), + /*source_url=*/script_source_url, + /*base_url=*/KURL(), ScriptFetchOptions(), + ScriptSourceLocationType::kUnknown, SanitizeScriptErrors::kSanitize, + cached_metadata_handler); + + ScriptState* script_state = ScriptController()->GetScriptState(); + DCHECK(script_state); v8::HandleScope handle_scope(script_state->GetIsolate()); ScriptEvaluationResult result = @@ -635,6 +709,12 @@ .Run(true, /*error_message=*/g_empty_string); } +void SharedStorageWorkletGlobalScope::DidReceiveCachedCode() { + if (handle_script_download_response_after_code_cache_response_) { + std::move(handle_script_download_response_after_code_cache_response_).Run(); + } +} + void SharedStorageWorkletGlobalScope::RecordAddModuleFinished() { add_module_finished_ = true; }
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.h b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.h index e497c01..af29597 100644 --- a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.h +++ b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.h
@@ -9,6 +9,7 @@ #include "base/check.h" #include "base/functional/callback_forward.h" +#include "mojo/public/cpp/base/big_buffer.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -36,10 +37,12 @@ namespace blink { struct GlobalScopeCreationParams; +class CodeCacheFetcher; class ModuleScriptDownloader; class SharedStorageOperationDefinition; class V8NoArgumentConstructor; class SharedStorage; +class ScriptCachedMetadataHandler; class PrivateAggregation; class Crypto; @@ -141,7 +144,10 @@ const KURL& script_source_url, mojom::blink::SharedStorageWorkletService::AddModuleCallback callback, std::unique_ptr<std::string> response_body, - std::string error_message); + std::string error_message, + network::mojom::URLResponseHeadPtr response_head); + + void DidReceiveCachedCode(); void RecordAddModuleFinished(); @@ -182,6 +188,8 @@ int64_t operation_counter_ = 0; + base::OnceClosure handle_script_download_response_after_code_cache_response_; + // `receiver_`'s disconnect handler explicitly deletes the worklet thread // object that owns this service, thus deleting `this` upon disconnect. To // ensure that the worklet thread object and this service are not leaked, @@ -215,6 +223,8 @@ std::unique_ptr<ModuleScriptDownloader> module_script_downloader_; + scoped_refptr<CodeCacheFetcher> code_cache_fetcher_; + // This is associated because on the client side (i.e. worklet host), we want // the call-in methods (e.g. storage access) and the callback methods // (e.g. finish of a run-operation) to preserve their invocation order. This
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc index c4d5462..c48ad1a6 100644 --- a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc +++ b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc
@@ -38,6 +38,7 @@ #include "third_party/blink/public/mojom/aggregation_service/aggregatable_report.mojom-blink.h" #include "third_party/blink/public/mojom/blob/blob.mojom-blink.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h" #include "third_party/blink/public/mojom/private_aggregation/private_aggregation_host.mojom-blink.h" #include "third_party/blink/public/mojom/shared_storage/shared_storage_worklet_service.mojom.h" #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-blink.h" @@ -60,6 +61,8 @@ constexpr char kModuleScriptSource[] = "https://foo.com/module_script.js"; constexpr char kMaxChar16StringLengthPlusOneLiteral[] = "2621441"; +constexpr base::Time kScriptResponseTime = + base::Time::FromDeltaSinceWindowsEpoch(base::Days(100)); struct VoidOperationResult { bool success = true; @@ -304,6 +307,75 @@ mojo::ReceiverSet<blink::mojom::blink::PrivateAggregationHost> receiver_set_; }; +class MockMojomCoceCacheHost : public blink::mojom::blink::CodeCacheHost { + public: + MockMojomCoceCacheHost() = default; + + void FlushForTesting() { receiver_set_.FlushForTesting(); } + + mojo::ReceiverSet<blink::mojom::blink::CodeCacheHost>& receiver_set() { + return receiver_set_; + } + + // blink::mojom::blink::CoceCacheHost: + void DidGenerateCacheableMetadata(mojom::CodeCacheType cache_type, + const KURL& url, + base::Time expected_response_time, + mojo_base::BigBuffer data) override { + did_generate_cacheable_metadata_count_++; + + // Store the time and data. This mirrors the real-world behavior. + response_time_ = expected_response_time; + data_ = std::move(data); + } + + void FetchCachedCode(mojom::CodeCacheType cache_type, + const KURL& url, + FetchCachedCodeCallback callback) override { + fetch_cached_code_count_++; + std::move(callback).Run(response_time_, data_.Clone()); + } + + void ClearCodeCacheEntry(mojom::CodeCacheType cache_type, + const KURL& url) override { + clear_code_cache_entry_count_++; + } + + void DidGenerateCacheableMetadataInCacheStorage( + const KURL& url, + base::Time expected_response_time, + mojo_base::BigBuffer data, + const String& cache_storage_cache_name) override { + NOTREACHED(); + } + + void OverrideFetchCachedCodeResult(base::Time response_time, + mojo_base::BigBuffer data) { + response_time_ = response_time; + data_ = std::move(data); + } + + size_t did_generate_cacheable_metadata_count() const { + return did_generate_cacheable_metadata_count_; + } + + size_t fetch_cached_code_count() const { return fetch_cached_code_count_; } + + size_t clear_code_cache_entry_count() const { + return clear_code_cache_entry_count_; + } + + private: + base::Time response_time_; + mojo_base::BigBuffer data_; + + size_t did_generate_cacheable_metadata_count_ = 0; + size_t fetch_cached_code_count_ = 0; + size_t clear_code_cache_entry_count_ = 0; + + mojo::ReceiverSet<blink::mojom::blink::CodeCacheHost> receiver_set_; +}; + std::unique_ptr<GlobalScopeCreationParams> MakeTestGlobalScopeCreationParams() { return std::make_unique<GlobalScopeCreationParams>( KURL("https://foo.com"), @@ -332,7 +404,9 @@ class SharedStorageWorkletTest : public PageTestBase { public: - SharedStorageWorkletTest() = default; + SharedStorageWorkletTest() { + mock_code_cache_host_ = std::make_unique<MockMojomCoceCacheHost>(); + } void TearDown() override { // Shut down the worklet gracefully. Otherwise, there could the a data race @@ -358,6 +432,7 @@ auto head = network::mojom::URLResponseHead::New(); head->mime_type = mime_type; head->charset = "us-ascii"; + head->response_time = kScriptResponseTime; proxied_url_loader_factory.AddResponse( GURL(kModuleScriptSource), std::move(head), @@ -451,6 +526,7 @@ std::unique_ptr<TestWorkletDevToolsHost> test_worklet_devtools_host_; std::unique_ptr<MockMojomPrivateAggregationHost> mock_private_aggregation_host_; + std::unique_ptr<MockMojomCoceCacheHost> mock_code_cache_host_; base::HistogramTester histogram_tester_; @@ -512,6 +588,16 @@ test_worklet_devtools_host_ = std::make_unique<TestWorkletDevToolsHost>( std::move(pending_devtools_host_receiver)); + mojo::PendingRemote<mojom::blink::CodeCacheHost> + pending_code_cache_host_remote; + mojo::PendingReceiver<mojom::blink::CodeCacheHost> + pending_code_cache_host_receiver = + pending_code_cache_host_remote.InitWithNewPipeAndPassReceiver(); + + mock_code_cache_host_->receiver_set().Add( + mock_code_cache_host_.get(), + std::move(pending_code_cache_host_receiver)); + messaging_proxy_ = MakeGarbageCollected<SharedStorageWorkletMessagingProxy>( base::SingleThreadTaskRunner::GetCurrentDefault(), CrossVariantMojoReceiver< @@ -524,6 +610,7 @@ Vector({mojom::blink::OriginTrialFeature::kSharedStorageAPI}), /*devtools_worker_token=*/base::UnguessableToken(), std::move(pending_devtools_host_remote), + std::move(pending_code_cache_host_remote), /*wait_for_debugger=*/false), worklet_terminated_future_.GetCallback()); @@ -584,6 +671,135 @@ "unexpected MIME type."); } +TEST_F(SharedStorageWorkletTest, + CodeCache_NoClearDueToEmptyCache_NoGenerateData) { + // Configure to return empty data, with matched response time. + mock_code_cache_host_->OverrideFetchCachedCodeResult( + /*response_time=*/kScriptResponseTime, + /*data=*/std::vector<uint8_t>()); + + AddModule(/*script_content=*/""); + + mock_code_cache_host_->FlushForTesting(); + + EXPECT_EQ(mock_code_cache_host_->fetch_cached_code_count(), 1u); + + // No invalidation was triggered, as `FetchCachedCode()` responded with empty + // data. + EXPECT_EQ(mock_code_cache_host_->clear_code_cache_entry_count(), 0u); + + // No code cache was generated, as the script size is too small. + EXPECT_EQ(mock_code_cache_host_->did_generate_cacheable_metadata_count(), 0u); +} + +TEST_F(SharedStorageWorkletTest, + CodeCache_DidClearDueToUnmatchedTime_NoGenerateData) { + // Configure to return non-empty data, with unmatched response time. + mock_code_cache_host_->OverrideFetchCachedCodeResult( + /*response_time=*/kScriptResponseTime - base::Days(1), + /*data=*/std::vector<uint8_t>(1)); + + AddModule(/*script_content=*/""); + mock_code_cache_host_->FlushForTesting(); + + EXPECT_EQ(mock_code_cache_host_->fetch_cached_code_count(), 1u); + + // Cache was cleared, as the response time did not match the time from the + // script loading. + EXPECT_EQ(mock_code_cache_host_->clear_code_cache_entry_count(), 1u); + + // No code cache was generated, as the script size is too small. + EXPECT_EQ(mock_code_cache_host_->did_generate_cacheable_metadata_count(), 0u); +} + +TEST_F(SharedStorageWorkletTest, + CodeCache_NoClearDueToMatchedTime_NoGenerateData) { + // Configure to return non-empty data, with matched response time. + mock_code_cache_host_->OverrideFetchCachedCodeResult( + /*response_time=*/kScriptResponseTime, + /*data=*/std::vector<uint8_t>(1)); + + AddModule(/*script_content=*/""); + mock_code_cache_host_->FlushForTesting(); + + EXPECT_EQ(mock_code_cache_host_->fetch_cached_code_count(), 1u); + + // No invalidation was triggered, as `FetchCachedCode()` responded with some + // data with a matched response time. + EXPECT_EQ(mock_code_cache_host_->clear_code_cache_entry_count(), 0u); + + // No code cache was generated, as the script size is too small. + EXPECT_EQ(mock_code_cache_host_->did_generate_cacheable_metadata_count(), 0u); +} + +TEST_F(SharedStorageWorkletTest, CodeCache_DidGenerateData) { + // Code cache will be generated when the code length is at least 1024 bytes. + std::string large_script; + while (large_script.size() < 1024) { + large_script += "a=1;"; + } + + AddModule(large_script); + mock_code_cache_host_->FlushForTesting(); + + EXPECT_EQ(mock_code_cache_host_->fetch_cached_code_count(), 1u); + + // No invalidation was triggered, as `FetchCachedCode()` responded with empty + // data. + EXPECT_EQ(mock_code_cache_host_->clear_code_cache_entry_count(), 0u); + + // Code cache was generated. + EXPECT_EQ(mock_code_cache_host_->did_generate_cacheable_metadata_count(), 1u); +} + +TEST_F(SharedStorageWorkletTest, CodeCache_AddModuleTwice) { + // Code cache will be generated when the code length is at least 1024 bytes. + std::string large_script; + while (large_script.size() < 1024) { + large_script += "a=1;"; + } + + AddModule(large_script); + AddModule(large_script); + mock_code_cache_host_->FlushForTesting(); + + EXPECT_EQ(mock_code_cache_host_->fetch_cached_code_count(), 2u); + + // No invalidation was triggered. The second code cache fetch returns a + // response time from the first result, which matches the response time from + // the second script loading. + EXPECT_EQ(mock_code_cache_host_->clear_code_cache_entry_count(), 0u); + + // The second script loading also triggered the code cache generation. This + // implies that the code cache was still not used. This is expected, as we + // won't store the cached code entirely for first seen URLs. + EXPECT_EQ(mock_code_cache_host_->did_generate_cacheable_metadata_count(), 2u); +} + +TEST_F(SharedStorageWorkletTest, CodeCache_AddModuleThreeTimes) { + // Code cache will be generated when the code length is at least 1024 bytes. + std::string large_script; + while (large_script.size() < 1024) { + large_script += "a=1;"; + } + + AddModule(large_script); + AddModule(large_script); + AddModule(large_script); + mock_code_cache_host_->FlushForTesting(); + + EXPECT_EQ(mock_code_cache_host_->fetch_cached_code_count(), 3u); + + // No invalidation was triggered. The second and third code cache fetch + // returns a response time from the first result, which matches the response + // time from the second and third script loading. + EXPECT_EQ(mock_code_cache_host_->clear_code_cache_entry_count(), 0u); + + // The third script loading did not trigger the code cache generation. This + // implies that the cached code was used for the third script loading. + EXPECT_EQ(mock_code_cache_host_->did_generate_cacheable_metadata_count(), 2u); +} + TEST_F(SharedStorageWorkletTest, WorkletTerminationDueToDisconnect) { AddModuleResult result = AddModule(/*script_content=*/"");
diff --git a/third_party/blink/renderer/platform/bindings/exception_context.h b/third_party/blink/renderer/platform/bindings/exception_context.h index 7da1982..df8b659 100644 --- a/third_party/blink/renderer/platform/bindings/exception_context.h +++ b/third_party/blink/renderer/platform/bindings/exception_context.h
@@ -26,7 +26,6 @@ kIndexedPropertySetter, kIndexedPropertyDefiner, kIndexedPropertyDeleter, - kIndexedPropertyQuery, kNamedPropertyGetter, kNamedPropertyDescriptor, kNamedPropertySetter, @@ -70,7 +69,6 @@ case ExceptionContextType::kIndexedPropertySetter: case ExceptionContextType::kIndexedPropertyDefiner: case ExceptionContextType::kIndexedPropertyDeleter: - case ExceptionContextType::kIndexedPropertyQuery: case ExceptionContextType::kNamedPropertyGetter: case ExceptionContextType::kNamedPropertyDescriptor: case ExceptionContextType::kNamedPropertySetter:
diff --git a/third_party/blink/renderer/platform/loader/BUILD.gn b/third_party/blink/renderer/platform/loader/BUILD.gn index 99c4902..40d175d 100644 --- a/third_party/blink/renderer/platform/loader/BUILD.gn +++ b/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -132,6 +132,8 @@ "fetch/url_loader/background_url_loader.h", "fetch/url_loader/cached_metadata_handler.cc", "fetch/url_loader/cached_metadata_handler.h", + "fetch/url_loader/code_cache_fetcher.cc", + "fetch/url_loader/code_cache_fetcher.h", "fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc", "fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.h", "fetch/url_loader/mojo_url_loader_client.cc",
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.cc new file mode 100644 index 0000000..3d3dec3 --- /dev/null +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.cc
@@ -0,0 +1,201 @@ +// 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 "third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.h" + +#include "base/memory/scoped_refptr.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/blink/renderer/platform/loader/fetch/code_cache_host.h" +#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" + +namespace blink { + +namespace { + +bool ShouldUseIsolatedCodeCache( + const network::mojom::URLResponseHead& response_head, + const KURL& initial_url, + const KURL& current_url, + base::Time code_cache_response_time) { + // We only support code cache for other service worker provided + // resources when a direct pass-through fetch handler is used. If the service + // worker synthesizes a new Response or provides a Response fetched from a + // different URL, then do not use the code cache. + // Also, responses coming from cache storage use a separate code cache + // mechanism. + if (response_head.was_fetched_via_service_worker) { + // Do the same check as !ResourceResponse::IsServiceWorkerPassThrough(). + if (!response_head.cache_storage_cache_name.empty()) { + // Responses was produced by cache_storage + return false; + } + if (response_head.url_list_via_service_worker.empty()) { + // Response was synthetically constructed. + return false; + } + if (KURL(response_head.url_list_via_service_worker.back()) != current_url) { + // Response was fetched from different URLs. + return false; + } + } + if (SchemeRegistry::SchemeSupportsCodeCacheWithHashing( + initial_url.Protocol())) { + // This resource should use a source text hash rather than a response time + // comparison. + if (!SchemeRegistry::SchemeSupportsCodeCacheWithHashing( + current_url.Protocol())) { + // This kind of Resource doesn't support requiring a hash, so we can't + // send cached code to it. + return false; + } + } else if (!response_head.should_use_source_hash_for_js_code_cache) { + // If the timestamps don't match or are null, the code cache data may be + // for a different response. See https://crbug.com/1099587. + if (code_cache_response_time.is_null() || + response_head.response_time.is_null() || + code_cache_response_time != response_head.response_time) { + return false; + } + } + return true; +} + +bool ShouldFetchCodeCache(const network::ResourceRequest& request) { + // Since code cache requests use a per-frame interface, don't fetch cached + // code for keep-alive requests. These are only used for beaconing and we + // don't expect code cache to help there. + if (request.keepalive) { + return false; + } + + // Aside from http and https, the only other supported protocols are those + // listed in the SchemeRegistry as requiring a content equality check. + bool should_use_source_hash = + SchemeRegistry::SchemeSupportsCodeCacheWithHashing( + String(request.url.scheme())); + if (!request.url.SchemeIsHTTPOrHTTPS() && !should_use_source_hash) { + return false; + } + + // Supports script resource requests and shared storage worklet module + // requests. + // TODO(crbug.com/964467): Currently Chrome doesn't support code cache for + // dedicated worker, shared worker, audio worklet and paint worklet. For + // the service worker scripts, Blink receives the code cache via + // URLLoaderClient::OnReceiveResponse() IPC. + if (request.destination == network::mojom::RequestDestination::kScript || + request.destination == + network::mojom::RequestDestination::kSharedStorageWorklet) { + return true; + } + + // WebAssembly module request have RequestDestination::kEmpty. Note that + // we always perform a code fetch for all of these requests because: + // + // * It is not easy to distinguish WebAssembly modules from other kEmpty + // requests + // * The fetch might be handled by Service Workers, but we can't still know + // if the response comes from the CacheStorage (in such cases its own + // code cache will be used) or not. + // + // These fetches should be cheap, however, requiring one additional IPC and + // no browser process disk IO since the cache index is in memory and the + // resource key should not be present. + // + // The only case where it's easy to skip a kEmpty request is when a content + // equality check is required, because only ScriptResource supports that + // requirement. + if (request.destination == network::mojom::RequestDestination::kEmpty) { + return true; + } + return false; +} + +mojom::blink::CodeCacheType GetCodeCacheType( + network::mojom::RequestDestination destination) { + if (destination == network::mojom::RequestDestination::kEmpty) { + // For requests initiated by the fetch function, we use code cache for + // WASM compiled code. + return mojom::blink::CodeCacheType::kWebAssembly; + } else { + // Otherwise, we use code cache for scripting. + return mojom::blink::CodeCacheType::kJavascript; + } +} + +} // namespace + +// static +scoped_refptr<CodeCacheFetcher> CodeCacheFetcher::TryCreateAndStart( + const network::ResourceRequest& request, + CodeCacheHost& code_cache_host, + base::OnceClosure done_closure) { + if (!ShouldFetchCodeCache(request)) { + return nullptr; + } + auto fetcher = base::MakeRefCounted<CodeCacheFetcher>( + code_cache_host, GetCodeCacheType(request.destination), KURL(request.url), + std::move(done_closure)); + fetcher->Start(); + return fetcher; +} + +CodeCacheFetcher::CodeCacheFetcher(CodeCacheHost& code_cache_host, + mojom::blink::CodeCacheType code_cache_type, + const KURL& url, + base::OnceClosure done_closure) + : code_cache_host_(code_cache_host.GetWeakPtr()), + code_cache_type_(code_cache_type), + initial_url_(url), + current_url_(url), + done_closure_(std::move(done_closure)) {} + +void CodeCacheFetcher::Start() { + CHECK(code_cache_host_); + (*code_cache_host_) + ->FetchCachedCode(code_cache_type_, initial_url_, + WTF::BindOnce(&CodeCacheFetcher::DidReceiveCachedCode, + base::WrapRefCounted(this))); +} + +void CodeCacheFetcher::DidReceiveCachedMetadataFromUrlLoader() { + did_receive_cached_metadata_from_url_loader_ = true; + if (!is_waiting_) { + ClearCodeCacheEntryIfPresent(); + } +} + +std::optional<mojo_base::BigBuffer> CodeCacheFetcher::TakeCodeCacheForResponse( + const network::mojom::URLResponseHead& response_head) { + CHECK(!is_waiting_); + if (!ShouldUseIsolatedCodeCache(response_head, initial_url_, current_url_, + code_cache_response_time_)) { + ClearCodeCacheEntryIfPresent(); + return std::nullopt; + } + return std::move(code_cache_data_); +} + +void CodeCacheFetcher::DidReceiveCachedCode(base::Time response_time, + mojo_base::BigBuffer data) { + is_waiting_ = false; + code_cache_data_ = std::move(data); + if (did_receive_cached_metadata_from_url_loader_) { + ClearCodeCacheEntryIfPresent(); + return; + } + code_cache_response_time_ = response_time; + std::move(done_closure_).Run(); +} + +void CodeCacheFetcher::ClearCodeCacheEntryIfPresent() { + if (code_cache_host_ && code_cache_data_ && (code_cache_data_->size() > 0)) { + (*code_cache_host_)->ClearCodeCacheEntry(code_cache_type_, initial_url_); + } + code_cache_data_.reset(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.h new file mode 100644 index 0000000..78e09fd --- /dev/null +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.h
@@ -0,0 +1,84 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CODE_CACHE_FETCHER_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CODE_CACHE_FETCHER_H_ + +#include "base/functional/callback_forward.h" +#include "base/functional/callback_helpers.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "mojo/public/cpp/base/big_buffer.h" +#include "services/network/public/mojom/url_response_head.mojom-forward.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink-forward.h" +#include "third_party/blink/public/platform/web_common.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/ref_counted.h" + +namespace network { +struct ResourceRequest; +} // namespace network + +namespace blink { + +class CodeCacheHost; + +// Handles the fetching and validation of code cache entries. +class BLINK_PLATFORM_EXPORT CodeCacheFetcher + : public WTF::RefCounted<CodeCacheFetcher> { + public: + static scoped_refptr<CodeCacheFetcher> TryCreateAndStart( + const network::ResourceRequest& request, + CodeCacheHost& code_cache_host, + base::OnceClosure done_closure); + + CodeCacheFetcher(CodeCacheHost& code_cache_host, + mojom::blink::CodeCacheType code_cache_type, + const KURL& url, + base::OnceClosure done_closure); + + CodeCacheFetcher(const CodeCacheFetcher&) = delete; + CodeCacheFetcher& operator=(const CodeCacheFetcher&) = delete; + + bool is_waiting() const { return is_waiting_; } + + void SetCurrentUrl(const KURL& new_url) { current_url_ = new_url; } + void DidReceiveCachedMetadataFromUrlLoader(); + std::optional<mojo_base::BigBuffer> TakeCodeCacheForResponse( + const network::mojom::URLResponseHead& response_head); + + private: + friend class WTF::RefCounted<CodeCacheFetcher>; + ~CodeCacheFetcher() = default; + + void Start(); + + void DidReceiveCachedCode(base::Time response_time, + mojo_base::BigBuffer data); + + void ClearCodeCacheEntryIfPresent(); + + base::WeakPtr<CodeCacheHost> code_cache_host_; + mojom::blink::CodeCacheType code_cache_type_; + + // The initial URL used for code cache fetching, prior to redirects. This + // should match the initial URL for script fetching. + const KURL initial_url_; + + // The current URL used for code cache fetching. This should match / will be + // updated to the current url for script fetching (either initial or + // redirected). + KURL current_url_; + + base::OnceClosure done_closure_; + + bool is_waiting_ = true; + bool did_receive_cached_metadata_from_url_loader_ = false; + std::optional<mojo_base::BigBuffer> code_cache_data_; + base::Time code_cache_response_time_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CODE_CACHE_FETCHER_H_
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc index 5b2e0bb..00c1e5d7 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.cc
@@ -53,6 +53,7 @@ #include "third_party/blink/public/platform/web_url_request_util.h" #include "third_party/blink/renderer/platform/loader/fetch/code_cache_host.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h" +#include "third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_fetcher.h" #include "third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client.h" #include "third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_client.h" #include "third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h" @@ -138,238 +139,8 @@ return original_url.scheme_piece() != redirect_url.scheme_piece(); } -bool ShouldFetchCodeCache(const network::ResourceRequest& request) { - // Since code cache requests use a per-frame interface, don't fetch cached - // code for keep-alive requests. These are only used for beaconing and we - // don't expect code cache to help there. - if (request.keepalive) { - return false; - } - - // Aside from http and https, the only other supported protocols are those - // listed in the SchemeRegistry as requiring a content equality check. - bool should_use_source_hash = - SchemeRegistry::SchemeSupportsCodeCacheWithHashing( - String(request.url.scheme())); - if (!request.url.SchemeIsHTTPOrHTTPS() && !should_use_source_hash) { - return false; - } - - // Supports script resource requests. - // TODO(crbug.com/964467): Currently Chrome doesn't support code cache for - // dedicated worker, shared worker, audio worklet and paint worklet. For - // the service worker scripts, Blink receives the code cache via - // URLLoaderClient::OnReceiveResponse() IPC. - if (request.destination == network::mojom::RequestDestination::kScript) { - return true; - } - - // WebAssembly module request have RequestDestination::kEmpty. Note that - // we always perform a code fetch for all of these requests because: - // - // * It is not easy to distinguish WebAssembly modules from other kEmpty - // requests - // * The fetch might be handled by Service Workers, but we can't still know - // if the response comes from the CacheStorage (in such cases its own - // code cache will be used) or not. - // - // These fetches should be cheap, however, requiring one additional IPC and - // no browser process disk IO since the cache index is in memory and the - // resource key should not be present. - // - // The only case where it's easy to skip a kEmpty request is when a content - // equality check is required, because only ScriptResource supports that - // requirement. - if (request.destination == network::mojom::RequestDestination::kEmpty) { - return true; - } - return false; -} - -mojom::blink::CodeCacheType GetCodeCacheType( - network::mojom::RequestDestination destination) { - if (destination == network::mojom::RequestDestination::kEmpty) { - // For requests initiated by the fetch function, we use code cache for - // WASM compiled code. - return mojom::blink::CodeCacheType::kWebAssembly; - } else { - // Otherwise, we use code cache for scripting. - return mojom::blink::CodeCacheType::kJavascript; - } -} - -bool ShouldUseIsolatedCodeCache( - const network::mojom::URLResponseHead& response_head, - const KURL& initial_url, - const KURL& current_url, - base::Time code_cache_response_time) { - // We only support code cache for other service worker provided - // resources when a direct pass-through fetch handler is used. If the service - // worker synthesizes a new Response or provides a Response fetched from a - // different URL, then do not use the code cache. - // Also, responses coming from cache storage use a separate code cache - // mechanism. - if (response_head.was_fetched_via_service_worker) { - // Do the same check as !ResourceResponse::IsServiceWorkerPassThrough(). - if (!response_head.cache_storage_cache_name.empty()) { - // Responses was produced by cache_storage - return false; - } - if (response_head.url_list_via_service_worker.empty()) { - // Response was synthetically constructed. - return false; - } - if (KURL(response_head.url_list_via_service_worker.back()) != current_url) { - // Response was fetched from different URLs. - return false; - } - } - if (SchemeRegistry::SchemeSupportsCodeCacheWithHashing( - initial_url.Protocol())) { - // This resource should use a source text hash rather than a response time - // comparison. - if (!SchemeRegistry::SchemeSupportsCodeCacheWithHashing( - current_url.Protocol())) { - // This kind of Resource doesn't support requiring a hash, so we can't - // send cached code to it. - return false; - } - } else if (!response_head.should_use_source_hash_for_js_code_cache) { - // If the timestamps don't match or are null, the code cache data may be - // for a different response. See https://crbug.com/1099587. - if (code_cache_response_time.is_null() || - response_head.response_time.is_null() || - code_cache_response_time != response_head.response_time) { - return false; - } - } - return true; -} - } // namespace -class ResourceRequestSender::CodeCacheFetcher - : public WTF::RefCounted<ResourceRequestSender::CodeCacheFetcher> { - public: - static scoped_refptr<CodeCacheFetcher> TryCreateAndStart( - const network::ResourceRequest& request, - CodeCacheHost& code_cache_host, - base::OnceClosure done_closure); - - CodeCacheFetcher(CodeCacheHost& code_cache_host, - mojom::blink::CodeCacheType code_cache_type, - const GURL& url, - base::OnceClosure done_closure); - - CodeCacheFetcher(const CodeCacheFetcher&) = delete; - CodeCacheFetcher& operator=(const CodeCacheFetcher&) = delete; - - bool is_waiting() const { return is_waiting_; } - - void SetCurrentUrl(const GURL& new_url) { current_url_ = KURL(new_url); } - void DidReceiveCachedMetadataFromUrlLoader(); - std::optional<mojo_base::BigBuffer> TakeCodeCacheForResponse( - const network::mojom::URLResponseHead& response_head); - - private: - friend class WTF::RefCounted<CodeCacheFetcher>; - ~CodeCacheFetcher() = default; - - void Start(); - - void DidReceiveCachedCode(base::Time response_time, - mojo_base::BigBuffer data); - - void ClearCodeCacheEntryIfPresent(); - - base::WeakPtr<CodeCacheHost> code_cache_host_; - mojom::blink::CodeCacheType code_cache_type_; - const KURL initial_url_; - KURL current_url_; - base::OnceClosure done_closure_; - - bool is_waiting_ = true; - bool did_receive_cached_metadata_from_url_loader_ = false; - std::optional<mojo_base::BigBuffer> code_cache_data_; - base::Time code_cache_response_time_; -}; - -// static -scoped_refptr<ResourceRequestSender::CodeCacheFetcher> -ResourceRequestSender::CodeCacheFetcher::TryCreateAndStart( - const network::ResourceRequest& request, - CodeCacheHost& code_cache_host, - base::OnceClosure done_closure) { - if (!ShouldFetchCodeCache(request)) { - return nullptr; - } - auto fetcher = base::MakeRefCounted<ResourceRequestSender::CodeCacheFetcher>( - code_cache_host, GetCodeCacheType(request.destination), request.url, - std::move(done_closure)); - fetcher->Start(); - return fetcher; -} - -ResourceRequestSender::CodeCacheFetcher::CodeCacheFetcher( - CodeCacheHost& code_cache_host, - mojom::blink::CodeCacheType code_cache_type, - const GURL& url, - base::OnceClosure done_closure) - : code_cache_host_(code_cache_host.GetWeakPtr()), - code_cache_type_(code_cache_type), - initial_url_(url), - current_url_(url), - done_closure_(std::move(done_closure)) {} - -void ResourceRequestSender::CodeCacheFetcher::Start() { - CHECK(code_cache_host_); - (*code_cache_host_) - ->FetchCachedCode(code_cache_type_, KURL(initial_url_), - WTF::BindOnce(&CodeCacheFetcher::DidReceiveCachedCode, - base::WrapRefCounted(this))); -} - -void ResourceRequestSender::CodeCacheFetcher:: - DidReceiveCachedMetadataFromUrlLoader() { - did_receive_cached_metadata_from_url_loader_ = true; - if (!is_waiting_) { - ClearCodeCacheEntryIfPresent(); - } -} - -std::optional<mojo_base::BigBuffer> -ResourceRequestSender::CodeCacheFetcher::TakeCodeCacheForResponse( - const network::mojom::URLResponseHead& response_head) { - CHECK(!is_waiting_); - if (!ShouldUseIsolatedCodeCache(response_head, initial_url_, current_url_, - code_cache_response_time_)) { - ClearCodeCacheEntryIfPresent(); - return std::nullopt; - } - return std::move(code_cache_data_); -} - -void ResourceRequestSender::CodeCacheFetcher::DidReceiveCachedCode( - base::Time response_time, - mojo_base::BigBuffer data) { - is_waiting_ = false; - code_cache_data_ = std::move(data); - if (did_receive_cached_metadata_from_url_loader_) { - ClearCodeCacheEntryIfPresent(); - return; - } - code_cache_response_time_ = response_time; - std::move(done_closure_).Run(); -} - -void ResourceRequestSender::CodeCacheFetcher::ClearCodeCacheEntryIfPresent() { - if (code_cache_host_ && code_cache_data_ && (code_cache_data_->size() > 0)) { - (*code_cache_host_) - ->ClearCodeCacheEntry(code_cache_type_, KURL(initial_url_)); - } - code_cache_data_.reset(); -} - ResourceRequestSender::ResourceRequestSender() = default; ResourceRequestSender::~ResourceRequestSender() = default; @@ -763,7 +534,7 @@ CHECK(request_info_->url_loader); if (code_cache_fetcher_) { - code_cache_fetcher_->SetCurrentUrl(redirect_info.new_url); + code_cache_fetcher_->SetCurrentUrl(KURL(redirect_info.new_url)); } request_info_->local_response_start = redirect_ipc_arrival_time;
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h index 9852193a..b3ed40d 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/resource_request_sender.h
@@ -28,6 +28,7 @@ #include "services/network/public/mojom/url_response_head.mojom-forward.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink-forward.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h" #include "third_party/blink/public/mojom/navigation/renderer_eviction_reason.mojom-blink-forward.h" @@ -52,6 +53,7 @@ } // namespace network namespace blink { +class CodeCacheFetcher; class CodeCacheHost; class ResourceLoadInfoNotifierWrapper; class ThrottlingURLLoader; @@ -162,7 +164,6 @@ friend class URLLoaderClientImpl; friend class URLResponseBodyConsumer; - class CodeCacheFetcher; struct PendingRequestInfo { PendingRequestInfo(scoped_refptr<ResourceRequestClient> client, network::mojom::RequestDestination request_destination,
diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.cc b/third_party/blink/renderer/platform/media/web_media_player_impl.cc index b5314246..669ab109 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl.cc +++ b/third_party/blink/renderer/platform/media/web_media_player_impl.cc
@@ -1019,7 +1019,6 @@ void WebMediaPlayerImpl::Seek(double seconds) { DVLOG(1) << __func__ << "(" << seconds << "s)"; DCHECK(main_task_runner_->BelongsToCurrentThread()); - media_log_->AddEvent<MediaLogEvent::kSeek>(seconds); DoSeek(base::Seconds(seconds), true); } @@ -1032,6 +1031,26 @@ if (ready_state_ > WebMediaPlayer::kReadyStateHaveMetadata) SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata); + // For zero duration video-only media, if we can elide the seek, use a large + // delay to avoid an expensive spin loop. Per spec we must still deliver all + // the requisite events, but we're not required to be timely about it. + // + // 250ms matches the max timeupdate interval used by the media element. + auto delay = base::TimeDelta(); + bool is_at_eos = false; + if (ended_) { + if (time == base::Seconds(Duration())) { + is_at_eos = true; + } else if (!HasAudio()) { + if (auto frame = compositor_->GetCurrentFrameOnAnyThread()) { + if (frame->timestamp() == GetCurrentTimeInternal()) { + is_at_eos = true; + delay = base::Milliseconds(250); + } + } + } + } + // When paused or ended, we know exactly what the current time is and can // elide seeks to it. However, there are three cases that are not elided: // 1) When the pipeline state is not stable. @@ -1044,21 +1063,34 @@ // 3) For MSE. // Because the buffers may have changed between seeks, MSE seeks are // never elided. - if (paused_ && pipeline_controller_->IsStable() && - (paused_time_ == time || (ended_ && time == base::Seconds(Duration()))) && + if (((paused_ && paused_time_ == time) || (ended_ && is_at_eos)) && + pipeline_controller_->IsStable() && GetDemuxerType() != media::DemuxerType::kChunkDemuxer) { if (old_state == kReadyStateHaveEnoughData) { // This will in turn SetReadyState() to signal the demuxer seek, followed // by timeChanged() to signal the renderer seek. should_notify_time_changed_ = true; - main_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&WebMediaPlayerImpl::OnBufferingStateChange, - weak_this_, media::BUFFERING_HAVE_ENOUGH, - media::BUFFERING_CHANGE_REASON_UNKNOWN)); + + // Seek will always emit a new frame -- even if the it's the same frame it + // will be decoded again with a new frame id, so simulate that here. + main_task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&WebMediaPlayerImpl::OnNewFramePresentedCallback, + weak_this_), + delay); + + main_task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&WebMediaPlayerImpl::OnBufferingStateChange, + weak_this_, media::BUFFERING_HAVE_ENOUGH, + media::BUFFERING_CHANGE_REASON_UNKNOWN), + delay); return; } } + media_log_->AddEvent<MediaLogEvent::kSeek>(time.InSecondsF()); + if (playback_events_recorder_) playback_events_recorder_->OnSeeking(); @@ -1933,7 +1965,9 @@ return; ended_ = true; - client_->TimeChanged(); + if (!paused_) { + client_->TimeChanged(); + } if (playback_events_recorder_) playback_events_recorder_->OnEnded(); @@ -2893,7 +2927,7 @@ auto create_demuxer_error = demuxer_manager_->CreateDemuxer( load_type_ == kLoadTypeMediaSource, preload_, needs_first_frame_, base::BindOnce(&WebMediaPlayerImpl::OnDemuxerCreated, - base::Unretained(this)), + base::Unretained(this)), headers); if (!create_demuxer_error.is_ok()) {
diff --git a/third_party/blink/renderer/platform/network/http_parsers.cc b/third_party/blink/renderer/platform/network/http_parsers.cc index 8182059..ead726c4 100644 --- a/third_party/blink/renderer/platform/network/http_parsers.cc +++ b/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -310,7 +310,7 @@ ? std::make_optional(ConvertToBlink(in->content_language.value())) : std::nullopt, ConvertToBlink(in->no_vary_search_with_parse_error), - in->observe_browsing_topics); + in->observe_browsing_topics, in->allow_cross_origin_event_reporting); } } // namespace mojom
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py index f009d59..e79de55 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
@@ -54,12 +54,12 @@ # pylint: disable=import-error # pylint: disable=invalid-name # pylint: disable=redefined-outer-name - global SDK_ROOT, SDK_TOOLS_DIR, run_continuous_ffx_command, run_ffx_command - from common import SDK_ROOT, SDK_TOOLS_DIR, run_continuous_ffx_command, run_ffx_command - global get_ssh_prefix - from compatible_utils import get_ssh_prefix - global port_forward - from test_server import port_forward + global SDK_ROOT, SDK_TOOLS_DIR, get_ssh_address, run_continuous_ffx_command, run_ffx_command + from common import SDK_ROOT, SDK_TOOLS_DIR, get_ssh_address, run_continuous_ffx_command, run_ffx_command + global get_host_arch, get_ssh_prefix + from compatible_utils import get_host_arch, get_ssh_prefix + global ports_forward, port_forward + from test_server import ports_forward, port_forward # pylint: enable=import-error # pylint: enable=invalid-name # pylint: disable=redefined-outer-name @@ -118,27 +118,15 @@ # Tell SSH to forward all server ports from the Fuchsia device to # the host. - self._host_port_pair = run_ffx_command( - cmd=('target', 'get-ssh-address'), - target_id=self._target_id, - capture_output=True).stdout.strip() - self._proxy = self._port_forward_list(ports_to_forward) + self._host_port_pair = get_ssh_address(self._target_id) + self._port_forward_list(ports_to_forward) def _port_forward_list(self, ports): """Reverse forward all ports listed in |ports| to the device.""" - - ssh_prefix = get_ssh_prefix(self._host_port_pair) - forwarding_flags = [ - '-O', - 'forward', # Send SSH mux control signal. - '-N', # Don't execute command - '-T' # Don't allocate terminal. - ] + forwarding_ports = [] for port in ports: - forwarding_flags += ['-R', f'{port}:localhost:{port}'] - return subprocess.Popen(ssh_prefix + forwarding_flags, - stdout=subprocess.PIPE, - stderr=open('/dev/null')) + forwarding_ports.append((port, port)) + ports_forward(self._host_port_pair, forwarding_ports) def run_command(self, command): ssh_prefix = get_ssh_prefix(self._host_port_pair) @@ -173,13 +161,11 @@ def __init__(self, host, port_name, target_host=None, **kwargs): super(FuchsiaPort, self).__init__(host, port_name, **kwargs) + _import_fuchsia_runner() self._operating_system = 'fuchsia' self._version = 'fuchsia' - self._target_device = self.get_option('device') - - self._architecture = 'x86_64' if self._target_cpu( - ) == 'x64' else 'arm64' + self._architecture = 'x86_64' if get_host_arch() == 'x64' else 'arm64' self.server_process_constructor = FuchsiaServerProcess @@ -188,10 +174,10 @@ self._target_host = target_host self._zircon_logger = None - _import_fuchsia_runner() self._symbolizer = os.path.join(SDK_TOOLS_DIR, 'symbolizer') self._build_id_dir = os.path.join(SDK_ROOT, '.build-id') + # TODO(b/340288531): Should use ffx debug symbolize. def run_symbolizer(self, input_fd, output_fd, ids_txt_paths): """Starts a symbolizer process. @@ -225,9 +211,6 @@ if self._zircon_logger: self._zircon_logger.close() - def _target_cpu(self): - return self.get_option('fuchsia_target_cpu') - def _cpu_cores(self): # TODO(crbug.com/1340573): Four parallel jobs always gives reasonable # performance, while using larger numbers may actually slow things. @@ -240,13 +223,11 @@ target_id = self.get_option('fuchsia_target_id') self._target_host = _TargetHost(self.SERVER_PORTS, target_id) - if self.get_option('zircon_logging'): - klog_proc = self._target_host.run_command(['dlog', '-f']) - symbolized_klog_proc = self.run_symbolizer( - klog_proc.stdout, subprocess.PIPE, - [self.get_build_ids_path()]) - self._zircon_logger = SubprocessOutputLogger(symbolized_klog_proc, - 'Zircon') + klog_proc = self._target_host.run_command(['dlog', '-f']) + symbolized_klog_proc = self.run_symbolizer( + klog_proc.stdout, subprocess.PIPE, [self.get_build_ids_path()]) + self._zircon_logger = SubprocessOutputLogger( + symbolized_klog_proc, 'Zircon') except: return exit_codes.NO_DEVICES_EXIT_STATUS @@ -313,17 +294,11 @@ more_logging=self._port.get_option('driver_logging')) def _base_cmd_line(self): - cmd = [] - if self._port._target_device == 'qemu': - cmd.append('--ozone-platform=headless') - # Use Scenic on AEMU - else: - cmd.extend([ - '--use-vulkan', '--enable-gpu-rasterization', - '--force-device-scale-factor=1', '--enable-features=Vulkan', - '--gpu-watchdog-timeout-seconds=60' - ]) - return cmd + return [ + '--use-vulkan', '--enable-gpu-rasterization', + '--force-device-scale-factor=1', '--enable-features=Vulkan', + '--gpu-watchdog-timeout-seconds=60' + ] def _command_from_driver_input(self, driver_input): command = super(ChromiumFuchsiaDriver,
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py index 067e814..15747cf 100644 --- a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py +++ b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
@@ -96,42 +96,14 @@ printing.add_print_options_group(parser) fuchsia_group = parser.add_argument_group('Fuchsia-specific Options') - fuchsia_group.add_argument( - '--zircon-logging', - action='store_true', - default=True, - help='Log Zircon debug messages (enabled by default).') - fuchsia_group.add_argument('--no-zircon-logging', - dest='zircon_logging', - action='store_false', - default=True, - help='Do not log Zircon debug messages.') - fuchsia_group.add_argument( - '--device', - choices=['qemu', 'device', 'fvdl'], - default='fvdl', - help='Choose device to launch Fuchsia with. Defaults to fvdl.') - fuchsia_group.add_argument( - '--fuchsia-target-cpu', - choices=['x64', 'arm64'], - default='x64', - help='cpu architecture of the device. Defaults to x64.') fuchsia_group.add_argument('--fuchsia-out-dir', help='Path to Fuchsia build output directory.') fuchsia_group.add_argument( '--custom-image', help='Specify an image used for booting up the emulator.') fuchsia_group.add_argument( - '--fuchsia-ssh-config', - help=('The path to the SSH configuration used for ' - 'connecting to the target device.')) - fuchsia_group.add_argument( '--fuchsia-target-id', help='The node-name of the device to boot or deploy to.') - fuchsia_group.add_argument( - '--fuchsia-host-ip', - help=('The IP address of the test host observed by the Fuchsia ' - 'device. Required if running on hardware devices.')) fuchsia_group.add_argument('--logs-dir', help='Location of diagnostics logs')
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index b868b2d..9e154f0f 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -2704,6 +2704,9 @@ crbug.com/40278771 [ Mac ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/buffer.https.any.worker.html?gpu [ Skip ] crbug.com/40278771 [ Linux ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/buffer.https.any.html?cpu [ Skip ] crbug.com/40278771 [ Linux ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/buffer.https.any.worker.html?cpu [ Skip ] +crbug.com/40278771 [ Win ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/buffer.https.any.html?cpu [ Skip ] +crbug.com/40278771 [ Win ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/buffer.https.any.worker.html?cpu [ Skip ] + ######## Unload Deprecation # This is for tests in the "unload-allowed" virtual suite that
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 0768615..2c1f211 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -6032,6 +6032,8 @@ crbug.com/1362106 [ Win ] virtual/media-foundation-for-clear-dcomp/media/W3C/video/readyState/readyState_during_canplaythrough.html [ Failure Skip ] crbug.com/1362106 [ Win ] virtual/media-foundation-for-clear-dcomp/media/W3C/video/readyState/readyState_during_loadeddata.html [ Failure Skip ] crbug.com/1362106 [ Win ] virtual/media-foundation-for-clear-dcomp/media/W3C/video/readyState/readyState_during_playing.html [ Failure Skip ] +crbug.com/1362106 [ Win ] virtual/media-foundation-for-clear-dcomp/media/video-no-infinite-loop-playing.html [ Failure Skip ] +crbug.com/1362106 [ Win ] virtual/media-foundation-for-clear-dcomp/media/video-no-infinite-loop-playing-rvfc.html [ Failure Skip ] # crbug.com/1356128 Disable flaky tests for fetch keepalive migration. # Some of the following tests are both flaky in non-virtual and virtual versions.
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index c314d31..dfb6722 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -2579,7 +2579,7 @@ "Run the WebNN WPTs with a CPU context with the WebNN service enabled.", { "prefix": "webnn-service-on-cpu", - "platforms": ["Linux"], + "platforms": ["Linux", "Win"], "bases": [ "external/wpt/webnn/validation_tests", "external/wpt/webnn/conformance_tests/arg_min_max.https.any.html?cpu",
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index f32d0df7..679c714f 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -122342,6 +122342,19 @@ {} ] ], + "downloadable-font-scoped-to-document.html": [ + "2dbc350069cd9c61925967655f83217b800fc9eb", + [ + null, + [ + [ + "/css/css-fonts/downloadable-font-scoped-to-document-ref.html", + "==" + ] + ], + {} + ] + ], "first-available-font-001.html": [ "5eb88f7bf6713b80e0adb4728681e62c3f2dc2bc", [ @@ -160220,6 +160233,214 @@ {} ] ], + "line-clamp-auto-001.tentative.html": [ + "02d8479736d4d6fd7e26df53611624e7a75d0989", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-005-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-002.tentative.html": [ + "ff9e802f0f9e376635230707972611ab5a0ec7d6", + [ + null, + [ + [ + "/css/css-overflow/reference/line-clamp-auto-002-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-003.tentative.html": [ + "a74704dd3b0765434c27935c944fac010415b13c", + [ + null, + [ + [ + "/css/css-overflow/reference/line-clamp-auto-002-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-004.tentative.html": [ + "2dbf9d54084034f2a1b83eccf370e281af24dc8c", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-005-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-005.tentative.html": [ + "1c9148e2647f310522103d1b5c6c2765a6c6644c", + [ + null, + [ + [ + "/css/css-overflow/reference/line-clamp-auto-005-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-006.tentative.html": [ + "ab6915f52163f9cbd1c4c2f2fa4e9d8bf90a3a88", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-001-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-007.tentative.html": [ + "f7d56bfa6557413e33bbb2422c5234437ac302b4", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-001-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-008.tentative.html": [ + "9e7f38ab7ca09debf7628505d8d63ce473dc355e", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-001-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-009.tentative.html": [ + "44d111056c6b021c796ea694d744816125314def", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-036-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-010.tentative.html": [ + "cb706bba08e2c9dd6ff05b926be23eb22c9c25b7", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-037-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-011.tentative.html": [ + "00076a5336e89004b6a2143e9bd6c72ec9fe95e0", + [ + null, + [ + [ + "/css/css-overflow/reference/line-clamp-auto-011-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-012.tentative.html": [ + "56957b15c9223466ddd6f06a45bb854cab18fda6", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-001-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-013.tentative.html": [ + "dd864fbdcb3fbd3cfeb11a385df61a99e739aba9", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-005-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-014.tentative.html": [ + "6738c708706e778dd4ee307b8532ca32e8b7b881", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-005-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-015.tentative.html": [ + "cdb1ed18c0d7a913fc3b9e446dbff15add266300", + [ + null, + [ + [ + "/css/css-overflow/reference/webkit-line-clamp-005-ref.html", + "==" + ] + ], + {} + ] + ], + "line-clamp-auto-016.tentative.html": [ + "372213983b7a753037616485bfc2aae7524abfd5", + [ + null, + [ + [ + "/css/css-overflow/reference/line-clamp-auto-016-ref.html", + "==" + ] + ], + {} + ] + ], "line-clamp-with-abspos-001.tentative.html": [ "79667f23fbdc3d941484c343b2cf0a04ec34363f", [ @@ -170816,7 +171037,7 @@ ] ], "ruby-no-transform.html": [ - "1cdd4f3bbf5af81309805285a25622f7e444a3ee", + "56b2fc8380957743ddad8b6de6787c6110fae353", [ null, [ @@ -313495,6 +313716,10 @@ "28a92a86dcaf6bc9c45bb75fce4869bc0ae21c37", [] ], + "downloadable-font-scoped-to-document-ref.html": [ + "4d7da060cbf1a161aa1366f0bcb00b94e09502ad", + [] + ], "first-available-font-001-ref.html": [ "0acbd338e0ce9f558d2eaa2e48ad4be0524fb0ae", [] @@ -320670,6 +320895,18 @@ "6ed4aa506e95a35a065318f597547653bda52eb5", [] ], + "iframe-missing-font-face-rule.html": [ + "da97b781e8072923138e0160320e76d3013c3e53", + [] + ], + "iframe-using-ahem-as-web-font.html": [ + "b21066df8f57a8b11432a1168a62e7a4fbbe07b1", + [] + ], + "iframe-without-web-font.html": [ + "85e7fef282889894016088e082b623b92a436784", + [] + ], "js": { "font-variant-features.js": [ "4b56fee193956710b847ba79c5f9c3a5a7d15a33", @@ -327314,6 +327551,22 @@ "d794c76e3c9653dd94b2bad73cdf2a4574db5f50", [] ], + "line-clamp-auto-002-ref.html": [ + "fe0a8dbd588a8a56c8ac0488713a061ef83474f9", + [] + ], + "line-clamp-auto-005-ref.html": [ + "01eea67a0da77dc7a99bcd0b8677abdd3a4033f5", + [] + ], + "line-clamp-auto-011-ref.html": [ + "5f7120ee39a2014f75f2f700ebedcc0b0e6e6275", + [] + ], + "line-clamp-auto-016-ref.html": [ + "4a5f3536cc62c33e1a30ed9fce9a21cecda341bc", + [] + ], "line-clamp-with-abspos-001-ref.html": [ "d756162dde0c54bd52646597b01bbff8a80f5fd8", [] @@ -330358,7 +330611,7 @@ [] ], "ruby-no-transform-ref.html": [ - "56afd9366fe787670771a82874f1016335f1b7c6", + "1c075de18fab1951de3a809e2d85cd2f2d6c3827", [] ], "ruby-position-alternate-expected.txt": [ @@ -392203,7 +392456,7 @@ [] ], "utils.js": [ - "bc1bc5911eb8552efd689f84a0e61d2f74aa268a", + "9cd47b69dd75128e6c522833325e1538c35a1f78", [] ], "wake-lock.https.html": [
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-001.https.html b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-001.https.html index 1746ea9f..2c60c3d 100644 --- a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-001.https.html +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-001.https.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<meta http-equiv="Delegate-CH" content="Sec-CH-Width"> +<meta name="Delegate-CH" content="Sec-CH-Width"> <title>Tests Sec-CH-Width with auto sizes and a single srcset value</title> <link rel="help" href="https://wicg.github.io/responsive-image-client-hints/#sec-ch-width"> <link rel="help" href="https://html.spec.whatwg.org/#sizes-attributes">
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-001.https.html.headers b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-001.https.html.headers new file mode 100644 index 0000000..8a6a65bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-001.https.html.headers
@@ -0,0 +1 @@ +Accept-CH: sec-ch-width
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-002.https.html b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-002.https.html index 0dfaf2e..c45b8308 100644 --- a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-002.https.html +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-002.https.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<meta http-equiv="Delegate-CH" content="Sec-CH-Width"> +<meta name="Delegate-CH" content="Sec-CH-Width"> <title>Tests Sec-CH-Width with auto sizes and multiple srcset values</title> <link rel="help" href="https://wicg.github.io/responsive-image-client-hints/#sec-ch-width"> <link rel="help" href="https://html.spec.whatwg.org/#sizes-attributes">
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-002.https.html.headers b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-002.https.html.headers new file mode 100644 index 0000000..8a6a65bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-002.https.html.headers
@@ -0,0 +1 @@ +Accept-CH: sec-ch-width
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-003.https.html b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-003.https.html index 235529d..3675af8b 100644 --- a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-003.https.html +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-003.https.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<meta http-equiv="Delegate-CH" content="Sec-CH-Width"> +<meta name="Delegate-CH" content="Sec-CH-Width"> <title>Tests Sec-CH-Width with auto sizes and picture</title> <link rel="help" href="https://wicg.github.io/responsive-image-client-hints/#sec-ch-width"> <link rel="help" href="https://html.spec.whatwg.org/#sizes-attributes">
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-003.https.html.headers b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-003.https.html.headers new file mode 100644 index 0000000..8a6a65bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width-auto-sizes-003.https.html.headers
@@ -0,0 +1 @@ +Accept-CH: sec-ch-width
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width.https.html b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width.https.html index ec13ff96..af0fa53 100644 --- a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width.https.html +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width.https.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<meta http-equiv="Delegate-CH" content="Sec-CH-Width"> +<meta name="Delegate-CH" content="Sec-CH-Width"> <title>Tests Sec-CH-Width</title> <link rel="help" href="https://wicg.github.io/responsive-image-client-hints/#sec-ch-width"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width.https.html.headers b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width.https.html.headers new file mode 100644 index 0000000..8a6a65bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/client-hints/sec-ch-width.https.html.headers
@@ -0,0 +1 @@ +Accept-CH: sec-ch-width
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/downloadable-font-scoped-to-document-ref.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/downloadable-font-scoped-to-document-ref.html new file mode 100644 index 0000000..4d7da060 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/downloadable-font-scoped-to-document-ref.html
@@ -0,0 +1,17 @@ + <!DOCTYPE html> + +<html> + <head> + <title>CSS fonts: Web fonts loaded in a document are not available in other documents</title> + <link rel="author" title="Martin Robinson" href="mrobinson@igalia.com"> + <link rel="author" title="Mukilan Thiyagarajan" href="mukilan@igalia.com"> + </head> + + <body> + <p>Test passes if Ahem is only used in the first iframe.</p> + <iframe src="support/iframe-using-ahem-as-web-font.html"></iframe> + <iframe src="support/iframe-without-web-font.html"></iframe> + </body> + +</html> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/downloadable-font-scoped-to-document.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/downloadable-font-scoped-to-document.html new file mode 100644 index 0000000..2dbc350 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/downloadable-font-scoped-to-document.html
@@ -0,0 +1,28 @@ + <!DOCTYPE html> + +<html class="reftest-wait"> + <head> + <title>CSS fonts: Web fonts loaded in a document are not available in other documents</title> + <link rel="author" title="Martin Robinson" href="mrobinson@igalia.com"> + <link rel="author" title="Mukilan Thiyagarajan" href="mukilan@igalia.com"> + <link rel="match" href="downloadable-font-scoped-to-document-ref.html"> + <link rel="help" href="https://drafts.csswg.org/css-fonts/#font-face-rule"> + </head> + + <body> + <p>Test passes if Ahem is only used in the first iframe.</p> + <iframe id="iframe1" src="support/iframe-using-ahem-as-web-font.html"></iframe> + <iframe id="iframe2" src=""></iframe> + + <script> + // Delay the loading of the second iframe to make it more likely that the font + // has loaded properly into the first iframe. + iframe1.onload = () => { + iframe2.src ="support/iframe-missing-font-face-rule.html"; + document.documentElement.classList.remove('reftest-wait'); + }; + </script> + </body> + +</html> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-missing-font-face-rule.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-missing-font-face-rule.html new file mode 100644 index 0000000..da97b781 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-missing-font-face-rule.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<div style="font-size: 30px; font-family: CustomFontFamily">Hello!</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-using-ahem-as-web-font.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-using-ahem-as-web-font.html new file mode 100644 index 0000000..b21066d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-using-ahem-as-web-font.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<style> +@font-face { + font-family: CustomFontFamily; + src: url(/fonts/Ahem.ttf); +} +</style> +<div style="font-size: 30px; font-family: CustomFontFamily">Hello!</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-without-web-font.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-without-web-font.html new file mode 100644 index 0000000..85e7fef2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/iframe-without-web-font.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<div style="font-size: 30px;">Hello!</div>
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-content-initiated.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-content-initiated.https.html index 9c1d47d..bdd5d4c 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-content-initiated.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-content-initiated.https.html
@@ -14,7 +14,7 @@ const fencedframe = await attachFencedFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true, origin: get_host_info().HTTPS_ORIGIN
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested-urn-iframe.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested-urn-iframe.https.html index 7d0544a5..ea4a4c1 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested-urn-iframe.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested-urn-iframe.https.html
@@ -24,7 +24,7 @@ const fencedframe = await attachIFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested.https.html index 4d1262f..8b8070e 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-nested.https.html
@@ -24,7 +24,7 @@ const fencedframe = await attachFencedFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-embedder-opt-in.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-embedder-opt-in.https.html index d8fa513..954de24 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-embedder-opt-in.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-embedder-opt-in.https.html
@@ -14,7 +14,7 @@ const fencedframe = await attachFencedFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'false' + 'Allow-Cross-Origin-Event-Reporting', '?0' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-subframe-opt-in.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-subframe-opt-in.https.html index 2b054c18..ea5d0cd 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-subframe-opt-in.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-no-subframe-opt-in.https.html
@@ -14,7 +14,7 @@ const fencedframe = await attachFencedFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-content-initiated.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-content-initiated.https.html index 21c9ea1..e4971dc 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-content-initiated.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-content-initiated.https.html
@@ -14,7 +14,7 @@ const iframe = await attachIFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true, origin: get_host_info().HTTPS_ORIGIN
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-embedder-opt-in.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-embedder-opt-in.https.html index 5d368fe7..6f6835b 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-embedder-opt-in.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-embedder-opt-in.https.html
@@ -14,7 +14,7 @@ const iframe = await attachIFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'false' + 'Allow-Cross-Origin-Event-Reporting', '?0' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-subframe-opt-in.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-subframe-opt-in.https.html index df22749..855ad1f 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-subframe-opt-in.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe-no-subframe-opt-in.https.html
@@ -14,7 +14,7 @@ const outer_iframe = await attachIFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe.https.html index b37fec81..d62a46d 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin-urn-iframe.https.html
@@ -14,7 +14,7 @@ const outer_iframe = await attachIFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin.https.html index df7ae77..f198ea4 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-cross-origin.https.html
@@ -14,7 +14,7 @@ const fencedframe = await attachFencedFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-sub-fencedframe.https.html b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-sub-fencedframe.https.html index 0b3231ca..558125d 100644 --- a/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-sub-fencedframe.https.html +++ b/third_party/blink/web_tests/external/wpt/fenced-frame/fence-report-event-sub-fencedframe.https.html
@@ -14,7 +14,7 @@ const fencedframe = await attachFencedFrameContext({ generator_api: 'fledge', headers: [[ - 'Allow-Cross-Origin-Event-Reporting', 'true' + 'Allow-Cross-Origin-Event-Reporting', '?1' ]], register_beacon: true });
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading-for-print-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading-for-print-ref.html new file mode 100644 index 0000000..a6bf424 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading-for-print-ref.html
@@ -0,0 +1,4 @@ +<!DOCTYPE html> +<p> + Object image not displayed should not load. +</p>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading-for-print.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading-for-print.html new file mode 100644 index 0000000..40158cb3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading-for-print.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>Test loading of 'display: none' image for print</title> + +<link rel="help" href="https://crbug.com/41477900"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element"> +<!-- + Based on step 2 of the spec algorithm: + "... if the element is not being rendered, + then jump to the step below labeled fallback." +--> + +<link rel="match" href="object-image-display-none-loading-for-print-ref.html"> + +<style> + #target { + display: none; + } +</style> + +<script> + function obj_onload() { + const p = document.createElement('p'); + p.innerHTML = `FAIL: Object image was loaded.`; + p.style.color = 'red'; + document.body.appendChild(p); + } +</script> + +<p> + Object image not displayed should not load. +</p> + +<div> +<object + data="/images/red.png" + id="target" + onload="obj_onload();" + type="image/png" +></object> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading.html new file mode 100644 index 0000000..de95aef4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-display-none-loading.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<link rel="help" href="https://crbug.com/41477900"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element"> +<!-- + Based on step 2 of the spec algorithm: + "... if the element is not being rendered, + then jump to the step below labeled fallback." +--> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + const t = async_test( + "Test that object image not displayed is not loaded unnecessarily." + ); + + function obj_onload() { + t.unreached_func( + "Object image not displayed on screen should not load." + )(); + } + + t.step_timeout(() => { + t.done(); + }, 2000); +</script> + +<style> + #target { + display: none; + } +</style> + +<object + data="/images/red.png" + id="target" + onload="obj_onload();" + type="image/png" +> + Fallback Text +</object>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-only-for-print-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-only-for-print-ref.html new file mode 100644 index 0000000..bee4a57 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-only-for-print-ref.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<p> + Should print a green rectangle rectangle but not display it on screen. +</p> +<img src="/images/green.png" alt="A green rectangle">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-only-for-print.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-only-for-print.html new file mode 100644 index 0000000..938ebdc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/object-image-only-for-print.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Test print result of image not displayed on screen</title> + +<link rel="help" href="https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element"> +<link rel="help" href="https://crbug.com/41477900"> + +<link rel="match" href="object-image-only-for-print-ref.html"> + +<style> + @media not print { + .print-only { + display: none; + } + } +</style> + +<p> + Should print a green rectangle rectangle but not display it on screen. +</p> + +<div> +<object + class="print-only" + data="/images/green.png" + type="image/png" +></object> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-scroll-within-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-scroll-within-expected.txt deleted file mode 100644 index a1acfb2c..0000000 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-scroll-within-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] Scrolling within a popover should not close the popover - assert_equals: popover should be scrolled expected 50 but got 0 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-scroll-within.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-scroll-within.html index 2329aea..053ea03 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-scroll-within.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-scroll-within.html
@@ -1,7 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8" /> <title>Popover light dismiss behavior when scrolled within</title> -<meta name="timeout" content="long"> <link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://open-ui.org/components/popover.research.explainer"> <script src="/resources/testharness.js"></script> @@ -26,11 +25,11 @@ <div popover id=p>Inside popover <div style="height:2000px;background:lightgreen"></div> - Bottom of popover6 + Bottom of popover </div> <button popovertarget=p>Popover</button> <style> - #p6 { + #p { width: 300px; height: 300px; overflow-y: scroll;
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-for-data-url.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-for-data-url.tentative.https.sub.html new file mode 100644 index 0000000..51283579 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-for-data-url.tentative.https.sub.html
@@ -0,0 +1,18 @@ +<!doctype html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script> + 'use strict'; + + promise_test(async t => { + const innerCode = + `window.parent.postMessage({fetchStatus: "success"}, '*');`; + const dataURL = 'data:text/javascript;base64,' + + btoa(unescape(encodeURIComponent(innerCode))); + await promise_rejects_js(t, TypeError, + fetch(dataURL, {sharedStorageWritable: true})); + + }, 'shared storage fetch request disallowed for data URL'); + </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-in-data-url.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-in-data-url.tentative.https.sub.html new file mode 100644 index 0000000..1ebfdbc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-in-data-url.tentative.https.sub.html
@@ -0,0 +1,69 @@ +<!doctype html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/common/utils.js></script> + <script src=/fenced-frame/resources/utils.js></script> + <script src=/shared-storage/resources/util.js></script> + <script> + 'use strict'; + const origin = window.location.origin; + const rawSetHeader = 'set;key=hello;value=world'; + const setHeader = encodeURIComponent(rawSetHeader); + + promise_test(async t => { + let frame = document.createElement('iframe'); + const promise = new Promise((resolve, reject) => { + window.addEventListener('message', async function handler(evt) { + if (evt.source === frame.contentWindow && + evt.data.sharedStorageFetchStatus) { + document.body.removeChild(frame); + window.removeEventListener('message', handler); + resolve(evt.data.sharedStorageFetchStatus); + } + }); + window.addEventListener('error', (error) => { + reject(error); + }); + }); + + const fetchUrl = + `${origin}\\/shared-storage\\/resources\\/shared-storage-write.py` + + `?write=${setHeader}`; + const fetchCode = ` +let parentOrOpener = window.opener || window.parent; +let innerFrame = document.createElement('iframe'); +window.addEventListener('message', async (evt) => { + if (evt.source === innerFrame.contentWindow) { + parentOrOpener.postMessage({sharedStorageFetchStatus: "success"}, '*'); + } +}); +window.addEventListener('error', (error) => { + parentOrOpener.postMessage({sharedStorageFetchStatus: error.message}, '*'); +}); +fetch('${fetchUrl}', {sharedStorageWritable: true}) + .then(response => response.text()) + .then(htmlContent => { + innerFrame.srcdoc = htmlContent; + document.body.appendChild(innerFrame); + }) + .catch(error => { + parentOrOpener.postMessage({sharedStorageFetchStatus: error.name}, + "*"); + }); +`; + + const dataURL = 'data:text/html;base64,' + + btoa(unescape('%3Chtml%3E%3Cbody%3E%3Cscript%3E' + + encodeURIComponent(fetchCode) + + '%3C%2Fscript%3E%3C%2Fbody%3E%3C%2Fhtml%3E')); + frame.src = dataURL; + document.body.appendChild(frame); + + const result = await promise; + assert_equals(result, "TypeError"); + await verifyKeyNotFoundForOrigin('hello', origin); + + }, 'shared storage fetch request disallowed in opaque origin from data URL'); + </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-in-sandboxed-frame.tentative.https.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-in-sandboxed-frame.tentative.https.html index de935b2..cb0f8fb 100644 --- a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-in-sandboxed-frame.tentative.https.html +++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-fetch-request-in-sandboxed-frame.tentative.https.html
@@ -79,7 +79,7 @@ /*key=*/'c', /*value=*/'d', /*sandbox_flags=*/'allow-scripts', - /*expect_success=*/false); + /*expect_success=*/true); }, 'test sharedStorageWritable fetch request in sandboxed iframe without ' + '"allow-same-origin"'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-iframe-request-in-data-url.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-iframe-request-in-data-url.tentative.https.sub.html new file mode 100644 index 0000000..1833e842 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-iframe-request-in-data-url.tentative.https.sub.html
@@ -0,0 +1,64 @@ +<!doctype html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/common/utils.js></script> + <script src=/fenced-frame/resources/utils.js></script> + <script src=/shared-storage/resources/util.js></script> + <script> + 'use strict'; + const origin = window.location.origin; + const rawSetHeader = 'set;key=hello;value=world'; + const setHeader = encodeURIComponent(rawSetHeader); + + promise_test(async t => { + let frame = document.createElement('iframe'); + const promise = new Promise((resolve, reject) => { + window.addEventListener('message', async function handler(evt) { + if (evt.source === frame.contentWindow && + evt.data.sharedStorageWritableHeader) { + document.body.removeChild(frame); + window.removeEventListener('message', handler); + resolve(evt.data.sharedStorageWritableHeader); + } + }); + window.addEventListener('error', (error) => { + reject(error); + }); + }); + + const innerUrl = + `${origin}\\/shared-storage\\/resources\\/shared-storage-write-` + + `notify-parent.py?write=${setHeader}`; + const innerCode = ` +let parentOrOpener = window.opener || window.parent; +let innerFrame = document.createElement('iframe'); +window.addEventListener('message', async (evt) => { + if (evt.source === innerFrame.contentWindow && + evt.data.sharedStorageWritableHeader) { + parentOrOpener.postMessage({sharedStorageWritableHeader: + evt.data.sharedStorageWritableHeader}, '*'); + } +}); +window.addEventListener('error', (error) => { + parentOrOpener.postMessage({sharedStorageWritableHeader: error.message}, '*'); +}); +innerFrame.src = '${innerUrl}'; +innerFrame.sharedStorageWritable = true; +document.body.appendChild(innerFrame); +`; + + const dataURL = 'data:text/html;base64,' + + btoa(unescape('%3Chtml%3E%3Cbody%3E%3Cscript%3E' + + encodeURIComponent(innerCode) + + '%3C%2Fscript%3E%3C%2Fbody%3E%3C%2Fhtml%3E')); + frame.src = dataURL; + document.body.appendChild(frame); + + const result = await promise; + assert_equals(result, "NO_SHARED_STORAGE_WRITABLE_HEADER"); + await verifyKeyNotFoundForOrigin('hello', origin); + + }, 'shared storage iframe request disallowed in opaque origin from data URL'); + </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-img-request-in-data-url.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-img-request-in-data-url.tentative.https.sub.html new file mode 100644 index 0000000..75d6b51 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-img-request-in-data-url.tentative.https.sub.html
@@ -0,0 +1,62 @@ +<!doctype html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/common/utils.js></script> + <script src=/fenced-frame/resources/utils.js></script> + <script src=/shared-storage/resources/util.js></script> + <script> + 'use strict'; + const origin = window.location.origin; + const rawSetHeader = 'set;key=hello;value=world'; + const setHeader = encodeURIComponent(rawSetHeader); + + promise_test(async t => { + let frame = document.createElement('iframe'); + const promise = new Promise((resolve, reject) => { + window.addEventListener('message', async function handler(evt) { + if (evt.source === frame.contentWindow && + evt.data.sharedStorageWritableLoadStatus) { + document.body.removeChild(frame); + window.removeEventListener('message', handler); + resolve(evt.data.sharedStorageWritableLoadStatus); + } + }); + window.addEventListener('error', (error) => { + reject(error); + }); + }); + + const imageUrl = + `${origin}\\/shared-storage\\/resources\\/shared-storage-writable-` + + `pixel-write.png?write=${setHeader}`; + const innerCode = ` +let parentOrOpener = window.opener || window.parent; +let image = document.createElement('img'); +window.addEventListener('load', async (evt) => { + parentOrOpener.postMessage({sharedStorageWritableLoadStatus: + 'loaded'}, '*'); +}); +window.addEventListener('error', (error) => { + parentOrOpener.postMessage({sharedStorageWritableLoadStatus: error.message}, + '*'); +}); +image.src = '${imageUrl}'; +image.sharedStorageWritable = true; +document.body.appendChild(image); +`; + + const dataURL = 'data:text/html;base64,' + + btoa(unescape('%3Chtml%3E%3Cbody%3E%3Cscript%3E' + + encodeURIComponent(innerCode) + + '%3C%2Fscript%3E%3C%2Fbody%3E%3C%2Fhtml%3E')); + frame.src = dataURL; + document.body.appendChild(frame); + + const result = await promise; + assert_equals(result, "loaded"); + await verifyKeyNotFoundForOrigin('hello', origin); + + }, 'shared storage iframe request disallowed in opaque origin from data URL'); + </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-img-request-in-sandboxed-frame.tentative.https.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-img-request-in-sandboxed-frame.tentative.https.html index a901500d..8e33c68 100644 --- a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-img-request-in-sandboxed-frame.tentative.https.html +++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-img-request-in-sandboxed-frame.tentative.https.html
@@ -72,7 +72,7 @@ /*key=*/'c', /*value=*/'d', /*sandbox_flags=*/'allow-scripts', - /*expect_success=*/false); + /*expect_success=*/true); }, 'test sharedStorageWritable img request in sandboxed iframe without ' + '"allow-same-origin"'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-opaque-origin.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-opaque-origin.tentative.https.sub.html deleted file mode 100644 index 4829af0..0000000 --- a/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-writable-opaque-origin.tentative.https.sub.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!doctype html> -<body> - <script src=/resources/testharness.js></script> - <script src=/resources/testharnessreport.js></script> - <script> - 'use strict'; - const rawSetHeader = 'set;key=hello;value=world'; - const setHeader = encodeURIComponent(rawSetHeader); - - promise_test(async t => { - const fetchUrl = - `/shared-storage/resources/shared-storage-write.py?write=${setHeader}`; - const fetchCode = - `try { - new Request(fetchUrl,{sharedStorageWritable: true}); - } catch (e) { - assert_equals(e.name, 'TypeError'); - assert_equals(e.message, "Failed to construct 'Request': " - + "sharedStorageWritable: sharedStorage operations " - + "are not available for opaque origins."); - return; - } - assert_unreached("did not catch an error");` - - const dataURL = 'data:text/javascript;base64,' - + btoa(unescape(encodeURIComponent(fetchCode))); - let frame = document.createElement('iframe'); - frame.src = dataURL; - const promise = new Promise((resolve, reject) => { - frame.addEventListener('load', () => { - resolve(); - }); - frame.addEventListener('error', () => { - reject(new Error('Navigation failed')); - }); - }); - document.body.appendChild(frame); - await promise; - }, 'shared storage fetch request disallowed for opaque origin'); - </script> -</body>
diff --git a/third_party/blink/web_tests/media/resources/one_frame.webm b/third_party/blink/web_tests/media/resources/one_frame.webm new file mode 100644 index 0000000..e343106a --- /dev/null +++ b/third_party/blink/web_tests/media/resources/one_frame.webm Binary files differ
diff --git a/third_party/blink/web_tests/media/video-no-infinite-loop-paused.html b/third_party/blink/web_tests/media/video-no-infinite-loop-paused.html new file mode 100644 index 0000000..61c193555 --- /dev/null +++ b/third_party/blink/web_tests/media/video-no-infinite-loop-paused.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>Test a single frame video doesn't loop too quickly</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<video loop paused muted></video> +<script> +async_test(function(t) { + var video = document.querySelector("video"); + var count = 0; + video.onseeked = t.unreached_func("Paused video shouldn't loop"); + video.onended = t.unreached_func("Paused video shouldn't end"); + video.oncanplaythrough = t.step_func(_ => { + // 275ms chosen since 250ms is the max timeupdate frequency. + t.step_timeout(t.step_func_done(), 275); + }); + video.src = "resources/one_frame.webm"; +}); +</script>
diff --git a/third_party/blink/web_tests/media/video-no-infinite-loop-playing-rvfc.html b/third_party/blink/web_tests/media/video-no-infinite-loop-playing-rvfc.html new file mode 100644 index 0000000..c950ffd --- /dev/null +++ b/third_party/blink/web_tests/media/video-no-infinite-loop-playing-rvfc.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Test a single frame looping video generates rVFCs properly</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<video loop autoplay muted></video> +<script> +async_test(function(t) { + var video = document.querySelector("video"); + var start = 0; + var count = 0; + var rvfc = 0; + + video.onseeking = t.step_func(_ => { + video.requestVideoFrameCallback(_ => { + ++rvfc; + }); + }); + video.onseeked = t.step_func(_ => { + if (++count == 3) { + // Approximate since ordering is not guaranteed. + assert_approx_equals(rvfc, count, 1); + t.done(); + } + }); + video.src = "resources/one_frame.webm"; +}); +</script>
diff --git a/third_party/blink/web_tests/media/video-no-infinite-loop-playing.html b/third_party/blink/web_tests/media/video-no-infinite-loop-playing.html new file mode 100644 index 0000000..ab71860 --- /dev/null +++ b/third_party/blink/web_tests/media/video-no-infinite-loop-playing.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<title>Test a single frame video doesn't loop too quickly</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<video loop autoplay muted></video> +<script> +async_test(function(t) { + var video = document.querySelector("video"); + var start = 0; + var count = 0; + video.onseeked = t.step_func(_ => { + if (++count == 1) { + start = performance.now(); + } else if (count == 3) { + let dur = performance.now() - start; + assert_greater_than_equal(dur / (count - 1), 250); + t.done(); + } + }); + video.src = "resources/one_frame.webm"; +}); +</script>
diff --git a/third_party/blink/web_tests/media/video-seek-to-duration-with-playbackrate-zero.html b/third_party/blink/web_tests/media/video-seek-to-duration-with-playbackrate-zero.html index 454ebb81..605ffc48 100644 --- a/third_party/blink/web_tests/media/video-seek-to-duration-with-playbackrate-zero.html +++ b/third_party/blink/web_tests/media/video-seek-to-duration-with-playbackrate-zero.html
@@ -6,31 +6,29 @@ <script> async_test(function(t) { var video = document.querySelector("video"); - - video.src = "content/test.ogv"; - video.load(); - video.onseeking = t.step_func(function() {}); - video.onloadedmetadata = t.step_func(function() { video.onloadedmetadata = null; - video.currentTime = video.duration; video.playbackRate = 0; - video.onended = t.step_func(function() { + video.currentTime = video.duration; + video.onseeked = t.step_func(function() { assert_equals(video.currentTime, video.duration); - // Seeking to the middle of the video. - video.currentTime = video.duration / 2; video.onseeked = t.step_func(function() { - // Setting loop to true and seeking to duration. - video.loop = true; - video.currentTime = video.duration; video.onseeked = t.step_func(function() { // Seek to duration completed. Waiting for a seek to the beginning. video.onseeked = t.step_func_done(function() { assert_equals(video.currentTime, 0); }); + video.play(); }); + // Setting loop to true and seeking to duration. + video.loop = true; + video.currentTime = video.duration; }); + + // Seeking to the middle of the video. + video.currentTime = video.duration / 2; }); }); + video.src = "content/test.ogv"; }); -</script> \ No newline at end of file +</script>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt new file mode 100644 index 0000000..552532e --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt
@@ -0,0 +1,32 @@ +This is a testharness.js-based test. +Found 14 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] idl_test setup + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Not implemented" +[FAIL] NavigatorML must be primary interface of navigator + assert_own_property: self does not have own property "NavigatorML" expected property "NavigatorML" missing +[FAIL] Stringification of navigator + assert_class_string: class string of navigator expected "[object NavigatorML]" but got "[object Navigator]" +[FAIL] MLGraph must be primary interface of graph + assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined" +[FAIL] Stringification of graph + assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined" +[FAIL] MLGraphBuilder interface: operation constant(MLOperandDescriptor, ArrayBufferView) + assert_equals: property has wrong .length expected 1 but got 2 +[FAIL] MLGraphBuilder interface: operation constant(double, optional MLOperandDataType) + assert_equals: property has wrong .length expected 1 but got 2 +[FAIL] MLGraphBuilder interface: operation not(MLOperand) + assert_own_property: interface prototype object missing non-static operation expected property "not" missing +[FAIL] MLGraphBuilder interface: operation softmax(MLOperand, unsigned long) + assert_equals: property has wrong .length expected 1 but got 0 +[FAIL] MLGraphBuilder interface: operation softmax(unsigned long) + assert_equals: property has wrong .length expected 1 but got 0 +[FAIL] MLGraphBuilder interface: builder must inherit property "not(MLOperand)" with the proper type + assert_inherits: property "not" not found in prototype chain +[FAIL] MLGraphBuilder interface: calling not(MLOperand) on builder with too few arguments must throw TypeError + assert_inherits: property "not" not found in prototype chain +[FAIL] MLGraphBuilder interface: calling softmax(MLOperand, unsigned long) on builder with too few arguments must throw TypeError + assert_throws_js: Called with 0 arguments function "function() {\n fn.apply(obj, args);\n }" did not throw +[FAIL] MLGraphBuilder interface: calling softmax(unsigned long) on builder with too few arguments must throw TypeError + assert_throws_js: Called with 0 arguments function "function() {\n fn.apply(obj, args);\n }" did not throw +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt new file mode 100644 index 0000000..70c9d9e1 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt
@@ -0,0 +1,34 @@ +This is a testharness.js-based test. +Found 15 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] idl_test setup + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Not implemented" +[FAIL] NavigatorML must be primary interface of navigator + assert_own_property: self does not have own property "NavigatorML" expected property "NavigatorML" missing +[FAIL] Stringification of navigator + assert_class_string: class string of navigator expected "[object NavigatorML]" but got "[object WorkerNavigator]" +[FAIL] NavigatorML interface: navigator must not have property "ml" + assert_false: expected false got true +[FAIL] MLGraph must be primary interface of graph + assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined" +[FAIL] Stringification of graph + assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: graph is not defined" +[FAIL] MLGraphBuilder interface: operation constant(MLOperandDescriptor, ArrayBufferView) + assert_equals: property has wrong .length expected 1 but got 2 +[FAIL] MLGraphBuilder interface: operation constant(double, optional MLOperandDataType) + assert_equals: property has wrong .length expected 1 but got 2 +[FAIL] MLGraphBuilder interface: operation not(MLOperand) + assert_own_property: interface prototype object missing non-static operation expected property "not" missing +[FAIL] MLGraphBuilder interface: operation softmax(MLOperand, unsigned long) + assert_equals: property has wrong .length expected 1 but got 0 +[FAIL] MLGraphBuilder interface: operation softmax(unsigned long) + assert_equals: property has wrong .length expected 1 but got 0 +[FAIL] MLGraphBuilder interface: builder must inherit property "not(MLOperand)" with the proper type + assert_inherits: property "not" not found in prototype chain +[FAIL] MLGraphBuilder interface: calling not(MLOperand) on builder with too few arguments must throw TypeError + assert_inherits: property "not" not found in prototype chain +[FAIL] MLGraphBuilder interface: calling softmax(MLOperand, unsigned long) on builder with too few arguments must throw TypeError + assert_throws_js: Called with 0 arguments function "function() {\n fn.apply(obj, args);\n }" did not throw +[FAIL] MLGraphBuilder interface: calling softmax(unsigned long) on builder with too few arguments must throw TypeError + assert_throws_js: Called with 0 arguments function "function() {\n fn.apply(obj, args);\n }" did not throw +Harness: the test ran to completion. +
diff --git a/third_party/chromite b/third_party/chromite index 8a31c4e..8199e2b 160000 --- a/third_party/chromite +++ b/third_party/chromite
@@ -1 +1 @@ -Subproject commit 8a31c4e2f3416b669a31b6e6b8be77bf4ec12532 +Subproject commit 8199e2bbaef867e258148454b1ee7a472fe3a638
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index 9e9b012..9485c21 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit 9e9b01285b3b1febec28c95040e7ed89e3b86bc8 +Subproject commit 9485c21d7b149d1fd9a663762182a7838095913e
diff --git a/third_party/dawn b/third_party/dawn index 7ffb6e9..538f02e 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit 7ffb6e9573216af00374a8dd474598ce94f2d97a +Subproject commit 538f02eecf1a80738f1ece234bbf6c947d127add
diff --git a/third_party/depot_tools b/third_party/depot_tools index d32e1cb..0dd5028 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit d32e1cb5717853a1837347884abc85149813c398 +Subproject commit 0dd502813398cb44477df2c246ed4495c4a0c46d
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index 701f478..454bc68 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit 701f4784e9e7d73927dcf4d60bc0f0db552b79b7 +Subproject commit 454bc68b84610f49e617ab997e056e7cb2429ad5
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index c1d688b..ecbae84 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit c1d688bcb2e1d1ebcebbe07e48ddcfa90228b138 +Subproject commit ecbae84d39c9a39365dfbcb791c6b78d4df6e373
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 7463dd66..b6ce0758 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -1,7 +1,7 @@ Name: libvpx URL: https://chromium.googlesource.com/webm/libvpx Version: N/A -Revision: 611d9ba0a55df154ff5cb7a97d41a41103265f5e +Revision: 5b4cfe88e45a42fbdf22f7210ed253faec9c0fe6 CPEPrefix: cpe:/a:webmproject:libvpx:1.14.0 License: BSD License File: source/libvpx/LICENSE
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index 9b8a656..5672df6 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,8 +2,8 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 14 #define VERSION_PATCH 0 -#define VERSION_EXTRA "276-g611d9ba0a" +#define VERSION_EXTRA "277-g5b4cfe88e" #define VERSION_PACKED \ ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.14.0-276-g611d9ba0a" -#define VERSION_STRING " v1.14.0-276-g611d9ba0a" +#define VERSION_STRING_NOSP "v1.14.0-277-g5b4cfe88e" +#define VERSION_STRING " v1.14.0-277-g5b4cfe88e"
diff --git a/third_party/libvpx/source/libvpx b/third_party/libvpx/source/libvpx index 611d9ba..5b4cfe8 160000 --- a/third_party/libvpx/source/libvpx +++ b/third_party/libvpx/source/libvpx
@@ -1 +1 @@ -Subproject commit 611d9ba0a55df154ff5cb7a97d41a41103265f5e +Subproject commit 5b4cfe88e45a42fbdf22f7210ed253faec9c0fe6
diff --git a/third_party/openscreen/src b/third_party/openscreen/src index 1766121..d77735d 160000 --- a/third_party/openscreen/src +++ b/third_party/openscreen/src
@@ -1 +1 @@ -Subproject commit 17661211decceb52c9597a8bed5c5bdfcc44a2a2 +Subproject commit d77735d9e5ef30477139b0fc1ca3db6706ec8651
diff --git a/third_party/re2/BUILD.gn b/third_party/re2/BUILD.gn index 046bf29..da39856 100644 --- a/third_party/re2/BUILD.gn +++ b/third_party/re2/BUILD.gn
@@ -44,7 +44,6 @@ "src/re2/unicode_groups.cc", "src/re2/unicode_groups.h", "src/re2/walker-inl.h", - "src/util/logging.h", "src/util/rune.cc", "src/util/strutil.cc", "src/util/strutil.h",
diff --git a/third_party/re2/src b/third_party/re2/src index a67d6c1..a771d3f 160000 --- a/third_party/re2/src +++ b/third_party/re2/src
@@ -1 +1 @@ -Subproject commit a67d6c1d5308b0950a91fed8e03e5c048d22d5cd +Subproject commit a771d3fbe7c432dc4db68360c6c0004fdde5646b
diff --git a/third_party/skia b/third_party/skia index 3d3d12b..62f369c 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 3d3d12b3fed33cf7d43f69204c3b91656f2f59d9 +Subproject commit 62f369c759947272dfdd2d8f060afadbcc361e79
diff --git a/third_party/webrtc b/third_party/webrtc index f317f71..fa4128e 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit f317f7106a7a15a04da7cd30c2e2ddb1b3025bc6 +Subproject commit fa4128eedbe427eecd28988f2585753645514296
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 9e5b8d7..2db5ad40 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -890,6 +890,10 @@ "META": {"sizes": {"includes": [50],}}, "includes": [6180], }, + "<(SHARED_INTERMEDIATE_DIR)/ash/webui/sanitize_ui/resources/resources.grd": { + "META": {"sizes": {"includes": [50],}}, + "includes": [6190], + }, "<(SHARED_INTERMEDIATE_DIR)/ash/webui/scanning/resources/resources.grd": { "META": {"sizes": {"includes": [100],}}, "includes": [6200],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4e0344e..1d46e76 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -35440,14 +35440,19 @@ <int value="-2025866230" label="chrome://usb-internals/"/> <int value="-2024468885" label="chrome://ntp-tiles-internals/"/> <int value="-2020874093" label="chrome://lock-reauth/"/> + <int value="-2008798042" label="chrome://extended-updates-dialog/"/> <int value="-1977692791" label="chrome://crash/"/> <int value="-1970917350" label="chrome-untrusted://compose/"/> <int value="-1949142440" label="chrome://smb-credentials-dialog/"/> + <int value="-1941995226" label="chrome://attribution-internals/"/> <int value="-1911971715" label="chrome://history/"/> + <int value="-1899361569" label="chrome-untrusted://eche-app/"/> <int value="-1887206190" label="chrome://nfc-debug/"/> + <int value="-1837941403" label="chrome://launcher-internals/"/> <int value="-1825876526" label="chrome://delayeduithreadhang/"/> <int value="-1808179141" label="chrome://password-manager-internals/"/> <int value="-1777503123" label="chrome://thumb2/"/> + <int value="-1774623401" label="chrome://os-print/"/> <int value="-1743341803" label="chrome://bookmarks/"/> <int value="-1737358104" label="chrome://account-migration-welcome/"/> <int value="-1729122580" label="chrome://chrome-urls/"/> @@ -35458,29 +35463,39 @@ <int value="-1697077152" label="chrome://device-log/"/> <int value="-1690355375" label="chrome://mobilesetup/"/> <int value="-1681544613" label="chrome://print/"/> + <int value="-1667471433" label="chrome://vc-background/"/> <int value="-1649429396" label="chrome://chrome-signin/edu-coexistence/"/> <int value="-1647734092" label="chrome://net-export/"/> <int value="-1638649228" label="chrome://webapks/"/> <int value="-1636191836" label="chrome://history-clusters-side-panel.top-chrome/"/> <int value="-1634933990" label="chrome://web-footer-experiment/"/> + <int value="-1631133219" label="chrome://help-app/"/> + <int value="-1618666743" label="chrome://office-fallback/"/> <int value="-1591890659" label="chrome://syncfs-internals/"/> <int value="-1564946100" label="chrome://tab-strip.top-chrome/"/> <int value="-1532727290" label="chrome://whats-new/"/> + <int value="-1500737448" label="chrome://manage-mirrorsync/"/> <int value="-1493822642" label="chrome://invalidations/"/> <int value="-1493762713" label="chrome://settings/cookies/"/> <int value="-1475777739" label="chrome://physical-web-diagnostics/"/> + <int value="-1471376798" label="chrome-untrusted://print/"/> <int value="-1440785181" label="chrome://profile-signin-confirmation/"/> <int value="-1423026122" label="chrome://md-user-manager/"/> <int value="-1401057585" label="chrome://account-manager-error/"/> <int value="-1398642514" label="chrome://gesture/"/> + <int value="-1384888924" label="chrome-untrusted://file-manager/"/> <int value="-1382906531" label="chrome://managed-user-passphrase/"/> <int value="-1379571130" label="chrome://newtab/"/> <int value="-1378421581" label="chrome://media-router/"/> <int value="-1346911023" label="chrome://signin-dice-web-intercept/"/> <int value="-1331415629" label="chrome://os-settings/"/> <int value="-1313432739" label="chrome://plugins/"/> + <int value="-1296182448" label="chrome://vc-tray-tester/"/> + <int value="-1293039192" label="chrome://os-feedback/"/> <int value="-1282128285" label="chrome://suggest-internals/"/> + <int value="-1267771224" label="chrome://sensor-info/"/> + <int value="-1265265027" label="chrome-untrusted://help-app/"/> <int value="-1259871417" label="chrome://browser-switch/"/> <int value="-1239015343" label="chrome://kill/"/> <int value="-1224398205" label="chrome://prefs-internals/"/> @@ -35489,13 +35504,18 @@ <int value="-1177126000" label="chrome://profile-internals/"/> <int value="-1176451566" label="chrome://access-code-cast/"/> <int value="-1169621742" label="chrome://linux-proxy-config/"/> + <int value="-1147478891" label="chrome-untrusted://sample-system-web-app/"/> <int value="-1137946367" label="chrome://webrt-logs/"/> <int value="-1108319739" label="chrome://sync-internals/"/> <int value="-1087461470" label="chrome://management/"/> <int value="-1082746738" label="chrome://credits/"/> <int value="-1078583150" label="chrome://view-cert-dialog/"/> <int value="-1043041749" label="chrome://offline-internals/"/> + <int value="-1033927589" label="chrome://files-internals/"/> + <int value="-1013183905" label="chrome://media-app/"/> + <int value="-992950394" label="chrome://compare/"/> <int value="-992301003" label="chrome://bookmarks-side-panel.top-chrome/"/> + <int value="-986956132" label="chrome://app-install-dialog/"/> <int value="-986409800" label="chrome://identity-internals/"/> <int value="-969979971" label="chrome://sandbox/"/> <int value="-949665427" @@ -35503,21 +35523,27 @@ <int value="-946383082" label="chrome://translate-internals/"/> <int value="-940484840" label="chrome://arc-power-control/"/> <int value="-936786926" label="chrome://settings/"/> + <int value="-933829627" label="chrome-untrusted://mako/"/> <int value="-907485548" label="chrome://policy-tool/"/> <int value="-905972126" label="chrome://signin-email-confirmation/"/> <int value="-892484505" label="chrome://sys-internals/"/> <int value="-891260101" label="chrome://inspect/"/> <int value="-853789543" label="chrome://bluetooth-pairing/"/> + <int value="-833683433" label="chrome://on-device-internals/"/> <int value="-823585847" label="chrome://chrome-signin/"/> <int value="-756514973" label="chrome://version/"/> <int value="-753390931" label="chrome://interstitials/"/> <int value="-734627230" label="chrome://extension-icon/"/> <int value="-727952446" label="chrome://nacl/"/> <int value="-707542503" label="chrome://choose-mobile-network/"/> + <int value="-680649366" label="chrome-untrusted://hats/"/> + <int value="-675896339" label="chrome://healthd-internals/"/> <int value="-672072143" label="chrome://site-engagement/"/> <int value="-661305899" label="chrome://set-time/"/> <int value="-652517395" label="chrome://signin-reauth/"/> <int value="-644310325" label="chrome://os-credits/"/> + <int value="-643868788" + label="chrome-untrusted://companion-side-panel.top-chrome/"/> <int value="-634350465" label="chrome://ukm/"/> <int value="-631384656" label="chrome://assistant-optin/"/> <int value="-624584089" @@ -35526,12 +35552,16 @@ <int value="-623121238" label="chrome://arc-graphics-tracing/"/> <int value="-614294009" label="chrome://crostini-credits/"/> <int value="-606058756" label="chrome://accessibility/"/> + <int value="-601472337" label="chrome://shimless-rma/"/> <int value="-566908909" label="chrome://suggestions/"/> <int value="-548156607" label="chrome://feedback/"/> <int value="-528306235" label="chrome://sync/"/> + <int value="-525954994" label="chrome-untrusted://lens/"/> <int value="-516792794" label="chrome://downloads/"/> + <int value="-515586256" label="chrome-untrusted://media-app/"/> <int value="-512782085" label="chrome://salsa/"/> <int value="-511253776" label="chrome://snippets-internals/"/> + <int value="-492330636" label="chrome://connectivity-diagnostics/"/> <int value="-485494550" label="chrome://interventions-internals/"/> <int value="-476825727" label="chrome://user-notes-side-panel.top-chrome/"/> <int value="-451371558" label="chrome://serviceworker-internals/"/> @@ -35539,11 +35569,15 @@ <int value="-394586044" label="chrome://confirm-password-change/"/> <int value="-377028639" label="chrome://copresence/"/> <int value="-359703631" label="chrome://slow_trace/"/> + <int value="-336117866" label="chrome://focus-mode-media/"/> <int value="-245337017" label="chrome://user-actions/"/> + <int value="-233401490" label="chrome://accessory-update/"/> <int value="-222190329" label="chrome://dino/"/> + <int value="-207369615" label="chrome://location-internals/"/> <int value="-206925255" label="chrome://popular-sites-internals/"/> <int value="-176639700" label="chrome://omnibox/"/> <int value="-106823253" label="chrome://conflicts/"/> + <int value="-103805443" label="chrome://nearby-internals/"/> <int value="-90956977" label="chrome://dns/"/> <int value="-89853739" label="chrome://thumbnails/"/> <int value="-88246682" label="chrome://uithreadhang/"/> @@ -35556,16 +35590,19 @@ <int value="6575726" label="chrome://app-settings/"/> <int value="9727114" label="chrome://favicon/"/> <int value="14651785" label="chrome://download-internals/"/> + <int value="30059183" label="chrome://kerberos-in-browser/"/> <int value="34035361" label="chrome://apps/"/> <int value="43923599" label="chrome://tracing/"/> <int value="47779771" label="chrome://media-router-internals/"/> <int value="48333657" label="chrome://about/"/> + <int value="57900378" label="chrome://conch/"/> <int value="58807865" label="chrome://local-state/"/> <int value="84832110" label="chrome://fileicon/"/> <int value="112165789" label="chrome://device-emulator/"/> <int value="114748825" label="chrome-devtools://devtools/"/> <int value="164517522" label="chrome://discards/"/> <int value="171659041" label="chrome://webrtc-device-provider/"/> + <int value="182993612" label="chrome-untrusted://help-app-kids-magazine/"/> <int value="253258497" label="chrome://components/"/> <int value="260253931" label="chrome://devices/"/> <int value="275260142" label="chrome://eoc-internals/"/> @@ -35574,14 +35611,21 @@ <int value="361621847" label="chrome://make-metro/"/> <int value="372516928" label="chrome://histograms/"/> <int value="399773145" label="chrome://commander/"/> + <int value="402408777" label="chrome-untrusted://crosh/"/> + <int value="405280734" label="chrome://data-sharing-internals/"/> + <int value="435700552" label="chrome-untrusted://scalable-iph-debug/"/> <int value="436626245" label="chrome://settings/content/cookies/"/> <int value="454041716" label="chrome://new-tab-page-third-party/"/> + <int value="459058510" label="chrome://status-area-internals/"/> + <int value="460232055" label="chrome://lens-search-bubble/"/> <int value="461287992" label="chrome://help/"/> <int value="507734656" label="chrome://profile-customization/"/> <int value="520299179" label="chrome://media-engagement/"/> + <int value="543723090" label="chrome://traces-internals/"/> <int value="554090510" label="chrome://first-run/"/> <int value="581234974" label="chrome://tcmalloc/"/> <int value="584098160" label="chrome://profile-picker/"/> + <int value="592330525" label="chrome://metrics-internals/"/> <int value="607659257" label="chrome://cast/"/> <int value="634002171" label="chrome://projector-selfie-cam/"/> <int value="646837226" label="chrome://crashes/"/> @@ -35590,53 +35634,73 @@ <int value="689991895" label="chrome://supervised-user-internals/"/> <int value="701883986" label="chrome://privacy-sandbox-dialog/"/> <int value="703814809" label="chrome://intro/"/> + <int value="705531796" label="chrome://webxr-internals/"/> <int value="709341402" label="chrome://omnibox-popup.top-chrome/"/> <int value="742272091" label="chrome://extensions/"/> + <int value="745470397" label="chrome://parent-access/"/> <int value="748142712" label="chrome://crostini-upgrader/"/> <int value="749881882" label="chrome://webuijserror/"/> <int value="754315733" label="chrome://theme/"/> + <int value="770641362" label="chrome://shortcut-customization/"/> <int value="784140714" label="chrome://predictors/"/> <int value="812624791" label="chrome://dom-distiller/"/> <int value="821023334" label="chrome://screenlock-icon/"/> + <int value="858923205" label="chrome://cloud-upload/"/> <int value="864711974" label="chrome://emoji-picker/"/> + <int value="890996135" label="chrome://enterprise-reporting/"/> <int value="894368493" label="chrome://internet-config-dialog/"/> <int value="911597664" label="chrome://multidevice-setup/"/> <int value="918960088" label="chrome://instant/"/> <int value="943766809" label="chrome://view-cert/"/> + <int value="962490408" label="chrome-untrusted://camera-app/"/> + <int value="971254590" + label="chrome://shopping-insights-side-panel.top-chrome/"/> <int value="977219287" label="chrome://memory/"/> <int value="985294599" label="chrome://webrtc-logs/"/> <int value="1015167335" label="chrome://lens/"/> + <int value="1044107189" label="chrome://sample-system-web-app/"/> <int value="1050328415" label="chrome://diagnostics/"/> + <int value="1050817548" label="chrome://camera-app/"/> <int value="1055519744" label="chrome://webrtc-internals/"/> + <int value="1058168190" label="chrome://color-internals/"/> + <int value="1059833308" label="chrome://hps-internals/"/> <int value="1066907868" label="chrome://physical-web/"/> <int value="1076364348" label="chrome://web-app-internals/"/> + <int value="1084212752" label="chrome://personalization/"/> <int value="1109407387" label="chrome://keyboardoverlay/"/> <int value="1131405887" label="chrome://taskscheduler-internals/"/> <int value="1134924982" label="chrome://app-icon/"/> <int value="1145000455" label="chrome://arc-overview-tracing/"/> <int value="1145963223" label="chrome://process-internals/"/> <int value="1148733422" label="chrome://restart/"/> + <int value="1181155999" label="chrome://audio/"/> + <int value="1206367958" label="chrome://private-aggregation-internals/"/> <int value="1211642987" label="chrome://voicesearch/"/> <int value="1213428635" label="chrome://memory-redirect/"/> <int value="1214710734" label="chrome://welcome/"/> <int value="1221097359" label="chrome://constrained-test/"/> + <int value="1222534887" label="chrome://multidevice-internals/"/> <int value="1265583806" label="chrome://password-manager/"/> <int value="1272316136" label="chrome://image/"/> <int value="1281801197" label="chrome://terms/"/> <int value="1286620182" label="chrome://reset-password/"/> <int value="1306215264" label="chrome://activationmessage/"/> <int value="1326111536" label="chrome://new-tab-page/"/> + <int value="1332050252" label="chrome://borealis-installer/"/> <int value="1340926535" label="chrome://network/"/> <int value="1354146226" label="chrome://tab-modal-confirm-dialog/"/> <int value="1356087814" label="chrome://add-supervision/"/> <int value="1361577626" label="chrome://connectors-internals/"/> <int value="1371905827" label="chrome://flags/"/> + <int value="1384721582" label="chrome-untrusted://demo-mode-app/"/> <int value="1396129399" label="chrome://flash/"/> <int value="1397728473" label="chrome://crostini-installer/"/> <int value="1399992914" label="chrome://java-crash/"/> <int value="1403605293" label="chrome://internet-detail-dialog/ (duplicate)"/> <int value="1411665301" label="chrome://lock-network/"/> <int value="1427179406" label="chrome://gcm-internals/"/> + <int value="1437913193" label="chrome://file-manager/"/> + <int value="1452136061" label="chrome-untrusted://terminal/"/> <int value="1454088830" label="chrome://uber-frame/"/> <int value="1457759734" label="chrome://user-manager/"/> <int value="1463418339" label="chrome://proximity-auth/"/> @@ -35644,6 +35708,7 @@ <int value="1467342679" label="chrome://memory-internals/"/> <int value="1476643520" label="chrome://internet-detail-dialog/"/> <int value="1506419762" label="devtools://devtools/"/> + <int value="1527200748" label="chrome://security-curtain/"/> <int value="1531448147" label="chrome://urgent-password-expiry-notification/"/> <int value="1540230808" label="chrome://power/"/> @@ -35655,6 +35720,8 @@ <int value="1615939424" label="chrome://chrome/"/> <int value="1628875649" label="chrome://quota-internals/"/> <int value="1631369147" label="chrome://domain-reliability-internals/"/> + <int value="1645027983" label="chrome://notification-tester/"/> + <int value="1648729965" label="chrome://vm/"/> <int value="1662453825" label="chrome://indexeddb-internals/"/> <int value="1673299360" label="chrome://tab-search.top-chrome/"/> <int value="1677735296" label="chrome://sync-confirmation/"/> @@ -35664,18 +35731,22 @@ <int value="1725906496" label="chrome://imageburner/"/> <int value="1765337366" label="chrome://certificate-manager/"/> <int value="1776179126" label="chrome://thumb/"/> + <int value="1780987498" label="chrome://eche-app/"/> <int value="1797107942" label="chrome://md-settings/"/> <int value="1834776370" label="chrome://password-change/"/> <int value="1887784693" label="chrome://policy/"/> <int value="1906728906" label="chrome://privacy-sandbox-internals/"/> + <int value="1918190389" label="chrome-untrusted://projector-annotator/"/> <int value="1926101309" label="chrome://cryptohome/"/> <int value="1928106753" label="chrome://app-disabled/"/> <int value="1961263039" label="chrome://profiler/"/> <int value="1963964324" label="chrome://read-later.top-chrome/"/> <int value="1965127181" label="chrome://cast-feedback/"/> <int value="1975618905" label="chrome://app-list/"/> + <int value="2033331720" label="chrome-untrusted://os-feedback/"/> <int value="2040878656" label="chrome://bluetooth-internals/"/> <int value="2052019697" label="chrome://userimage/"/> + <int value="2108016874" label="chrome-untrusted://projector/"/> <int value="2111953935" label="chrome://topics-internals/"/> <int value="2114840772" label="chrome://drive-internals/"/> <int value="2120829362" label="chrome://account-manager-welcome/"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml index 3823ce7..4c2b541a 100644 --- a/tools/metrics/histograms/metadata/accessibility/histograms.xml +++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -28,6 +28,7 @@ <variant name="CursorHighlight"/> <variant name="Dictation"/> <variant name="DockedMagnifier"/> + <variant name="FaceGaze"/> <variant name="FocusHighlight"/> <variant name="HighContrast"/> <variant name="LargeCursor"/> @@ -994,7 +995,6 @@ </summary> <token key="FeatureName" variants="BaseCrosAccessibilityFeatures"> <variant name="Autoclick"/> - <variant name="FaceGaze"/> <variant name="LiveCaption"/> <variant name="MonoAudio"/> <variant name="SpokenFeedback"/> @@ -1094,7 +1094,6 @@ <token key="FeatureName" variants="BaseCrosAccessibilityFeatures"> <variant name="Autoclick"/> <variant name="CursorColor"/> - <variant name="FaceGaze"/> <variant name="LiveCaption"/> <variant name="MonoAudio"/> <variant name="MouseKeys"/>
diff --git a/tools/metrics/histograms/metadata/bluetooth/histograms.xml b/tools/metrics/histograms/metadata/bluetooth/histograms.xml index a6e32df..c763cbeb 100644 --- a/tools/metrics/histograms/metadata/bluetooth/histograms.xml +++ b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
@@ -1105,7 +1105,7 @@ </histogram> <histogram name="Bluetooth.ChromeOS.FastPair.PairingMethod" - enum="FastPairPairingMethod" expires_after="2024-06-28"> + enum="FastPairPairingMethod" expires_after="2025-06-28"> <owner>jackshira@google.com</owner> <owner>dclasson@google.com</owner> <owner>brandosocarras@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/cookie/histograms.xml b/tools/metrics/histograms/metadata/cookie/histograms.xml index 834768b..d1914e0 100644 --- a/tools/metrics/histograms/metadata/cookie/histograms.xml +++ b/tools/metrics/histograms/metadata/cookie/histograms.xml
@@ -219,7 +219,7 @@ </histogram> <histogram name="Cookie.CorruptMetaTableRecovered" enum="Boolean" - expires_after="2024-07-01"> + expires_after="2024-12-01"> <owner>arichiv@chromium.org</owner> <owner>bingler@chromium.org</owner> <owner>src/net/cookies/OWNERS</owner> @@ -389,7 +389,7 @@ </histogram> <histogram name="Cookie.ExpirationDuration400DaysGT" units="days" - expires_after="2024-07-01"> + expires_after="2024-12-01"> <owner>arichiv@chromium.org</owner> <owner>bingler@chromium.org</owner> <summary> @@ -399,7 +399,7 @@ </histogram> <histogram name="Cookie.ExpirationDuration400DaysLTE" units="days" - expires_after="2024-09-01"> + expires_after="2024-12-01"> <owner>arichiv@chromium.org</owner> <owner>bingler@chromium.org</owner> <summary> @@ -409,7 +409,7 @@ </histogram> <histogram name="Cookie.ExpirationDurationMinutesNonSecure" units="minutes" - expires_after="2024-07-01"> + expires_after="2024-12-01"> <owner>arichiv@chromium.org</owner> <owner>kaustubhag@chromium.org</owner> <owner>bingler@chromium.org</owner> @@ -1104,7 +1104,7 @@ </histogram> <histogram name="Cookie.TimeDatabaseMigrationToV18" units="ms" - expires_after="2024-07-01"> + expires_after="2024-12-01"> <owner>arichiv@chromium.org</owner> <owner>src/net/cookies/OWNERS</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/download/histograms.xml b/tools/metrics/histograms/metadata/download/histograms.xml index d01a3b1..de9d4e1 100644 --- a/tools/metrics/histograms/metadata/download/histograms.xml +++ b/tools/metrics/histograms/metadata/download/histograms.xml
@@ -383,21 +383,6 @@ <summary>The size of successfully completed downloads.</summary> </histogram> -<histogram name="Download.DownloadsPageDangerousWarningWasShownBefore" - enum="BooleanShown" expires_after="2024-06-30"> - <owner>chlily@chromium.org</owner> - <owner>chrome-counter-abuse-alerts@google.com</owner> - <summary> - Records whether a dangerous download warning has been shown previously, when - it is shown on the chrome://downloads page. Logged when a dangerous download - item is sent to the chrome://downloads page for display, either as a new - item or as an update. "Not shown" may be logged only once per - download, since afterwards it will have been shown. "Shown" may be - logged more than once per download, because a given download can be shown - and updated multiple times. - </summary> -</histogram> - <histogram name="Download.HttpResponseCode" enum="HttpResponseCode" expires_after="never"> <!-- expires-never: Used to monitor download system health. -->
diff --git a/tools/metrics/histograms/metadata/history/enums.xml b/tools/metrics/histograms/metadata/history/enums.xml index edf184a3..e8227cf 100644 --- a/tools/metrics/histograms/metadata/history/enums.xml +++ b/tools/metrics/histograms/metadata/history/enums.xml
@@ -133,6 +133,15 @@ <int value="3" label="Both"/> </enum> +<enum name="EmbeddingsModelInfoStatus"> + <int value="0" label="Unknown"/> + <int value="1" label="Model info is valid"/> + <int value="2" label="Model info is empty"/> + <int value="3" label="Model info does not contain model metadata"/> + <int value="4" label="Model info has invalid model metadata"/> + <int value="5" label="Model info has invalid data for additional files"/> +</enum> + <enum name="EmbeddingsUserActions"> <int value="0" label="Non-empty query History search"/> <int value="1" label="Embeddings search"/>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index 1cb819b..34a7f9be 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1792,6 +1792,17 @@ </summary> </histogram> +<histogram name="History.Embeddings.Embedder.ModelInfoStatus" + enum="EmbeddingsModelInfoStatus" expires_after="2024-12-31"> + <owner>sophiechang@chromium.org</owner> + <owner>zekunjiang@google.com</owner> + <summary> + Whether the model metadata received from optimization guide model provider + is valid. Logged each time the embedder receives an model update from + optimization guide. + </summary> +</histogram> + <histogram name="History.Embeddings.Embedder.PassageTokenCount" units="tokens" expires_after="2024-12-31"> <owner>sophiechang@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index 0ae668de..1dd7b2c1 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1118,7 +1118,7 @@ </histogram> <histogram name="Navigation.MainFrameHasRTLDomain2" enum="Boolean" - expires_after="2024-05-19"> + expires_after="2024-11-19"> <owner>cthomp@chromium.org</owner> <owner>trusty-transport@chromium.org</owner> <summary> @@ -1129,7 +1129,7 @@ </histogram> <histogram name="Navigation.MainFrameHasRTLDomainDifferentPage2" enum="Boolean" - expires_after="2024-05-19"> + expires_after="2024-11-19"> <owner>cthomp@chromium.org</owner> <owner>trusty-transport@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/nearby/enums.xml b/tools/metrics/histograms/metadata/nearby/enums.xml index 6000801..5aa098d 100644 --- a/tools/metrics/histograms/metadata/nearby/enums.xml +++ b/tools/metrics/histograms/metadata/nearby/enums.xml
@@ -33,7 +33,7 @@ <enum name="NearbyConnectionsMedium"> <int value="0" label="Unknown"/> - <int value="1" label="mDNS"/> + <int value="1" label="mDNS (deprecated)"/> <int value="2" label="Bluetooth"/> <int value="3" label="WiFi hotspot"/> <int value="4" label="BLE"/> @@ -42,6 +42,8 @@ <int value="7" label="NFC"/> <int value="8" label="WiFi Direct"/> <int value="9" label="WebRTC"/> + <int value="10" label="BLE_L2CAP"/> + <int value="11" label="USB"/> </enum> <enum name="NearbyConnectionsStartAdvertisingFailureReason">
diff --git a/tools/metrics/histograms/metadata/nearby/histograms.xml b/tools/metrics/histograms/metadata/nearby/histograms.xml index c2bb379b..9159d22 100644 --- a/tools/metrics/histograms/metadata/nearby/histograms.xml +++ b/tools/metrics/histograms/metadata/nearby/histograms.xml
@@ -315,6 +315,17 @@ </summary> </histogram> +<histogram name="Nearby.Connections.V3.Medium.ChangedToMedium" + enum="NearbyConnectionsMedium" expires_after="2025-05-01"> + <owner>crisrael@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the data-transfer medium that the Nearby Connections library + successfully switches to for V3 connections. Emitted when the Nearby + Connections library notifies of a bandwidth upgrade. + </summary> +</histogram> + <histogram name="Nearby.Connections.WifiLan.ConnectResult" enum="NearbyConnectionsWifiLanConnectResult" expires_after="2024-07-10"> <owner>hansenmichael@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/quota/histograms.xml b/tools/metrics/histograms/metadata/quota/histograms.xml index c39cba0f..f8fe7ec 100644 --- a/tools/metrics/histograms/metadata/quota/histograms.xml +++ b/tools/metrics/histograms/metadata/quota/histograms.xml
@@ -347,7 +347,7 @@ </histogram> <histogram name="Quota.TimeSpentToAEvictionRound" units="units" - expires_after="2024-05-19"> + expires_after="2025-05-19"> <owner>ayui@chromium.org</owner> <owner>chrome-owp-storage@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/readaloud/histograms.xml b/tools/metrics/histograms/metadata/readaloud/histograms.xml index cf39e99..3a53fdf 100644 --- a/tools/metrics/histograms/metadata/readaloud/histograms.xml +++ b/tools/metrics/histograms/metadata/readaloud/histograms.xml
@@ -299,31 +299,6 @@ </summary> </histogram> -<histogram name="ReadAloud.VoiceChanged.{VoiceID}" enum="Boolean" - expires_after="2024-06-02"> - <owner>andreaxg@google.com</owner> - <owner>basiaz@google.com</owner> - <owner>iwells@chromium.org</owner> - <summary> - Histogram for recording what voice a user changes to. Emitted when the - ReadAloud pref for voice is changed by the user. This only ever logs the - value "true" because we only care about the total count. - </summary> -</histogram> - -<histogram name="ReadAloud.VoicePreviewed.{VoiceID}" enum="Boolean" - expires_after="2024-06-02"> - <owner>andreaxg@google.com</owner> - <owner>basiaz@google.com</owner> - <owner>iwells@chromium.org</owner> - <summary> - Histogram for recording what voice a user previews. Emitted when a voice - preview playback is created successfully in ReadAloudController. This only - ever logs the value "true" because we only care about the total - count. - </summary> -</histogram> - </histograms> </histogram-configuration>
diff --git a/ui/accessibility/ax_action_data.h b/ui/accessibility/ax_action_data.h index 9e7643f..e16b138c 100644 --- a/ui/accessibility/ax_action_data.h +++ b/ui/accessibility/ax_action_data.h
@@ -44,14 +44,14 @@ // // Note that `target_role` should not be set if `target_node_id` is set, or // vice versa. - AXNodeID target_node_id = -1; + AXNodeID target_node_id = kInvalidAXNodeID; // Searches for the first node with the given role and performs the action on // that node. // // Note that `target_role` should not be set if `target_node_id` is set, or // vice versa. - ax::mojom::Role target_role = ax::mojom::Role::kNone; + ax::mojom::Role target_role = ax::mojom::Role::kUnknown; // The request id of this action tracked by the client. int request_id = -1;
diff --git a/ui/accessibility/mojom/ax_action_data.mojom b/ui/accessibility/mojom/ax_action_data.mojom index f88b613..189477af 100644 --- a/ui/accessibility/mojom/ax_action_data.mojom +++ b/ui/accessibility/mojom/ax_action_data.mojom
@@ -36,5 +36,5 @@ [MinVersion=1] ax.mojom.AXTreeID? child_tree_id; // Note that `target_role` should not be set if `target_node_id` is set, or // vice versa. - [MinVersion=2] ax.mojom.Role target_role; + [MinVersion=2] ax.mojom.Role target_role = ax.mojom.Role.kUnknown; };
diff --git a/ui/accessibility/mojom/ax_action_data_mojom_traits.cc b/ui/accessibility/mojom/ax_action_data_mojom_traits.cc index 9c7e685..291425b 100644 --- a/ui/accessibility/mojom/ax_action_data_mojom_traits.cc +++ b/ui/accessibility/mojom/ax_action_data_mojom_traits.cc
@@ -4,6 +4,7 @@ #include "ui/accessibility/mojom/ax_action_data_mojom_traits.h" +#include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h" #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" @@ -28,8 +29,10 @@ if (!data.ReadSourceExtensionId(&out->source_extension_id)) { return false; } - if (data.target_node_id() != -1 && - data.target_role() != ax::mojom::Role::kNone) { + if (data.target_node_id() != ui::kInvalidAXNodeID && + data.target_role() != ax::mojom::Role::kUnknown) { + // The target could either be found by ID, or by role. Having both set makes + // no sense. return false; } out->target_node_id = data.target_node_id();
diff --git a/ui/color/mac/native_color_mixers_mac.mm b/ui/color/mac/native_color_mixers_mac.mm index ed3e28a..f5f2975 100644 --- a/ui/color/mac/native_color_mixers_mac.mm +++ b/ui/color/mac/native_color_mixers_mac.mm
@@ -8,7 +8,6 @@ #include "base/containers/fixed_flat_set.h" #import "skia/ext/skia_utils_mac.h" -#include "ui/base/ui_base_features.h" #include "ui/color/color_id.h" #include "ui/color/color_mixer.h" #include "ui/color/color_provider.h" @@ -112,15 +111,7 @@ mixer[kColorSysStateFocusRing] = PickGoogleColor( skia::NSSystemColorToSkColor(NSColor.keyboardFocusIndicatorColor), kColorSysBase, color_utils::kMinimumVisibleContrastRatio); - } - if (!features::IsChromeRefresh2023()) { - SkColor menu_separator_color = - properties.dark ? SkColorSetA(gfx::kGoogleGrey800, 0xCC) - : SkColorSetA(SK_ColorBLACK, 0x26); - mixer[kColorMenuSeparator] = {menu_separator_color}; - } - if (!features::IsChromeRefresh2023() || !key.user_color.has_value()) { const SkColor system_highlight_color = skia::NSSystemColorToSkColor(NSColor.selectedTextBackgroundColor); mixer[kColorTextSelectionBackground] = {system_highlight_color}; @@ -156,7 +147,7 @@ // Ensure the system tint is applied by default for pre-refresh browsers. For // post-refresh only apply the tint if running old design system themes or the // color source is explicitly configured for grayscale. - if (features::IsChromeRefresh2023() && !key.custom_theme && + if (!key.custom_theme && key.user_color_source != ColorProviderKey::UserColorSource::kGrayscale) { return; }
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn index 1dd366d9..805c7e44 100644 --- a/ui/display/manager/BUILD.gn +++ b/ui/display/manager/BUILD.gn
@@ -5,13 +5,49 @@ import("//build/config/chromeos/ui_mode.gni") import("//build/config/ui.gni") -assert(is_chromeos_ash || is_castos || is_cast_android) +assert(is_chromeos_ash) component("manager") { sources = [ + "apply_content_protection_task.cc", + "apply_content_protection_task.h", + "configure_displays_task.cc", + "configure_displays_task.h", + "content_protection_key_manager.cc", + "content_protection_key_manager.h", + "content_protection_manager.cc", + "content_protection_manager.h", + "default_touch_transform_setter.cc", + "default_touch_transform_setter.h", + "display_change_observer.cc", + "display_change_observer.h", + "display_configurator.cc", + "display_configurator.h", + "display_layout_manager.h", + "display_layout_store.cc", + "display_layout_store.h", + "display_manager.cc", + "display_manager.h", "display_manager_export.h", + "display_manager_observer.cc", + "display_manager_observer.h", + "display_port_observer.cc", + "display_port_observer.h", + "display_properties_parser.cc", + "display_properties_parser.h", + "json_converter.cc", + "json_converter.h", "managed_display_info.cc", "managed_display_info.h", + "query_content_protection_task.cc", + "query_content_protection_task.h", + "touch_device_manager.cc", + "touch_device_manager.h", + "touch_transform_controller.cc", + "touch_transform_controller.h", + "touch_transform_setter.h", + "update_display_configuration_task.cc", + "update_display_configuration_task.h", "util/display_manager_test_util.cc", "util/display_manager_test_util.h", "util/display_manager_util.cc", @@ -25,6 +61,10 @@ deps = [ "//base", "//build:chromeos_buildflags", + "//chromeos/ash/components/system", + "//chromeos/ui/base", + "//components/device_event_log", + "//third_party/re2:re2", "//ui/base", "//ui/display/mojom:mojom", "//ui/display/util", @@ -34,51 +74,4 @@ ] defines = [ "DISPLAY_MANAGER_IMPLEMENTATION" ] - - if (is_chromeos_ash) { - sources += [ - "apply_content_protection_task.cc", - "apply_content_protection_task.h", - "configure_displays_task.cc", - "configure_displays_task.h", - "content_protection_key_manager.cc", - "content_protection_key_manager.h", - "content_protection_manager.cc", - "content_protection_manager.h", - "default_touch_transform_setter.cc", - "default_touch_transform_setter.h", - "display_change_observer.cc", - "display_change_observer.h", - "display_configurator.cc", - "display_configurator.h", - "display_layout_manager.h", - "display_layout_store.cc", - "display_layout_store.h", - "display_manager.cc", - "display_manager.h", - "display_manager_observer.cc", - "display_manager_observer.h", - "display_port_observer.cc", - "display_port_observer.h", - "display_properties_parser.cc", - "display_properties_parser.h", - "json_converter.cc", - "json_converter.h", - "query_content_protection_task.cc", - "query_content_protection_task.h", - "touch_device_manager.cc", - "touch_device_manager.h", - "touch_transform_controller.cc", - "touch_transform_controller.h", - "touch_transform_setter.h", - "update_display_configuration_task.cc", - "update_display_configuration_task.h", - ] - deps += [ - "//chromeos/ash/components/system", - "//chromeos/ui/base", - "//components/device_event_log", - "//third_party/re2:re2", - ] - } }
diff --git a/ui/gfx/font_render_params_mac.cc b/ui/gfx/font_render_params_mac.cc index 86111a9..4e2f7b9 100644 --- a/ui/gfx/font_render_params_mac.cc +++ b/ui/gfx/font_render_params_mac.cc
@@ -20,8 +20,7 @@ params.use_bitmaps = true; params.subpixel_positioning = true; - if (features::IsChromeRefresh2023() && - !base::FeatureList::IsEnabled(features::kCr2023MacFontSmoothing)) { + if (!base::FeatureList::IsEnabled(features::kCr2023MacFontSmoothing)) { params.subpixel_rendering = FontRenderParams::SUBPIXEL_RENDERING_NONE; params.hinting = FontRenderParams::HINTING_NONE; } else {
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index a619e2c6..b14490a 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -7725,8 +7725,7 @@ #if !BUILDFLAG(IS_MAC) EXPECT_EQ(GetRendererFont().getEdging(), SkFont::Edging::kSubpixelAntiAlias); #else - if (features::IsChromeRefresh2023() && - !base::FeatureList::IsEnabled(features::kCr2023MacFontSmoothing)) { + if (!base::FeatureList::IsEnabled(features::kCr2023MacFontSmoothing)) { EXPECT_EQ(GetRendererFont().getEdging(), SkFont::Edging::kAntiAlias); } else { EXPECT_EQ(GetRendererFont().getEdging(),
diff --git a/ui/gl/egl_bindings_autogen_mock.cc b/ui/gl/egl_bindings_autogen_mock.cc index 73a2ed1..aff9ff9 100644 --- a/ui/gl/egl_bindings_autogen_mock.cc +++ b/ui/gl/egl_bindings_autogen_mock.cc
@@ -672,12 +672,6 @@ interface_->SetBlobCacheFuncsANDROID(dpy, set, get); } -void GL_BINDING_CALL MockEGLInterface::Mock_eglSetValidationEnabledANGLE( - EGLBoolean validationState) { - MakeEglMockFunctionUnique("eglSetValidationEnabledANGLE"); - interface_->SetValidationEnabledANGLE(validationState); -} - EGLBoolean GL_BINDING_CALL MockEGLInterface::Mock_eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, @@ -998,10 +992,6 @@ if (strcmp(name, "eglSetBlobCacheFuncsANDROID") == 0) return reinterpret_cast<GLFunctionPointerType>( Mock_eglSetBlobCacheFuncsANDROID); - if (strcmp(name, "eglSetValidationEnabledANGLE") == 0) { - return reinterpret_cast<GLFunctionPointerType>( - Mock_eglSetValidationEnabledANGLE); - } if (strcmp(name, "eglStreamAttribKHR") == 0) return reinterpret_cast<GLFunctionPointerType>(Mock_eglStreamAttribKHR); if (strcmp(name, "eglStreamConsumerAcquireKHR") == 0)
diff --git a/ui/gl/egl_bindings_autogen_mock.h b/ui/gl/egl_bindings_autogen_mock.h index 576785b7..c831999b 100644 --- a/ui/gl/egl_bindings_autogen_mock.h +++ b/ui/gl/egl_bindings_autogen_mock.h
@@ -291,8 +291,6 @@ Mock_eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); -static void GL_BINDING_CALL -Mock_eglSetValidationEnabledANGLE(EGLBoolean validationState); static EGLBoolean GL_BINDING_CALL Mock_eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py index ab2dcd0..e6f0bc94 100755 --- a/ui/gl/generate_bindings.py +++ b/ui/gl/generate_bindings.py
@@ -2844,11 +2844,6 @@ 'extensions': ['EGL_ANDROID_blob_cache'] }], 'arguments': 'EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get' }, -{ 'return_type': 'void', - 'versions': [{ 'name': 'eglSetValidationEnabledANGLE', - 'extensions': ['EGL_ANGLE_no_error'] }], - 'arguments': - 'EGLBoolean validationState' }, { 'return_type': 'EGLBoolean', 'versions': [{ 'name': 'eglStreamAttribKHR', 'extensions': ['EGL_KHR_stream'] }], @@ -2923,7 +2918,6 @@ # EGL client extensions that may not add a function but are still queried. EGL_CLIENT_EXTENSIONS_EXTRA = [ 'EGL_ANGLE_display_power_preference', - 'EGL_ANGLE_no_error', 'EGL_ANGLE_platform_angle', 'EGL_ANGLE_platform_angle_d3d', 'EGL_ANGLE_platform_angle_device_id',
diff --git a/ui/gl/gl_bindings_api_autogen_egl.h b/ui/gl/gl_bindings_api_autogen_egl.h index c1c59cf..ef0ec5e 100644 --- a/ui/gl/gl_bindings_api_autogen_egl.h +++ b/ui/gl/gl_bindings_api_autogen_egl.h
@@ -250,7 +250,6 @@ void eglSetBlobCacheFuncsANDROIDFn(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get) override; -void eglSetValidationEnabledANGLEFn(EGLBoolean validationState) override; EGLBoolean eglStreamAttribKHRFn(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
diff --git a/ui/gl/gl_bindings_autogen_egl.cc b/ui/gl/gl_bindings_autogen_egl.cc index cc0770f7..ce1a889 100644 --- a/ui/gl/gl_bindings_autogen_egl.cc +++ b/ui/gl/gl_bindings_autogen_egl.cc
@@ -215,9 +215,6 @@ fn.eglSetBlobCacheFuncsANDROIDFn = reinterpret_cast<eglSetBlobCacheFuncsANDROIDProc>( GetGLProcAddress("eglSetBlobCacheFuncsANDROID")); - fn.eglSetValidationEnabledANGLEFn = - reinterpret_cast<eglSetValidationEnabledANGLEProc>( - GetGLProcAddress("eglSetValidationEnabledANGLE")); fn.eglStreamAttribKHRFn = reinterpret_cast<eglStreamAttribKHRProc>( GetGLProcAddress("eglStreamAttribKHR")); fn.eglStreamConsumerAcquireKHRFn = @@ -270,7 +267,6 @@ gfx::HasExtension(extensions, "EGL_ANGLE_display_power_preference"); b_EGL_ANGLE_feature_control = gfx::HasExtension(extensions, "EGL_ANGLE_feature_control"); - b_EGL_ANGLE_no_error = gfx::HasExtension(extensions, "EGL_ANGLE_no_error"); b_EGL_ANGLE_platform_angle = gfx::HasExtension(extensions, "EGL_ANGLE_platform_angle"); b_EGL_ANGLE_platform_angle_d3d = @@ -342,7 +338,6 @@ gfx::HasExtension(extensions, "EGL_ANGLE_keyed_mutex"); b_EGL_ANGLE_metal_shared_event_sync = gfx::HasExtension(extensions, "EGL_ANGLE_metal_shared_event_sync"); - b_EGL_ANGLE_no_error = gfx::HasExtension(extensions, "EGL_ANGLE_no_error"); b_EGL_ANGLE_power_preference = gfx::HasExtension(extensions, "EGL_ANGLE_power_preference"); b_EGL_ANGLE_query_surface_pointer = @@ -927,10 +922,6 @@ driver_->fn.eglSetBlobCacheFuncsANDROIDFn(dpy, set, get); } -void EGLApiBase::eglSetValidationEnabledANGLEFn(EGLBoolean validationState) { - driver_->fn.eglSetValidationEnabledANGLEFn(validationState); -} - EGLBoolean EGLApiBase::eglStreamAttribKHRFn(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, @@ -1632,12 +1623,6 @@ egl_api_->eglSetBlobCacheFuncsANDROIDFn(dpy, set, get); } -void TraceEGLApi::eglSetValidationEnabledANGLEFn(EGLBoolean validationState) { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", - "TraceEGLAPI::eglSetValidationEnabledANGLE"); - egl_api_->eglSetValidationEnabledANGLEFn(validationState); -} - EGLBoolean TraceEGLApi::eglStreamAttribKHRFn(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, @@ -2634,12 +2619,6 @@ egl_api_->eglSetBlobCacheFuncsANDROIDFn(dpy, set, get); } -void LogEGLApi::eglSetValidationEnabledANGLEFn(EGLBoolean validationState) { - GL_SERVICE_LOG("eglSetValidationEnabledANGLE" << "(" << validationState - << ")"); - egl_api_->eglSetValidationEnabledANGLEFn(validationState); -} - EGLBoolean LogEGLApi::eglStreamAttribKHRFn(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute,
diff --git a/ui/gl/gl_bindings_autogen_egl.h b/ui/gl/gl_bindings_autogen_egl.h index 60ee3e2..c84a446 100644 --- a/ui/gl/gl_bindings_autogen_egl.h +++ b/ui/gl/gl_bindings_autogen_egl.h
@@ -308,8 +308,6 @@ EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); -typedef void(GL_BINDING_CALL* eglSetValidationEnabledANGLEProc)( - EGLBoolean validationState); typedef EGLBoolean(GL_BINDING_CALL* eglStreamAttribKHRProc)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, @@ -362,7 +360,6 @@ struct GL_EXPORT ClientExtensionsEGL { bool b_EGL_ANGLE_display_power_preference; bool b_EGL_ANGLE_feature_control; - bool b_EGL_ANGLE_no_error; bool b_EGL_ANGLE_platform_angle; bool b_EGL_ANGLE_platform_angle_d3d; bool b_EGL_ANGLE_platform_angle_device_id; @@ -404,7 +401,6 @@ bool b_EGL_ANGLE_iosurface_client_buffer; bool b_EGL_ANGLE_keyed_mutex; bool b_EGL_ANGLE_metal_shared_event_sync; - bool b_EGL_ANGLE_no_error; bool b_EGL_ANGLE_power_preference; bool b_EGL_ANGLE_query_surface_pointer; bool b_EGL_ANGLE_robust_resource_initialization; @@ -536,7 +532,6 @@ eglReleaseTexImageProc eglReleaseTexImageFn; eglReleaseThreadProc eglReleaseThreadFn; eglSetBlobCacheFuncsANDROIDProc eglSetBlobCacheFuncsANDROIDFn; - eglSetValidationEnabledANGLEProc eglSetValidationEnabledANGLEFn; eglStreamAttribKHRProc eglStreamAttribKHRFn; eglStreamConsumerAcquireKHRProc eglStreamConsumerAcquireKHRFn; eglStreamConsumerGLTextureExternalAttribsNVProc @@ -816,7 +811,6 @@ virtual void eglSetBlobCacheFuncsANDROIDFn(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get) = 0; - virtual void eglSetValidationEnabledANGLEFn(EGLBoolean validationState) = 0; virtual EGLBoolean eglStreamAttribKHRFn(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, @@ -975,8 +969,6 @@ #define eglReleaseThread ::gl::g_current_egl_context->eglReleaseThreadFn #define eglSetBlobCacheFuncsANDROID \ ::gl::g_current_egl_context->eglSetBlobCacheFuncsANDROIDFn -#define eglSetValidationEnabledANGLE \ - ::gl::g_current_egl_context->eglSetValidationEnabledANGLEFn #define eglStreamAttribKHR ::gl::g_current_egl_context->eglStreamAttribKHRFn #define eglStreamConsumerAcquireKHR \ ::gl::g_current_egl_context->eglStreamConsumerAcquireKHRFn
diff --git a/ui/gl/gl_display.cc b/ui/gl/gl_display.cc index 78f5f1e..8bb85fd 100644 --- a/ui/gl/gl_display.cc +++ b/ui/gl/gl_display.cc
@@ -724,11 +724,6 @@ SetEglDebugMessageControl(); } - if (g_driver_egl.client_ext.b_EGL_ANGLE_no_error && - !features::IsANGLEValidationEnabled()) { - eglSetValidationEnabledANGLE(EGL_FALSE); - } - std::vector<std::string> enabled_angle_features; std::vector<std::string> disabled_angle_features; features::GetANGLEFeaturesFromCommandLineAndFinch(
diff --git a/ui/gl/gl_features.cc b/ui/gl/gl_features.cc index 65c085670..e682928 100644 --- a/ui/gl/gl_features.cc +++ b/ui/gl/gl_features.cc
@@ -188,22 +188,6 @@ #endif // defined(PASSTHROUGH_COMMAND_DECODER_LAUNCHED) } -#if DCHECK_IS_ON() -bool IsANGLEValidationEnabled() { - return true; -} -#else -// Enables the use of ANGLE validation for EGL and GL (non-WebGL) contexts. -BASE_FEATURE(kDefaultEnableANGLEValidation, - "DefaultEnableANGLEValidation", - base::FEATURE_DISABLED_BY_DEFAULT); - -bool IsANGLEValidationEnabled() { - return base::FeatureList::IsEnabled(kDefaultEnableANGLEValidation) && - UsePassthroughCommandDecoder(); -} -#endif - void GetANGLEFeaturesFromCommandLineAndFinch( const base::CommandLine* command_line, std::vector<std::string>& enabled_angle_features,
diff --git a/ui/gl/gl_features.h b/ui/gl/gl_features.h index 35e4884..31b3aaa8 100644 --- a/ui/gl/gl_features.h +++ b/ui/gl/gl_features.h
@@ -36,7 +36,6 @@ GL_EXPORT bool IsAndroidFrameDeadlineEnabled(); GL_EXPORT bool UsePassthroughCommandDecoder(); -GL_EXPORT bool IsANGLEValidationEnabled(); GL_EXPORT void GetANGLEFeaturesFromCommandLineAndFinch( const base::CommandLine* command_line,
diff --git a/ui/gl/gl_mock_autogen_egl.h b/ui/gl/gl_mock_autogen_egl.h index 82cc829..7ff6959 100644 --- a/ui/gl/gl_mock_autogen_egl.h +++ b/ui/gl/gl_mock_autogen_egl.h
@@ -277,7 +277,6 @@ void(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)); -MOCK_METHOD1(SetValidationEnabledANGLE, void(EGLBoolean validationState)); MOCK_METHOD4(StreamAttribKHR, EGLBoolean(EGLDisplay dpy, EGLStreamKHR stream,
diff --git a/ui/gtk/window_frame_provider_gtk.cc b/ui/gtk/window_frame_provider_gtk.cc index 0b8fa0ec..e24cce8 100644 --- a/ui/gtk/window_frame_provider_gtk.cc +++ b/ui/gtk/window_frame_provider_gtk.cc
@@ -7,7 +7,6 @@ #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "third_party/skia/include/core/SkRRect.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect.h" @@ -69,9 +68,7 @@ if (!focused) { gtk_style_context_set_state(context, GTK_STATE_FLAG_BACKDROP); } - if (features::IsChromeRefresh2023()) { - ApplyCssToContext(context, "* { border-bottom-style: none; }"); - } + ApplyCssToContext(context, "* { border-bottom-style: none; }"); return context; }
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc index d9d27baa..f463c3ec4 100644 --- a/ui/message_center/views/notification_view_unittest.cc +++ b/ui/message_center/views/notification_view_unittest.cc
@@ -463,11 +463,8 @@ EXPECT_TRUE(delegate_->disable_notification_called()); } -// TODO (crbug/1521442): Test fails under ChromeRefresh2023. Fix and re-enable. -TEST_F(NotificationViewTest, TestAccentColor) { - if (features::IsChromeRefresh2023()) { - GTEST_SKIP(); - } +// TODO (crbug/1521442): Test fails post-ChromeRefresh2023. Fix and re-enable. +TEST_F(NotificationViewTest, DISABLED_TestAccentColor) { std::unique_ptr<Notification> notification = CreateSimpleNotification(); notification->set_buttons(CreateButtons(2));
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc index e87ddca5..6f6cf2e4 100644 --- a/ui/views/controls/button/checkbox.cc +++ b/ui/views/controls/button/checkbox.cc
@@ -107,46 +107,43 @@ // the checkbox view (otherwise it gets clipped which looks weird). views::InstallEmptyHighlightPathGenerator(this); - if (features::IsChromeRefresh2023()) { - InkDrop::Install(image_container_view(), - std::make_unique<InkDropHost>(image_container_view())); - SetInkDropView(image_container_view()); - InkDrop::Get(image_container_view())->SetMode(InkDropHost::InkDropMode::ON); + InkDrop::Install(image_container_view(), + std::make_unique<InkDropHost>(image_container_view())); + SetInkDropView(image_container_view()); + InkDrop::Get(image_container_view())->SetMode(InkDropHost::InkDropMode::ON); - // Allow ImageView to capture mouse events in order for InkDrop effects to - // trigger. - image_container_view()->SetCanProcessEventsWithinSubtree(true); + // Allow ImageView to capture mouse events in order for InkDrop effects to + // trigger. + image_container_view()->SetCanProcessEventsWithinSubtree(true); - // Avoid the default ink-drop mask to allow the InkDrop effect to extend - // beyond the image view (otherwise it gets clipped which looks weird). - views::InstallEmptyHighlightPathGenerator(image_container_view()); + // Avoid the default ink-drop mask to allow the InkDrop effect to extend + // beyond the image view (otherwise it gets clipped which looks weird). + views::InstallEmptyHighlightPathGenerator(image_container_view()); - InkDrop::Get(image_container_view()) - ->SetCreateHighlightCallback(base::BindRepeating( - [](View* host) { - int radius = - InkDropHost::GetLargeSize(kCheckboxInkDropSize).width() / 2; - return std::make_unique<views::InkDropHighlight>( - gfx::PointF(host->GetContentsBounds().CenterPoint()), - std::make_unique<CircleLayerDelegate>( - views::InkDrop::Get(host)->GetBaseColor(), radius)); - }, - image_container_view())); + InkDrop::Get(image_container_view()) + ->SetCreateHighlightCallback(base::BindRepeating( + [](View* host) { + int radius = + InkDropHost::GetLargeSize(kCheckboxInkDropSize).width() / 2; + return std::make_unique<views::InkDropHighlight>( + gfx::PointF(host->GetContentsBounds().CenterPoint()), + std::make_unique<CircleLayerDelegate>( + views::InkDrop::Get(host)->GetBaseColor(), radius)); + }, + image_container_view())); - InkDrop::Get(image_container_view()) - ->SetCreateRippleCallback(base::BindRepeating( - [](View* host) { - return InkDrop::Get(host)->CreateSquareRipple( - host->GetContentsBounds().CenterPoint(), - kCheckboxInkDropSize); - }, - image_container_view())); + InkDrop::Get(image_container_view()) + ->SetCreateRippleCallback(base::BindRepeating( + [](View* host) { + return InkDrop::Get(host)->CreateSquareRipple( + host->GetContentsBounds().CenterPoint(), kCheckboxInkDropSize); + }, + image_container_view())); - // Usually ink-drop ripples match the text color. Checkboxes use the - // color of the unchecked, enabled icon. - InkDrop::Get(image_container_view()) - ->SetBaseColorId(ui::kColorCheckboxForegroundUnchecked); - } + // Usually ink-drop ripples match the text color. Checkboxes use the + // color of the unchecked, enabled icon. + InkDrop::Get(image_container_view()) + ->SetBaseColorId(ui::kColorCheckboxForegroundUnchecked); } Checkbox::~Checkbox() = default; @@ -204,22 +201,17 @@ gfx::ImageSkia Checkbox::GetImage(ButtonState for_state) const { const int icon_state = GetIconState(for_state); - if (features::IsChromeRefresh2023()) { - const SkColor container_color = GetIconImageColor(icon_state); - if (GetChecked()) { - const gfx::ImageSkia check_icon = gfx::CreateVectorIcon( - GetVectorIcon(), kCheckboxIconDipSize, GetIconCheckColor(icon_state)); + const SkColor container_color = GetIconImageColor(icon_state); + if (GetChecked()) { + const gfx::ImageSkia check_icon = gfx::CreateVectorIcon( + GetVectorIcon(), kCheckboxIconDipSize, GetIconCheckColor(icon_state)); - return gfx::ImageSkiaOperations::CreateImageWithRoundRectBackground( - gfx::SizeF(kCheckboxIconDipSize, kCheckboxIconDipSize), - kCheckboxIconCornerRadius, container_color, check_icon); - } - return gfx::CreateVectorIcon(GetVectorIcon(), kCheckboxIconDipSize, - container_color); + return gfx::ImageSkiaOperations::CreateImageWithRoundRectBackground( + gfx::SizeF(kCheckboxIconDipSize, kCheckboxIconDipSize), + kCheckboxIconCornerRadius, container_color, check_icon); } - return gfx::CreateVectorIcon(GetVectorIcon(), kCheckboxIconDipSize, - GetIconImageColor(icon_state)); + container_color); } std::unique_ptr<LabelButtonBorder> Checkbox::CreateDefaultBorder() const { @@ -241,43 +233,20 @@ SkPath Checkbox::GetFocusRingPath() const { SkPath path; gfx::Rect bounds = image_container_view()->GetMirroredContentsBounds(); - // Don't add extra insets in the ChromeRefresh case so that the focus ring can - // be drawn in the ChromeRefresh style. - if (!features::IsChromeRefresh2023()) { - bounds.Inset(1); - } path.addRect(RectToSkRect(bounds)); return path; } SkColor Checkbox::GetIconImageColor(int icon_state) const { - if (features::IsChromeRefresh2023()) { - if (icon_state & IconState::CHECKED) { - return GetColorProvider()->GetColor( - (icon_state & IconState::ENABLED) - ? ui::kColorCheckboxContainer - : ui::kColorCheckboxContainerDisabled); - } + if (icon_state & IconState::CHECKED) { return GetColorProvider()->GetColor( - (icon_state & IconState::ENABLED) ? ui::kColorCheckboxOutline + (icon_state & IconState::ENABLED) + ? ui::kColorCheckboxContainer + : ui::kColorCheckboxContainerDisabled); + } + return GetColorProvider()->GetColor((icon_state & IconState::ENABLED) + ? ui::kColorCheckboxOutline : ui::kColorCheckboxOutlineDisabled); - } - - SkColor active_color = - GetColorProvider()->GetColor((icon_state & IconState::CHECKED) - ? ui::kColorCheckboxForegroundChecked - : ui::kColorCheckboxForegroundUnchecked); - - // Use the overridden checked icon image color instead if set. - if (icon_state & IconState::CHECKED && - checked_icon_image_color_.has_value()) { - active_color = checked_icon_image_color_.value(); - } - - return (icon_state & IconState::ENABLED) - ? active_color - : color_utils::BlendTowardMaxContrast(active_color, - gfx::kDisabledControlAlpha); } SkColor Checkbox::GetIconCheckColor(int icon_state) const { @@ -294,11 +263,7 @@ } const gfx::VectorIcon& Checkbox::GetVectorIcon() const { - if (features::IsChromeRefresh2023()) { - return GetChecked() ? kCheckboxCheckCr2023Icon : kCheckboxNormalCr2023Icon; - } - - return GetChecked() ? kCheckboxActiveIcon : kCheckboxNormalIcon; + return GetChecked() ? kCheckboxCheckCr2023Icon : kCheckboxNormalCr2023Icon; } int Checkbox::GetIconState(ButtonState for_state) const {
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc index d886c50..5734c51 100644 --- a/ui/views/controls/button/md_text_button.cc +++ b/ui/views/controls/button/md_text_button.cc
@@ -58,16 +58,11 @@ [](MdTextButton* host) { return host->GetHoverColor(host->GetStyle()); }, this)); - if (features::IsChromeRefresh2023()) { - constexpr int kImageSpacing = 8; - SetImageLabelSpacing(kImageSpacing); - // Highlight button colors already have opacity applied. - // Set the opacity to 1 so the two values do not compound. - InkDrop::Get(this)->SetHighlightOpacity(1); - } else { - SetCornerRadius(LayoutProvider::Get()->GetCornerRadiusMetric( - ShapeContextTokens::kButtonRadius)); - } + constexpr int kImageSpacing = 8; + SetImageLabelSpacing(kImageSpacing); + // Highlight button colors already have opacity applied. + // Set the opacity to 1 so the two values do not compound. + InkDrop::Get(this)->SetHighlightOpacity(1); SetHorizontalAlignment(gfx::ALIGN_CENTER); @@ -240,7 +235,7 @@ int right_padding = LayoutProvider::Get()->GetDistanceMetric( DISTANCE_BUTTON_HORIZONTAL_PADDING); int left_padding = right_padding; - if (HasImage(GetVisualState()) && features::IsChromeRefresh2023()) { + if (HasImage(GetVisualState())) { constexpr int kLeftPadding = 12; left_padding = kLeftPadding; } @@ -316,13 +311,11 @@ SetBackground( CreateBackgroundFromPainter(Painter::CreateRoundRectWith1PxBorderPainter( bg_color, stroke_color, GetCornerRadiusValue(), SkBlendMode::kSrcOver, - true /* antialias */, - features::IsChromeRefresh2023() /* should_border_scale */))); + true /* antialias */, true /* should_border_scale */))); } void MdTextButton::UpdateIconColor() { - if (features::IsChromeRefresh2023() && use_text_color_for_icon_ && - HasImage(ButtonState::STATE_NORMAL)) { + if (use_text_color_for_icon_ && HasImage(ButtonState::STATE_NORMAL)) { const std::optional<ui::ImageModel>& image_model = GetImageModel(ButtonState::STATE_NORMAL); if (image_model.has_value() && image_model->IsVectorIcon()) { @@ -346,10 +339,6 @@ } SkColor MdTextButton::GetHoverColor(ui::ButtonStyle button_style) { - if (!features::IsChromeRefresh2023()) { - return color_utils::DeriveDefaultIconColor(label()->GetEnabledColor()); - } - switch (button_style) { case ui::ButtonStyle::kProminent: return GetColorProvider()->GetColor(ui::kColorSysStateHoverOnProminent);
diff --git a/ui/views/controls/button/radio_button.cc b/ui/views/controls/button/radio_button.cc index cc279d1a..2cba2f9 100644 --- a/ui/views/controls/button/radio_button.cc +++ b/ui/views/controls/button/radio_button.cc
@@ -29,7 +29,6 @@ namespace { constexpr int kFocusRingRadius = 16; -constexpr int kRadioButtonIconDipSize = 16; constexpr int kRadioButtonIconDipSizeCr2023 = 20; } // namespace @@ -133,10 +132,7 @@ } gfx::ImageSkia RadioButton::GetImage(ButtonState for_state) const { - return gfx::CreateVectorIcon(GetVectorIcon(), - features::IsChromeRefresh2023() - ? kRadioButtonIconDipSizeCr2023 - : kRadioButtonIconDipSize, + return gfx::CreateVectorIcon(GetVectorIcon(), kRadioButtonIconDipSizeCr2023, GetIconImageColor(GetIconState(for_state))); }
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc index 15cc189..2ba08d5 100644 --- a/ui/views/controls/combobox/combobox.cc +++ b/ui/views/controls/combobox/combobox.cc
@@ -80,10 +80,8 @@ button_controller()->set_notify_action( ButtonController::NotifyAction::kOnPress); - if (features::IsChromeRefresh2023()) { - views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), - GetCornerRadius()); - } + views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), + GetCornerRadius()); ConfigureComboboxButtonInkDrop(this); } TransparentButton(const TransparentButton&) = delete; @@ -141,9 +139,7 @@ SetFocusBehavior(FocusBehavior::ALWAYS); #endif - SetBackgroundColorId(features::IsChromeRefresh2023() - ? ui::kColorComboboxBackground - : ui::kColorTextfieldBackground); + SetBackgroundColorId(ui::kColorComboboxBackground); UpdateBorder(); @@ -154,31 +150,25 @@ AddChildView(std::make_unique<TransparentButton>(base::BindRepeating( &Combobox::ArrowButtonPressed, base::Unretained(this)))); - if (features::IsChromeRefresh2023()) { - // TODO(crbug.com/40250124): This setter should be removed and the behavior - // made default when ChromeRefresh2023 is finalized. - SetEventHighlighting(true); - enabled_changed_subscription_ = - AddEnabledChangedCallback(base::BindRepeating( - [](Combobox* combobox) { - combobox->SetBackgroundColorId( - combobox->GetEnabled() - ? ui::kColorComboboxBackground - : ui::kColorComboboxBackgroundDisabled); - combobox->UpdateBorder(); - }, - base::Unretained(this))); - } + // TODO(crbug.com/40250124): This setter should be removed and the behavior + // made default when ChromeRefresh2023 is finalized. + SetEventHighlighting(true); + enabled_changed_subscription_ = AddEnabledChangedCallback(base::BindRepeating( + [](Combobox* combobox) { + combobox->SetBackgroundColorId( + combobox->GetEnabled() ? ui::kColorComboboxBackground + : ui::kColorComboboxBackgroundDisabled); + combobox->UpdateBorder(); + }, + base::Unretained(this))); // A layer is applied to make sure that canvas bounds are snapped to pixel // boundaries (for the sake of drawing the arrow). SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); - if (features::IsChromeRefresh2023()) { - views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), - GetCornerRadius()); - } + views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), + GetCornerRadius()); SetAccessibilityProperties(ax::mojom::Role::kComboBoxSelect); } @@ -568,23 +558,15 @@ } void Combobox::UpdateBorder() { - if (features::IsChromeRefresh2023()) { - if (!GetEnabled()) { - SetBorder(nullptr); - return; - } - SetBorder(CreateThemedRoundedRectBorder( - kBorderThickness, GetCornerRadius(), - invalid_ - ? ui::kColorAlertHighSeverity - : border_color_id_.value_or(ui::kColorComboboxContainerOutline))); - } else { - auto border = std::make_unique<FocusableBorder>(); - border->SetColorId(invalid_ ? ui::kColorAlertHighSeverity - : border_color_id_.value_or( - ui::kColorFocusableBorderUnfocused)); - SetBorder(std::move(border)); + if (!GetEnabled()) { + SetBorder(nullptr); + return; } + SetBorder(CreateThemedRoundedRectBorder( + kBorderThickness, GetCornerRadius(), + invalid_ + ? ui::kColorAlertHighSeverity + : border_color_id_.value_or(ui::kColorComboboxContainerOutline))); } void Combobox::AdjustBoundsForRTLUI(gfx::Rect* rect) const {
diff --git a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc index 7e4d033..92f99ff 100644 --- a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc +++ b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -371,11 +371,6 @@ EXPECT_TRUE(IsTextfieldFocused()); SendKeyEvent(ui::VKEY_TAB); EXPECT_FALSE(IsTextfieldFocused()); - // In Chrome Refresh the drop down arrow will behave more like a normal button - // and therefore will be focusable. - if (!features::IsChromeRefresh2023()) { - EXPECT_TRUE(dummy_focusable_view_->HasFocus()); - } WaitForMenuClosureAnimation(); EXPECT_FALSE(IsMenuOpen()); }
diff --git a/ui/views/controls/focus_ring.cc b/ui/views/controls/focus_ring.cc index c2db104..8799d7a 100644 --- a/ui/views/controls/focus_ring.cc +++ b/ui/views/controls/focus_ring.cc
@@ -374,7 +374,7 @@ // move the focus ring away from the host. If those places want to outset the // focus ring in the chrome refresh style, they need to be audited separately // with UX. - return features::IsChromeRefresh2023() && !outset_focus_ring_disabled_ && + return !outset_focus_ring_disabled_ && halo_inset_ == FocusRing::kDefaultHaloInset; }
diff --git a/ui/views/controls/focusable_border.cc b/ui/views/controls/focusable_border.cc index 6479325e..bd98936 100644 --- a/ui/views/controls/focusable_border.cc +++ b/ui/views/controls/focusable_border.cc
@@ -26,10 +26,8 @@ namespace views { -FocusableBorder::FocusableBorder(bool should_scale) - : insets_(kInsetSize), - corner_radius_(FocusRing::kDefaultCornerRadiusDp), - should_scale_(should_scale) {} +FocusableBorder::FocusableBorder() + : insets_(kInsetSize), corner_radius_(FocusRing::kDefaultCornerRadiusDp) {} FocusableBorder::~FocusableBorder() = default; @@ -45,7 +43,7 @@ gfx::ScopedCanvas scoped(canvas); const float dsf = canvas->UndoDeviceScaleFactor(); - const float kStrokeWidth = should_scale_ ? dsf : 1.0f; + const float kStrokeWidth = dsf; flags.setStrokeWidth(kStrokeWidth); // Scale the rect and snap to pixel boundaries.
diff --git a/ui/views/controls/focusable_border.h b/ui/views/controls/focusable_border.h index 0f5958f1..e43df7c 100644 --- a/ui/views/controls/focusable_border.h +++ b/ui/views/controls/focusable_border.h
@@ -21,7 +21,7 @@ // A Border class to draw a focused border around a field (e.g textfield). class VIEWS_EXPORT FocusableBorder : public Border { public: - explicit FocusableBorder(bool should_scale = false); + FocusableBorder(); FocusableBorder(const FocusableBorder&) = delete; FocusableBorder& operator=(const FocusableBorder&) = delete; @@ -50,7 +50,6 @@ gfx::Insets insets_; float corner_radius_; std::optional<ui::ColorId> override_color_id_; - bool should_scale_; }; } // namespace views
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc index 7bc2882..75eb167 100644 --- a/ui/views/controls/menu/menu_item_view.cc +++ b/ui/views/controls/menu/menu_item_view.cc
@@ -1443,10 +1443,7 @@ const Colors colors = CalculateColors(paint_as_selected); if (submenu_arrow_image_view_) { submenu_arrow_image_view_->SetImage(ui::ImageModel::FromVectorIcon( - features::IsChromeRefresh2023() - ? vector_icons::kSubmenuArrowChromeRefreshIcon - : vector_icons::kSubmenuArrowIcon, - colors.icon_color)); + vector_icons::kSubmenuArrowChromeRefreshIcon, colors.icon_color)); } MenuDelegate* delegate = GetDelegate(); if (type_ == Type::kCheckbox && delegate &&
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index c8a4f58..af34317 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -231,20 +231,18 @@ GetCornerRadius()); FocusRing::Install(this); FocusRing::Get(this)->SetOutsetFocusRingDisabled(true); - if (::features::IsChromeRefresh2023()) { - InkDropHost* ink_drop_host = - InkDrop::Install(this, std::make_unique<views::InkDropHost>(this)); - ink_drop_host->SetMode(InkDropHost::InkDropMode::ON); - ink_drop_host->SetLayerRegion(LayerRegion::kAbove); - ink_drop_host->SetHighlightOpacity(1.0f); - ink_drop_host->SetBaseColorCallback(base::BindRepeating( - [](Textfield* host) { - return host->HasFocus() ? SK_ColorTRANSPARENT - : host->GetColorProvider()->GetColor( - ui::kColorTextfieldHover); - }, - this)); - } + InkDropHost* ink_drop_host = + InkDrop::Install(this, std::make_unique<views::InkDropHost>(this)); + ink_drop_host->SetMode(InkDropHost::InkDropMode::ON); + ink_drop_host->SetLayerRegion(LayerRegion::kAbove); + ink_drop_host->SetHighlightOpacity(1.0f); + ink_drop_host->SetBaseColorCallback(base::BindRepeating( + [](Textfield* host) { + return host->HasFocus() ? SK_ColorTRANSPARENT + : host->GetColorProvider()->GetColor( + ui::kColorTextfieldHover); + }, + this)); #if !BUILDFLAG(IS_MAC) // Do not map accelerators on Mac. E.g. They might not reflect custom @@ -673,7 +671,7 @@ bool Textfield::OnMousePressed(const ui::MouseEvent& event) { const bool had_focus = HasFocus(); bool handled = controller_ && controller_->HandleMouseEvent(this, event); - if (::features::IsChromeRefresh2023() && InkDrop::Get(this)) { + if (InkDrop::Get(this)) { // When a textfield is pressed, the hover state should be off and the // background color should no longer have a mask. InkDrop::Get(this)->GetInkDrop()->SetHovered(false); @@ -2625,8 +2623,7 @@ if (!use_default_border_) { return; } - auto border = std::make_unique<views::FocusableBorder>( - ::features::IsChromeRefresh2023()); + auto border = std::make_unique<views::FocusableBorder>(); const LayoutProvider* provider = LayoutProvider::Get(); border->SetColorId(ui::kColorTextfieldOutline); border->SetInsets(gfx::Insets::TLBR(
diff --git a/ui/views/controls/tree/tree_view_unittest.cc b/ui/views/controls/tree/tree_view_unittest.cc index 0cad5eb5..96188d9 100644 --- a/ui/views/controls/tree/tree_view_unittest.cc +++ b/ui/views/controls/tree/tree_view_unittest.cc
@@ -17,6 +17,7 @@ #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h" #include "ui/base/models/tree_node_model.h" #include "ui/compositor/canvas_painter.h" @@ -1027,7 +1028,7 @@ // Do nothing when a valid node id is not provided. This can happen if the // actions target the owner view itself. tree()->SetSelectedNode(GetNodeByTitle("b")); - data.target_node_id = -1; + data.target_node_id = ui::kInvalidAXNodeID; data.action = ax::mojom::Action::kDoDefault; EXPECT_FALSE(tree()->HandleAccessibleAction(data)); EXPECT_EQ("b", GetActiveNodeTitle()); @@ -1047,7 +1048,7 @@ // Do not handle accessible actions when no node is selected. tree()->SetSelectedNode(nullptr); - data.target_node_id = -1; + data.target_node_id = ui::kInvalidAXNodeID; data.action = ax::mojom::Action::kDoDefault; EXPECT_FALSE(tree()->HandleAccessibleAction(data)); EXPECT_EQ(std::string(), GetActiveNodeTitle()); @@ -1156,7 +1157,7 @@ ClearAccessibilityEvents(); tree()->GetFocusManager()->ClearFocus(); tree()->SetSelectedNode(GetNodeByTitle("b")); - data.target_node_id = -1; + data.target_node_id = ui::kInvalidAXNodeID; data.action = ax::mojom::Action::kFocus; EXPECT_FALSE(tree()->HandleAccessibleAction(data)); EXPECT_FALSE(tree()->HasFocus()); @@ -1177,7 +1178,7 @@ static_cast<TestNode*>(empty_model.GetRoot())->SetTitle(u"root"); tree()->SetModel(&empty_model); tree()->SetRootShown(false); - data.target_node_id = -1; + data.target_node_id = ui::kInvalidAXNodeID; data.action = ax::mojom::Action::kFocus; EXPECT_TRUE(tree()->HandleAccessibleAction(data)); EXPECT_TRUE(tree()->HasFocus());
diff --git a/ui/webui/resources/cr_components/commerce/shopping_service.mojom b/ui/webui/resources/cr_components/commerce/shopping_service.mojom index a8954a9..696114d 100644 --- a/ui/webui/resources/cr_components/commerce/shopping_service.mojom +++ b/ui/webui/resources/cr_components/commerce/shopping_service.mojom
@@ -25,9 +25,7 @@ // Direct link to the product image. url.mojom.Url image_url; - // Direct link to the product page. Right now this is - // only used to fetch site favicon in case image_url - // is not available. + // Direct link to the product page. url.mojom.Url product_url; // Price as shown in the page. This should include
diff --git a/ui/webui/resources/tools/codemods/lit_migration_templates.mjs b/ui/webui/resources/tools/codemods/lit_migration_templates.mjs index c5dd93e..8a03d5f 100644 --- a/ui/webui/resources/tools/codemods/lit_migration_templates.mjs +++ b/ui/webui/resources/tools/codemods/lit_migration_templates.mjs
@@ -27,11 +27,22 @@ const LISTENER_BINDING_REGEX = /on-(?<eventName>[a-zA-Z-]+)="(?<listenerName>[a-zA-Z_]+)"/g; +// Regular expression to parse 2-way bindings like value="{{myValue_}}", +// and extract 'value' and 'myValue_' into captured groups for further +// processing. +const LISTENER_BIDNING_TWO_WAY_REGEX = + /(?<childProp>[a-z-]+)="\{\{(?<parentProp>[a-zA-Z_]+)\}\}"/g; + // Regular expression to extract any "${this.foo}" ocurrences in the HTML // template, referring to TS methods or member variables. const TS_REFERENCE_REGEX = /"\$\{this\.(?<reference>[a-zA-Z_]+)\}"/g; +// Replaces part of a string with a the provided replacement string. +function replaceRange(string, start, end, replacement) { + return string.substring(0, start) + replacement + string.substring(end); +} + function processFile(file) { const basename = path.basename(file, '.ts'); const tsFile = path.join(path.dirname(file), basename + '.ts'); @@ -56,17 +67,42 @@ return `@${groups.eventName}="\${this.${groups.listenerName}}"`; }); - // Step 4: Update property access syntax in HTML template + // Step 4: Update property access syntax in HTML template (1-way bindings) htmlContent = htmlContent.replaceAll(/\[\[!item/g, () => '${!item'); htmlContent = htmlContent.replaceAll(/\[\[item/g, () => '${item'); htmlContent = htmlContent.replaceAll(/\[\[!/g, () => '${!this.'); htmlContent = htmlContent.replaceAll(/\[\[/g, () => '${this.'); htmlContent = htmlContent.replaceAll(/\]\]/g, () => '}'); - // Step 5: Write updated HTML content to disk + // Step 5: Update property access syntax in HTML template (2-way bindings) + const matches = Array.from(htmlContent.matchAll(LISTENER_BIDNING_TWO_WAY_REGEX)); + // Reverse the order so that the character indices don't get messed up after + // modifying the original string, effectively processing the matches from the + // end of the string to the start. + matches.reverse(); + + // For each match, change + // value="{{myValue_}}" + // to + // value="${this.myValue_}" @value-changed="${this.onMyValueChanged_}" + for (let i = 0; i < matches.length; i++) { + const g = matches[i].groups; + let listenerPart = + g['parentProp'].charAt(0).toUpperCase() + g['parentProp'].slice(1); + listenerPart = listenerPart.replace('_', ''); + const listener = + `@${g['childProp']}-changed="\${this.on${listenerPart}Changed_}"` + const binding = matches[i][0].replace("{{", "${this.").replace("}}", "}"); + const start = matches[i].index; + const end = matches[i].index + matches[i][0].length; + htmlContent = + replaceRange(htmlContent, start, end, `${binding} ${listener}`); + } + + // Step 6: Write updated HTML content to disk fs.writeFileSync(htmlFile, htmlContent, 'utf8'); - // Step 6: Extract all methods/variables being referenced from the template + // Step 7: Extract all methods/variables being referenced from the template // and if they are 'private' change them to 'protected'. const references = Array.from( htmlContent.matchAll(TS_REFERENCE_REGEX)).map(m => m[1]); @@ -75,7 +111,7 @@ for (const ref of references) { tsContent = tsContent.replace(`private ${ref}`, `protected ${ref}`); } - // Step 7: Write updated TS content to disk + // Step 7b: Write updated TS content to disk. fs.writeFileSync(tsFile, tsContent, 'utf8'); } }
diff --git a/v8 b/v8 index 2a06d4e..dbccf56 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 2a06d4e3534debe1294744c208e85d8c4f06d579 +Subproject commit dbccf5638033c2f65fa8726313050ddecadda427