diff --git a/BUILD.gn b/BUILD.gn index 965efcf..3d036c1 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1195,7 +1195,6 @@ } data = [ - "$root_out_dir/args.gn", "//build/skia_gold_common/", "//testing/scripts/common.py", "//testing/scripts/run_isolated_script_test.py", @@ -1260,6 +1259,9 @@ _common_web_test_args += [ "--timeout-ms=12000" ] } } + if (is_chrome_branded) { + _common_web_test_args += [ "--chrome-branded" ] + } if (is_android) { _common_web_test_args += [
diff --git a/DEPS b/DEPS index 0ace6e783..a647221 100644 --- a/DEPS +++ b/DEPS
@@ -241,7 +241,7 @@ # # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab - 'lacros_sdk_version': '15691.0.0', + 'lacros_sdk_version': '15692.0.0', # Generate location tag metadata to include in tests result data uploaded # to ResultDB. This isn't needed on some configs and the tool that generates @@ -302,7 +302,7 @@ # 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': '244adce210fdea03ebaf44ba20db144ccd668ae2', + 'src_internal_revision': '63855671b456f868bcdbce8a29290156fca3dc6b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. @@ -310,11 +310,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '225e4baa97487bad251fffec7f5460845c394f6c', + 'v8_revision': '30e826391ad51011e6829dde5a1b246dd1588f19', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'aaafecee56791dc8431d0446403f25e73f00b59c', + 'angle_revision': 'd696b40fad24202791ecb40d9ea13a2ab4be15cf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -377,7 +377,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '2823d8f8bea1f1324448fcc2423200b9ad7939ed', + 'catapult_revision': 'd9aa189385c2a4ec17be2f88291a6cd826ca62fd', # 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. @@ -397,7 +397,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': '2979e07e0a704c3ada139cb6f2757c56c61bf73e', + 'devtools_frontend_revision': '2c58d1b91203d9e638f50506b6d9532189d3a671', # 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. @@ -441,7 +441,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavif # and whatever else without interference from each other. - 'libavif_revision': '7845153645cfe245de5add94fb07c227c2d16402', + 'libavif_revision': '286f1b9a66e7f05ac5a32510e4c08ecd03f0ba0f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavifinfo # and whatever else without interference from each other. @@ -477,7 +477,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libunwind_revision': '85df028e4c5e8a3eaa38fe75e0d78157bee2d668', + 'libunwind_revision': 'bbe2764382995e4ec9a8c26c50018afc9520ea4f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -821,7 +821,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '6af5e217cc69a0ce9ad30b506c5e9be6897b5d46', + 'e4d96a442aa336f431e66b1a29d61da34f59bcb6', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1221,7 +1221,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '484c659ff02abe8b427ceec35911c914b794d59d', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'd567cf29ad32e9aaeac80a6f7f69a978c28c2aa0', 'condition': 'checkout_src_internal', }, @@ -1871,7 +1871,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '2979ce07231ba66e06675c83e1cdd3c483165820', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'ad3e66138dff54063ad7bbef8cf9c365b89e1d3e', + Var('webrtc_git') + '/src.git' + '@' + 'ee46340054fac6072259be0d7f43263299d9b88b', # 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. @@ -1994,7 +1994,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'wl5GqDnJVGCBcKf_tX9aIrqt29ey4_SF8PyBizwZRdMC', + 'version': 'b76WQQ2q302v6w8T7sdWHno4IKAuwuxVIL6auTc3dcUC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3786,7 +3786,7 @@ # Dependencies from src_internal 'src/chromeos/assistant/internal': { 'url': Var('chrome_git') + '/chrome/assistant.git' + '@' + - '10ab734474bc4ca9387c874f748cdd60c3b212f4', + '610eee397e5729aae646eb66551cd00df2228c6d', 'condition': 'checkout_src_internal and checkout_chromeos', }, @@ -3951,7 +3951,7 @@ 'src/components/autofill/core/browser/form_parsing/internal_resources': { 'url': Var('chrome_git') + '/chrome/components/autofill_regex_patterns.git' + '@' + - 'a28833de8a3c64abc9afc0158b79b14cf2ff8348', + 'f4dc712c172a20560d4b834b8d42bdf751ec0bef', 'condition': 'checkout_src_internal', }, @@ -4004,7 +4004,7 @@ 'src/components/test/data/autofill/heuristics-json/internal': { 'url': Var('chrome_git') + '/chrome/test/autofill/structured_forms.git' + '@' + - '2a35e0b28ccdd4298cc12ba2ef477f9e1320c711', + '2b834f173d97ca859a49701c51dadb6f7cc7387f', 'condition': 'checkout_chromium_autofill_test_dependencies', }, @@ -4028,7 +4028,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '0715482852883c643a16a68c3f6c01965c7e0ab2', + 'a71771e41c4c362860b19a619ce1ba6b018903b1', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 0dccaeb..b73738dc 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1892,8 +1892,10 @@ '|chrome/test/data/webui/search_engine_choice/'\ '|components/resources/default_100_percent/search_engine_choice/'\ '|components/resources/default_200_percent/search_engine_choice/'\ - '|components/search_engines/search_engine_choice_utils.cc'\ + '|components/search_engines/generated_marketing_snippets.cc'\ + '|components/search_engines/search_engine_choice_.cc'\ '|components/search_engine_choice_strings.grdp'\ + '|components/search_engine_descriptions_strings.grd'\ '|ios/chrome/browser/providers/signin/chromium_choice.mm'\ '|ios/chrome/test/providers/signin/test_choice.mm'\ '|ios/public/provider/chrome/browser/signin/choice_api.h'\ @@ -2437,10 +2439,12 @@ 'assistive': ['croissant-eng+reviews@chromium.org'], 'attribution_reporting': ['apaseltiner+watch@chromium.org'], 'audio_service': ['marinaciocea+watch@chromium.org', - 'olka+watch@chromium.org'], + 'olka+watch@chromium.org', + 'zhangwenyu+watch@google.com'], 'audio_settings': ['gordonseto+audio-settings-watch@google.com', 'michaelcheco+audio-settings-watch@google.com', - 'owenzhang+audio-settings-watch@google.com'], + 'owenzhang+audio-settings-watch@google.com', + 'zhangwenyu+audio-settings-watch@google.com'], 'aura': ['sadrul@chromium.org'], 'aura_compositor': ['jbauman+watch@chromium.org'], 'autofill_payments': ['armalhotra+autofillwatch@google.com',
diff --git a/android_webview/browser/BUILD.gn b/android_webview/browser/BUILD.gn index 91af897..38fb9e9f 100644 --- a/android_webview/browser/BUILD.gn +++ b/android_webview/browser/BUILD.gn
@@ -237,6 +237,7 @@ "//components/embedder_support/origin_trials", "//components/favicon_base:favicon_base", "//components/flags_ui", + "//components/history/core/browser:browser", "//components/keyed_service/content", "//components/optimization_guide/core:bloomfilter", "//components/profile_metrics",
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS index 70e92d6..b651225c 100644 --- a/android_webview/browser/DEPS +++ b/android_webview/browser/DEPS
@@ -22,6 +22,7 @@ "+components/favicon_base", "+components/flags_ui", "+components/heap_profiling", + "+components/history/core/browser", "+components/keyed_service/core", "+components/leveldb_proto/public", "+components/minidump_uploader",
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc index e877d23..e78b007 100644 --- a/android_webview/browser/aw_autofill_client.cc +++ b/android_webview/browser/aw_autofill_client.cc
@@ -21,7 +21,7 @@ #include "base/types/cxx23_to_underlying.h" #include "components/android_autofill/browser/android_autofill_manager.h" #include "components/android_autofill/browser/autofill_provider_android.h" -#include "components/autofill/core/browser/autofill_download_manager.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/payments/legal_message_line.h" #include "components/autofill/core/browser/ui/autofill_popup_delegate.h" #include "components/autofill/core/browser/ui/popup_item_ids.h" @@ -71,16 +71,19 @@ ->GetURLLoaderFactoryForBrowserProcess(); } -autofill::AutofillDownloadManager* AwAutofillClient::GetDownloadManager() { - if (autofill::AutofillProvider::is_download_manager_disabled_for_testing()) { +autofill::AutofillCrowdsourcingManager* +AwAutofillClient::GetCrowdsourcingManager() { + if (autofill::AutofillProvider:: + is_crowdsourcing_manager_disabled_for_testing()) { return nullptr; } - if (!download_manager_) { + if (!crowdsourcing_manager_) { // Lazy initialization to avoid virtual function calls in the constructor. - download_manager_ = std::make_unique<autofill::AutofillDownloadManager>( - this, GetChannel(), GetLogManager()); + crowdsourcing_manager_ = + std::make_unique<autofill::AutofillCrowdsourcingManager>( + this, GetChannel(), GetLogManager()); } - return download_manager_.get(); + return crowdsourcing_manager_.get(); } autofill::PersonalDataManager* AwAutofillClient::GetPersonalDataManager() {
diff --git a/android_webview/browser/aw_autofill_client.h b/android_webview/browser/aw_autofill_client.h index 0196d6cc..dc0ad557 100644 --- a/android_webview/browser/aw_autofill_client.h +++ b/android_webview/browser/aw_autofill_client.h
@@ -68,7 +68,7 @@ // AutofillClient: bool IsOffTheRecord() override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; - autofill::AutofillDownloadManager* GetDownloadManager() override; + autofill::AutofillCrowdsourcingManager* GetCrowdsourcingManager() override; autofill::PersonalDataManager* GetPersonalDataManager() override; autofill::AutocompleteHistoryManager* GetAutocompleteHistoryManager() override; @@ -162,7 +162,8 @@ // The current Autofill query values. std::vector<autofill::Suggestion> suggestions_; base::WeakPtr<autofill::AutofillPopupDelegate> delegate_; - std::unique_ptr<autofill::AutofillDownloadManager> download_manager_; + std::unique_ptr<autofill::AutofillCrowdsourcingManager> + crowdsourcing_manager_; #if DCHECK_IS_ON() bool use_android_autofill_manager_;
diff --git a/android_webview/browser/aw_field_trials.cc b/android_webview/browser/aw_field_trials.cc index 8df32de..f6b851c6 100644 --- a/android_webview/browser/aw_field_trials.cc +++ b/android_webview/browser/aw_field_trials.cc
@@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "base/metrics/persistent_histogram_allocator.h" #include "base/path_service.h" +#include "components/history/core/browser/features.h" #include "components/metrics/persistent_histograms.h" #include "components/safe_browsing/core/common/features.h" #include "content/public/common/content_features.h" @@ -103,5 +104,8 @@ // default on Android, but we need a slower ramp up on WebView). aw_feature_overrides.DisableFeature(::features::kPrefetchNewLimits); + // Disable Populating the VisitedLinkDatabase on WebView. + aw_feature_overrides.DisableFeature(history::kPopulateVisitedLinkDatabase); + aw_feature_overrides.RegisterOverrides(feature_list); }
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc index e78da6d1..825fb40 100644 --- a/android_webview/browser/cookie_manager.cc +++ b/android_webview/browser/cookie_manager.cc
@@ -205,8 +205,10 @@ base::android::BuildInfo::GetInstance()->target_sdk_version() < base::android::SDK_VERSION_R), cookie_store_client_thread_("CookieMonsterClient"), + cookie_store_backend_thread_("CookieMonsterBackend"), setting_new_mojo_cookie_manager_(false) { 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_) { @@ -320,15 +322,12 @@ DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence()); if (!cookie_store_) { - DCHECK(!cookie_store_created_); - cookie_store_backend_thread_.emplace("CookieMonsterBackend"); - cookie_store_backend_thread_->Start(); content::CookieStoreConfig cookie_config( cookie_store_path_, /* restore_old_session_cookies= */ true, /* persist_session_cookies= */ true); cookie_config.client_task_runner = cookie_store_task_runner_; cookie_config.background_task_runner = - cookie_store_backend_thread_->task_runner(); + cookie_store_backend_thread_.task_runner(); { base::AutoLock lock(allow_file_scheme_cookies_lock_); @@ -392,9 +391,6 @@ return; } - // Queue a flush for the temporary cookie store. This will be the last method - // call on the cookie store: any subsequent CookieManager calls will defer - // their tasks because setting_new_mojo_cookie_manager_ == true. GetCookieStore()->FlushStore(base::BindOnce( &CookieManager::SwapMojoCookieManagerAsync, base::Unretained(this), std::move(cookie_manager_remote), std::move(complete))); @@ -410,21 +406,6 @@ FROM_HERE, base::BindOnce(&CookieManager::ClearClientHintsCachedPerOriginMapIfNeeded, base::Unretained(this))); - if (cookie_store_created_) { - // This method is called after the flush-to-disk of the temporary cookie - // store has completed, but we still have the SQLite database open; we need - // to close this before anyone tries to use the new Mojo CookieManager, - // because the first time it's used it will open the SQLite database itself. - - // First, delete the cookie store. This will queue a task on the backend - // task runner to actually close the database. - cookie_store_.reset(); - - // Then, delete the backend task runner thread. This will block until the - // thread has drained its task queue and exited, which should be fast as we - // already flushed any pending writes. - cookie_store_backend_thread_ = std::nullopt; - } std::move(complete).Run(); // unblock content initialization RunPendingCookieTasks(); }
diff --git a/android_webview/browser/cookie_manager.h b/android_webview/browser/cookie_manager.h index 2414985..89ea066 100644 --- a/android_webview/browser/cookie_manager.h +++ b/android_webview/browser/cookie_manager.h
@@ -6,7 +6,6 @@ #define ANDROID_WEBVIEW_BROWSER_COOKIE_MANAGER_H_ #include <memory> -#include <optional> #include <vector> #include "base/android/jni_array.h" @@ -291,7 +290,7 @@ bool workaround_http_secure_cookies_; base::Thread cookie_store_client_thread_; - std::optional<base::Thread> cookie_store_backend_thread_; + base::Thread cookie_store_backend_thread_; scoped_refptr<base::SingleThreadTaskRunner> cookie_store_task_runner_; std::unique_ptr<net::CookieStore> cookie_store_;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java index bbb77719..3507a1f 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -405,7 +405,7 @@ }); mContentsClient = new AwAutofillTestClient(); TestThreadUtils.runOnUiThreadBlocking( - () -> AutofillProviderTestHelper.disableDownloadServerForTesting()); + () -> AutofillProviderTestHelper.disableCrowdsourcingForTesting()); mTestContainerView = mRule.createAwTestContainerViewOnMainSync( mContentsClient, false, new TestDependencyFactory());
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 19d02df..8c85f97 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -7202,21 +7202,20 @@ Keys, buttons, and more </message> - <!-- TODO(b/286930911): Translate strings for input device settings notifications. --> <!-- Input device settings notifications --> <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_ALT_RIGHT_CLICK" desc="The message shown to notify a user that the shortcut used to simulate a right-click using touchpad and keyboard has changed."> The right-click shortcut is updated to <ph name="LAUNCHER_KEY_NAME">$1<ex>launcher</ex></ph> key + click from alt + click </message> - <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_PERIPHERAL_CUSTOMIZATION_TITLE" translateable="false" desc="Notification title to tell users that the peripheral is customizable."> + <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_PERIPHERAL_CUSTOMIZATION_TITLE" desc="Notification title to tell users that the peripheral is customizable."> Customize your <ph name="PERIPHERAL_NAME">$1<ex>MX Anywhere</ex></ph> </message> - <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_MOUSE_CUSTOMIZATION" translateable="false" desc="The message shown to notify a user that the mouse is customizable in settings."> + <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_MOUSE_CUSTOMIZATION" desc="The message shown to notify a user that the mouse is customizable in settings."> <ph name="PERIPHERAL_NAME">$1<ex>MX Anywhere</ex></ph> is connected and ready to use. You can customize your mouse in Settings. </message> - <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_GRAPHICS_TABLET_CUSTOMIZATION" translateable="false" desc="The message shown to notify a user that the graphics tablet is customizable in settings."> + <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_GRAPHICS_TABLET_CUSTOMIZATION" desc="The message shown to notify a user that the graphics tablet is customizable in settings."> <ph name="PERIPHERAL_NAME">$1<ex>MX Anywhere</ex></ph> is connected and ready to use. You can customize your graphics tablet in Settings. </message> - <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_OPEN_SETTINGS_BUTTON" translateable="false" desc="Notification button text, if the user clicks on the button it will redirect them to the Settings App."> + <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_OPEN_SETTINGS_BUTTON" desc="Notification button text, if the user clicks on the button it will redirect them to the Settings App."> Open Settings </message> <message name="IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_LAUNCHER_RIGHT_CLICK" desc="The message shown to notify a user that the shortcut used to simulate a right-click using touchpad and keyboard has changed.">
diff --git a/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_GRAPHICS_TABLET_CUSTOMIZATION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_GRAPHICS_TABLET_CUSTOMIZATION.png.sha1 new file mode 100644 index 0000000..5552b59 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_GRAPHICS_TABLET_CUSTOMIZATION.png.sha1
@@ -0,0 +1 @@ +c5e6e072c6af948a2842fe3095549fa1bd62ac80 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_MOUSE_CUSTOMIZATION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_MOUSE_CUSTOMIZATION.png.sha1 new file mode 100644 index 0000000..63a6468 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_MOUSE_CUSTOMIZATION.png.sha1
@@ -0,0 +1 @@ +c15b9eb1d83ba8063a0c05de7c5f7082fe5e6e7f \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_OPEN_SETTINGS_BUTTON.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_OPEN_SETTINGS_BUTTON.png.sha1 new file mode 100644 index 0000000..63a6468 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_OPEN_SETTINGS_BUTTON.png.sha1
@@ -0,0 +1 @@ +c15b9eb1d83ba8063a0c05de7c5f7082fe5e6e7f \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_PERIPHERAL_CUSTOMIZATION_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_PERIPHERAL_CUSTOMIZATION_TITLE.png.sha1 new file mode 100644 index 0000000..63a6468 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DEVICE_SETTINGS_NOTIFICATIONS_PERIPHERAL_CUSTOMIZATION_TITLE.png.sha1
@@ -0,0 +1 @@ +c15b9eb1d83ba8063a0c05de7c5f7082fe5e6e7f \ No newline at end of file
diff --git a/ash/child_accounts/COMMON_METADATA b/ash/child_accounts/COMMON_METADATA new file mode 100644 index 0000000..f095129 --- /dev/null +++ b/ash/child_accounts/COMMON_METADATA
@@ -0,0 +1,15 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +# ChromeOS FamilyExperiences team +team_email: "cros-families-eng@google.com" +os: CHROME_OS +buganizer { + # ChromeOS > Software > Family > Parental controls + component_id: 1090157 +}
diff --git a/ash/child_accounts/DIR_METADATA b/ash/child_accounts/DIR_METADATA new file mode 100644 index 0000000..14cf923 --- /dev/null +++ b/ash/child_accounts/DIR_METADATA
@@ -0,0 +1 @@ +mixins: "//ash/child_accounts/COMMON_METADATA"
diff --git a/ash/child_accounts/OWNERS b/ash/child_accounts/OWNERS index 48a16ac..1548080 100644 --- a/ash/child_accounts/OWNERS +++ b/ash/child_accounts/OWNERS
@@ -1,2 +1,2 @@ agawronska@chromium.org -llin@chromium.org +courtneywong@chromium.org
diff --git a/ash/clipboard/views/clipboard_history_bitmap_item_view.cc b/ash/clipboard/views/clipboard_history_bitmap_item_view.cc index 2f8dbe7..ee31142 100644 --- a/ash/clipboard/views/clipboard_history_bitmap_item_view.cc +++ b/ash/clipboard/views/clipboard_history_bitmap_item_view.cc
@@ -50,6 +50,8 @@ // rendering. Expected to transition at most once in its lifetime. class FadeImageView : public views::ImageView, public ui::ImplicitAnimationObserver { + METADATA_HEADER(FadeImageView, views::ImageView) + public: FadeImageView( base::RepeatingCallback<const ClipboardHistoryItem*()> item_resolver, @@ -148,6 +150,9 @@ base::CallbackListSubscription display_image_updated_subscription_; }; +BEGIN_METADATA(FadeImageView, views::ImageView) +END_METADATA + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -155,8 +160,9 @@ class ClipboardHistoryBitmapItemView::BitmapContentsView : public ClipboardHistoryBitmapItemView::ContentsView { + METADATA_HEADER(BitmapContentsView, ContentsView) + public: - METADATA_HEADER(BitmapContentsView); explicit BitmapContentsView(ClipboardHistoryBitmapItemView* container) : container_(container) { views::Builder<views::View>(this)
diff --git a/ash/clipboard/views/clipboard_history_bitmap_item_view.h b/ash/clipboard/views/clipboard_history_bitmap_item_view.h index 38981c6e..ecc6ae4 100644 --- a/ash/clipboard/views/clipboard_history_bitmap_item_view.h +++ b/ash/clipboard/views/clipboard_history_bitmap_item_view.h
@@ -15,8 +15,9 @@ // The menu item showing a bitmap. class ClipboardHistoryBitmapItemView : public ClipboardHistoryItemView { + METADATA_HEADER(ClipboardHistoryBitmapItemView, ClipboardHistoryItemView) + public: - METADATA_HEADER(ClipboardHistoryBitmapItemView); ClipboardHistoryBitmapItemView(const base::UnguessableToken& item_id, const ClipboardHistory* clipboard_history, views::MenuItemView* container);
diff --git a/ash/clipboard/views/clipboard_history_delete_button.h b/ash/clipboard/views/clipboard_history_delete_button.h index 6fe4190..1d9fafb 100644 --- a/ash/clipboard/views/clipboard_history_delete_button.h +++ b/ash/clipboard/views/clipboard_history_delete_button.h
@@ -16,9 +16,9 @@ // The button to delete the menu item and its corresponding clipboard data. class ClipboardHistoryDeleteButton : public views::ImageButton, public views::ViewTargeterDelegate { - public: - METADATA_HEADER(ClipboardHistoryDeleteButton); + METADATA_HEADER(ClipboardHistoryDeleteButton, views::ImageButton) + public: ClipboardHistoryDeleteButton(ClipboardHistoryItemView* listener, const std::u16string& item_text); ClipboardHistoryDeleteButton(const ClipboardHistoryDeleteButton& rhs) =
diff --git a/ash/clipboard/views/clipboard_history_item_view.cc b/ash/clipboard/views/clipboard_history_item_view.cc index 09c8db2c..3d3b9da 100644 --- a/ash/clipboard/views/clipboard_history_item_view.cc +++ b/ash/clipboard/views/clipboard_history_item_view.cc
@@ -111,8 +111,9 @@ class ClipboardHistoryItemView::DisplayView : public views::BoxLayoutView, public views::ViewTargeterDelegate { + METADATA_HEADER(DisplayView, views::BoxLayoutView) + public: - METADATA_HEADER(DisplayView); explicit DisplayView(ClipboardHistoryItemView* container) : container_(container) { SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
diff --git a/ash/clipboard/views/clipboard_history_item_view.h b/ash/clipboard/views/clipboard_history_item_view.h index 72dd218..6e9e0e0 100644 --- a/ash/clipboard/views/clipboard_history_item_view.h +++ b/ash/clipboard/views/clipboard_history_item_view.h
@@ -23,8 +23,9 @@ // The base class for menu items of the clipboard history menu. class ASH_EXPORT ClipboardHistoryItemView : public views::View { + METADATA_HEADER(ClipboardHistoryItemView, views::View) + public: - METADATA_HEADER(ClipboardHistoryItemView); static std::unique_ptr<ClipboardHistoryItemView> CreateFromClipboardHistoryItem(const base::UnguessableToken& item_id, const ClipboardHistory* clipboard_history, @@ -74,8 +75,9 @@ // clipboard history refresh is enabled, a `ContentsView` observes its sibling // `ClipboardHistoryDeleteButton` so that it knows when to clip its contents. class ContentsView : public views::View, public views::ViewObserver { + METADATA_HEADER(ContentsView, views::View) + public: - METADATA_HEADER(ContentsView); ContentsView(); ContentsView(const ContentsView& rhs) = delete; ContentsView& operator=(const ContentsView& rhs) = delete;
diff --git a/ash/clipboard/views/clipboard_history_label.h b/ash/clipboard/views/clipboard_history_label.h index 4a5e3164..79bc430 100644 --- a/ash/clipboard/views/clipboard_history_label.h +++ b/ash/clipboard/views/clipboard_history_label.h
@@ -12,9 +12,9 @@ // The text label used by the clipboard history menu. class ClipboardHistoryLabel : public views::Label { - public: - METADATA_HEADER(ClipboardHistoryLabel); + METADATA_HEADER(ClipboardHistoryLabel, views::Label) + public: ClipboardHistoryLabel(const std::u16string& text, gfx::ElideBehavior elide_behavior, size_t max_lines);
diff --git a/ash/clipboard/views/clipboard_history_main_button.h b/ash/clipboard/views/clipboard_history_main_button.h index e8914c2..093efcd 100644 --- a/ash/clipboard/views/clipboard_history_main_button.h +++ b/ash/clipboard/views/clipboard_history_main_button.h
@@ -14,8 +14,9 @@ // The view responding to mouse click or gesture tap events. class ClipboardHistoryMainButton : public views::Button { + METADATA_HEADER(ClipboardHistoryMainButton, views::Button) + public: - METADATA_HEADER(ClipboardHistoryMainButton); explicit ClipboardHistoryMainButton(ClipboardHistoryItemView* container); ClipboardHistoryMainButton(const ClipboardHistoryMainButton& rhs) = delete; ClipboardHistoryMainButton& operator=(const ClipboardHistoryMainButton& rhs) =
diff --git a/ash/clipboard/views/clipboard_history_text_item_view.cc b/ash/clipboard/views/clipboard_history_text_item_view.cc index 5bc012c..5b28e74 100644 --- a/ash/clipboard/views/clipboard_history_text_item_view.cc +++ b/ash/clipboard/views/clipboard_history_text_item_view.cc
@@ -50,8 +50,9 @@ class ClipboardHistoryTextItemView::TextContentsView : public ClipboardHistoryTextItemView::ContentsView { + METADATA_HEADER(TextContentsView, ContentsView) + public: - METADATA_HEADER(TextContentsView); explicit TextContentsView(const ClipboardHistoryTextItemView* container) { const auto* item = container->GetClipboardHistoryItem(); const auto display_text_elide_behavior = GetDisplayTextElideBehavior(item);
diff --git a/ash/clipboard/views/clipboard_history_text_item_view.h b/ash/clipboard/views/clipboard_history_text_item_view.h index eaa7ca4..d232a2fc 100644 --- a/ash/clipboard/views/clipboard_history_text_item_view.h +++ b/ash/clipboard/views/clipboard_history_text_item_view.h
@@ -18,15 +18,16 @@ // The menu item showing the plain text. class ClipboardHistoryTextItemView : public ClipboardHistoryItemView { + METADATA_HEADER(ClipboardHistoryTextItemView, ClipboardHistoryItemView) + public: - METADATA_HEADER(ClipboardHistoryTextItemView); ClipboardHistoryTextItemView(const base::UnguessableToken& item_id, const ClipboardHistory* clipboard_history, views::MenuItemView* container); ClipboardHistoryTextItemView(const ClipboardHistoryTextItemView& rhs) = delete; - ClipboardHistoryItemView& operator=(const ClipboardHistoryTextItemView& rhs) = - delete; + ClipboardHistoryTextItemView& operator=( + const ClipboardHistoryTextItemView& rhs) = delete; ~ClipboardHistoryTextItemView() override; protected:
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index d33117da..021e231 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -759,7 +759,7 @@ // side wait time. BASE_FEATURE(kEnableGetDebugdLogsInParallel, "EnableGetDebugdLogsInParallel", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables setting the device hostname. BASE_FEATURE(kEnableHostnameSetting, @@ -781,7 +781,7 @@ // When enabled, it will make login WebUI loaded only before showing it. BASE_FEATURE(kEnableLazyLoginWebUILoading, "EnableLazyLoginWebUILoading", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables LocalSearchService to be initialized. BASE_FEATURE(kEnableLocalSearchService,
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc index 266f6d2..66b4a5e 100644 --- a/ash/constants/ash_switches.cc +++ b/ash/constants/ash_switches.cc
@@ -1115,6 +1115,11 @@ kCryptohomeUseAuthSession); } +bool ShouldRestoreKeyOnLockScreen() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + kRestoreKeyOnLockScreen); +} + bool IsCellularFirstDevice() { return base::CommandLine::ForCurrentProcess()->HasSwitch(kCellularFirst); }
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h index 74e6239..4dfa7937 100644 --- a/ash/constants/ash_switches.h +++ b/ash/constants/ash_switches.h
@@ -376,6 +376,10 @@ // cryptohomed instead of explicitly authorizing each operation. COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAuthSessionCryptohomeEnabled(); +// Returns true if the cryptohome filesystem keyset is evicted and needs to be +// restored on lock screen. +COMPONENT_EXPORT(ASH_CONSTANTS) bool ShouldRestoreKeyOnLockScreen(); + // Returns true if this is a Cellular First device. COMPONENT_EXPORT(ASH_CONSTANTS) bool IsCellularFirstDevice();
diff --git a/ash/glanceables/glanceables_pixeltest.cc b/ash/glanceables/glanceables_pixeltest.cc index 63b3067..243a4ce 100644 --- a/ash/glanceables/glanceables_pixeltest.cc +++ b/ash/glanceables/glanceables_pixeltest.cc
@@ -191,7 +191,7 @@ ASSERT_TRUE(GetDateTray()->is_active()); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( - "glanceables_calendar_height", /*revision_number=*/0, + "glanceables_calendar_height", /*revision_number=*/1, GetGlanceableTrayBubble()->GetBubbleView())); }
diff --git a/ash/public/cpp/child_accounts/DIR_METADATA b/ash/public/cpp/child_accounts/DIR_METADATA index eff0b992..14cf923 100644 --- a/ash/public/cpp/child_accounts/DIR_METADATA +++ b/ash/public/cpp/child_accounts/DIR_METADATA
@@ -1 +1 @@ -mixins: "//chrome/browser/ash/child_accounts/COMMON_METADATA" \ No newline at end of file +mixins: "//ash/child_accounts/COMMON_METADATA"
diff --git a/ash/public/cpp/child_accounts/OWNERS b/ash/public/cpp/child_accounts/OWNERS index 0bf7e39..c0d5272 100644 --- a/ash/public/cpp/child_accounts/OWNERS +++ b/ash/public/cpp/child_accounts/OWNERS
@@ -1,3 +1 @@ -agawronska@chromium.org -courtneywong@chromium.org -llin@chromium.org +file:///ash/child_accounts/OWNERS
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_item_impl.cc b/ash/public/cpp/external_arc/message_center/arc_notification_item_impl.cc index 6b32443..82eeb13 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_item_impl.cc +++ b/ash/public/cpp/external_arc/message_center/arc_notification_item_impl.cc
@@ -120,11 +120,8 @@ message_center::SettingsButtonHandler::NONE; } - bool is_snooze_supported = - (data->flags && (data->flags->value & - arc::mojom::ArcNotificationFlags::SUPPORT_SNOOZE) != 0); - rich_data.should_show_snooze_button = - is_snooze_supported && !is_setting_shown; + // TODO(b/313723218): Enable snooze on Chrome rendered ARC notifications. + rich_data.should_show_snooze_button = false; message_center::NotifierId notifier_id( message_center::NotifierType::ARC_APPLICATION,
diff --git a/ash/system/holding_space/downloads_section.cc b/ash/system/holding_space/downloads_section.cc index 3c0bc30..46f0cae1 100644 --- a/ash/system/holding_space/downloads_section.cc +++ b/ash/system/holding_space/downloads_section.cc
@@ -115,7 +115,7 @@ raw_ptr<views::ImageView, ExperimentalAsh> chevron_ = nullptr; }; -BEGIN_METADATA(Header) +BEGIN_METADATA(Header, views::Button) END_METADATA } // namespace @@ -128,10 +128,6 @@ DownloadsSection::~DownloadsSection() = default; -const char* DownloadsSection::GetClassName() const { - return "DownloadsSection"; -} - std::unique_ptr<views::View> DownloadsSection::CreateHeader() { auto header = std::make_unique<Header>(); header->SetPaintToLayer(); @@ -153,7 +149,7 @@ return std::make_unique<HoldingSpaceItemChipView>(delegate(), item); } -BEGIN_METADATA(DownloadsSection) +BEGIN_METADATA(DownloadsSection, HoldingSpaceItemViewsSection) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/downloads_section.h b/ash/system/holding_space/downloads_section.h index d73a718..f95b9c7 100644 --- a/ash/system/holding_space/downloads_section.h +++ b/ash/system/holding_space/downloads_section.h
@@ -23,7 +23,6 @@ ~DownloadsSection() override; // HoldingSpaceItemViewsSection: - const char* GetClassName() const override; std::unique_ptr<views::View> CreateHeader() override; std::unique_ptr<views::View> CreateContainer() override; std::unique_ptr<HoldingSpaceItemView> CreateView(
diff --git a/ash/system/holding_space/holding_space_drag_util.cc b/ash/system/holding_space/holding_space_drag_util.cc index d832a24..8e3d323 100644 --- a/ash/system/holding_space/holding_space_drag_util.cc +++ b/ash/system/holding_space/holding_space_drag_util.cc
@@ -188,7 +188,7 @@ const raw_ptr<const ui::ColorProvider, ExperimentalAsh> color_provider_; }; -BEGIN_METADATA(DragImageItemView) +BEGIN_METADATA(DragImageItemView, views::View) END_METADATA // DragImageItemChipView ------------------------------------------------------- @@ -254,7 +254,7 @@ } }; -BEGIN_METADATA(DragImageItemChipView) +BEGIN_METADATA(DragImageItemChipView, DragImageItemView) END_METADATA // DragImageItemScreenCaptureView ---------------------------------------------- @@ -296,7 +296,7 @@ } }; -BEGIN_METADATA(DragImageItemScreenCaptureView) +BEGIN_METADATA(DragImageItemScreenCaptureView, DragImageItemView) END_METADATA // DragImageOverflowBadge ------------------------------------------------------ @@ -356,7 +356,7 @@ const raw_ptr<const ui::ColorProvider, ExperimentalAsh> color_provider_; }; -BEGIN_METADATA(DragImageOverflowBadge) +BEGIN_METADATA(DragImageOverflowBadge, views::View) END_METADATA // DragImageView --------------------------------------------------------------- @@ -507,7 +507,7 @@ raw_ptr<views::View, ExperimentalAsh> drag_image_overflow_badge_ = nullptr; }; -BEGIN_METADATA(DragImageView) +BEGIN_METADATA(DragImageView, views::View) END_METADATA } // namespace
diff --git a/ash/system/holding_space/holding_space_item_chip_view.cc b/ash/system/holding_space/holding_space_item_chip_view.cc index 9cb0583f..8a71e5e0 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.cc +++ b/ash/system/holding_space/holding_space_item_chip_view.cc
@@ -78,6 +78,8 @@ // ObservableRoundedImageView -------------------------------------------------- class ObservableRoundedImageView : public RoundedImageView { + METADATA_HEADER(ObservableRoundedImageView, RoundedImageView) + public: ObservableRoundedImageView() = default; ObservableRoundedImageView(const ObservableRoundedImageView&) = delete; @@ -101,6 +103,9 @@ BoundsChangedCallback bounds_changed_callback_; }; +BEGIN_METADATA(ObservableRoundedImageView, RoundedImageView) +END_METADATA + BEGIN_VIEW_BUILDER(/*no export*/, ObservableRoundedImageView, RoundedImageView) VIEW_BUILDER_PROPERTY(ObservableRoundedImageView::BoundsChangedCallback, BoundsChangedCallback) @@ -109,6 +114,8 @@ // PaintCallbackLabel ---------------------------------------------------------- class PaintCallbackLabel : public views::Label { + METADATA_HEADER(PaintCallbackLabel, views::Label) + public: PaintCallbackLabel() = default; PaintCallbackLabel(const PaintCallbackLabel&) = delete; @@ -142,6 +149,9 @@ Callback callback_; }; +BEGIN_METADATA(PaintCallbackLabel, views::Label) +END_METADATA + BEGIN_VIEW_BUILDER(/*no export*/, PaintCallbackLabel, views::Label) VIEW_BUILDER_PROPERTY(PaintCallbackLabel::Callback, Callback) VIEW_BUILDER_PROPERTY(TypographyToken, Style) @@ -152,6 +162,8 @@ // ProgressIndicatorView ------------------------------------------------------- class ProgressIndicatorView : public views::View { + METADATA_HEADER(ProgressIndicatorView, views::View) + public: ProgressIndicatorView() = default; ProgressIndicatorView(const ProgressIndicatorView&) = delete; @@ -202,6 +214,9 @@ std::unique_ptr<ProgressIndicator> progress_indicator_; }; +BEGIN_METADATA(ProgressIndicatorView, views::View) +END_METADATA + BEGIN_VIEW_BUILDER(/*no export*/, ProgressIndicatorView, views::View) VIEW_BUILDER_METHOD(CopyProgressIndicatorAddressTo, raw_ptr<ProgressIndicator, ExperimentalAsh>*)
diff --git a/ash/system/holding_space/holding_space_item_chip_view.h b/ash/system/holding_space/holding_space_item_chip_view.h index 79fddc0f..2797a32 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.h +++ b/ash/system/holding_space/holding_space_item_chip_view.h
@@ -27,9 +27,9 @@ // A button with an image derived from a file's thumbnail and file's name as the // label. class ASH_EXPORT HoldingSpaceItemChipView : public HoldingSpaceItemView { - public: - METADATA_HEADER(HoldingSpaceItemChipView); + METADATA_HEADER(HoldingSpaceItemChipView, HoldingSpaceItemView) + public: HoldingSpaceItemChipView(HoldingSpaceViewDelegate* delegate, const HoldingSpaceItem* item); HoldingSpaceItemChipView(const HoldingSpaceItemChipView&) = delete;
diff --git a/ash/system/holding_space/holding_space_item_screen_capture_view.h b/ash/system/holding_space/holding_space_item_screen_capture_view.h index 1a5b06b..8055dc9c 100644 --- a/ash/system/holding_space/holding_space_item_screen_capture_view.h +++ b/ash/system/holding_space/holding_space_item_screen_capture_view.h
@@ -19,9 +19,9 @@ class ASH_EXPORT HoldingSpaceItemScreenCaptureView : public HoldingSpaceItemView { - public: - METADATA_HEADER(HoldingSpaceItemScreenCaptureView); + METADATA_HEADER(HoldingSpaceItemScreenCaptureView, HoldingSpaceItemView) + public: HoldingSpaceItemScreenCaptureView(HoldingSpaceViewDelegate* delegate, const HoldingSpaceItem* item); HoldingSpaceItemScreenCaptureView(const HoldingSpaceItemScreenCaptureView&) =
diff --git a/ash/system/holding_space/holding_space_item_view.cc b/ash/system/holding_space/holding_space_item_view.cc index f59884ec..eb995a1 100644 --- a/ash/system/holding_space/holding_space_item_view.cc +++ b/ash/system/holding_space/holding_space_item_view.cc
@@ -91,6 +91,8 @@ // A view which respects a minimum size restriction. class MinimumSizableView : public views::View { + METADATA_HEADER(MinimumSizableView, views::View) + public: explicit MinimumSizableView(const gfx::Size& min_size) : min_size_(min_size) {} @@ -114,6 +116,9 @@ const gfx::Size min_size_; }; +BEGIN_METADATA(MinimumSizableView, views::View) +END_METADATA + } // namespace // HoldingSpaceItemView --------------------------------------------------------
diff --git a/ash/system/holding_space/holding_space_item_view.h b/ash/system/holding_space/holding_space_item_view.h index 6ecebcf..6644a87 100644 --- a/ash/system/holding_space/holding_space_item_view.h +++ b/ash/system/holding_space/holding_space_item_view.h
@@ -34,9 +34,9 @@ // animated out. class ASH_EXPORT HoldingSpaceItemView : public views::View, public HoldingSpaceModelObserver { - public: - METADATA_HEADER(HoldingSpaceItemView); + METADATA_HEADER(HoldingSpaceItemView, views::View) + public: HoldingSpaceItemView(HoldingSpaceViewDelegate*, const HoldingSpaceItem*); HoldingSpaceItemView(const HoldingSpaceItemView&) = delete; HoldingSpaceItemView& operator=(const HoldingSpaceItemView&) = delete;
diff --git a/ash/system/holding_space/holding_space_item_views_section.cc b/ash/system/holding_space/holding_space_item_views_section.cc index 7908462..ae6fa7d 100644 --- a/ash/system/holding_space/holding_space_item_views_section.cc +++ b/ash/system/holding_space/holding_space_item_views_section.cc
@@ -119,7 +119,7 @@ this}; }; -BEGIN_METADATA(HoldingSpaceScrollView) +BEGIN_METADATA(HoldingSpaceScrollView, views::ScrollView) END_METADATA } // namespace @@ -540,7 +540,7 @@ MaybeAnimateIn(); } -BEGIN_METADATA(HoldingSpaceItemViewsSection) +BEGIN_METADATA(HoldingSpaceItemViewsSection, views::View) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/holding_space_tray.h b/ash/system/holding_space/holding_space_tray.h index c61203e..9a6ac4381 100644 --- a/ash/system/holding_space/holding_space_tray.h +++ b/ash/system/holding_space/holding_space_tray.h
@@ -56,9 +56,9 @@ public SessionObserver, public ui::SimpleMenuModel::Delegate, public views::WidgetObserver { - public: - METADATA_HEADER(HoldingSpaceTray); + METADATA_HEADER(HoldingSpaceTray, TrayBackgroundView) + public: explicit HoldingSpaceTray(Shelf* shelf); HoldingSpaceTray(const HoldingSpaceTray& other) = delete; HoldingSpaceTray& operator=(const HoldingSpaceTray& other) = delete;
diff --git a/ash/system/holding_space/holding_space_tray_child_bubble.cc b/ash/system/holding_space/holding_space_tray_child_bubble.cc index 108e226..7167746 100644 --- a/ash/system/holding_space/holding_space_tray_child_bubble.cc +++ b/ash/system/holding_space/holding_space_tray_child_bubble.cc
@@ -321,10 +321,6 @@ return nullptr; } -const char* HoldingSpaceTrayChildBubble::GetClassName() const { - return "HoldingSpaceTrayChildBubble"; -} - void HoldingSpaceTrayChildBubble::ChildPreferredSizeChanged( views::View* child) { PreferredSizeChanged(); @@ -505,7 +501,7 @@ } } -BEGIN_METADATA(HoldingSpaceTrayChildBubble) +BEGIN_METADATA(HoldingSpaceTrayChildBubble, views::View) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/holding_space_tray_child_bubble.h b/ash/system/holding_space/holding_space_tray_child_bubble.h index 19dc076..d674064 100644 --- a/ash/system/holding_space/holding_space_tray_child_bubble.h +++ b/ash/system/holding_space/holding_space_tray_child_bubble.h
@@ -82,7 +82,6 @@ private: // views::View: - const char* GetClassName() const override; void ChildPreferredSizeChanged(views::View* child) override; void ChildVisibilityChanged(views::View* child) override; void OnGestureEvent(ui::GestureEvent* event) override;
diff --git a/ash/system/holding_space/holding_space_tray_icon.h b/ash/system/holding_space/holding_space_tray_icon.h index be51406..736b8ee 100644 --- a/ash/system/holding_space/holding_space_tray_icon.h +++ b/ash/system/holding_space/holding_space_tray_icon.h
@@ -29,9 +29,9 @@ class ASH_EXPORT HoldingSpaceTrayIcon : public views::View, public ShellObserver, public ShelfConfig::Observer { - public: - METADATA_HEADER(HoldingSpaceTrayIcon); + METADATA_HEADER(HoldingSpaceTrayIcon, views::View) + public: explicit HoldingSpaceTrayIcon(Shelf* shelf); HoldingSpaceTrayIcon(const HoldingSpaceTrayIcon&) = delete; HoldingSpaceTrayIcon& operator=(const HoldingSpaceTrayIcon&) = delete;
diff --git a/ash/system/holding_space/pinned_files_bubble.cc b/ash/system/holding_space/pinned_files_bubble.cc index 8e10d06..7873f4d6 100644 --- a/ash/system/holding_space/pinned_files_bubble.cc +++ b/ash/system/holding_space/pinned_files_bubble.cc
@@ -26,7 +26,7 @@ return sections; } -BEGIN_METADATA(PinnedFilesBubble) +BEGIN_METADATA(PinnedFilesBubble, HoldingSpaceTrayChildBubble) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/pinned_files_section.cc b/ash/system/holding_space/pinned_files_section.cc index 572b46a..9a7900c 100644 --- a/ash/system/holding_space/pinned_files_section.cc +++ b/ash/system/holding_space/pinned_files_section.cc
@@ -109,6 +109,8 @@ // FilesAppChip ---------------------------------------------------------------- class FilesAppChip : public views::Button { + METADATA_HEADER(FilesAppChip, views::Button) + public: explicit FilesAppChip(views::Button::PressedCallback pressed_callback) : views::Button(std::move(pressed_callback)) { @@ -177,6 +179,9 @@ } }; +BEGIN_METADATA(FilesAppChip, views::Button) +END_METADATA + } // namespace // PinnedFilesSection ---------------------------------------------------------- @@ -296,7 +301,7 @@ } } -BEGIN_METADATA(PinnedFilesSection) +BEGIN_METADATA(PinnedFilesSection, HoldingSpaceItemViewsSection) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/recent_files_bubble.cc b/ash/system/holding_space/recent_files_bubble.cc index 3f195c0..a7d7089e 100644 --- a/ash/system/holding_space/recent_files_bubble.cc +++ b/ash/system/holding_space/recent_files_bubble.cc
@@ -36,10 +36,6 @@ RecentFilesBubble::~RecentFilesBubble() = default; -const char* RecentFilesBubble::GetClassName() const { - return "RecentFilesBubble"; -} - std::unique_ptr<views::View> RecentFilesBubble::CreatePlaceholder() { if (!features::IsHoldingSpacePredictabilityEnabled()) return nullptr; @@ -68,7 +64,7 @@ return sections; } -BEGIN_METADATA(RecentFilesBubble) +BEGIN_METADATA(RecentFilesBubble, HoldingSpaceTrayChildBubble) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/recent_files_bubble.h b/ash/system/holding_space/recent_files_bubble.h index b0a2c47..16d5903 100644 --- a/ash/system/holding_space/recent_files_bubble.h +++ b/ash/system/holding_space/recent_files_bubble.h
@@ -24,7 +24,6 @@ ~RecentFilesBubble() override; // HoldingSpaceTrayChildBubble: - const char* GetClassName() const override; std::unique_ptr<views::View> CreatePlaceholder() override; std::vector<std::unique_ptr<HoldingSpaceItemViewsSection>> CreateSections() override;
diff --git a/ash/system/holding_space/screen_captures_section.cc b/ash/system/holding_space/screen_captures_section.cc index 8328cad..6f5481f 100644 --- a/ash/system/holding_space/screen_captures_section.cc +++ b/ash/system/holding_space/screen_captures_section.cc
@@ -28,10 +28,6 @@ ScreenCapturesSection::~ScreenCapturesSection() = default; -const char* ScreenCapturesSection::GetClassName() const { - return "ScreenCapturesSection"; -} - std::unique_ptr<views::View> ScreenCapturesSection::CreateHeader() { auto header = holding_space_ui::CreateSectionHeaderLabel( @@ -58,7 +54,7 @@ return std::make_unique<HoldingSpaceItemScreenCaptureView>(delegate(), item); } -BEGIN_METADATA(ScreenCapturesSection) +BEGIN_METADATA(ScreenCapturesSection, HoldingSpaceItemViewsSection) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/screen_captures_section.h b/ash/system/holding_space/screen_captures_section.h index bff29ac6..fe0f6da 100644 --- a/ash/system/holding_space/screen_captures_section.h +++ b/ash/system/holding_space/screen_captures_section.h
@@ -24,7 +24,6 @@ ~ScreenCapturesSection() override; // HoldingSpaceItemViewsSection: - const char* GetClassName() const override; std::unique_ptr<views::View> CreateHeader() override; std::unique_ptr<views::View> CreateContainer() override; std::unique_ptr<HoldingSpaceItemView> CreateView(
diff --git a/ash/system/holding_space/suggestions_section.cc b/ash/system/holding_space/suggestions_section.cc index c58d27a8..e7e4354 100644 --- a/ash/system/holding_space/suggestions_section.cc +++ b/ash/system/holding_space/suggestions_section.cc
@@ -25,6 +25,7 @@ #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/rrect_f.h" @@ -170,10 +171,6 @@ SuggestionsSection::~SuggestionsSection() = default; -const char* SuggestionsSection::GetClassName() const { - return "SuggestionsSection"; -} - std::unique_ptr<views::View> SuggestionsSection::CreateHeader() { return std::make_unique<Header>(); } @@ -198,4 +195,7 @@ return holding_space_prefs::IsSuggestionsExpanded(prefs); } +BEGIN_METADATA(SuggestionsSection, HoldingSpaceItemViewsSection) +END_METADATA + } // namespace ash
diff --git a/ash/system/holding_space/suggestions_section.h b/ash/system/holding_space/suggestions_section.h index e5a4027a..584d4a12 100644 --- a/ash/system/holding_space/suggestions_section.h +++ b/ash/system/holding_space/suggestions_section.h
@@ -8,6 +8,7 @@ #include <memory> #include "ash/system/holding_space/holding_space_item_views_section.h" +#include "ui/base/metadata/metadata_header_macros.h" class PrefChangeRegistrar; @@ -15,6 +16,8 @@ // Section for suggestions in the `PinnedFilesBubble`. class SuggestionsSection : public HoldingSpaceItemViewsSection { + METADATA_HEADER(SuggestionsSection, HoldingSpaceItemViewsSection) + public: explicit SuggestionsSection(HoldingSpaceViewDelegate* delegate); SuggestionsSection(const SuggestionsSection& other) = delete; @@ -22,7 +25,6 @@ ~SuggestionsSection() override; // HoldingSpaceItemViewsSection: - const char* GetClassName() const override; std::unique_ptr<views::View> CreateHeader() override; std::unique_ptr<views::View> CreateContainer() override; std::unique_ptr<HoldingSpaceItemView> CreateView(
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc index c8cbd3b..e43a58a 100644 --- a/ash/system/message_center/ash_notification_view.cc +++ b/ash/system/message_center/ash_notification_view.cc
@@ -711,179 +711,6 @@ main_view_->SetVisible(expanded); } -void AshNotificationView::AnimateGroupedChildExpandedCollapse(bool expanded) { - message_center_utils::InitLayerForAnimations(collapsed_summary_view_); - message_center_utils::InitLayerForAnimations(main_view_); - // Fade out `collapsed_summary_view_`, then fade in `main_view_` in expanded - // state and vice versa in collapsed state. - if (expanded) { - message_center_utils::FadeOutView( - collapsed_summary_view_, - base::BindRepeating( - [](base::WeakPtr<ash::AshNotificationView> parent, - views::View* collapsed_summary_view) { - if (parent) { - collapsed_summary_view->layer()->SetOpacity(1.0f); - collapsed_summary_view->SetVisible(false); - } - }, - weak_factory_.GetWeakPtr(), collapsed_summary_view_), - 0, kCollapsedSummaryViewAnimationDurationMs, gfx::Tween::LINEAR, - "Ash.NotificationView.CollapsedSummaryView.FadeOut." - "AnimationSmoothness"); - message_center_utils::FadeInView( - main_view_, kCollapsedSummaryViewAnimationDurationMs, - kChildMainViewFadeInAnimationDurationMs, gfx::Tween::LINEAR, - "Ash.NotificationView.MainView.FadeIn.AnimationSmoothness"); - return; - } - - message_center_utils::FadeOutView( - main_view_, - base::BindRepeating( - [](base::WeakPtr<ash::AshNotificationView> parent, - views::View* main_view) { - if (parent) { - main_view->layer()->SetOpacity(1.0f); - main_view->SetVisible(false); - } - }, - weak_factory_.GetWeakPtr(), main_view_), - 0, kChildMainViewFadeOutAnimationDurationMs, gfx::Tween::LINEAR, - "Ash.NotificationView.MainView.FadeOut.AnimationSmoothness"); - message_center_utils::FadeInView( - collapsed_summary_view_, kChildMainViewFadeOutAnimationDurationMs, - kCollapsedSummaryViewAnimationDurationMs, gfx::Tween::LINEAR, - "Ash.NotificationView.CollapsedSummaryView.FadeIn.AnimationSmoothness"); -} - -void AshNotificationView::AnimateSingleToGroup( - NotificationGroupingController* grouping_controller, - const std::string& notification_id, - std::string parent_id) { - ash::message_center_utils::InitLayerForAnimations(left_content()); - ash::message_center_utils::InitLayerForAnimations(right_content()); - ash::message_center_utils::InitLayerForAnimations( - message_label_in_expanded_state_); - ash::message_center_utils::InitLayerForAnimations(image_container_view()); - ash::message_center_utils::InitLayerForAnimations(action_buttons_row()); - - auto on_animation_ended = base::BindOnce( - [](base::WeakPtr<ash::AshNotificationView> parent, - views::View* left_content, views::View* right_content, - views::View* message_label_in_expanded_state, - views::View* image_container_view, views::View* action_buttons_row, - AshNotificationExpandButton* expand_button, - NotificationGroupingController* grouping_controller, - const std::string& notification_id, std::string parent_id) { - if (!parent) { - return; - } - - auto* parent_notification = - message_center::MessageCenter::Get()->FindNotificationById( - parent_id); - auto* child_notification = - message_center::MessageCenter::Get()->FindNotificationById( - notification_id); - // The child and parent notifications are not guaranteed to exist. If - // they were deleted avoid the animation cleanup. - if (!parent_notification || !child_notification) { - return; - } - - grouping_controller->ConvertFromSingleToGroupNotificationAfterAnimation( - notification_id, parent_id, parent_notification); - - left_content->layer()->SetOpacity(1.0f); - right_content->layer()->SetOpacity(1.0f); - message_label_in_expanded_state->layer()->SetOpacity(1.0f); - image_container_view->layer()->SetOpacity(1.0f); - action_buttons_row->layer()->SetOpacity(1.0f); - - // After fade out single notification and set up a group one, perform - // a fade in. - parent->AnimateSingleToGroupFadeIn(); - - expand_button->set_previous_bounds(expand_button->GetContentsBounds()); - parent->Layout(); - expand_button->AnimateSingleToGroupNotification(); - }, - weak_factory_.GetWeakPtr(), left_content_, right_content(), - message_label_in_expanded_state_, image_container_view(), - action_buttons_row(), expand_button_, grouping_controller, - notification_id, parent_id); - - std::pair<base::OnceClosure, base::OnceClosure> split = - base::SplitOnceCallback(std::move(on_animation_ended)); - - ui::AnimationThroughputReporter reporter( - left_content()->layer()->GetAnimator(), - metrics_util::ForSmoothness(base::BindRepeating([](int smoothness) { - base::UmaHistogramPercentage( - "Ash.NotificationView.ConvertSingleToGroup.FadeOut." - "AnimationSmoothness", - smoothness); - }))); - - views::AnimationBuilder() - .SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET) - .OnEnded(std::move(split.first)) - .OnAborted(std::move(split.second)) - .Once() - .SetDuration( - base::Milliseconds(kConvertFromSingleToGroupFadeOutDurationMs)) - .SetOpacity(left_content(), 0.0f, gfx::Tween::LINEAR) - .SetOpacity(right_content(), 0.0f, gfx::Tween::LINEAR) - .SetOpacity(message_label_in_expanded_state_, 0.0f, gfx::Tween::LINEAR) - .SetOpacity(image_container_view(), 0.0f, gfx::Tween::LINEAR) - .SetOpacity(action_buttons_row(), 0.0f, gfx::Tween::LINEAR); -} - -void AshNotificationView::ToggleExpand() { - const bool target_expanded_state = !IsExpanded(); - - SetManuallyExpandedOrCollapsed( - target_expanded_state ? message_center::ExpandState::USER_EXPANDED - : message_center::ExpandState::USER_COLLAPSED); - - if (inline_reply() && inline_reply()->GetVisible()) { - message_center_utils::FadeOutView( - inline_reply(), - base::BindOnce( - [](base::WeakPtr<ash::AshNotificationView> parent, - views::View* inline_reply) { - if (parent) { - inline_reply->layer()->SetOpacity(1.0f); - } - }, - weak_factory_.GetWeakPtr(), inline_reply()), - /*delay_in_ms=*/0, kInlineReplyFadeOutAnimationDurationMs, - gfx::Tween::LINEAR, - "Ash.NotificationView.InlineReply.FadeOut.AnimationSmoothness"); - } - - SetExpanded(target_expanded_state); - - PerformExpandCollapseAnimation(); - - // Log expand button click action. - if (IsExpanded()) { - is_grouped_parent_view_ - ? metrics_utils::LogExpandButtonClickAction( - metrics_utils::ExpandButtonClickAction::EXPAND_GROUP) - : metrics_utils::LogExpandButtonClickAction( - metrics_utils::ExpandButtonClickAction::EXPAND_INDIVIDUAL); - } else { - is_grouped_parent_view_ - ? metrics_utils::LogExpandButtonClickAction( - metrics_utils::ExpandButtonClickAction::COLLAPSE_GROUP) - : metrics_utils::LogExpandButtonClickAction( - metrics_utils::ExpandButtonClickAction::COLLAPSE_INDIVIDUAL); - } -} - void AshNotificationView::GroupedNotificationsPreferredSizeChanged() { PreferredSizeChanged(); } @@ -981,6 +808,178 @@ return base::Milliseconds(kGeneralCollapseAnimationDuration); } +void AshNotificationView::AnimateGroupedChildExpandedCollapse(bool expanded) { + message_center_utils::InitLayerForAnimations(collapsed_summary_view_); + message_center_utils::InitLayerForAnimations(main_view_); + // Fade out `collapsed_summary_view_`, then fade in `main_view_` in expanded + // state and vice versa in collapsed state. + if (expanded) { + message_center_utils::FadeOutView( + collapsed_summary_view_, + base::BindRepeating( + [](base::WeakPtr<ash::AshNotificationView> parent, + views::View* collapsed_summary_view) { + if (parent) { + collapsed_summary_view->layer()->SetOpacity(1.0f); + collapsed_summary_view->SetVisible(false); + } + }, + weak_factory_.GetWeakPtr(), collapsed_summary_view_), + 0, kCollapsedSummaryViewAnimationDurationMs, gfx::Tween::LINEAR, + "Ash.NotificationView.CollapsedSummaryView.FadeOut." + "AnimationSmoothness"); + message_center_utils::FadeInView( + main_view_, kCollapsedSummaryViewAnimationDurationMs, + kChildMainViewFadeInAnimationDurationMs, gfx::Tween::LINEAR, + "Ash.NotificationView.MainView.FadeIn.AnimationSmoothness"); + return; + } + + message_center_utils::FadeOutView( + main_view_, + base::BindRepeating( + [](base::WeakPtr<ash::AshNotificationView> parent, + views::View* main_view) { + if (parent) { + main_view->layer()->SetOpacity(1.0f); + main_view->SetVisible(false); + } + }, + weak_factory_.GetWeakPtr(), main_view_), + 0, kChildMainViewFadeOutAnimationDurationMs, gfx::Tween::LINEAR, + "Ash.NotificationView.MainView.FadeOut.AnimationSmoothness"); + message_center_utils::FadeInView( + collapsed_summary_view_, kChildMainViewFadeOutAnimationDurationMs, + kCollapsedSummaryViewAnimationDurationMs, gfx::Tween::LINEAR, + "Ash.NotificationView.CollapsedSummaryView.FadeIn.AnimationSmoothness"); +} + +void AshNotificationView::AnimateSingleToGroup( + const std::string& notification_id, + std::string parent_id) { + ash::message_center_utils::InitLayerForAnimations(left_content()); + ash::message_center_utils::InitLayerForAnimations(right_content()); + ash::message_center_utils::InitLayerForAnimations( + message_label_in_expanded_state_); + ash::message_center_utils::InitLayerForAnimations(image_container_view()); + ash::message_center_utils::InitLayerForAnimations(action_buttons_row()); + + auto on_animation_ended = base::BindOnce( + [](base::WeakPtr<ash::AshNotificationView> parent, + views::View* left_content, views::View* right_content, + views::View* message_label_in_expanded_state, + views::View* image_container_view, views::View* action_buttons_row, + AshNotificationExpandButton* expand_button, + const std::string& notification_id, std::string parent_id) { + if (!parent) { + return; + } + + auto* parent_notification = + message_center::MessageCenter::Get()->FindNotificationById( + parent_id); + auto* child_notification = + message_center::MessageCenter::Get()->FindNotificationById( + notification_id); + // The child and parent notifications are not guaranteed to exist. If + // they were deleted avoid the animation cleanup. + if (!parent_notification || !child_notification) { + return; + } + + message_center_utils::GetGroupingControllerForNotificationView( + parent.get()) + ->ConvertFromSingleToGroupNotificationAfterAnimation( + notification_id, parent_id, parent_notification); + + left_content->layer()->SetOpacity(1.0f); + right_content->layer()->SetOpacity(1.0f); + message_label_in_expanded_state->layer()->SetOpacity(1.0f); + image_container_view->layer()->SetOpacity(1.0f); + action_buttons_row->layer()->SetOpacity(1.0f); + + // After fade out single notification and set up a group one, perform + // a fade in. + parent->AnimateSingleToGroupFadeIn(); + + expand_button->set_previous_bounds(expand_button->GetContentsBounds()); + parent->Layout(); + expand_button->AnimateSingleToGroupNotification(); + }, + weak_factory_.GetWeakPtr(), left_content_, right_content(), + message_label_in_expanded_state_, image_container_view(), + action_buttons_row(), expand_button_, notification_id, parent_id); + + std::pair<base::OnceClosure, base::OnceClosure> split = + base::SplitOnceCallback(std::move(on_animation_ended)); + + ui::AnimationThroughputReporter reporter( + left_content()->layer()->GetAnimator(), + metrics_util::ForSmoothness(base::BindRepeating([](int smoothness) { + base::UmaHistogramPercentage( + "Ash.NotificationView.ConvertSingleToGroup.FadeOut." + "AnimationSmoothness", + smoothness); + }))); + + views::AnimationBuilder() + .SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET) + .OnEnded(std::move(split.first)) + .OnAborted(std::move(split.second)) + .Once() + .SetDuration( + base::Milliseconds(kConvertFromSingleToGroupFadeOutDurationMs)) + .SetOpacity(left_content(), 0.0f, gfx::Tween::LINEAR) + .SetOpacity(right_content(), 0.0f, gfx::Tween::LINEAR) + .SetOpacity(message_label_in_expanded_state_, 0.0f, gfx::Tween::LINEAR) + .SetOpacity(image_container_view(), 0.0f, gfx::Tween::LINEAR) + .SetOpacity(action_buttons_row(), 0.0f, gfx::Tween::LINEAR); +} + +void AshNotificationView::ToggleExpand() { + const bool target_expanded_state = !IsExpanded(); + + SetManuallyExpandedOrCollapsed( + target_expanded_state ? message_center::ExpandState::USER_EXPANDED + : message_center::ExpandState::USER_COLLAPSED); + + if (inline_reply() && inline_reply()->GetVisible()) { + message_center_utils::FadeOutView( + inline_reply(), + base::BindOnce( + [](base::WeakPtr<ash::AshNotificationView> parent, + views::View* inline_reply) { + if (parent) { + inline_reply->layer()->SetOpacity(1.0f); + } + }, + weak_factory_.GetWeakPtr(), inline_reply()), + /*delay_in_ms=*/0, kInlineReplyFadeOutAnimationDurationMs, + gfx::Tween::LINEAR, + "Ash.NotificationView.InlineReply.FadeOut.AnimationSmoothness"); + } + + SetExpanded(target_expanded_state); + + PerformExpandCollapseAnimation(); + + // Log expand button click action. + if (IsExpanded()) { + is_grouped_parent_view_ + ? metrics_utils::LogExpandButtonClickAction( + metrics_utils::ExpandButtonClickAction::EXPAND_GROUP) + : metrics_utils::LogExpandButtonClickAction( + metrics_utils::ExpandButtonClickAction::EXPAND_INDIVIDUAL); + } else { + is_grouped_parent_view_ + ? metrics_utils::LogExpandButtonClickAction( + metrics_utils::ExpandButtonClickAction::COLLAPSE_GROUP) + : metrics_utils::LogExpandButtonClickAction( + metrics_utils::ExpandButtonClickAction::COLLAPSE_INDIVIDUAL); + } +} + void AshNotificationView::AddGroupNotification( const message_center::Notification& notification) { DCHECK(is_grouped_parent_view_); @@ -1020,15 +1019,10 @@ for (auto* notification : notifications) { auto notification_view = MessageViewFactory::Create(*notification, /*shown_in_popup=*/false); - // The child can either be an AshNotificationView or an ARC custom - // notification view. - // TODO(b/308814203): clean the static_cast checks by replacing - // `AshNotificationView*` with a base class. - if (message_center_utils::IsAshNotification(notification)) { - auto* ash_notification_view = - static_cast<AshNotificationView*>(notification_view.get()); - ash_notification_view->SetGroupedChildExpanded(IsExpanded()); - } + + auto* child_notification_view = + static_cast<message_center::MessageView*>(notification_view.get()); + child_notification_view->SetGroupedChildExpanded(IsExpanded()); if (!total_grouped_notifications_) { header_row()->SetTimestamp(notification->timestamp()); @@ -1213,13 +1207,10 @@ int notification_count = 0; for (auto* child : grouped_notifications_container_->children()) { - // TODO(b/308814203): clean the static_cast checks by replacing - // `AshNotificationView*` with a base class. - if (message_center_utils::IsAshNotificationView(child)) { - auto* notification_view = static_cast<AshNotificationView*>(child); - notification_view->AnimateGroupedChildExpandedCollapse(expanded); - notification_view->SetGroupedChildExpanded(expanded); - } + auto* notification_view = + static_cast<message_center::MessageView*>(child); + notification_view->AnimateGroupedChildExpandedCollapse(expanded); + notification_view->SetGroupedChildExpanded(expanded); notification_count++; if (notification_count >
diff --git a/ash/system/message_center/ash_notification_view.h b/ash/system/message_center/ash_notification_view.h index 80f56e9..670e41cf 100644 --- a/ash/system/message_center/ash_notification_view.h +++ b/ash/system/message_center/ash_notification_view.h
@@ -36,7 +36,6 @@ class RoundedImageView; class AshNotificationExpandButton; class IconButton; -class NotificationGroupingController; // Customized NotificationView for notification on ChromeOS. This view is used // to displays all current types of notification on ChromeOS (web, basic, image, @@ -55,18 +54,6 @@ AshNotificationView& operator=(const AshNotificationView&) = delete; ~AshNotificationView() override; - // Update the expanded state for grouped child notification. - void SetGroupedChildExpanded(bool expanded); - - // Animate the grouped child notification when switching between expand and - // collapse state. - void AnimateGroupedChildExpandedCollapse(bool expanded); - - // Animations when converting from single to group notification. - void AnimateSingleToGroup(NotificationGroupingController* grouping_controller, - const std::string& notification_id, - std::string parent_id); - // Toggle the expand state of the notification. This function should only be // used to handle user manually expand/collapse a notification. void ToggleExpand(); @@ -93,12 +80,16 @@ bool IsDraggable() const; // message_center::MessageView: + void AnimateGroupedChildExpandedCollapse(bool expanded) override; + void AnimateSingleToGroup(const std::string& notification_id, + std::string parent_id) override; void AddGroupNotification( const message_center::Notification& notification) override; void PopulateGroupNotifications( const std::vector<const message_center::Notification*>& notifications) override; void RemoveGroupNotification(const std::string& notification_id) override; + void SetGroupedChildExpanded(bool expanded) override; // Called after `PreferredSizeChanged()`, so the current state is the target // state. base::TimeDelta GetBoundsAnimationDuration(
diff --git a/ash/system/message_center/message_center_utils.cc b/ash/system/message_center/message_center_utils.cc index cb1ecd2..ec397ef 100644 --- a/ash/system/message_center/message_center_utils.cc +++ b/ash/system/message_center/message_center_utils.cc
@@ -153,6 +153,7 @@ GetActiveNotificationViewControllerForDisplay(int64_t display_id) { RootWindowController* root_window_controller = Shell::GetRootWindowControllerWithDisplayId(display_id); + // Can be null in tests. if (!root_window_controller || !root_window_controller->GetStatusAreaWidget()) { return nullptr; @@ -174,6 +175,25 @@ return GetActiveNotificationViewControllerForDisplay(display_id); } +NotificationGroupingController* GetGroupingControllerForNotificationView( + views::View* notification_view) { + aura::Window* window = notification_view->GetWidget()->GetNativeWindow(); + auto display_id = + display::Screen::GetScreen()->GetDisplayNearestWindow(window).id(); + + RootWindowController* root_window_controller = + Shell::GetRootWindowControllerWithDisplayId(display_id); + // Can be null in tests. + if (!root_window_controller || + !root_window_controller->GetStatusAreaWidget()) { + return nullptr; + } + + return root_window_controller->GetStatusAreaWidget() + ->notification_center_tray() + ->notification_grouping_controller(); +} + void InitLayerForAnimations(views::View* view) { view->SetPaintToLayer(); view->layer()->SetFillsBoundsOpaquely(false);
diff --git a/ash/system/message_center/message_center_utils.h b/ash/system/message_center/message_center_utils.h index b7b9168..861a211 100644 --- a/ash/system/message_center/message_center_utils.h +++ b/ash/system/message_center/message_center_utils.h
@@ -21,7 +21,11 @@ class View; } -namespace ash::message_center_utils { +namespace ash { + +class NotificationGroupingController; + +namespace message_center_utils { // Return a hash string derived from `notifier_id` data. This is appended to a // notification's `id` to create a unique identifier for a grouped notification. @@ -62,6 +66,12 @@ GetActiveNotificationViewControllerForNotificationView( views::View* notification_view); +// Gets the grouping controller for the provided notification view. Each display +// has it's own `NotificationGroupingController` so we need to look up the +// display for the provide view first. +NotificationGroupingController* GetGroupingControllerForNotificationView( + views::View* notification_view); + // Utils for animation within a notification view. // Initializes the layer for the specified `view` for animations. @@ -107,6 +117,7 @@ // checks for casting `AshNotificationView*`. bool IsAshNotification(const message_center::Notification* notification); -} // namespace ash::message_center_utils +} // namespace message_center_utils +} // namespace ash #endif // ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_UTILS_H_
diff --git a/ash/system/message_center/notification_grouping_controller.cc b/ash/system/message_center/notification_grouping_controller.cc index c2874d7..e5d0e71 100644 --- a/ash/system/message_center/notification_grouping_controller.cc +++ b/ash/system/message_center/notification_grouping_controller.cc
@@ -371,12 +371,9 @@ } std::string parent_id = parent_notification->id(); - // TODO(b/308814203): clean the static_cast checks by replacing - // AshNotificationView* with a base class. auto* parent_view = - (GetActiveNotificationViewController() && - message_center_utils::IsAshNotification(parent_notification)) - ? static_cast<AshNotificationView*>( + (GetActiveNotificationViewController()) + ? static_cast<MessageView*>( GetActiveNotificationViewController() ->GetMessageViewForNotificationId(parent_id)) : nullptr; @@ -393,7 +390,7 @@ // will be handled in // `ConvertFromSingleToGroupNotificationAfterAnimation()`, which is called // after the animation from the parent view is completed. - parent_view->AnimateSingleToGroup(this, notification_id, parent_id); + parent_view->AnimateSingleToGroup(notification_id, parent_id); return; }
diff --git a/ash/system/notification_center/notification_list_view.cc b/ash/system/notification_center/notification_list_view.cc index fae28c13f5..e60fe44a 100644 --- a/ash/system/notification_center/notification_list_view.cc +++ b/ash/system/notification_center/notification_list_view.cc
@@ -697,18 +697,17 @@ } // Update the child notification view with the updated notification. - // TODO(b/308814203): clean the static_cast checks by replacing - // `AshNotificationView*` with a base class. auto* child_view = parent_view->FindGroupNotificationView(child_notification_id); + + if (!child_view) { + return; + } + auto* notification = MessageCenter::Get()->FindNotificationById(child_notification_id); - - if (child_view && message_center_utils::IsAshNotification(notification)) { - auto* ash_child_view = static_cast<AshNotificationView*>(child_view); - ash_child_view->UpdateWithNotification(*notification); - ResetBounds(); - } + static_cast<MessageView*>(child_view)->UpdateWithNotification(*notification); + ResetBounds(); } void NotificationListView::OnNotificationAdded(const std::string& id) {
diff --git a/ash/system/time/calendar_month_view.cc b/ash/system/time/calendar_month_view.cc index b46ff90..4222512 100644 --- a/ash/system/time/calendar_month_view.cc +++ b/ash/system/time/calendar_month_view.cc
@@ -40,8 +40,9 @@ // The radius used to draw the border. constexpr float kBorderRadius = 21.f; +constexpr float kBorderRadiusGlanceables = 19.f; -// The radius used to draw "today's" date cell view border and background . +// The radius used to draw "today's" date cell view border and background. constexpr float kTodayBorderRadius = 100.f; // The insets used to draw "today's" date cell view. @@ -52,6 +53,9 @@ constexpr float kTodayRoundedBackgroundVerticalFocusedInset = kTodayRoundedBackgroundVerticalInset + kBorderLineThickness + 2.f; +// For Glanceables: The horizontal inset used to draw "today's" date cell view. +constexpr float kTodayRoundedBackgroundHorizontalInsetGlanceables = 9.f; + // Radius of the small dot displayed on a CalendarDateCellView if events are // present for that day. constexpr float kEventsPresentRoundedRadius = 1.f; @@ -60,7 +64,9 @@ constexpr int kGapBetweenDateAndIndicator = 1; // For GlanceablesV2: the insets within the date cell. -constexpr auto kDateCellInsetsGlanceables = gfx::Insets::VH(10, 16); +constexpr int kDateCellVerticalPaddingGlanceables = 10; +constexpr auto kDateCellInsetsGlanceables = + gfx::Insets::VH(kDateCellVerticalPaddingGlanceables, 16); // Move to the next day. Both the column and the current date are moved to the // next one. @@ -161,6 +167,7 @@ highlight_border.setStyle(cc::PaintFlags::kStroke_Style); highlight_border.setStrokeWidth(kBorderLineThickness); + const bool is_for_glanceables = calendar_utils::IsForGlanceablesV2(); if (is_today_) { gfx::RectF background_rect(local_bounds); @@ -179,7 +186,9 @@ gfx::RectF border_rect(local_bounds); const int half_stroke_thickness = kBorderLineThickness / 2; border_rect.Inset(gfx::InsetsF::VH( - half_stroke_thickness, kTodayRoundedBackgroundHorizontalInset)); + half_stroke_thickness, + is_for_glanceables ? kTodayRoundedBackgroundHorizontalInsetGlanceables + : kTodayRoundedBackgroundHorizontalInset)); canvas->DrawRoundRect(border_rect, kTodayBorderRadius, highlight_border); background_rect.Inset( @@ -204,8 +213,14 @@ if (views::View::HasFocus() || is_selected_) { const gfx::Point center( (content.width() + calendar_utils::kDateHorizontalPadding * 2) / 2, - (content.height() + calendar_utils::kDateVerticalPadding * 2) / 2); - canvas->DrawCircle(center, kBorderRadius, highlight_border); + (content.height() + (is_for_glanceables + ? kDateCellVerticalPaddingGlanceables + : calendar_utils::kDateVerticalPadding) * + 2) / + 2); + canvas->DrawCircle( + center, is_for_glanceables ? kBorderRadiusGlanceables : kBorderRadius, + highlight_border); } } @@ -348,9 +363,12 @@ gfx::Point CalendarDateCellView::GetEventsPresentIndicatorCenterPosition() { const gfx::Rect content = GetContentsBounds(); const int horizontal_padding = calendar_utils::kDateHorizontalPadding; - return gfx::Point((content.width() + horizontal_padding * 2) / 2, - content.height() + calendar_utils::kDateVerticalPadding + - kGapBetweenDateAndIndicator); + const int vertical_padding = calendar_utils::IsForGlanceablesV2() + ? kDateCellVerticalPaddingGlanceables + : calendar_utils::kDateVerticalPadding; + return gfx::Point( + (content.width() + horizontal_padding * 2) / 2, + content.height() + vertical_padding + kGapBetweenDateAndIndicator); } void CalendarDateCellView::MaybeDrawEventsIndicator(gfx::Canvas* canvas) {
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc index 32d5c602..4c225f9 100644 --- a/ash/system/time/calendar_view.cc +++ b/ash/system/time/calendar_view.cc
@@ -639,7 +639,7 @@ auto* today_button = new IconButton( base::BindRepeating(&CalendarView::ResetToTodayWithAnimation, base::Unretained(this)), - IconButton::Type::kMedium, &kGlanceablesCalendarTodayIcon, + IconButton::Type::kMediumFloating, &kGlanceablesCalendarTodayIcon, IDS_ASH_CALENDAR_INFO_BUTTON_ACCESSIBLE_DESCRIPTION); today_button->SetBackgroundColor(cros_tokens::kCrosSysBaseElevated); today_button->SetProperty(views::kMarginsKey, kHeaderIconButtonMargin);
diff --git a/ash/system/time/calendar_view_pixeltest.cc b/ash/system/time/calendar_view_pixeltest.cc index a25c857..c15951ac 100644 --- a/ash/system/time/calendar_view_pixeltest.cc +++ b/ash/system/time/calendar_view_pixeltest.cc
@@ -108,7 +108,7 @@ EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "calendar_view", - /*revision_number=*/8, GetCalendarView())); + /*revision_number=*/9, GetCalendarView())); } TEST_P(CalendarViewPixelTest, EventList) {
diff --git a/ash/user_education/views/help_bubble_view_ash.cc b/ash/user_education/views/help_bubble_view_ash.cc index 2446130..4ff3810 100644 --- a/ash/user_education/views/help_bubble_view_ash.cc +++ b/ash/user_education/views/help_bubble_view_ash.cc
@@ -140,8 +140,9 @@ // The alt-text and button callback can be set based on the needs of the // specific bubble. class ClosePromoButton : public views::ImageButton { + METADATA_HEADER(ClosePromoButton, views::ImageButton) + public: - METADATA_HEADER(ClosePromoButton); ClosePromoButton(const std::u16string accessible_name, PressedCallback callback) { SetCallback(callback); @@ -174,8 +175,9 @@ END_METADATA class DotView : public views::View { + METADATA_HEADER(DotView, views::View) + public: - METADATA_HEADER(DotView); DotView(gfx::Size size, bool should_fill) : size_(size), should_fill_(should_fill) { // In order to anti-alias properly, we'll grow by the stroke width and then
diff --git a/ash/user_education/views/help_bubble_view_ash.h b/ash/user_education/views/help_bubble_view_ash.h index bc14d9f..eda2e3d 100644 --- a/ash/user_education/views/help_bubble_view_ash.h +++ b/ash/user_education/views/help_bubble_view_ash.h
@@ -49,8 +49,9 @@ // in-product help which educates users about certain Chrome features in // a deferred context. class ASH_EXPORT HelpBubbleViewAsh : public views::BubbleDialogDelegateView { + METADATA_HEADER(HelpBubbleViewAsh, views::BubbleDialogDelegateView) + public: - METADATA_HEADER(HelpBubbleViewAsh); DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kHelpBubbleElementIdForTesting); DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kDefaultButtonIdForTesting); DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kFirstNonDefaultButtonIdForTesting);
diff --git a/ash/user_education/welcome_tour/welcome_tour_dialog.h b/ash/user_education/welcome_tour/welcome_tour_dialog.h index 9db4b48..e38f990 100644 --- a/ash/user_education/welcome_tour/welcome_tour_dialog.h +++ b/ash/user_education/welcome_tour/welcome_tour_dialog.h
@@ -15,9 +15,9 @@ // dialog, a user can choose to accept or cancel the Welcome Tour tutorial. Used // if and only if the Welcome Tour feature is enabled. class ASH_EXPORT WelcomeTourDialog : public SystemDialogDelegateView { - public: - METADATA_HEADER(WelcomeTourDialog); + METADATA_HEADER(WelcomeTourDialog, SystemDialogDelegateView) + public: // Creates and shows the Welcome Tour dialog at the center of the primary // display. `accept_callback` is the callback that runs when the accept button // is clicked. `cancel_callback` is the callback that runs when the cancel
diff --git a/ash/user_education/welcome_tour/welcome_tour_metrics.h b/ash/user_education/welcome_tour/welcome_tour_metrics.h index a88e54f..c57a926 100644 --- a/ash/user_education/welcome_tour/welcome_tour_metrics.h +++ b/ash/user_education/welcome_tour/welcome_tour_metrics.h
@@ -104,6 +104,20 @@ Interaction::kSettingsApp, }); +// Enumeration of quantized time values for easy to interpret metrics about +// human scale time measurements that can range from minutes to weeks. +enum class TimeBucket { + kMinValue = 0, + kOneMinute = kMinValue, + kTenMinutes = 1, + kOneHour = 2, + kOneDay = 3, + kOneWeek = 4, + kTwoWeeks = 5, + kOverTwoWeeks = 6, + kMaxValue = kOverTwoWeeks, +}; + // Utilities ------------------------------------------------------------------- // Record that a given `interaction` has occurred.
diff --git a/ash/webui/common/resources/post_message_api/DIR_METADATA b/ash/webui/common/resources/post_message_api/DIR_METADATA new file mode 100644 index 0000000..14cf923 --- /dev/null +++ b/ash/webui/common/resources/post_message_api/DIR_METADATA
@@ -0,0 +1 @@ +mixins: "//ash/child_accounts/COMMON_METADATA"
diff --git a/ash/webui/common/resources/post_message_api/OWNERS b/ash/webui/common/resources/post_message_api/OWNERS new file mode 100644 index 0000000..7f1a4e1 --- /dev/null +++ b/ash/webui/common/resources/post_message_api/OWNERS
@@ -0,0 +1 @@ +file://ash/child_accounts/OWNERS
diff --git a/ash/webui/personalization_app/resources/js/ambient/ambient_actions.ts b/ash/webui/personalization_app/resources/js/ambient/ambient_actions.ts index 1b83134..4365955 100644 --- a/ash/webui/personalization_app/resources/js/ambient/ambient_actions.ts +++ b/ash/webui/personalization_app/resources/js/ambient/ambient_actions.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 {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js'; import {AmbientModeAlbum, AmbientTheme, AmbientUiVisibility, TemperatureUnit, TopicSource} from '../../personalization_app.mojom-webui.js';
diff --git a/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_actions.ts b/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_actions.ts index ccb313d..c29eb66 100644 --- a/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_actions.ts +++ b/ash/webui/personalization_app/resources/js/keyboard_backlight/keyboard_backlight_actions.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 {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js'; import {CurrentBacklightState} from '../../personalization_app.mojom-webui.js';
diff --git a/ash/webui/personalization_app/resources/js/personalization_actions.ts b/ash/webui/personalization_app/resources/js/personalization_actions.ts index 163ae60..96d75fe 100644 --- a/ash/webui/personalization_app/resources/js/personalization_actions.ts +++ b/ash/webui/personalization_app/resources/js/personalization_actions.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 {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {AmbientActions} from './ambient/ambient_actions.js'; import {KeyboardBacklightActions} from './keyboard_backlight/keyboard_backlight_actions.js';
diff --git a/ash/webui/personalization_app/resources/js/personalization_store.ts b/ash/webui/personalization_app/resources/js/personalization_store.ts index 7c7853c..27f92f2 100644 --- a/ash/webui/personalization_app/resources/js/personalization_store.ts +++ b/ash/webui/personalization_app/resources/js/personalization_store.ts
@@ -6,7 +6,7 @@ import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {ListPropertyUpdateMixin} from 'chrome://resources/cr_elements/list_property_update_mixin.js'; import {makeStoreClientMixin} from 'chrome://resources/cr_elements/store_client/store_client.js'; -import {Store} from 'chrome://resources/js/store_ts.js'; +import {Store} from 'chrome://resources/js/store.js'; import {Actions} from './personalization_actions.js'; import {reduce} from './personalization_reducers.js';
diff --git a/ash/webui/personalization_app/resources/js/theme/theme_actions.ts b/ash/webui/personalization_app/resources/js/theme/theme_actions.ts index 1b1c809e..df70bdcc 100644 --- a/ash/webui/personalization_app/resources/js/theme/theme_actions.ts +++ b/ash/webui/personalization_app/resources/js/theme/theme_actions.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 {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js'; import {ColorScheme} from '../../color_scheme.mojom-webui.js';
diff --git a/ash/webui/personalization_app/resources/js/user/user_actions.ts b/ash/webui/personalization_app/resources/js/user/user_actions.ts index 3505b84..0da5781 100644 --- a/ash/webui/personalization_app/resources/js/user/user_actions.ts +++ b/ash/webui/personalization_app/resources/js/user/user_actions.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 {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js'; import {DefaultUserImage, UserImage, UserInfo} from '../../personalization_app.mojom-webui.js';
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/sea_pen/sea_pen_actions.ts b/ash/webui/personalization_app/resources/js/wallpaper/sea_pen/sea_pen_actions.ts index 717ac598..ef317c2 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/sea_pen/sea_pen_actions.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/sea_pen/sea_pen_actions.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 {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {SeaPenThumbnail} from '../../../sea_pen.mojom-webui.js'; import {SeaPenWallpaper} from '../constants.js';
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts index bdc9255..61dda93 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_actions.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.js'; -import {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js'; import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
diff --git a/ash/wm/splitview/split_view_overview_session.cc b/ash/wm/splitview/split_view_overview_session.cc index 9adc6e6..c5bff7b 100644 --- a/ash/wm/splitview/split_view_overview_session.cc +++ b/ash/wm/splitview/split_view_overview_session.cc
@@ -78,17 +78,7 @@ } SplitViewOverviewSession::~SplitViewOverviewSession() { - if (is_shutting_down_) { - return; - } WindowState::Get(window_)->RemoveObserver(this); - if (window_util::IsFasterSplitScreenOrSnapGroupEnabledInClamshell() && - IsInOverviewSession()) { - // `EndOverview()` will also try to end this again. - base::AutoReset<bool> ignore(&is_shutting_down_, true); - Shell::Get()->overview_controller()->EndOverview( - OverviewEndAction::kSplitView); - } } void SplitViewOverviewSession::Init(std::optional<OverviewStartAction> action, @@ -236,10 +226,16 @@ presentation_time_recorder_->RequestNext(); } - if (GetOverviewSession()) { + if (window_util::IsFasterSplitScreenOrSnapGroupEnabledInClamshell() && + IsInOverviewSession()) { + // When `FasterSplitScreenSetup` or `SnapGroup` is enabled, we need to + // manually refresh the grid bounds, because `OverviewGrid` will calculate + // the bounds based on `SplitViewController::divider_position_` which + // wouldn't work for multiple groups. GetOverviewSession() ->GetGridWithRootWindow(window->GetRootWindow()) ->RefreshGridBounds(/*animate=*/false); + return; } // SplitViewController will update the divider position and notify observers @@ -254,9 +250,7 @@ void SplitViewOverviewSession::OnWindowDestroying(aura::Window* window) { CHECK(window_observation_.IsObservingSource(window)); CHECK_EQ(window_, window); - // Destroys `this`. - RootWindowController::ForWindow(window_)->EndSplitViewOverviewSession( - SplitViewOverviewSessionExitPoint::kWindowDestroy); + MaybeEndOverview(SplitViewOverviewSessionExitPoint::kWindowDestroy); } void SplitViewOverviewSession::OnPreWindowStateTypeChange( @@ -266,9 +260,25 @@ // Normally split view would have ended and destroy this, but the window can // get unsnapped, e.g. during mid-drag or mid-resize, so bail out here. if (!window_state->IsSnapped()) { - RootWindowController::ForWindow(window_)->EndSplitViewOverviewSession( - SplitViewOverviewSessionExitPoint::kUnspecified); + MaybeEndOverview(SplitViewOverviewSessionExitPoint::kUnspecified); } } +void SplitViewOverviewSession::MaybeEndOverview( + SplitViewOverviewSessionExitPoint exit_point) { + if (window_util::IsFasterSplitScreenOrSnapGroupEnabledInClamshell()) { + // If `FasterSplitScreenOrSnapGroup` is enabled, end full overview. + RecordSplitViewOverviewSessionExitPointMetrics(exit_point); + // `EndOverview()` will also destroy `this`. + Shell::Get()->overview_controller()->EndOverview( + OverviewEndAction::kSplitView); + return; + } + // Otherwise simply end `SplitViewOverviewSession` and remain in overview. + // TODO(sophiewen): Fix tests that expect overview to still be active after + // `FasterSplitScreenOrSnapGroup` is enabled. + RootWindowController::ForWindow(window_)->EndSplitViewOverviewSession( + exit_point); +} + } // namespace ash
diff --git a/ash/wm/splitview/split_view_overview_session.h b/ash/wm/splitview/split_view_overview_session.h index f2def26..e0380a5 100644 --- a/ash/wm/splitview/split_view_overview_session.h +++ b/ash/wm/splitview/split_view_overview_session.h
@@ -99,6 +99,9 @@ } private: + // Either ends full overview, or only `SplitViewOverviewSession`. + void MaybeEndOverview(SplitViewOverviewSessionExitPoint exit_point); + // True while we are processing a window resize event. bool is_resizing_ = false; @@ -113,9 +116,6 @@ // the opposite side. const raw_ptr<aura::Window> window_; - // True when `this` is being destroyed. - bool is_shutting_down_ = false; - SplitViewOverviewSetupType setup_type_ = SplitViewOverviewSetupType::kSnapThenAutomaticOverview;
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc index a0cee8c..b55139b4 100644 --- a/cc/raster/bitmap_raster_buffer_provider.cc +++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -34,8 +34,6 @@ base::UnsafeSharedMemoryRegion AllocateSharedMemory( const gfx::Size& size, viz::SharedImageFormat format) { - DCHECK(format.IsBitmapFormatSupported()) - << "(format = " << format.ToString() << ")"; size_t bytes = 0; if (!viz::ResourceSizes::MaybeSizeInBytes(size, format, &bytes)) { @@ -83,6 +81,7 @@ public: BitmapRasterBufferImpl(const gfx::Size& size, const gfx::ColorSpace& color_space, + BitmapSoftwareBacking* backing, void* pixels, uint64_t resource_content_id, uint64_t previous_content_id) @@ -90,8 +89,8 @@ color_space_(color_space), pixels_(pixels), resource_has_previous_content_( - resource_content_id && resource_content_id == previous_content_id) { - } + resource_content_id && resource_content_id == previous_content_id), + backing_(backing) {} BitmapRasterBufferImpl(const BitmapRasterBufferImpl&) = delete; BitmapRasterBufferImpl& operator=(const BitmapRasterBufferImpl&) = delete; @@ -112,9 +111,13 @@ << "Why are we rastering a tile that's not dirty?"; size_t stride = 0u; + viz::SharedImageFormat format = + backing_->frame_sink->shared_image_interface() + ? viz::SinglePlaneFormat::kBGRA_8888 + : viz::SinglePlaneFormat::kRGBA_8888; RasterBufferProvider::PlaybackToMemory( - pixels_, viz::SinglePlaneFormat::kRGBA_8888, resource_size_, stride, - raster_source, raster_full_rect, playback_rect, transform, color_space_, + pixels_, format, resource_size_, stride, raster_source, + raster_full_rect, playback_rect, transform, color_space_, /*gpu_compositing=*/false, playback_settings); } @@ -129,6 +132,7 @@ // `mmap`, MapViewOfFile or base::AllocPages directly. RAW_PTR_EXCLUSION void* const pixels_; bool resource_has_previous_content_; + raw_ptr<BitmapSoftwareBacking> backing_; }; } // namespace @@ -147,7 +151,9 @@ bool depends_on_at_raster_decodes, bool depends_on_hardware_accelerated_jpeg_candidates, bool depends_on_hardware_accelerated_webp_candidates) { - DCHECK_EQ(resource.format(), viz::SinglePlaneFormat::kRGBA_8888); + DCHECK_EQ(resource.format(), frame_sink_->shared_image_interface() + ? viz::SinglePlaneFormat::kBGRA_8888 + : viz::SinglePlaneFormat::kRGBA_8888); const gfx::Size& size = resource.size(); const gfx::ColorSpace& color_space = resource.color_space(); @@ -158,19 +164,19 @@ if (frame_sink_->shared_image_interface()) { constexpr char kDebugLabel[] = "BitmapRasterBufferProvider"; backing->unsafe_region = - AllocateSharedMemory(size, viz::SinglePlaneFormat::kRGBA_8888); + AllocateSharedMemory(size, viz::SinglePlaneFormat::kBGRA_8888); backing->mapping = backing->unsafe_region.Map(); gfx::GpuMemoryBufferHandle handle; handle.type = gfx::SHARED_MEMORY_BUFFER; handle.offset = 0; handle.stride = static_cast<int32_t>(gfx::RowSizeForBufferFormat( - size.width(), gfx::BufferFormat::RGBA_8888, 0)); + size.width(), gfx::BufferFormat::BGRA_8888, 0)); handle.region = backing->unsafe_region.Duplicate(); backing->shared_image = frame_sink_->shared_image_interface()->CreateSharedImage( - viz::SinglePlaneFormat::kRGBA_8888, size, color_space, + viz::SinglePlaneFormat::kBGRA_8888, size, color_space, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, gpu::SHARED_IMAGE_USAGE_CPU_WRITE, kDebugLabel, std::move(handle)); @@ -192,14 +198,16 @@ static_cast<BitmapSoftwareBacking*>(resource.software_backing()); return std::make_unique<BitmapRasterBufferImpl>( - size, color_space, backing->mapping.memory(), resource_content_id, - previous_content_id); + size, color_space, backing, backing->mapping.memory(), + resource_content_id, previous_content_id); } void BitmapRasterBufferProvider::Flush() {} viz::SharedImageFormat BitmapRasterBufferProvider::GetFormat() const { - return viz::SinglePlaneFormat::kRGBA_8888; + return frame_sink_->shared_image_interface() + ? viz::SinglePlaneFormat::kBGRA_8888 + : viz::SinglePlaneFormat::kRGBA_8888; } bool BitmapRasterBufferProvider::IsResourcePremultiplied() const {
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index c16d9f31..c32d72f 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -401,7 +401,7 @@ if (mUseMagicSpace) return; if (type == TabSelectionType.FROM_CLOSE - && UrlUtilities.isNTPUrl(tab.getUrl())) { + && UrlUtilities.isNtpUrl(tab.getUrl())) { setTabCarouselVisibility(false); } } @@ -1621,7 +1621,7 @@ return mTabModelSelector.isTabStateInitialized() && currentTab != null && currentTab.getUrl() != null - ? UrlUtilities.isNTPUrl(currentTab.getUrl()) + ? UrlUtilities.isNtpUrl(currentTab.getUrl()) : ChromeSharedPreferences.getInstance() .readInt( ChromePreferenceKeys.APP_LAUNCH_LAST_KNOWN_ACTIVE_TAB_STATE)
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherOnNtpMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherOnNtpMediator.java index d58816f..2e82310 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherOnNtpMediator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherOnNtpMediator.java
@@ -211,7 +211,7 @@ * @return Whether has a Tab to track. Returns false if the Tab to track is set as null. */ boolean setTab(Tab tabToTrack) { - if (tabToTrack != null && UrlUtilities.isNTPUrl(tabToTrack.getUrl())) { + if (tabToTrack != null && UrlUtilities.isNtpUrl(tabToTrack.getUrl())) { tabToTrack = null; }
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartNewTabFromLauncherTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartNewTabFromLauncherTest.java index 1b1c45b1..2864a39 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartNewTabFromLauncherTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartNewTabFromLauncherTest.java
@@ -125,7 +125,7 @@ Assert.assertFalse(cta.getLayoutManager().isLayoutVisible(LayoutType.TAB_SWITCHER)); TestThreadUtils.runOnUiThreadBlocking( () -> { - Assert.assertTrue(UrlUtilities.isNTPUrl(cta.getActivityTab().getUrl())); + Assert.assertTrue(UrlUtilities.isNtpUrl(cta.getActivityTab().getUrl())); }); } @@ -147,7 +147,7 @@ Assert.assertFalse(cta.getLayoutManager().isLayoutVisible(LayoutType.TAB_SWITCHER)); TestThreadUtils.runOnUiThreadBlocking( () -> { - Assert.assertTrue(UrlUtilities.isNTPUrl(cta.getActivityTab().getUrl())); + Assert.assertTrue(UrlUtilities.isNtpUrl(cta.getActivityTab().getUrl())); }); }
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ShowNtpAtStartupTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ShowNtpAtStartupTest.java index 43353f02c..5fdfa909 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ShowNtpAtStartupTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ShowNtpAtStartupTest.java
@@ -150,7 +150,7 @@ public void testShowNtpAtStartupWithNtpExist() throws IOException { // The existing NTP isn't the last active Tab. String modifiedNtpUrl = UrlConstants.NTP_URL + "/1"; - Assert.assertTrue(UrlUtilities.isNTPUrl(modifiedNtpUrl)); + Assert.assertTrue(UrlUtilities.isNtpUrl(modifiedNtpUrl)); HistogramWatcher histogram = HistogramWatcher.newBuilder() @@ -178,7 +178,7 @@ public void testShowNtpAtStartupWithActiveNtpExist() throws IOException { // The existing NTP is set as the last active Tab. String modifiedNtpUrl = UrlConstants.NTP_URL + "/1"; - Assert.assertTrue(UrlUtilities.isNTPUrl(modifiedNtpUrl)); + Assert.assertTrue(UrlUtilities.isNtpUrl(modifiedNtpUrl)); HistogramWatcher histogram = HistogramWatcher.newBuilder() .expectBooleanRecord(HOME_SURFACE_SHOWN_AT_STARTUP_UMA, true)
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 79c5ac3..d48e480 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -502,7 +502,7 @@ // Click the home button should navigate to NTP instead of showing start surface. StartSurfaceTestUtils.pressHomePageButton(cta); CriteriaHelper.pollUiThread( - () -> UrlUtilities.isNTPUrl(cta.getTabModelSelector().getCurrentTab().getUrl())); + () -> UrlUtilities.isNtpUrl(cta.getTabModelSelector().getCurrentTab().getUrl())); assertFalse( cta.getLayoutManager() .isLayoutVisible(StartSurfaceTestUtils.getStartSurfaceLayoutType()));
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java index e91feeea..eaf5bde4 100644 --- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java +++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -99,7 +99,6 @@ import org.chromium.chrome.browser.logo.LogoBridge; import org.chromium.chrome.browser.logo.LogoBridgeJni; import org.chromium.chrome.browser.logo.LogoView; -import org.chromium.chrome.browser.night_mode.NightModeStateProvider; import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.omnibox.OmniboxStub; import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; @@ -164,7 +163,6 @@ @Mock private OmniboxStub mOmniboxStub; @Mock private ExploreSurfaceCoordinator mExploreSurfaceCoordinator; @Mock private ExploreSurfaceCoordinatorFactory mExploreSurfaceCoordinatorFactory; - @Mock private NightModeStateProvider mNightModeStateProvider; @Mock private BrowserControlsStateProvider mBrowserControlsStateProvider; @Mock private StartSurfaceMediator.ActivityStateChecker mActivityStateChecker; @Mock private VoiceRecognitionHandler mVoiceRecognitionHandler; @@ -178,7 +176,7 @@ @Mock private Supplier<Tab> mParentTabSupplier; @Mock private View mLogoContainerView; @Mock private LogoView mLogoView; - @Mock LogoBridge.Natives mLogoBridge; + @Mock private LogoBridge.Natives mLogoBridge; @Mock private Profile mProfile; @Mock private TemplateUrlService mTemplateUrlService; @Mock private ActivityLifecycleDispatcher mActivityLifecycleDispatcher; @@ -205,15 +203,15 @@ @Captor private ArgumentCaptor<TemplateUrlServiceObserver> mTemplateUrlServiceObserverCaptor; - private ObservableSupplierImpl<Boolean> + private final ObservableSupplierImpl<Boolean> mCarouselTabSwitcherModuleControllerBackPressStateSupplier = new ObservableSupplierImpl<>(); - private ObservableSupplierImpl<Boolean> + private final ObservableSupplierImpl<Boolean> mCarouselTabSwitcherModuleControllerDialogVisibleSupplier = new ObservableSupplierImpl<>(); - private ObservableSupplierImpl<Boolean> mSecondaryControllerBackPressStateSupplier = + private final ObservableSupplierImpl<Boolean> mSecondaryControllerBackPressStateSupplier = new ObservableSupplierImpl<>(); - private ObservableSupplierImpl<Boolean> mSecondaryControllerDialogVisibleSupplier = + private final ObservableSupplierImpl<Boolean> mSecondaryControllerDialogVisibleSupplier = new ObservableSupplierImpl<>(); private ObservableSupplierImpl<Profile> mProfileSupplier = new ObservableSupplierImpl<>();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java index 0cf1550..6d877414f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
@@ -361,7 +361,7 @@ isStandardActiveIndex, isIncognitoActiveIndex) -> { // Skip restoring of non-selected NTP to match the real restoration logic. - if (UrlUtilities.isCanonicalizedNTPUrl(url) && !isStandardActiveIndex) { + if (UrlUtilities.isCanonicalizedNtpUrl(url) && !isStandardActiveIndex) { return; } PseudoTab tab = PseudoTab.fromTabId(id);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java index e700c5e6..9beb94b 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
@@ -478,7 +478,7 @@ */ void getFaviconForUrlAsync( GURL url, boolean isIncognito, Callback<TabFavicon> faviconCallback) { - if (mFaviconHelper == null || UrlUtilities.isNTPUrl(url)) { + if (mFaviconHelper == null || UrlUtilities.isNtpUrl(url)) { faviconCallback.onResult(getRoundedChromeFavicon(isIncognito)); } else { mFaviconHelper.getLocalFaviconImageForURL(
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index a50da5d6..88d13bc6 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -467,7 +467,7 @@ // new one. // See https://crbug.com/1359002. if (navigationHandle.isSameDocument() - || UrlUtilities.isNTPUrl(tab.getUrl()) + || UrlUtilities.isNtpUrl(tab.getUrl()) || tab.getUrl().equals(navigationHandle.getUrl())) { return; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java new file mode 100644 index 0000000..71cb8ea --- /dev/null +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java
@@ -0,0 +1,50 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.tab_management; + +import android.view.View.OnClickListener; + +import androidx.annotation.NonNull; + +import org.chromium.chrome.browser.hub.DrawableButtonData; +import org.chromium.chrome.browser.hub.LoadHint; +import org.chromium.chrome.browser.hub.Pane; +import org.chromium.chrome.browser.hub.PaneId; +import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable; + +/** + * A {@link Pane} representing the tab switcher. This is effectively an adapter layer between the + * {@link Pane} and {@link TabSwitcher} APIs. + */ +public class TabSwitcherPane extends TabSwitcherPaneBase { + /** + * @param tabSwitcher The {@link TabSwitcher} hosted by the Pane. + * @param newTabButtonClickListener The {@link OnClickListener} for the new tab button. + * @param tabSwitcherDrawable The {@link TabSwitcherDrawable} to represent the UI. + */ + TabSwitcherPane( + @NonNull TabSwitcher tabSwitcher, + @NonNull OnClickListener newTabButtonClickListener, + @NonNull TabSwitcherDrawable tabSwitcherDrawable) { + super(tabSwitcher, newTabButtonClickListener); + + // TODO(crbug/1505772): Update this string to not be an a11y string and it should probably + // just say "Tabs". + mReferenceButtonDataSupplier.set( + new DrawableButtonData( + org.chromium.chrome.tab_ui.R.string.accessibility_tab_switcher, + tabSwitcherDrawable)); + } + + @Override + public @PaneId int getPaneId() { + return PaneId.TAB_SWITCHER; + } + + @Override + public void notifyLoadHint(@LoadHint int loadHint) { + // TODO(crbug/1505772): Implement. + } +}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java new file mode 100644 index 0000000..c2f6d17 --- /dev/null +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java
@@ -0,0 +1,97 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.tab_management; + +import android.view.View; +import android.view.View.OnClickListener; + +import androidx.annotation.NonNull; + +import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.base.supplier.ObservableSupplierImpl; +import org.chromium.chrome.browser.hub.DelegateButtonData; +import org.chromium.chrome.browser.hub.DisplayButtonData; +import org.chromium.chrome.browser.hub.FadeHubLayoutAnimationFactory; +import org.chromium.chrome.browser.hub.FullButtonData; +import org.chromium.chrome.browser.hub.HubContainerView; +import org.chromium.chrome.browser.hub.HubLayoutAnimatorProvider; +import org.chromium.chrome.browser.hub.HubLayoutConstants; +import org.chromium.chrome.browser.hub.Pane; +import org.chromium.chrome.browser.hub.ResourceButtonData; +import org.chromium.ui.base.DeviceFormFactor; + +/** + * A abstract {@link Pane} representing a tab switcher for shared logic between the normal and + * incognito modes. This is effectively an adapter layer between the {@link Pane} and {@link + * TabSwitcher} APIs. + */ +public abstract class TabSwitcherPaneBase implements Pane { + protected final TabSwitcher mTabSwitcher; + protected final ObservableSupplierImpl<DisplayButtonData> mReferenceButtonDataSupplier = + new ObservableSupplierImpl<>(); + protected final ObservableSupplierImpl<FullButtonData> mNewTabButtonDataSupplier = + new ObservableSupplierImpl<>(); + + private OnClickListener mNewTabButtonClickListener; + + /** + * @param tabSwitcher The {@link TabSwitcher} hosted by the Pane. + * @param newTabButtonClickListener The {@link OnClickListener} for the new tab button. + */ + TabSwitcherPaneBase( + @NonNull TabSwitcher tabSwitcher, @NonNull OnClickListener newTabButtonClickListener) { + mTabSwitcher = tabSwitcher; + + mNewTabButtonDataSupplier.set( + new DelegateButtonData( + new ResourceButtonData( + org.chromium.chrome.browser.toolbar.R.string.button_new_tab, + org.chromium.chrome.browser.toolbar.R.drawable.new_tab_icon), + () -> newTabButtonClickListener.onClick(null))); + } + + @Override + public @NonNull View getRootView() { + return mTabSwitcher.getController().getTabSwitcherContainer(); + } + + @Override + public @NonNull ObservableSupplier<FullButtonData> getActionButtonDataSupplier() { + return mNewTabButtonDataSupplier; + } + + @Override + public @NonNull ObservableSupplier<DisplayButtonData> getReferenceButtonDataSupplier() { + return mReferenceButtonDataSupplier; + } + + @Override + public @NonNull HubLayoutAnimatorProvider createShowHubLayoutAnimatorProvider( + @NonNull HubContainerView hubContainerView) { + assert !DeviceFormFactor.isNonMultiDisplayContextOnTablet(hubContainerView.getContext()); + // TODO(crbug/1505772): Replace with shrink animator. + return FadeHubLayoutAnimationFactory.createFadeInAnimatorProvider( + hubContainerView, HubLayoutConstants.FADE_DURATION_MS); + } + + @Override + public @NonNull HubLayoutAnimatorProvider createHideHubLayoutAnimatorProvider( + @NonNull HubContainerView hubContainerView) { + assert !DeviceFormFactor.isNonMultiDisplayContextOnTablet(hubContainerView.getContext()); + // TODO(crbug/1505772): Replace with expand animator. + return FadeHubLayoutAnimationFactory.createFadeOutAnimatorProvider( + hubContainerView, HubLayoutConstants.FADE_DURATION_MS); + } + + @Override + public @BackPressResult int handleBackPress() { + return mTabSwitcher.getController().handleBackPress(); + } + + @Override + public ObservableSupplier<Boolean> getHandleBackPressChangedSupplier() { + return mTabSwitcher.getController().getHandleBackPressChangedSupplier(); + } +}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java new file mode 100644 index 0000000..c512486 --- /dev/null +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java
@@ -0,0 +1,158 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.tab_management; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import androidx.appcompat.content.res.AppCompatResources; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.base.supplier.ObservableSupplierImpl; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.hub.DisplayButtonData; +import org.chromium.chrome.browser.hub.FullButtonData; +import org.chromium.chrome.browser.hub.HubContainerView; +import org.chromium.chrome.browser.hub.HubLayoutAnimationType; +import org.chromium.chrome.browser.hub.LoadHint; +import org.chromium.chrome.browser.hub.PaneId; +import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable; +import org.chromium.components.browser_ui.widget.gesture.BackPressHandler.BackPressResult; + +/** Unit tests for {@link TabSwitcherPane}. */ +@RunWith(BaseRobolectricTestRunner.class) +public class TabSwitcherPaneUnitTest { + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock private TabSwitcher mTabSwitcher; + @Mock private TabSwitcher.Controller mTabSwitcherController; + @Mock private TabSwitcherDrawable mTabSwitcherDrawable; + @Mock private HubContainerView mHubContainerView; + @Mock private ViewGroup mContainerView; + @Mock private View.OnClickListener mNewTabButtonClickListener; + + private Context mContext; + private ObservableSupplierImpl<Boolean> mHandleBackPressChangeSupplier = + new ObservableSupplierImpl<>(); + private TabSwitcherPane mTabSwitcherPane; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + when(mHubContainerView.getContext()).thenReturn(mContext); + when(mTabSwitcher.getController()).thenReturn(mTabSwitcherController); + mHandleBackPressChangeSupplier.set(false); + when(mTabSwitcherController.getTabSwitcherContainer()).thenReturn(mContainerView); + when(mTabSwitcherController.getHandleBackPressChangedSupplier()) + .thenReturn(mHandleBackPressChangeSupplier); + doAnswer( + invocation -> { + return mHandleBackPressChangeSupplier.get() + ? BackPressResult.SUCCESS + : BackPressResult.FAILURE; + }) + .when(mTabSwitcherController) + .handleBackPress(); + + mTabSwitcherPane = + new TabSwitcherPane(mTabSwitcher, mNewTabButtonClickListener, mTabSwitcherDrawable); + } + + @Test + @SmallTest + public void testPaneId() { + assertEquals(PaneId.TAB_SWITCHER, mTabSwitcherPane.getPaneId()); + } + + @Test + @SmallTest + public void testLoadHint() { + // TODO(crbug/1505772): this is a noop right now. + mTabSwitcherPane.notifyLoadHint(LoadHint.COLD); + mTabSwitcherPane.notifyLoadHint(LoadHint.WARM); + mTabSwitcherPane.notifyLoadHint(LoadHint.HOT); + } + + @Test + @SmallTest + public void testGetRootView() { + assertEquals(mContainerView, mTabSwitcherPane.getRootView()); + } + + @Test + @SmallTest + public void testNewTabButton() { + FullButtonData buttonData = mTabSwitcherPane.getActionButtonDataSupplier().get(); + + assertEquals(mContext.getString(R.string.button_new_tab), buttonData.resolveText(mContext)); + assertTrue( + AppCompatResources.getDrawable(mContext, R.drawable.new_tab_icon) + .getConstantState() + .equals(buttonData.resolveIcon(mContext).getConstantState())); + + buttonData.getOnPressRunnable().run(); + verify(mNewTabButtonClickListener).onClick(isNull()); + } + + @Test + @SmallTest + public void testReferenceButton() { + DisplayButtonData buttonData = mTabSwitcherPane.getReferenceButtonDataSupplier().get(); + + assertEquals( + mContext.getString(R.string.accessibility_tab_switcher), + buttonData.resolveText(mContext)); + assertEquals(mTabSwitcherDrawable, buttonData.resolveIcon(mContext)); + } + + @Test + @SmallTest + public void testBackPress() { + ObservableSupplier<Boolean> handlesBackPressSupplier = + mTabSwitcherPane.getHandleBackPressChangedSupplier(); + assertFalse(handlesBackPressSupplier.get()); + assertEquals(BackPressResult.FAILURE, mTabSwitcherPane.handleBackPress()); + + mHandleBackPressChangeSupplier.set(true); + assertTrue(handlesBackPressSupplier.get()); + assertEquals(BackPressResult.SUCCESS, mTabSwitcherPane.handleBackPress()); + } + + @Test + @SmallTest + public void testCreatesAnimatorProviders() { + // TODO(crbug/1505772): This test will need to be reworked to confirm shrink expand + // animators are correctly created. This is a temporary test for coverage. + assertEquals( + HubLayoutAnimationType.FADE_OUT, + mTabSwitcherPane + .createHideHubLayoutAnimatorProvider(mHubContainerView) + .getPlannedAnimationType()); + assertEquals( + HubLayoutAnimationType.FADE_IN, + mTabSwitcherPane + .createShowHubLayoutAnimatorProvider(mHubContainerView) + .getPlannedAnimationType()); + } +}
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java index a4f15f7..704f96b3 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -29,7 +29,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.areAnimatorsEnabled; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.closeFirstTabInTabSwitcher; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.createTabGroup; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.createTabs; @@ -125,7 +124,6 @@ import org.chromium.chrome.test.util.MenuUtils; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; -import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.WebContentsUtils; @@ -189,8 +187,8 @@ @SuppressWarnings("FieldCanBeLocal") private EmbeddedTestServer mTestServer; - @Nullable private TabSwitcherAndStartSurfaceLayout mTabSwitcherAndStartSurfaceLayout; - @Nullable private TabSwitcherLayout mTabSwitcherLayout; + private @Nullable TabSwitcherAndStartSurfaceLayout mTabSwitcherAndStartSurfaceLayout; + private @Nullable TabSwitcherLayout mTabSwitcherLayout; private String mUrl; private int mRepeat; private List<WeakReference<Bitmap>> mAllBitmaps = new LinkedList<>(); @@ -338,8 +336,7 @@ @UseMethodParameter(RefactorTestParams.class) @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study"}) @CommandLineFlags.Add({BASE_PARAMS}) - public void testSwitchTabModel_ScrollToSelectedTab(boolean isStartSurfaceRefactorEnabled) - throws IOException { + public void testSwitchTabModel_ScrollToSelectedTab(boolean isStartSurfaceRefactorEnabled) { ChromeTabbedActivity cta = mActivityTestRule.getActivity(); prepareTabs(10, 0, "about:blank"); assertEquals(9, cta.getCurrentTabModel().index()); @@ -405,7 +402,6 @@ // Make sure all thumbnails are there before switching tabs. enterGTSWithThumbnailRetry(); leaveTabSwitcher(cta); - // Espresso.pressBack(); ChromeTabUtils.switchTabInCurrentTabModel(cta, 0); enterTabSwitcher(cta); @@ -432,7 +428,6 @@ // Make sure all thumbnails are there before switching tabs. enterGTSWithThumbnailRetry(); leaveTabSwitcher(cta); - // Espresso.pressBack(); ChromeTabUtils.switchTabInCurrentTabModel(cta, 0); enterTabSwitcher(cta); @@ -758,18 +753,6 @@ return doneHiding; }, "Overview not hidden yet"); - int delta; - if (switchToAnotherTab - && !UrlUtilities.isNTPUrl( - mActivityTestRule - .getActivity() - .getCurrentWebContents() - .getLastCommittedUrl())) { - // Capture the original tab. - delta = 1; - } else { - delta = 0; - } } } @@ -1294,8 +1277,7 @@ // TODO(crbug.com/1491942): This fails with the field trial testing config. "disable-field-trial-config" }) - public void testThumbnailFetchingResult_liveLayer(boolean isStartSurfaceRefactorEnabled) - throws Exception { + public void testThumbnailFetchingResult_liveLayer(boolean isStartSurfaceRefactorEnabled) { // May be called when setting both grid card size and thumbnail fetcher. var histograms = HistogramWatcher.newBuilder() @@ -1561,8 +1543,7 @@ @UseMethodParameter(RefactorTestParams.class) @DisableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION) @DisabledTest(message = "crbug.com/1096997") - public void testTabGroupManualSelection(boolean isStartSurfaceRefactorEnabled) - throws InterruptedException { + public void testTabGroupManualSelection(boolean isStartSurfaceRefactorEnabled) { ChromeTabbedActivity cta = mActivityTestRule.getActivity(); TabListEditorTestingRobot robot = new TabListEditorTestingRobot(); createTabs(cta, false, 3); @@ -1671,7 +1652,7 @@ @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study"}) @DisabledTest(message = "crbug.com/1187320 This doesn't work with FeedV2 and crbug.com/1096295") public void testActivityCanBeGarbageCollectedAfterFinished( - boolean isStartSurfaceRefactorEnabled) throws Exception { + boolean isStartSurfaceRefactorEnabled) { prepareTabs(1, 0, "about:blank"); WeakReference<ChromeTabbedActivity> activityRef = @@ -1740,8 +1721,7 @@ @MediumTest @UseMethodParameter(RefactorTestParams.class) @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION}) - public void testUndoClosure_AccessibilityMode(boolean isStartSurfaceRefactorEnabled) - throws Exception { + public void testUndoClosure_AccessibilityMode(boolean isStartSurfaceRefactorEnabled) { TestThreadUtils.runOnUiThreadBlocking( () -> ChromeAccessibilityUtil.get().setAccessibilityEnabledForTesting(true)); ChromeTabbedActivity cta = mActivityTestRule.getActivity(); @@ -1771,7 +1751,7 @@ }) // TODO(crbug.com/1112557): Remove this test when critical tests in StartSurfaceLayoutTest are // running with InstantStart on. - public void testSetup_WithInstantStart(boolean isStartSurfaceRefactorEnabled) throws Exception { + public void testSetup_WithInstantStart(boolean isStartSurfaceRefactorEnabled) { ChromeTabbedActivity cta = mActivityTestRule.getActivity(); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 1); @@ -2108,7 +2088,7 @@ @Test @MediumTest - public void testEmptyStateView_ToggleIncognito() throws Exception { + public void testEmptyStateView_ToggleIncognito() { mActivityTestRule.loadUrl(mUrl); ChromeTabbedActivity cta = mActivityTestRule.getActivity(); @@ -2258,21 +2238,6 @@ LayoutTestUtils.startShowingAndWaitForLayout( mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER, true); - // Make sure the fading animation is done. - int delta; - if (UrlUtilities.isNTPUrl( - mActivityTestRule.getActivity().getCurrentWebContents().getLastCommittedUrl())) { - // NTP is not invalidated, so no new captures. - delta = 0; - } else { - // The final capture at StartSurfaceLayout#finishedShowing time. - delta = 1; - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_TO_GTS_ANIMATION) - && areAnimatorsEnabled()) { - // The faster capturing without writing back to cache. - delta += 1; - } - } TabUiTestHelper.verifyAllTabsHaveThumbnail( mActivityTestRule.getActivity().getCurrentTabModel()); } @@ -2318,7 +2283,7 @@ assertThumbnailsAreReleased(); } - /** Enters the GTS and leaves if Start surface refactoring isn't enabled. TODO( */ + /** Enters the GTS and leaves if Start surface refactoring isn't enabled. */ private void mayEnterGTSAndLeave(ChromeTabbedActivity cta) throws InterruptedException { if (mIsStartSurfaceRefactorEnabled) return; @@ -2401,25 +2366,6 @@ outputStream.close(); } - private void verifyAllThumbnailHasAspectRatio(double ratio) { - TabModel currentModel = mActivityTestRule.getActivity().getCurrentTabModel(); - for (int i = 0; i < currentModel.getCount(); i++) { - Tab tab = currentModel.getTabAt(i); - Bitmap bitmap = TabContentManager.getJpegForTab(tab.getId(), null); - double bitmapRatio = bitmap.getWidth() * 1.0 / bitmap.getHeight(); - int pixelDelta = - Math.abs((int) Math.round(bitmap.getHeight() * ratio) - bitmap.getWidth()); - assertTrue( - "Actual ratio: " - + bitmapRatio - + "; Expected ratio: " - + ratio - + "; Pixel delta: " - + pixelDelta, - pixelDelta <= bitmap.getWidth() * TabContentManager.PIXEL_TOLERANCE_PERCENT); - } - } - private void verifyOnlyOneTabSuggestionMessageCardIsShowing() throws InterruptedException { String suggestionMessageTemplate = mActivityTestRule
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni index f297e4e..179054aa 100644 --- a/chrome/android/features/tab_ui/tab_management_java_sources.gni +++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -100,6 +100,8 @@ "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java", + "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java", + "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiMetricsHelper.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ThumbnailProvider.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsClientFetcher.java", @@ -135,6 +137,7 @@ ] tab_management_junit_java_sources = [ + "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCacheUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtilsUnitTest.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java index 4fdfea5..3194ddb 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java
@@ -119,7 +119,7 @@ // NTP itself, at which point the last committed entry is not for the NTP yet. This method // will then be called a second time when the user navigates away, at which point the last // committed entry is for the NTP. The extra data must only be set in the latter case. - if (!UrlUtilities.isNTPUrl(entry.getUrl())) return; + if (!UrlUtilities.isNtpUrl(entry.getUrl())) return; controller.setEntryExtraData( index, FEED_SAVED_INSTANCE_STATE_KEY, mCoordinator.getSavedInstanceStateString());
diff --git a/chrome/android/java/res/layout/sync_custom_passphrase.xml b/chrome/android/java/res/layout/sync_custom_passphrase.xml index c40f573e..bfbd1a64 100644 --- a/chrome/android/java/res/layout/sync_custom_passphrase.xml +++ b/chrome/android/java/res/layout/sync_custom_passphrase.xml
@@ -35,6 +35,8 @@ android:layout_height="wrap_content" android:layout_marginBottom="25dp" android:layout_marginTop="25dp" - android:text="@string/new_sync_custom_passphrase" /> + android:text="@string/new_sync_custom_passphrase" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" + /> </LinearLayout> </ScrollView>
diff --git a/chrome/android/java/res/layout/sync_enter_passphrase.xml b/chrome/android/java/res/layout/sync_enter_passphrase.xml index ae751ff..4234516 100644 --- a/chrome/android/java/res/layout/sync_enter_passphrase.xml +++ b/chrome/android/java/res/layout/sync_enter_passphrase.xml
@@ -35,6 +35,7 @@ android:id="@+id/reset_text" android:layout_width="match_parent" android:layout_height="wrap_content" - android:visibility="gone" /> + android:visibility="gone" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" /> </LinearLayout> </ScrollView>
diff --git a/chrome/android/java/res/layout/sync_passphrase_types.xml b/chrome/android/java/res/layout/sync_passphrase_types.xml index 6d9c9a2..0f3389e0 100644 --- a/chrome/android/java/res/layout/sync_passphrase_types.xml +++ b/chrome/android/java/res/layout/sync_passphrase_types.xml
@@ -42,6 +42,7 @@ android:id="@+id/reset_sync_link" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingTop="25dp" /> + android:paddingTop="25dp" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" /> </LinearLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 0fbd9284..35553a7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1498,7 +1498,7 @@ onStandardActiveIndexRead = url -> { mLastActiveTabUrl = url; - if (UrlUtilities.isNTPUrl(url)) { + if (UrlUtilities.isNtpUrl(url)) { assert !mTabModelSelector.isIncognitoSelected(); isActiveUrlNTP.set(true); } @@ -1658,7 +1658,7 @@ } else { // Migrate legacy NTP URLs (chrome://newtab) to the newer format // (chrome-native://newtab) - if (UrlUtilities.isNTPUrl(homepageGurl)) { + if (UrlUtilities.isNtpUrl(homepageGurl)) { url = UrlConstants.NTP_URL; } else { url = homepageGurl.getSpec(); @@ -2813,7 +2813,7 @@ } private boolean isTabNtp(Tab tab) { - return tab != null && UrlUtilities.isNTPUrl(tab.getUrl()); + return tab != null && UrlUtilities.isNtpUrl(tab.getUrl()); } private boolean isTabRegularNtp(Tab tab) { @@ -3112,7 +3112,7 @@ */ private Tab launchIntent( LoadUrlParams loadUrlParams, String externalAppId, boolean forceNewTab, Intent intent) { - if (mUIWithNativeInitialized && !UrlUtilities.isNTPUrl(loadUrlParams.getUrl())) { + if (mUIWithNativeInitialized && !UrlUtilities.isNtpUrl(loadUrlParams.getUrl())) { getLayoutManager().showLayout(LayoutType.BROWSING, false); getToolbarManager().finishAnimations(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index 2da0a6d..13407f3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -2595,7 +2595,7 @@ // 'currentTab' could only be null when opening history from start surface, which is // not available on tablet. assert (isTablet() && currentTab != null) || !isTablet(); - if (currentTab != null && UrlUtilities.isNTPUrl(currentTab.getUrl())) { + if (currentTab != null && UrlUtilities.isNtpUrl(currentTab.getUrl())) { NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_HISTORY_MANAGER); } RecordUserAction.record("MobileMenuHistory");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java index b8cd4a34..35c03c4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -1307,7 +1307,7 @@ } Tab currentTab = mActivityTabProvider.get(); if (currentTab != null - && UrlUtilities.isNTPUrl(currentTab.getUrl()) + && UrlUtilities.isNtpUrl(currentTab.getUrl()) && !currentTab.isIncognito()) { BrowserUiUtils.recordModuleClickHistogram( HostSurface.NEW_TAB_PAGE, ModuleTypeOnStartAndNTP.MENU_BUTTON);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingDelegateFactory.java index 59a0c63..5be54bf1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ReparentingDelegateFactory.java
@@ -53,7 +53,7 @@ @Override public boolean isNTPUrl(GURL url) { - return UrlUtilities.isNTPUrl(url); + return UrlUtilities.isNtpUrl(url); } }; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java index 5ba7116..0498399 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java
@@ -16,6 +16,7 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Spinner; @@ -49,6 +50,8 @@ private static Callback<Fragment> sObserverForTest; private static final String EXPIRATION_DATE_SEPARATOR = "/"; private static final String EXPIRATION_DATE_REGEX = "^(0[1-9]|1[0-2])\\/(\\d{2})$"; + // TODO(crbug.com/1504662): Leverage the value from C++ code to have a single source of truth. + private static final String AMEX_NETWORK_NAME = "amex"; protected Button mDoneButton; private TextInputLayout mNameLabel; @@ -56,7 +59,7 @@ protected TextInputLayout mNicknameLabel; protected EditText mNicknameText; private TextInputLayout mNumberLabel; - private EditText mNumberText; + protected EditText mNumberText; protected Spinner mExpirationMonth; protected Spinner mExpirationYear; // Since the nickname field is optional, an empty nickname is a valid nickname. @@ -65,6 +68,7 @@ private int mInitialExpirationMonthPos; protected EditText mExpirationDate; protected EditText mCvc; + protected ImageView mCvcHintImage; private boolean mIsValidExpirationDate; private int mInitialExpirationYearPos; @@ -112,6 +116,8 @@ mExpirationDate.addTextChangedListener(expirationDateTextWatcher()); mCvc = (EditText) v.findViewById(R.id.cvc); + mCvcHintImage = (ImageView) v.findViewById(R.id.cvc_hint_image); + mNumberText.addTextChangedListener(creditCardNumberTextWatcherForCvc()); } else { RelativeLayout creditCardExpirationAndCvcLayout = (RelativeLayout) v.findViewById(R.id.credit_card_expiration_and_cvc_layout); @@ -402,6 +408,28 @@ }; } + private TextWatcher creditCardNumberTextWatcherForCvc() { + return new EmptyTextWatcher() { + private boolean mUsingAmExCvcHintImage; + + @Override + public void afterTextChanged(Editable s) { + String cardNumber = s.toString().replaceAll("\\s+", ""); + if (isAmExCard(cardNumber)) { + if (!mUsingAmExCvcHintImage) { + mUsingAmExCvcHintImage = true; + mCvcHintImage.setImageResource(R.drawable.cvc_icon_amex); + } + } else { + if (mUsingAmExCvcHintImage) { + mUsingAmExCvcHintImage = false; + mCvcHintImage.setImageResource(R.drawable.cvc_icon); + } + } + } + }; + } + @VisibleForTesting public static String getExpirationMonth(String expirationDate) { String month = expirationDate.split(EXPIRATION_DATE_SEPARATOR)[0]; @@ -436,4 +464,10 @@ } return false; } + + public static boolean isAmExCard(String cardNumber) { + return PersonalDataManager.getInstance() + .getBasicCardIssuerNetwork(cardNumber, /* emptyIfInvalid= */ false) + .equals(AMEX_NETWORK_NAME); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderPickerViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderPickerViewBinder.java index 63f2c1fa..e386827 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderPickerViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderPickerViewBinder.java
@@ -22,11 +22,13 @@ } else if (key == BookmarkFolderPickerProperties.CANCEL_CLICK_LISTENER) { View cancelButton = view.findViewById(R.id.cancel_button); cancelButton.setOnClickListener( - (ignored) -> model.get(BookmarkFolderPickerProperties.CANCEL_CLICK_LISTENER)); + (ignored) -> + model.get(BookmarkFolderPickerProperties.CANCEL_CLICK_LISTENER).run()); } else if (key == BookmarkFolderPickerProperties.MOVE_CLICK_LISTENER) { View moveButton = view.findViewById(R.id.move_button); moveButton.setOnClickListener( - (ignored) -> model.get(BookmarkFolderPickerProperties.MOVE_CLICK_LISTENER)); + (ignored) -> + model.get(BookmarkFolderPickerProperties.MOVE_CLICK_LISTENER).run()); } else if (key == BookmarkFolderPickerProperties.MOVE_BUTTON_ENABLED) { View moveButton = view.findViewById(R.id.move_button); moveButton.setEnabled(model.get(BookmarkFolderPickerProperties.MOVE_BUTTON_ENABLED));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMediator.java index 8eceb72..10187da 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMediator.java
@@ -149,7 +149,7 @@ // The link Back to Safety on the interstitial page will go to the // previous page. If there is no previous page, i.e. previous page is // NTP, the preview tab will be closed. - if (mIsOnErrorPage && UrlUtilities.isNTPUrl(url)) { + if (mIsOnErrorPage && UrlUtilities.isNtpUrl(url)) { mBottomSheetController.hideContent( mSheetContent, /* animate= */ true); mCurrentUrl = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java index 600d177..6533e32d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
@@ -192,7 +192,7 @@ // - let the caller of the LayoutManager#switchToTab observe the LayoutState and close // the ntp tab in the #doneShowing event. Tab lastTab = mTabModelSelector.getTabById(mFromTabId); - if (UrlUtilities.isNTPUrl(lastTab.getUrl()) + if (UrlUtilities.isNtpUrl(lastTab.getUrl()) && !lastTab.canGoBack() && !lastTab.canGoForward()) { mTabModelSelector
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java index a21ac49..7d5e9dc5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
@@ -279,24 +279,18 @@ ::onShowSoftInput; } - mTabController - .get() - .registerTabObserver(new PartialCustomTabTabObserver(softInputCallback)); - mTabController - .get() - .registerTabObserver( - new EmptyTabObserver() { - @Override - public void didFirstVisuallyNonEmptyPaint(Tab tab) { - BaseCustomTabActivity baseActivity = - (BaseCustomTabActivity) mActivity; - assert baseActivity != null; - baseActivity - .getContextualSearchManagerSupplier() - .get() - .setCanHideAndroidBrowserControls(false); - } - }); + var tabController = mTabController.get(); + tabController.registerTabObserver(new PartialCustomTabTabObserver(softInputCallback)); + var csManager = mContextualSearchManagerSupplier.get(); + if (csManager != null) { + tabController.registerTabObserver( + new EmptyTabObserver() { + @Override + public void didFirstVisuallyNonEmptyPaint(Tab tab) { + csManager.setCanHideAndroidBrowserControls(false); + } + }); + } } } @@ -363,20 +357,22 @@ this::isPageInsightsHubEnabled, this::getPageInsightsConfig); - mContextualSearchObserver = - new ContextualSearchObserver() { - @Override - public void onShowContextualSearch( - @Nullable GSAContextDisplaySelection selectionContext) { - mPageInsightsCoordinator.onBottomUiStateChanged(true); - } + if (mContextualSearchManagerSupplier.get() != null) { + mContextualSearchObserver = + new ContextualSearchObserver() { + @Override + public void onShowContextualSearch( + @Nullable GSAContextDisplaySelection selectionContext) { + mPageInsightsCoordinator.onBottomUiStateChanged(true); + } - @Override - public void onHideContextualSearch() { - mPageInsightsCoordinator.onBottomUiStateChanged(false); - } - }; - mContextualSearchManagerSupplier.get().addObserver(mContextualSearchObserver); + @Override + public void onHideContextualSearch() { + mPageInsightsCoordinator.onBottomUiStateChanged(false); + } + }; + mContextualSearchManagerSupplier.get().addObserver(mContextualSearchObserver); + } } boolean isPageInsightsHubEnabled() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS index 995bcc3..43c49695 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS
@@ -1,4 +1,5 @@ eirage@chromium.org +jinsukkim@chromium.org kgrosu@google.com mvanouwerkerk@chromium.org peconn@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetMediator.java index a3773cb..8c799c174 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetMediator.java
@@ -151,7 +151,7 @@ Drawable drawable; if (favicon == null) { drawable = - UrlUtilities.isNTPUrl(pageUrl) + UrlUtilities.isNtpUrl(pageUrl) ? getNTPIcon() : new BitmapDrawable( mIconGenerator.generateIconForUrl(pageUrl)); @@ -165,7 +165,7 @@ private String getEntryText(NavigationEntry entry) { String entryText = entry.getTitle(); - if (UrlUtilities.isNTPUrl(entry.getUrl())) entryText = getNTPText(); + if (UrlUtilities.isNtpUrl(entry.getUrl())) entryText = getNTPText(); if (TextUtils.isEmpty(entryText)) entryText = entry.getVirtualUrl().getSpec(); if (TextUtils.isEmpty(entryText)) entryText = entry.getUrl().getSpec(); return entryText;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java index 5e5906e..7b82221c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java
@@ -108,7 +108,7 @@ */ public static boolean shouldCloseAppWithZeroTabs() { return HomepageManager.isHomepageEnabled() - && !UrlUtilities.isNTPUrl(HomepageManager.getHomepageGurl()); + && !UrlUtilities.isNtpUrl(HomepageManager.getHomepageGurl()); } /** @@ -202,7 +202,7 @@ */ public static boolean isHomepageNonNtp() { GURL currentHomepage = getHomepageGurl(); - return !currentHomepage.isEmpty() && !UrlUtilities.isNTPUrl(currentHomepage); + return !currentHomepage.isEmpty() && !UrlUtilities.isNtpUrl(currentHomepage); } /** @@ -348,7 +348,7 @@ @VisibleForTesting public @HomepageLocationType int getHomepageLocationType() { if (HomepagePolicyManager.isHomepageManagedByPolicy()) { - return UrlUtilities.isNTPUrl(HomepagePolicyManager.getHomepageUrl()) + return UrlUtilities.isNtpUrl(HomepagePolicyManager.getHomepageUrl()) ? HomepageLocationType.POLICY_NTP : HomepageLocationType.POLICY_OTHER; } @@ -361,13 +361,13 @@ return HomepageLocationType.DEFAULT_NTP; } - return UrlUtilities.isNTPUrl( + return UrlUtilities.isNtpUrl( PartnerBrowserCustomizations.getInstance().getHomePageUrl()) ? HomepageLocationType.PARTNER_PROVIDED_NTP : HomepageLocationType.PARTNER_PROVIDED_OTHER; } // If user type NTP URI as their customized homepage, we'll record user is using NTP. - return UrlUtilities.isNTPUrl(getPrefHomepageCustomGurl()) + return UrlUtilities.isNtpUrl(getPrefHomepageCustomGurl()) ? HomepageLocationType.USER_CUSTOMIZED_NTP : HomepageLocationType.USER_CUSTOMIZED_OTHER; } @@ -397,7 +397,7 @@ return new HomepageCharacterizationHelper() { @Override public boolean isUrlNtp(@Nullable String url) { - return UrlConstants.NTP_URL.equals(url) || UrlUtilities.isNTPUrl(url); + return UrlConstants.NTP_URL.equals(url) || UrlUtilities.isNtpUrl(url); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java index c6d67d8..a09454a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java
@@ -126,10 +126,10 @@ GURL defaultGurl = HomepageManager.getDefaultHomepageGurl(); GURL customGurl = mHomepageManager.getPrefHomepageCustomGurl(); if (mHomepageManager.getPrefHomepageUseDefaultUri()) { - return UrlUtilities.isNTPUrl(defaultGurl) ? GURL.emptyGURL() : defaultGurl; + return UrlUtilities.isNtpUrl(defaultGurl) ? GURL.emptyGURL() : defaultGurl; } - if (customGurl.isEmpty() && !UrlUtilities.isNTPUrl(defaultGurl)) { + if (customGurl.isEmpty() && !UrlUtilities.isNtpUrl(defaultGurl)) { return defaultGurl; } @@ -144,12 +144,12 @@ // URL, we don't check Chrome's Homepage radio button. boolean shouldCheckNTP; if (isPolicyEnabled) { - shouldCheckNTP = UrlUtilities.isNTPUrl(HomepagePolicyManager.getHomepageUrl()); + shouldCheckNTP = UrlUtilities.isNtpUrl(HomepagePolicyManager.getHomepageUrl()); } else { shouldCheckNTP = mHomepageManager.getPrefHomepageUseChromeNTP() || (mHomepageManager.getPrefHomepageUseDefaultUri() - && UrlUtilities.isNTPUrl( + && UrlUtilities.isNtpUrl( HomepageManager.getDefaultHomepageGurl())); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java index 8354eb2..2205948 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -360,7 +360,7 @@ HomepageManager.getHomepageGurl(); LaunchMetrics.recordHomePageLaunchMetrics( HomepageManager.isHomepageEnabled(), - UrlUtilities.isNTPUrl(homepageGurl), + UrlUtilities.isNtpUrl(homepageGurl), homepageGurl); } });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/new_tab_url/DseNewTabUrlManager.java b/chrome/android/java/src/org/chromium/chrome/browser/new_tab_url/DseNewTabUrlManager.java index 84e441d..f190f9fc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/new_tab_url/DseNewTabUrlManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/new_tab_url/DseNewTabUrlManager.java
@@ -58,7 +58,7 @@ if (isIncognito() || !shouldSwapOutNtp() || isDefaultSearchEngineGoogle() - || !UrlUtilities.isNTPUrl(gurl)) { + || !UrlUtilities.isNtpUrl(gurl)) { return gurl; } @@ -95,7 +95,7 @@ if ((profile != null && profile.isOffTheRecord()) || !shouldSwapOutNtp() || isDefaultSearchEngineGoogle() - || !UrlUtilities.isNTPUrl(gurl)) { + || !UrlUtilities.isNtpUrl(gurl)) { return gurl; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 25e961a..54e9ccb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -467,7 +467,7 @@ @Override public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) { - mNewTabPageLayout.onLoadUrl(UrlUtilities.isNTPUrl(tab.getUrl())); + mNewTabPageLayout.onLoadUrl(UrlUtilities.isNtpUrl(tab.getUrl())); } }; mTab.addObserver(mTabObserver); @@ -1186,7 +1186,7 @@ /** Show the module when the current new tab page is been used as the home surface. */ private void initializeSingleTabCard(Tab mostRecentTab) { - if (mostRecentTab == null || UrlUtilities.isNTPUrl(mostRecentTab.getUrl())) { + if (mostRecentTab == null || UrlUtilities.isNtpUrl(mostRecentTab.getUrl())) { return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java index 47ee87fc..f46e483 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
@@ -248,7 +248,7 @@ private static class TabCreationRecorder implements TabModelSelectorObserver { @Override public void onNewTabCreated(Tab tab, @TabCreationState int creationState) { - if (!UrlUtilities.isNTPUrl(tab.getUrl())) return; + if (!UrlUtilities.isNtpUrl(tab.getUrl())) return; RecordUserAction.record("MobileNTPOpenedInNewTab"); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java index 2b5ee5f8..7c45068 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java
@@ -34,7 +34,7 @@ * @return The {@link NewTabPageLaunchOrigin} decoded from the NTP url. */ public static @NewTabPageLaunchOrigin int decodeOriginFromNtpUrl(String url) { - if (!UrlUtilities.isNTPUrl(url)) { + if (!UrlUtilities.isNtpUrl(url)) { return NewTabPageLaunchOrigin.UNKNOWN; } Uri uri = Uri.parse(url);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java index 42703e7c..fc5a7b85 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
@@ -317,7 +317,8 @@ @Override public void openHistoryClustersUi(String query) {} }, - /* tabModelSelectorSupplier= */ null); + /* tabModelSelectorSupplier= */ null, + /* forcePhoneStyleOmnibox= */ true); mLocationBarCoordinator.setUrlBarFocusable(true); mLocationBarCoordinator.setShouldShowMicButtonWhenUnfocused(true); mLocationBarCoordinator.getOmniboxStub().addUrlFocusChangeListener(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java index 94e0215..79d0bde0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -255,7 +255,7 @@ Intent intent) { if (mOverviewNTPCreator != null && mOverviewNTPCreator.handleCreateNTPIfNeeded( - UrlUtilities.isNTPUrl(loadUrlParams.getUrl()), + UrlUtilities.isNtpUrl(loadUrlParams.getUrl()), mIncognito, parent, NewTabPageUtils.decodeOriginFromNtpUrl(loadUrlParams.getUrl()))) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java index 091fed1c..4b58b59 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -662,7 +662,7 @@ Log.w(TAG, "Failed to restore tab: not enough info about its type was available."); return; } else if (isIncognito) { - boolean isNtp = UrlUtilities.isNTPUrl(tabToRestore.url); + boolean isNtp = UrlUtilities.isNtpUrl(tabToRestore.url); boolean isNtpFromMerge = isNtp && tabToRestore.fromMerge; if (!isNtpFromMerge && (!isNtp || !setAsActive || mCancelIncognitoTabLoads)) { @@ -714,7 +714,7 @@ .createFrozenTab(tabState, tabToRestore.id, restoredIndex); } else { if (!mSkipSavingNonActiveNtps - && UrlUtilities.isNTPUrl(tabToRestore.url) + && UrlUtilities.isNtpUrl(tabToRestore.url) && !setAsActive && !tabToRestore.fromMerge) { Log.i(TAG, "Skipping restore of non-selected NTP."); @@ -869,7 +869,7 @@ } if (isTabUrlContentScheme(tab) - || (UrlUtilities.isNTPUrl(tab.getUrl()) + || (UrlUtilities.isNtpUrl(tab.getUrl()) && !tab.canGoBack() && !tab.canGoForward())) { // At present the tab is not in a valid state to save. Reset dirtiness state so that the @@ -985,7 +985,7 @@ Tab activeTab = normalModel.getTabAt(activeIndex); activeTabId = activeTab.getId(); activeTabState = - UrlUtilities.isNTPUrl(activeTab.getUrl()) + UrlUtilities.isNtpUrl(activeTab.getUrl()) ? ActiveTabState.NTP : ActiveTabState.OTHER; } @@ -1042,7 +1042,7 @@ // If any non-active NTPs have been skipped, the serialized tab model index // needs to be adjusted. modelInfo.index = modelInfo.ids.size(); - } else if (tab.isNativePage() && UrlUtilities.isNTPUrl(tab.getUrl())) { + } else if (tab.isNativePage() && UrlUtilities.isNtpUrl(tab.getUrl())) { // Skips saving the non-selected Ntps. continue; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java index 30f0223..50e61dc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java
@@ -504,7 +504,7 @@ ChromeActivity chromeActivity = (ChromeActivity) activity; assert LibraryLoader.getInstance().isInitialized(); - if (!chromeActivity.isInOverviewMode() && !UrlUtilities.isNTPUrl(url)) return null; + if (!chromeActivity.isInOverviewMode() && !UrlUtilities.isNtpUrl(url)) return null; return chromeActivity; } @@ -534,21 +534,19 @@ return HomepageManager.isHomepageEnabled() && ((HomepagePolicyManager.isInitializedWithNative() || sSkipInitializationCheckForTesting) - && (homePageGurl.isEmpty() || UrlUtilities.isNTPUrl(homePageGurl))); + && (homePageGurl.isEmpty() || UrlUtilities.isNtpUrl(homePageGurl))); } /** - * @return Whether we should show Start Surface as the home page on phone. Start surface - * hasn't been enabled on tablet yet. + * Returns whether we should show Start Surface as the home page on phone. Start surface hasn't + * been enabled on tablet yet. */ public static boolean shouldShowStartSurfaceAsTheHomePageOnPhone( Context context, boolean isTablet) { return !isTablet && shouldShowStartSurfaceAsTheHomePage(context); } - /** - * @return Whether Start Surface should be shown as a new Tab. - */ + /** Returns whether Start Surface should be shown as a new Tab. */ public static boolean shouldShowStartSurfaceHomeAsNewTab( Context context, boolean incognito, boolean isTablet) { return !incognito @@ -558,13 +556,6 @@ } /** - * @return Whether opening a NTP instead of Start surface for new Tab is enabled. - */ - public static boolean shouldOpenNTPInsteadOfStart() { - return StartSurfaceConfiguration.START_SURFACE_OPEN_NTP_INSTEAD_OF_START.getValue(); - } - - /** * Returns whether Start Surface is enabled in the given context. * This includes checks of: * 1) whether home page is enabled and whether it is Chrome' home page url; @@ -585,9 +576,9 @@ } /** - * @return Whether start surface should be hidden when accessibility is enabled. If it's true, - * NTP is shown as homepage. Also, when time threshold is reached, grid tab switcher or - * overview list layout is shown instead of start surface. + * Returns whether start surface should be hidden when accessibility is enabled. If it's true, + * NTP is shown as homepage. Also, when time threshold is reached, grid tab switcher or overview + * list layout is shown instead of start surface. */ public static boolean shouldHideStartSurfaceWithAccessibilityOn(Context context) { // TODO(crbug.com/1127732): Move this method back to StartSurfaceConfiguration. @@ -627,7 +618,7 @@ // and UrlUtilities.isCanonicalizedNTPUrl(intentUrl) returns true. // If user taps the "New Incognito Tab" item from the app icon, skip here and continue the // following checks. - if (UrlUtilities.isCanonicalizedNTPUrl(intentUrl) + if (UrlUtilities.isCanonicalizedNtpUrl(intentUrl) && ReturnToChromeUtil.shouldShowStartSurfaceHomeAsNewTab( context, tabModelSelector.isIncognitoSelected(), isTablet) && !intent.getBooleanExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false)) { @@ -744,7 +735,7 @@ Tab ntpTab = tabCreator.createNewTab( new LoadUrlParams(UrlConstants.NTP_URL), TabLaunchType.FROM_STARTUP, null); - boolean isNtpUrl = UrlUtilities.isNTPUrl(ntpTab.getUrl()); + boolean isNtpUrl = UrlUtilities.isNtpUrl(ntpTab.getUrl()); assert isNtpUrl : "The URL of the newly created NTP doesn't match NTP URL!"; if (!isNtpUrl) { recordFailToShowHomeSurfaceReasonUma( @@ -765,8 +756,9 @@ boolean isTabExpected = TextUtils.equals(lastActiveTabUrl, tab.getUrl().getSpec()); assert isTabExpected - : "The URL of first Tab restored doesn't match the URL of the last active " - + "Tab read from the Tab state metadata file! Existing Tab count = %d" + : "The URL of first Tab restored doesn't match the URL of the" + + " last active Tab read from the Tab state metadata" + + " file! Existing Tab count = %d" + tabModelSelector.getModel(false).getCount() + "."; if (!isTabExpected) { @@ -816,7 +808,7 @@ if (lastActiveTab == null) return; // If the last active Tab is a NTP, we continue to show this NTP as it is now. - if (UrlUtilities.isNTPUrl(lastActiveTab.getUrl())) { + if (UrlUtilities.isNtpUrl(lastActiveTab.getUrl())) { if (!homeSurfaceTracker.isHomeSurfaceTab(lastActiveTab)) { homeSurfaceTracker.updateHomeSurfaceAndTrackingTabs(lastActiveTab, null); } @@ -826,7 +818,7 @@ if (indexOfFirstNtp != TabModel.INVALID_TAB_INDEX) { Tab ntpTab = currentTabModel.getTabAt(indexOfFirstNtp); assert indexOfFirstNtp != index; - boolean isNtpUrl = UrlUtilities.isNTPUrl(ntpTab.getUrl()); + boolean isNtpUrl = UrlUtilities.isNtpUrl(ntpTab.getUrl()); assert isNtpUrl : "The URL of the first NTP found onResume doesn't match a NTP URL!"; if (!isNtpUrl) { @@ -868,10 +860,7 @@ @VisibleForTesting public static void cacheReturnTimeFromSegmentationImpl(ClassificationResult result) { - long returnTimeMs = - StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_SECONDS.getDefaultValue() - * DateUtils.SECOND_IN_MILLIS; - + long returnTimeMs; if (result.status != PredictionStatus.SUCCEEDED || result.orderedLabels.isEmpty()) { // Model execution failed or no label selected. returnTimeMs = -1; @@ -923,9 +912,7 @@ .getBoolean(Pref.ARTICLES_LIST_VISIBLE)); } - /** - * @return Whether the Feed articles are visible. - */ + /** Returns whether the Feed articles are visible. */ public static boolean getFeedArticlesVisibility() { return ChromeSharedPreferences.getInstance() .readBoolean(ChromePreferenceKeys.FEED_ARTICLES_LIST_VISIBLE, true); @@ -983,7 +970,7 @@ BrowserUiUtils.ModuleTypeOnStartAndNTP.TAB_SWITCHER_BUTTON); } else if (currentTab != null && !currentTab.isIncognito() - && UrlUtilities.isNTPUrl(currentTab.getUrl())) { + && UrlUtilities.isNtpUrl(currentTab.getUrl())) { BrowserUiUtils.recordModuleClickHistogram( HostSurface.NEW_TAB_PAGE, BrowserUiUtils.ModuleTypeOnStartAndNTP.TAB_SWITCHER_BUTTON); @@ -1019,7 +1006,7 @@ && ChromeFeatureList.sStartSurfaceOnTablet.isEnabled(); } - /** Shows the home surface UI on the given Ntp on tablets. */ + /** Shows the home surface UI on the given NTP on tablets. */ static void showHomeSurfaceUiOnNtp( Tab ntpTab, Tab lastActiveTab, HomeSurfaceTracker homeSurfaceTracker) { NativePage nativePage = ntpTab.getNativePage();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index d445f3b..7eb0204 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -824,7 +824,8 @@ BackPressManager.isEnabled() ? backPressManager : null, scrollListener, openHistoryClustersDelegate, - tabModelSelectorSupplier); + tabModelSelectorSupplier, + /* forcePhoneStyleOmnibox= */ false); toolbarLayout.setLocationBarCoordinator(locationBarCoordinator); toolbarLayout.setBrowserControlsVisibilityDelegate(mControlsVisibilityDelegate); mLocationBar = locationBarCoordinator; @@ -981,7 +982,7 @@ onBackPressStateChanged(); NewTabPage ntp = getNewTabPageForCurrentTab(); if (ntp == null) return; - if (!UrlUtilities.isNTPUrl(params.getUrl()) + if (!UrlUtilities.isNtpUrl(params.getUrl()) && loadType != Tab.TabLoadStatus.PAGE_LOAD_FAILED) { ntp.setUrlFocusAnimationsDisabled(true); onTabOrModelChanged(); @@ -999,7 +1000,7 @@ NavigationEntry pendingEntry = navigationController.getPendingEntry(); if (pendingEntry == null) return false; - return !UrlUtilities.isNTPUrl(pendingEntry.getUrl()); + return !UrlUtilities.isNtpUrl(pendingEntry.getUrl()); } @Override @@ -2498,7 +2499,7 @@ Tab tab = mLocationBarModel.getTab(); if (tab == null) return; NativePage nativePage = tab.getNativePage(); - boolean onNtp = UrlUtilities.isNTPUrl(tab.getUrl()); + boolean onNtp = UrlUtilities.isNtpUrl(tab.getUrl()); if (ChromeAccessibilityUtil.get().isAccessibilityEnabled() && nativePage instanceof NewTabPage) { @@ -2520,7 +2521,7 @@ private void maybeShowUrlBarCursorIfHardwareKeyboardAvailable() { if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity)) return; - if (!UrlUtilities.isNTPUrl(mLocationBarModel.getCurrentGurl())) return; + if (!UrlUtilities.isNtpUrl(mLocationBarModel.getCurrentGurl())) return; if (!ChromeFeatureList.isEnabled(ChromeFeatureList.ADVANCED_PERIPHERALS_SUPPORT)) return; if (mActivity.getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/AppLaunchDrawBlocker.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/AppLaunchDrawBlocker.java index 43d3e28..1577bca8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/AppLaunchDrawBlocker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/AppLaunchDrawBlocker.java
@@ -209,7 +209,7 @@ String url = IntentHandler.getUrlFromIntent(mIntentSupplier.get()); boolean hasValidIntentUrl = !mShouldIgnoreIntentSupplier.get() && !TextUtils.isEmpty(url); - boolean isNtpUrl = UrlUtilities.isCanonicalizedNTPUrl(url); + boolean isNtpUrl = UrlUtilities.isCanonicalizedNtpUrl(url); boolean shouldBlockWithoutIntent = shouldBlockDrawForNtpOnColdStartWithoutIntent(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java index d3cc467..90b6008 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java
@@ -124,7 +124,7 @@ Assert.assertTrue( "Tab should be an NTP. Tab url: " + ChromeTabUtils.getUrlOnUiThread(activityTab), - UrlUtilities.isNTPUrl(ChromeTabUtils.getUrlOnUiThread(activityTab))); + UrlUtilities.isNtpUrl(ChromeTabUtils.getUrlOnUiThread(activityTab))); // Verify tab model. Assert.assertEquals( @@ -183,7 +183,7 @@ Assert.assertTrue( "Tab should have the NTP tab url: " + ChromeTabUtils.getUrlOnUiThread(activityTab), - UrlUtilities.isNTPUrl(ChromeTabUtils.getUrlOnUiThread(activityTab))); + UrlUtilities.isNtpUrl(ChromeTabUtils.getUrlOnUiThread(activityTab))); // Verify the tab model. Assert.assertEquals(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivityTest.java index a40de7f..e5aa3eb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderPickerActivityTest.java
@@ -5,13 +5,11 @@ package org.chromium.chrome.browser.app.bookmarks; import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static org.junit.Assert.assertEquals; -import androidx.appcompat.widget.Toolbar; import androidx.test.filters.MediumTest; import org.junit.After; @@ -27,9 +25,7 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.R; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -62,6 +58,7 @@ private static BookmarkModel sBookmarkModel; private static BookmarkId sMobileFolderId; private static BookmarkId sOtherFolderId; + private BookmarkFolderPickerActivity mActivity; @BeforeClass @@ -94,36 +91,33 @@ @Test @MediumTest @Feature({"Bookmark"}) - @DisabledTest(message = "https://crbug.com/1469705") - public void testMoveBookmark() throws ExecutionException, TimeoutException { + public void testMoveBookmark() throws ExecutionException, TimeoutException, Exception { BookmarkId bookmark = addBookmark(sMobileFolderId, 0, "bookmark", new GURL("https://google.com")); BookmarkId folder = addFolder(sMobileFolderId, 1, "folder"); - startFolderPickerActivity(bookmark, folder); - Toolbar toolbar = (Toolbar) mActivity.findViewById(R.id.toolbar); + startFolderPickerActivity(bookmark); - assertEquals("Move to…", toolbar.getTitle()); + onView(withText("folder")).perform(click()); onView(withText("Move here")).perform(click()); BookmarkItem item = getBookmarkItem(bookmark); - assertEquals(sOtherFolderId, item.getParentId()); + assertEquals(folder, item.getParentId()); + + CriteriaHelper.pollUiThread(() -> mActivity.isFinishing()); } @Test @MediumTest @Feature({"Bookmark"}) - public void testCancel() throws ExecutionException, TimeoutException, InterruptedException { - BookmarkId folder = addFolder(sMobileFolderId, 0, "folder"); - BookmarkId bookmark = addBookmark(folder, 0, "bookmark", new GURL("https://google.com")); + public void testCancelButton() + throws ExecutionException, TimeoutException, InterruptedException { + BookmarkId bookmark = + addBookmark(sMobileFolderId, 0, "bookmark", new GURL("https://google.com")); startFolderPickerActivity(bookmark); - onView(withText("folder")); - pressBack(); - onView(withText("Move to...")); onView(withText("Cancel")).perform(click()); - BookmarkItem item = getBookmarkItem(folder); - assertEquals(sMobileFolderId, item.getParentId()); + CriteriaHelper.pollUiThread(() -> mActivity.isFinishing()); } private BookmarkItem getBookmarkItem(BookmarkId bookmarkId) throws ExecutionException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java index 0b546ef..eeefe9b8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java
@@ -12,9 +12,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.view.MenuItem; import android.view.View; +import android.widget.ImageView; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; @@ -28,6 +30,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.chromium.base.ContextUtils; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.chrome.browser.autofill.AutofillEditorBase; import org.chromium.chrome.browser.autofill.AutofillTestHelper; @@ -97,6 +100,36 @@ /* cardNameForAutofillDisplay= */ "", /* obfuscatedLastFourDigits= */ "", /* cvc= */ "123"); + private static final CreditCard SAMPLE_AMEX_CARD_WITH_CVC = + new CreditCard( + /* guid= */ "", + /* origin= */ "", + /* isLocal= */ true, + /* isCached= */ false, + /* isVirtual= */ false, + /* name= */ "John Doe", + /* number= */ "378282246310005", + /* obfuscatedNumber= */ "", + /* month= */ "5", + AutofillTestHelper.nextYear(), + /* basicCardIssuerNetwork= */ "amex", + /* issuerIconDrawableId= */ 0, + /* billingAddressId= */ "", + /* serverId= */ "", + /* instrumentId= */ 0, + /* cardLabel= */ "", + /* nickname= */ "", + /* cardArtUrl= */ null, + /* virtualCardEnrollmentState= */ VirtualCardEnrollmentState + .UNENROLLED_AND_ELIGIBLE, + /* productDescription= */ "", + /* cardNameForAutofillDisplay= */ "", + /* obfuscatedLastFourDigits= */ "", + /* cvc= */ "1234"); + private static final String AMEX_CARD_NUMBER = "378282246310005"; + private static final String AMEX_CARD_NUMBER_PREFIX = "37"; + private static final String NON_AMEX_CARD_NUMBER = "4111111111111111"; + private static final String NON_AMEX_CARD_NUMBER_PREFIX = "41"; @Mock private ObservableSupplierImpl<ModalDialogManager> mModalDialogManagerSupplierMock; @Mock private PersonalDataManager mPersonalDataManagerMock; @@ -337,6 +370,101 @@ @Test @MediumTest @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testSecurityCode_whenAmExCardIsSet_usesAmExCvcHintImage() throws Exception { + String guid = mAutofillTestHelper.setCreditCard(SAMPLE_AMEX_CARD_WITH_CVC); + + SettingsActivity activity = + mSettingsActivityTestRule.startSettingsActivity(fragmentArgs(guid)); + AutofillLocalCardEditor autofillLocalCardEditorFragment = + (AutofillLocalCardEditor) activity.getMainFragment(); + + verifyCvcHintImage( + autofillLocalCardEditorFragment, /* expectedImage= */ R.drawable.cvc_icon_amex); + } + + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testSecurityCode_whenCardIsNotSet_usesDefaultCvcHintImage() throws Exception { + SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); + AutofillLocalCardEditor autofillLocalCardEditorFragment = + (AutofillLocalCardEditor) activity.getMainFragment(); + + verifyCvcHintImage( + autofillLocalCardEditorFragment, /* expectedImage= */ R.drawable.cvc_icon); + } + + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testSecurityCode_whenAmExCardNumberIsEntered_usesAmExCvcHintImage() + throws Exception { + String guid = mAutofillTestHelper.setCreditCard(SAMPLE_LOCAL_CARD_WITH_CVC); + + SettingsActivity activity = + mSettingsActivityTestRule.startSettingsActivity(fragmentArgs(guid)); + AutofillLocalCardEditor autofillLocalCardEditorFragment = + (AutofillLocalCardEditor) activity.getMainFragment(); + setCardNumberOnEditor(autofillLocalCardEditorFragment, AMEX_CARD_NUMBER); + + verifyCvcHintImage( + autofillLocalCardEditorFragment, /* expectedImage= */ R.drawable.cvc_icon_amex); + } + + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testSecurityCode_whenNonAmExCardNumberIsEntered_usesDefaultCvcHintImage() + throws Exception { + String guid = mAutofillTestHelper.setCreditCard(SAMPLE_LOCAL_CARD_WITH_CVC); + + SettingsActivity activity = + mSettingsActivityTestRule.startSettingsActivity(fragmentArgs(guid)); + AutofillLocalCardEditor autofillLocalCardEditorFragment = + (AutofillLocalCardEditor) activity.getMainFragment(); + setCardNumberOnEditor(autofillLocalCardEditorFragment, NON_AMEX_CARD_NUMBER); + + verifyCvcHintImage( + autofillLocalCardEditorFragment, /* expectedImage= */ R.drawable.cvc_icon); + } + + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testSecurityCode_whenNumberIsChangedFromAmExToNonAmEx_usesDefaultCvcHintImage() + throws Exception { + String guid = mAutofillTestHelper.setCreditCard(SAMPLE_AMEX_CARD_WITH_CVC); + + SettingsActivity activity = + mSettingsActivityTestRule.startSettingsActivity(fragmentArgs(guid)); + AutofillLocalCardEditor autofillLocalCardEditorFragment = + (AutofillLocalCardEditor) activity.getMainFragment(); + setCardNumberOnEditor(autofillLocalCardEditorFragment, NON_AMEX_CARD_NUMBER); + + verifyCvcHintImage( + autofillLocalCardEditorFragment, /* expectedImage= */ R.drawable.cvc_icon); + } + + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testSecurityCode_whenNumberIsChangedFromNonAmExToAmEx_usesAmExCvcHintImage() + throws Exception { + String guid = mAutofillTestHelper.setCreditCard(SAMPLE_LOCAL_CARD_WITH_CVC); + + SettingsActivity activity = + mSettingsActivityTestRule.startSettingsActivity(fragmentArgs(guid)); + AutofillLocalCardEditor autofillLocalCardEditorFragment = + (AutofillLocalCardEditor) activity.getMainFragment(); + setCardNumberOnEditor(autofillLocalCardEditorFragment, AMEX_CARD_NUMBER); + + verifyCvcHintImage( + autofillLocalCardEditorFragment, /* expectedImage= */ R.drawable.cvc_icon_amex); + } + + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) public void expirationDateFieldSet_cardHasExpirationDate() throws Exception { String validExpirationMonth = "12"; String validExpirationYear = AutofillTestHelper.nextYear(); @@ -638,4 +766,55 @@ public void getExpirationYear_returnsYearWithPrefix() throws Exception { assertThat(AutofillLocalCardEditor.getExpirationYear("12/23")).isEqualTo("2023"); } + + @Test + @SmallTest + public void testIsAmExCard_whenAmExCardNumberPrefixIsEntered_returnsTrue() { + TestThreadUtils.runOnUiThreadBlocking( + () -> { + try { + assertThat(AutofillLocalCardEditor.isAmExCard(AMEX_CARD_NUMBER_PREFIX)) + .isTrue(); + } catch (Exception e) { + Assert.fail("Failed to verify AmEx card."); + } + }); + } + + @Test + @SmallTest + public void testIsAmExCard_whenNonAmExCardNumberPrefixIsEntered_returnsFalse() { + TestThreadUtils.runOnUiThreadBlocking( + () -> { + try { + assertThat(AutofillLocalCardEditor.isAmExCard(NON_AMEX_CARD_NUMBER_PREFIX)) + .isFalse(); + } catch (Exception e) { + Assert.fail("Failed to verify AmEx card."); + } + }); + } + + private void setCardNumberOnEditor( + AutofillLocalCardEditor autofillLocalCardEditorFragment, String cardNumber) { + TestThreadUtils.runOnUiThreadBlocking( + () -> { + try { + autofillLocalCardEditorFragment.mNumberText.setText(cardNumber); + } catch (Exception e) { + Assert.fail("Failed to set the card number"); + } + }); + } + + private void verifyCvcHintImage( + AutofillLocalCardEditor autofillLocalCardEditorFragment, int expectedImage) { + ImageView expectedCvcHintImage = new ImageView(ContextUtils.getApplicationContext()); + expectedCvcHintImage.setImageResource(expectedImage); + + BitmapDrawable expectedDrawable = (BitmapDrawable) expectedCvcHintImage.getDrawable(); + BitmapDrawable actualDrawable = + (BitmapDrawable) autofillLocalCardEditorFragment.mCvcHintImage.getDrawable(); + assertThat(expectedDrawable.getBitmap().sameAs(actualDrawable.getBitmap())).isTrue(); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java index 74cd1e7..b062e83 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java
@@ -72,6 +72,7 @@ public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() .setBugComponent(ChromeRenderTestRule.Component.PRIVACY) + .setRevision(1) .build(); @Mock private SyncService mMockSyncService;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java index c11378ed..632f5ac5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java
@@ -40,7 +40,7 @@ @Rule public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() - .setRevision(1) + .setRevision(2) .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_INCOGNITO) .build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java index b2f934b..ef6024e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
@@ -116,7 +116,7 @@ Assert.assertTrue( tab != null && !tab.isIncognito() - && UrlUtilities.isNTPUrl(tab.getUrl())); + && UrlUtilities.isNtpUrl(tab.getUrl())); }); TabUiTestHelper.enterTabSwitcher(cta); TabUiTestHelper.verifyTabSwitcherCardCount(cta, 1); @@ -138,7 +138,7 @@ Assert.assertTrue( tab != null && tab.isIncognito() - && UrlUtilities.isNTPUrl(tab.getUrl())); + && UrlUtilities.isNtpUrl(tab.getUrl())); }); TabUiTestHelper.enterTabSwitcher(cta); TabUiTestHelper.verifyTabSwitcherCardCount(cta, 1);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java index 09535363..882ad01 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java
@@ -305,7 +305,7 @@ Tab tab = TestThreadUtils.runOnUiThreadBlocking( () -> mTabbedActivityTestRule.getActivity().getActivityTab()); - Assert.assertTrue(UrlUtilities.isNTPUrl(ChromeTabUtils.getUrlOnUiThread(tab))); + Assert.assertTrue(UrlUtilities.isNtpUrl(ChromeTabUtils.getUrlOnUiThread(tab))); Assert.assertFalse(tab.isIncognito()); Assert.assertEquals( initialTabCount + 1,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java index 4ab5c84..d5a5ecf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -178,7 +178,7 @@ @Rule public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus() - .setRevision(2) + .setRevision(3) .setBugComponent(Component.UI_BROWSER_MOBILE_SETTINGS) .build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java index 21e51d7..822c4a7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java
@@ -43,7 +43,7 @@ @Rule public RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus() - .setRevision(1) + .setRevision(2) .setBugComponent(RenderTestRule.Component.SERVICES_SYNC) .build();
diff --git a/chrome/android/junit/DEPS b/chrome/android/junit/DEPS index 102d81ed..71bb5586 100644 --- a/chrome/android/junit/DEPS +++ b/chrome/android/junit/DEPS
@@ -44,11 +44,3 @@ "+content/public/android/java/src/org/chromium/content_public", "+content/public/android/java/src/org/chromium/content/browser/RenderCoordinatesImpl.java", ] - -specific_include_rules = { - # Added to allow tests to mock JNI methods within the implementation. Tests - # use the public API classes where possible. - "Fido2CredentialRequestRobolectricTest.java": [ - "+content/public/android/java/src/org/chromium/content/browser/ClientDataJsonImpl.java", - ] -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsUnitTest.java index b9fab5d..a35f7501 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsUnitTest.java
@@ -543,7 +543,7 @@ ASSERT_MESSAGE_EDIT_TEXT, "", mCustomUriRadioButton.getPrimaryText().toString()); Assert.assertTrue( ASSERT_HOMEPAGE_MANAGER_SETTINGS, - UrlUtilities.isNTPUrl(HomepageManager.getHomepageGurl())); + UrlUtilities.isNtpUrl(HomepageManager.getHomepageGurl())); assertUserActionRecorded(false); // Update the text box. To do this, request focus for customized radio button so that the
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestRobolectricTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestRobolectricTest.java index 621c1c6..778ae37 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestRobolectricTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestRobolectricTest.java
@@ -51,7 +51,6 @@ import org.chromium.components.webauthn.Fido2CredentialRequest; import org.chromium.components.webauthn.WebAuthnBrowserBridge; import org.chromium.components.webauthn.WebAuthnCredentialDetails; -import org.chromium.content.browser.ClientDataJsonImpl; import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.RenderFrameHost.WebAuthSecurityChecksResults; import org.chromium.device.DeviceFeatureList; @@ -76,7 +75,6 @@ @Mock private RenderFrameHost mFrameHost; @Mock GURLUtils.Natives mGURLUtilsJniMock; - @Mock ClientDataJsonImpl.Natives mClientDataJsonImplMock; @Mock Activity mActivity; @Mock WebAuthnBrowserBridge mBrowserBridgeMock; @Mock CredManHelper mCredManHelperMock;
diff --git a/chrome/app/media_live_preview_strings.grdp b/chrome/app/media_live_preview_strings.grdp index caf8c98..92cb0e06 100644 --- a/chrome/app/media_live_preview_strings.grdp +++ b/chrome/app/media_live_preview_strings.grdp
@@ -7,6 +7,10 @@ Camera </message> + <message name="IDS_MEDIA_PREVIEW_VIDEO_STREAM_ACCESSIBLE_NAME" desc="Text for accessability description of the video stream view"> + Preview of your camera + </message> + <message name="IDS_MEDIA_PREVIEW_NO_CAMERAS_FOUND" desc="Text shown when there are no cameras found connected. This is shown instead of video stream"> No camera connected </message>
diff --git a/chrome/app/media_live_preview_strings_grdp/IDS_MEDIA_PREVIEW_VIDEO_STREAM_ACCESSIBLE_NAME.png.sha1 b/chrome/app/media_live_preview_strings_grdp/IDS_MEDIA_PREVIEW_VIDEO_STREAM_ACCESSIBLE_NAME.png.sha1 new file mode 100644 index 0000000..92e71ad08 --- /dev/null +++ b/chrome/app/media_live_preview_strings_grdp/IDS_MEDIA_PREVIEW_VIDEO_STREAM_ACCESSIBLE_NAME.png.sha1
@@ -0,0 +1 @@ +9a84806a3f2c871b3cd6e573b715f52bb1f01011 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 13df7a3..499562a 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2644,6 +2644,8 @@ if (enable_search_engine_choice) { sources += [ + "search_engine_choice/search_engine_choice_client_side_trial.cc", + "search_engine_choice/search_engine_choice_client_side_trial.h", "search_engine_choice/search_engine_choice_profile_tagger.cc", "search_engine_choice/search_engine_choice_profile_tagger.h", "search_engine_choice/search_engine_choice_service.cc",
diff --git a/chrome/browser/android/browserservices/OWNERS b/chrome/browser/android/browserservices/OWNERS index b6cddfe3..1df9e879 100644 --- a/chrome/browser/android/browserservices/OWNERS +++ b/chrome/browser/android/browserservices/OWNERS
@@ -2,3 +2,4 @@ eirage@chromium.org per-file ...BrowserServicesIntentDataProvider.java=kgrosu@google.com +per-file ...BrowserServicesIntentDataProvider.java=jinsukkim@chromium.org
diff --git a/chrome/browser/ash/accessibility/live_caption/system_live_caption_service_browsertest.cc b/chrome/browser/ash/accessibility/live_caption/system_live_caption_service_browsertest.cc index 752bea2..e720081 100644 --- a/chrome/browser/ash/accessibility/live_caption/system_live_caption_service_browsertest.cc +++ b/chrome/browser/ash/accessibility/live_caption/system_live_caption_service_browsertest.cc
@@ -123,17 +123,15 @@ &profiles::testing::CreateProfileSync(profile_manager, profile_path); CHECK(secondary_profile_); - // Replace our CrosSpeechRecognitionService with a fake one. We can pass a - // unique_ptr into this lambda since it is only called once (despite being - // "repeating"). - auto service = std::make_unique<speech::FakeSpeechRecognitionService>(); - fake_speech_recognition_service_ = service.get(); - const auto spawn_test_service = - base::BindRepeating([](std::unique_ptr<KeyedService> s, - content::BrowserContext*) { return s; }, - base::Passed(std::move(service))); - CrosSpeechRecognitionServiceFactory::GetInstanceForTest() - ->SetTestingFactoryAndUse(primary_profile_, spawn_test_service); + // Replace our CrosSpeechRecognitionService with a fake one. + fake_speech_recognition_service_ = + CrosSpeechRecognitionServiceFactory::GetInstanceForTest() + ->SetTestingSubclassFactoryAndUse( + primary_profile_, + base::BindRepeating([](content::BrowserContext*) { + return std::make_unique< + speech::FakeSpeechRecognitionService>(); + })); // Pass in an inert audio system backend. SystemLiveCaptionServiceFactory::GetInstance()
diff --git a/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc index 2ccdf87d..0272cf8 100644 --- a/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ash/app_list/arc/arc_app_list_prefs.cc
@@ -1363,6 +1363,17 @@ return install_priority_handler_.get(); } +void ArcAppListPrefs::SetAppLocale(const std::string& package_name, + const std::string& selected_locale) { + arc::ArcAppScopedPrefUpdate update(prefs_, package_name, + arc::prefs::kArcPackages); + base::Value::Dict& package_dict = update.Get(); + package_dict.EnsureDict(kLocaleInfo)->Set(kSelectedLocale, selected_locale); + + const std::string& app_id = GetAppIdByPackageName(package_name); + NotifyAppStatesChanged(app_id); +} + void ArcAppListPrefs::SetResizeLockState(const std::string& app_id, arc::mojom::ArcResizeLockState state) { if (!IsRegistered(app_id)) {
diff --git a/chrome/browser/ash/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ash/app_list/arc/arc_app_list_prefs.h index 96cd2984..a3c87d52 100644 --- a/chrome/browser/ash/app_list/arc/arc_app_list_prefs.h +++ b/chrome/browser/ash/app_list/arc/arc_app_list_prefs.h
@@ -490,6 +490,10 @@ arc::ArcPackageInstallPriorityHandler* GetInstallPriorityHandler(); + // Update package prefs with |selected_locale| and notify app states changed. + void SetAppLocale(const std::string& package_name, + const std::string& selected_locale); + private: friend class ChromeShelfControllerTestBase; friend class ArcAppModelBuilderTest;
diff --git a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc index 417d5b0..af4f29e 100644 --- a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc
@@ -1463,6 +1463,29 @@ ValidateHavePackages(fake_packages()); } +TEST_P(ArcAppModelBuilderTest, SetAppLocale) { + // Setup. + SendRefreshAppList(fake_apps()); + app_instance()->SendRefreshPackageList( + ArcAppTest::ClonePackages(fake_packages())); + ValidateHavePackages(fake_packages()); + + // Update fake_packages to be used as validation. + // fake_packages[4] is the test package with localeInfo. + arc::mojom::ArcPackageInfoPtr updated_package = fake_packages()[4]->Clone(); + updated_package->locale_info->selected_locale = "ja"; + UpdateTestPackage(updated_package); + + // Run. + ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get()); + ASSERT_NE(nullptr, prefs); + prefs->SetAppLocale(fake_packages()[4]->package_name, + fake_packages()[4]->locale_info->selected_locale); + + // Assert. + ValidateHavePackages(fake_packages()); +} + TEST_P(ArcAppModelBuilderTest, RefreshAllFillsContent) { ValidateHaveApps({}); SendRefreshAppList(fake_apps());
diff --git a/chrome/browser/ash/crosapi/local_printer_ash.cc b/chrome/browser/ash/crosapi/local_printer_ash.cc index 74add026..6202c09 100644 --- a/chrome/browser/ash/crosapi/local_printer_ash.cc +++ b/chrome/browser/ash/crosapi/local_printer_ash.cc
@@ -346,14 +346,24 @@ LOG(WARNING) << "Ignoring invalid print job"; return; } + const auto& printer_id = job->printer().id(); + const auto& job_id = job->job_id(); for (auto& remote : print_job_remotes_) { - remote->OnPrintJobUpdate(job->printer().id(), job->job_id(), status); + remote->OnPrintJobUpdate(printer_id, job_id, status); } - if (job->source() != mojom::PrintJob::Source::kExtension) { - return; - } - for (auto& remote : extension_print_job_remotes_) { - remote->OnPrintJobUpdate(job->printer().id(), job->job_id(), status); + switch (job->source()) { + case mojom::PrintJob::Source::kExtension: + for (auto& remote : extension_print_job_remotes_) { + remote->OnPrintJobUpdate(printer_id, job_id, status); + } + break; + case mojom::PrintJob::Source::kIsolatedWebApp: + for (auto& remote : iwa_print_job_remotes_) { + remote->OnPrintJobUpdate(printer_id, job_id, status); + } + break; + default: + break; } } @@ -662,6 +672,9 @@ case mojom::PrintJobSource::kExtension: extension_print_job_remotes_.Add(std::move(remote)); break; + case mojom::PrintJobSource::kIsolatedWebApp: + iwa_print_job_remotes_.Add(std::move(remote)); + break; case mojom::PrintJobSource::kAny: print_job_remotes_.Add(std::move(remote)); break;
diff --git a/chrome/browser/ash/crosapi/local_printer_ash.h b/chrome/browser/ash/crosapi/local_printer_ash.h index 57a937c..c82f217d 100644 --- a/chrome/browser/ash/crosapi/local_printer_ash.h +++ b/chrome/browser/ash/crosapi/local_printer_ash.h
@@ -151,6 +151,9 @@ // Remotes which observe only extension print jobs. mojo::RemoteSet<mojom::PrintJobObserver> extension_print_job_remotes_; + // Remotes which observe only IWA print jobs. + mojo::RemoteSet<mojom::PrintJobObserver> iwa_print_job_remotes_; + // Remotes which observe local printer updates. mojo::RemoteSet<mojom::LocalPrintersObserver> local_printers_observer_remotes_;
diff --git a/chrome/browser/ash/growth/campaigns_manager_client_impl.cc b/chrome/browser/ash/growth/campaigns_manager_client_impl.cc index 6188534..176a8370 100644 --- a/chrome/browser/ash/growth/campaigns_manager_client_impl.cc +++ b/chrome/browser/ash/growth/campaigns_manager_client_impl.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/component_updater/cros_component_manager.h" #include "chrome/browser/profiles/profile_manager.h" #include "chromeos/ash/components/growth/campaigns_manager.h" +#include "chromeos/ash/components/growth/growth_metrics.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace { @@ -79,9 +80,8 @@ const auto& version = demo_session->components()->app_component_version(); if (!version.has_value()) { - // TODO(b/299305911): Add metrics to track the case that version is not - // available and convert to CHECK if we are confident that it will always - // available at this point. + growth::RecordCampaignsManagerError( + growth::CampaignsManagerError::kDemoModeAppVersionUnavailable); static const base::NoDestructor<base::Version> empty_version; return *empty_version; }
diff --git a/chrome/browser/ash/login/demo_mode/demo_session.cc b/chrome/browser/ash/login/demo_mode/demo_session.cc index 8a02bee..66d0c78 100644 --- a/chrome/browser/ash/login/demo_mode/demo_session.cc +++ b/chrome/browser/ash/login/demo_mode/demo_session.cc
@@ -54,6 +54,7 @@ #include "chrome/grit/generated_resources.h" #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/components/install_attributes/install_attributes.h" #include "chromeos/ash/components/system/statistics_provider.h" #include "chromeos/constants/chromeos_features.h" @@ -230,7 +231,8 @@ std::string payload_string; if (!JSONStringValueSerializer(&payload_string).Serialize(*model) || payload_string.empty()) { - // TODO(b/298467444): Log an error metrics. + growth::RecordCampaignsManagerError( + growth::CampaignsManagerError::kSerializingDemoModePayloadFail); LOG(ERROR) << "Failed to serialize demo mode payload."; return url; }
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc index bbfc6b8..ab60e5b 100644 --- a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc +++ b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
@@ -13,6 +13,7 @@ #include "ash/public/cpp/login_accelerators.h" #include "base/command_line.h" #include "base/containers/flat_map.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/functional/bind.h" #include "base/i18n/time_formatting.h" @@ -23,6 +24,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/scoped_run_loop_timeout.h" #include "base/test/test_timeouts.h" +#include "base/threading/thread_restrictions.h" #include "base/timer/timer.h" #include "base/values.h" #include "build/build_config.h" @@ -45,7 +47,10 @@ #include "chrome/browser/ash/login/wizard_controller.h" #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/ash/policy/enrollment/enrollment_status.h" +#include "chrome/browser/chrome_browser_main.h" +#include "chrome/browser/chrome_browser_main_extra_parts.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" +#include "chrome/browser/component_updater/fake_cros_component_manager.h" #include "chrome/browser/ui/webui/ash/login/demo_preferences_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/demo_setup_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/error_screen_handler.h" @@ -53,9 +58,12 @@ #include "chrome/browser/ui/webui/ash/login/network_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/welcome_screen_handler.h" #include "chrome/grit/generated_resources.h" +#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/ash/components/dbus/shill/shill_service_client.h" #include "chromeos/ash/components/dbus/update_engine/fake_update_engine_client.h" +#include "chromeos/ash/components/growth/campaigns_manager.h" +#include "chromeos/ash/components/growth/campaigns_model.h" #include "chromeos/ash/components/network/network_handler.h" #include "chromeos/ash/components/network/network_state.h" #include "chromeos/ash/components/network/network_state_handler.h" @@ -123,6 +131,11 @@ constexpr int kInvokeDemoModeGestureTapsCount = 10; +inline constexpr char kGrowthCampaignsComponentName[] = "growth-campaigns"; +inline constexpr char kDemoAppComponentName[] = "demo-mode-app"; +inline constexpr char kDemoResourcesComponentName[] = "demo-mode-resources"; +inline constexpr char kCampaignsFileName[] = "campaigns.json"; + // Basic tests for demo mode setup flow. class DemoSetupTestBase : public OobeBaseTest { public: @@ -170,6 +183,10 @@ ClickOkOnConfirmationDialog(); OobeScreenWaiter(NetworkScreenView::kScreenId).Wait(); + + WizardController::default_controller() + ->demo_setup_controller() + ->EnableLoadRealComponentsForTest(); } // Returns whether error message is shown on demo setup error screen and @@ -306,6 +323,87 @@ std::unique_ptr<base::AutoReset<bool>> branded_build_override_; }; +// Extra parts for setting up the FakeCrOSComponentManager before the real one +// has been initialized on the browser +class DemoSetupTestMainExtraParts : public ChromeBrowserMainExtraParts { + public: + explicit DemoSetupTestMainExtraParts( + bool growth_campaigns_enabled = false, + component_updater::CrOSComponentManager::Error + demo_mode_app_load_response = + component_updater::CrOSComponentManager::Error::NONE) + : growth_campaigns_enabled_(growth_campaigns_enabled), + demo_mode_app_load_response_(demo_mode_app_load_response) { + CHECK(components_temp_dir_.CreateUniqueTempDir()); + } + DemoSetupTestMainExtraParts(const DemoSetupTestMainExtraParts&) = delete; + DemoSetupTestMainExtraParts& operator=(const DemoSetupTestMainExtraParts&) = + delete; + + base::FilePath GetGrowthCampaignsPath() { + return components_temp_dir_.GetPath() + .AppendASCII("cros-components") + .AppendASCII(kGrowthCampaignsComponentName); + } + + void PostEarlyInitialization() override { + auto cros_component_manager = + base::MakeRefCounted<component_updater::FakeCrOSComponentManager>(); + std::set<std::string> supported_components = {kDemoResourcesComponentName, + kDemoAppComponentName}; + if (growth_campaigns_enabled_) { + supported_components.insert(kGrowthCampaignsComponentName); + } + + cros_component_manager->set_supported_components(supported_components); + if (demo_mode_app_load_response_ == + component_updater::CrOSComponentManager::Error::NONE) { + cros_component_manager->ResetComponentState( + kDemoAppComponentName, + component_updater::FakeCrOSComponentManager::ComponentInfo( + demo_mode_app_load_response_, base::FilePath("/dev/null"), + base::FilePath("/run/imageloader/demo-mode-app"))); + } else { + cros_component_manager->ResetComponentState( + kDemoAppComponentName, + component_updater::FakeCrOSComponentManager::ComponentInfo( + demo_mode_app_load_response_, base::FilePath(), + base::FilePath())); + } + cros_component_manager->ResetComponentState( + kDemoResourcesComponentName, + component_updater::FakeCrOSComponentManager::ComponentInfo( + component_updater::CrOSComponentManager::Error::NONE, + base::FilePath("/dev/null"), + base::FilePath("/run/imageloader/demo-mode-resources"))); + + if (growth_campaigns_enabled_) { + cros_component_manager->ResetComponentState( + kGrowthCampaignsComponentName, + component_updater::FakeCrOSComponentManager::ComponentInfo( + component_updater::CrOSComponentManager::Error::NONE, + base::FilePath("/dev/null"), GetGrowthCampaignsPath())); + } + + platform_part_test_api_ = + std::make_unique<BrowserProcessPlatformPartTestApi>( + g_browser_process->platform_part()); + platform_part_test_api_->InitializeCrosComponentManager( + std::move(cros_component_manager)); + } + + void PostMainMessageLoopRun() override { + platform_part_test_api_->ShutdownCrosComponentManager(); + platform_part_test_api_.reset(); + } + + private: + std::unique_ptr<BrowserProcessPlatformPartTestApi> platform_part_test_api_; + base::ScopedTempDir components_temp_dir_; + bool growth_campaigns_enabled_; + component_updater::CrOSComponentManager::Error demo_mode_app_load_response_; +}; + class DemoSetupArcSupportedTest : public DemoSetupTestBase { public: DemoSetupArcSupportedTest() { @@ -315,6 +413,14 @@ } ~DemoSetupArcSupportedTest() override = default; + void CreatedBrowserMainParts( + content::BrowserMainParts* browser_main_parts) override { + auto extra_parts = std::make_unique<DemoSetupTestMainExtraParts>(); + static_cast<ChromeBrowserMainParts*>(browser_main_parts) + ->AddParts(std::move(extra_parts)); + DemoSetupTestBase::CreatedBrowserMainParts(browser_main_parts); + } + // DemoSetupTestBase: void SetUpCommandLine(base::CommandLine* command_line) override { DemoSetupTestBase::SetUpCommandLine(command_line); @@ -680,34 +786,6 @@ EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, - OnlineSetupFlowCrosComponentFailure) { - // Simulate failure to load demo resources CrOS component. - // There is no enrollment attempt, as process fails earlier. - enrollment_helper_.ExpectNoEnrollment(); - SimulateNetworkConnected(); - - TriggerDemoModeOnWelcomeScreen(); - - UseOnlineModeOnNetworkScreen(); - - // Set the component to fail to install when requested. - WizardController::default_controller() - ->demo_setup_controller() - ->SetCrOSComponentLoadErrorForTest( - component_updater::CrOSComponentManager::Error::INSTALL_FAILURE); - - ProceedThroughDemoPreferencesScreen(); - - AcceptTermsAndExpectDemoSetupFailure(); - - ExpectErrorMessage(IDS_DEMO_SETUP_COMPONENT_ERROR, - IDS_DEMO_SETUP_RECOVERY_CHECK_NETWORK); - - EXPECT_FALSE(StartupUtils::IsOobeCompleted()); - EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); -} - IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, OfflineDemoModeUnavailable) { SimulateNetworkDisconnected(); @@ -956,6 +1034,47 @@ } /** + * Test case of Demo Mode setup with Growth Framework enabled. + */ +class DemoSetupComponentLoadErrorTest : public DemoSetupArcSupportedTest { + public: + DemoSetupComponentLoadErrorTest() = default; + ~DemoSetupComponentLoadErrorTest() override = default; + + void CreatedBrowserMainParts( + content::BrowserMainParts* browser_main_parts) override { + auto extra_parts = std::make_unique<DemoSetupTestMainExtraParts>( + /*growth_campaigns_enabled=*/false, + component_updater::CrOSComponentManager::Error::INSTALL_FAILURE); + static_cast<ChromeBrowserMainParts*>(browser_main_parts) + ->AddParts(std::move(extra_parts)); + DemoSetupTestBase::CreatedBrowserMainParts(browser_main_parts); + } +}; + +IN_PROC_BROWSER_TEST_F(DemoSetupComponentLoadErrorTest, + OnlineSetupFlowCrosComponentFailure) { + // Simulate failure to load demo resources CrOS component. + // There is no enrollment attempt, as process fails earlier. + enrollment_helper_.ExpectNoEnrollment(); + SimulateNetworkConnected(); + + TriggerDemoModeOnWelcomeScreen(); + + UseOnlineModeOnNetworkScreen(); + + ProceedThroughDemoPreferencesScreen(); + + AcceptTermsAndExpectDemoSetupFailure(); + + ExpectErrorMessage(IDS_DEMO_SETUP_COMPONENT_ERROR, + IDS_DEMO_SETUP_RECOVERY_CHECK_NETWORK); + + EXPECT_FALSE(StartupUtils::IsOobeCompleted()); + EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); +} + +/** * Test case of device variant region code, e.g. ca.fr etc. */ class DemoSetupVariantCountryCodeRegionTest : public DemoSetupArcSupportedTest { @@ -1168,5 +1287,124 @@ test::OobeJS().ExpectTrue(networkElementSelector + " == null"); } +/** + * Test case of Demo Mode setup with Growth Framework enabled. + */ +class DemoSetupGrowthFrameworkEnabledTest : public DemoSetupArcSupportedTest { + public: + ~DemoSetupGrowthFrameworkEnabledTest() override = default; + + DemoSetupGrowthFrameworkEnabledTest() { + feature_list_.InitWithFeatures( + {features::kGrowthCampaignsInDemoMode, ash::features::kGrowthFramework}, + {}); + } + + void CreatedBrowserMainParts( + content::BrowserMainParts* browser_main_parts) override { + auto extra_parts = std::make_unique<DemoSetupTestMainExtraParts>( + /*growth_campaigns_enabled=*/true); + growth_campaigns_mounted_path_ = extra_parts->GetGrowthCampaignsPath(); + static_cast<ChromeBrowserMainParts*>(browser_main_parts) + ->AddParts(std::move(extra_parts)); + DemoSetupTestBase::CreatedBrowserMainParts(browser_main_parts); + } + + void CreateTestCampaignsFile(base::StringPiece data) { + CHECK(base::CreateDirectory(growth_campaigns_mounted_path_)); + + base::FilePath campaigns_file( + growth_campaigns_mounted_path_.Append(kCampaignsFileName)); + CHECK(base::WriteFile(campaigns_file, data)); + } + + void SimulateSetupFlowAndVerifyComplete() { + // Simulate successful online setup. + enrollment_helper_.ExpectEnrollmentMode( + policy::EnrollmentConfig::MODE_ATTESTATION); + enrollment_helper_.ExpectAttestationEnrollmentSuccess(); + SimulateNetworkConnected(); + + TriggerDemoModeOnWelcomeScreen(); + + UseOnlineModeOnNetworkScreen(); + + // Test a couple valid inputs, verify the "continue" button is enabled. + SetAndVerifyValidRetailerNameAndStoreNumber("Ret@iler with $ymb0ls", + "0000"); + SetAndVerifyValidRetailerNameAndStoreNumber("R", "1"); + SetAndVerifyValidRetailerNameAndStoreNumber("Retailer", "1234"); + + test::OobeJS().ExpectElementText( + l10n_util::GetStringUTF8( + IDS_OOBE_DEMO_SETUP_PREFERENCES_STORE_NUMBER_INPUT_HELP_TEXT), + kDemoPreferencesStoreNumberInputDisplayMessage); + + test::OobeJS().ClickOnPath(kDemoPreferencesNext); + + AcceptTermsAndExpectDemoSetupProgress(); + + EXPECT_EQ("admin-us@cros-demo-mode.com", + DemoSetupController::GetSubOrganizationEmail()); + // LoginOrLockScreen is shown at beginning of OOBE, so we need to wait until + // it's shown again when Demo setup completes. + LoginOrLockScreenVisibleWaiter().WaitEvenIfShown(); + + // Verify that pref value has been normalized to uppercase. + EXPECT_EQ("retailer", g_browser_process->local_state()->GetString( + prefs::kDemoModeRetailerId)); + EXPECT_EQ("1234", g_browser_process->local_state()->GetString( + prefs::kDemoModeStoreId)); + } + + private: + base::test::ScopedFeatureList feature_list_; + base::FilePath growth_campaigns_mounted_path_; +}; + +IN_PROC_BROWSER_TEST_F(DemoSetupGrowthFrameworkEnabledTest, + OnlineSetupFlowSuccessWithNoCampaignsFile) { + SimulateSetupFlowAndVerifyComplete(); + // Verify that loading growth component failed silently and fetching campaign + // returns nullptr. + EXPECT_EQ(nullptr, growth::CampaignsManager::Get()->GetCampaignBySlot( + growth::Slot::kDemoModeApp)); +} + +IN_PROC_BROWSER_TEST_F(DemoSetupGrowthFrameworkEnabledTest, + OnlineSetupFlowSuccessWithCampaigns) { + base::ScopedAllowBlockingForTesting scoped_allow_blocking; + CreateTestCampaignsFile(R"({ + "reactiveCampaigns": { + "0": [ + { + "id": 3, + "targetings": [], + "payload": { + "demoModeApp": { + "attractionLoop": { + "videoSrcLang1": "/asset/peripherals_lang1.mp4", + "videoSrcLang2": "/asset/peripherals_lang2.mp4" + } + } + } + } + ] + }, + "proactiveCampaigns": {} + })"); + + SimulateSetupFlowAndVerifyComplete(); + + // Verify that loading growth component and fetching campaign successfully. + const auto* campaign = growth::CampaignsManager::Get()->GetCampaignBySlot( + growth::Slot::kDemoModeApp); + const auto* payload = campaign->FindDictByDottedPath("payload.demoModeApp"); + ASSERT_EQ("/asset/peripherals_lang1.mp4", + *payload->FindStringByDottedPath("attractionLoop.videoSrcLang1")); + ASSERT_EQ("/asset/peripherals_lang2.mp4", + *payload->FindStringByDottedPath("attractionLoop.videoSrcLang2")); +} + } // namespace } // namespace ash
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc b/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc index d973bcce..d9054be 100644 --- a/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc +++ b/chrome/browser/ash/login/demo_mode/demo_setup_controller.cc
@@ -7,6 +7,7 @@ #include <utility> #include "ash/components/arc/arc_util.h" +#include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/constants/ash_switches.h" #include "base/barrier_closure.h" @@ -32,6 +33,7 @@ #include "chrome/grit/generated_resources.h" #include "chromeos/ash/components/dbus/dbus_thread_manager.h" #include "chromeos/ash/components/demo_mode/utils/dimensions_utils.h" +#include "chromeos/ash/components/growth/campaigns_manager.h" #include "chromeos/ash/components/install_attributes/install_attributes.h" #include "chromeos/constants/chromeos_features.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" @@ -531,7 +533,9 @@ if (!demo_components_) demo_components_ = std::make_unique<DemoComponents>(demo_config_); - if (DBusThreadManager::Get()->IsUsingFakes()) { + // Simulate loading demo components completed for unit tests. + if (DBusThreadManager::Get()->IsUsingFakes() && + !load_real_components_for_test_) { demo_components_->SetCrOSComponentLoadedForTesting( base::FilePath(), component_error_for_tests_); @@ -540,13 +544,22 @@ weak_ptr_factory_.GetWeakPtr())); return; } + + auto is_growth_campaigns_enabled_in_demo_mode = + features::IsGrowthCampaignsInDemoModeEnabled(); base::OnceClosure load_callback = base::BindOnce(&DemoSetupController::OnDemoComponentsLoaded, weak_ptr_factory_.GetWeakPtr()); base::RepeatingClosure barrier_closure = - base::BarrierClosure(2, std::move(load_callback)); + base::BarrierClosure(is_growth_campaigns_enabled_in_demo_mode ? 3 : 2, + std::move(load_callback)); demo_components_->LoadResourcesComponent(barrier_closure); demo_components_->LoadAppComponent(barrier_closure); + if (is_growth_campaigns_enabled_in_demo_mode) { + // Growth campaign is enabled in demo mode, also load growth campaigns + // component. + growth::CampaignsManager::Get()->LoadCampaigns(barrier_closure); + } } void DemoSetupController::OnDemoComponentsLoaded() { @@ -636,6 +649,10 @@ component_error_for_tests_ = error; } +void DemoSetupController::EnableLoadRealComponentsForTest() { + load_real_components_for_test_ = true; +} + void DemoSetupController::OnDeviceRegistered() { VLOG(1) << "Demo mode setup finished successfully.";
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_controller.h b/chrome/browser/ash/login/demo_mode/demo_setup_controller.h index b33cffd..74406ae 100644 --- a/chrome/browser/ash/login/demo_mode/demo_setup_controller.h +++ b/chrome/browser/ash/login/demo_mode/demo_setup_controller.h
@@ -240,6 +240,8 @@ void SetCrOSComponentLoadErrorForTest( component_updater::CrOSComponentManager::Error error); + void EnableLoadRealComponentsForTest(); + private: // Attempts to load the demo SWA and demo resources ChromeOS components for // online enrollment and pass the results to OnDemoComponentsLoaded(). @@ -306,6 +308,8 @@ // The Demo Mode Resources ChromeOS Component downloaded for online Demo Mode. std::unique_ptr<DemoComponents> demo_components_; + bool load_real_components_for_test_ = false; + base::WeakPtrFactory<DemoSetupController> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml b/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml index 7e8d5be..5c2de3e 100644 --- a/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml +++ b/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml
@@ -157,7 +157,6 @@ android:hint="@string/autofill_optional_tag" android:imeOptions="actionNext" android:inputType="number" - android:maxLength="4" android:minHeight="@dimen/min_touch_target_size" tools:ignore="Autofill,LabelFor" /> </LinearLayout>
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc index 4882907..991208c 100644 --- a/chrome/browser/autofill/autofill_server_browsertest.cc +++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -82,7 +82,7 @@ bool OnIntercept(content::URLLoaderInterceptor::RequestParams* params) { // NOTE: This constant matches the one defined in - // components/autofill/core/browser/autofill_download_manager.cc + // components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc static const char kDefaultAutofillServerURL[] = "https://content-autofill.googleapis.com/"; DCHECK(params);
diff --git a/chrome/browser/autofill/automated_tests/cache_replayer.cc b/chrome/browser/autofill/automated_tests/cache_replayer.cc index 138238f1..5e67b1b1 100644 --- a/chrome/browser/autofill/automated_tests/cache_replayer.cc +++ b/chrome/browser/autofill/automated_tests/cache_replayer.cc
@@ -611,7 +611,7 @@ } // Streams in text format. For consistency, taken from anonymous namespace in -// components/autofill/core/browser/autofill_download_manager.cc +// components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc std::ostream& operator<<(std::ostream& out, const autofill::AutofillPageQueryRequest& query) { for (const auto& form : query.forms()) {
diff --git a/chrome/browser/autofill/automated_tests/cache_replayer.h b/chrome/browser/autofill/automated_tests/cache_replayer.h index 5ed80d0..6e54545 100644 --- a/chrome/browser/autofill/automated_tests/cache_replayer.h +++ b/chrome/browser/autofill/automated_tests/cache_replayer.h
@@ -24,7 +24,7 @@ std::pair<std::string, std::string> SplitHTTP(const std::string& http_text); // Streams in text format. For consistency, taken from anonymous namespace in -// components/autofill/core/browser/autofill_download_manager.cc +// components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc std::ostream& operator<<(std::ostream& out, const autofill::AutofillQueryContents& query); std::ostream& operator<<(std::ostream& out,
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc index bb15b74..c99b17ad 100644 --- a/chrome/browser/chrome_browser_field_trials.cc +++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -46,6 +46,10 @@ #include "chromeos/startup/startup.h" // nogncheck #endif +#if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) +#include "chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.h" +#endif + ChromeBrowserFieldTrials::ChromeBrowserFieldTrials(PrefService* local_state) : local_state_(local_state) { DCHECK(local_state_); @@ -97,6 +101,10 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::multidevice_setup::CreateFirstRunFieldTrial(feature_list); #endif +#if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) + SearchEngineChoiceClientSideTrial::SetUpIfNeeded( + entropy_providers.default_entropy(), feature_list, local_state_); +#endif // BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) } #if BUILDFLAG(IS_ANDROID) @@ -181,4 +189,7 @@ fre_consistency_trial_variation_id_); } #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) + SearchEngineChoiceClientSideTrial::RegisterSyntheticTrials(); +#endif // BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 5746f7c7..4304b468e 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1478,19 +1478,14 @@ callback, const enterprise_connectors::ContentAnalysisDelegate::Data& data, enterprise_connectors::ContentAnalysisDelegate::Result& result) { - if (!result.text_results[0] && !result.image_result) { - std::move(callback).Run(absl::nullopt); - return; - } - - ChromeContentBrowserClient::ClipboardPasteData clipboard_paste_data; - if (result.text_results[0]) { - clipboard_paste_data.text = std::move(data.text[0]); - } - if (result.image_result) { - clipboard_paste_data.image = std::move(data.image); - } - std::move(callback).Run(std::move(clipboard_paste_data)); + absl::optional<ChromeContentBrowserClient::ClipboardPasteData> + clipboard_paste_data; + clipboard_paste_data = + ChromeContentBrowserClient::ClipboardPasteData( + data.text[0], std::string(), {}); + std::move(callback).Run(result.text_results[0] + ? std::move(clipboard_paste_data) + : absl::nullopt); }, std::move(callback)), safe_browsing::DeepScanAccessPoint::PASTE); @@ -5727,7 +5722,6 @@ chrome_navigation_ui_data->is_no_state_prefetching()) { result.push_back( std::make_unique<prerender::NoStatePrefetchURLLoaderThrottle>( - chrome_navigation_ui_data->prerender_histogram_prefix(), GetPrerenderCanceler(wc_getter))); } @@ -7547,9 +7541,11 @@ std::move(dialog_data), connector, std::move(paths), std::move(callback))); } else { - dialog_data.text.push_back(std::move(clipboard_paste_data.text)); - dialog_data.image = std::move(clipboard_paste_data.image); - dialog_data.clipboard_mime_type = data_type.GetName(); + dialog_data.text.push_back(clipboard_paste_data.text); + // Send image only to local agent for analysis. + if (dialog_data.settings.cloud_or_local_settings.is_local_analysis()) { + dialog_data.image = std::move(clipboard_paste_data.image); + } HandleStringData(web_contents, std::move(dialog_data), connector, std::move(callback)); }
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc index 5ba548f..43d4e56 100644 --- a/chrome/browser/chrome_content_browser_client_browsertest.cc +++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -894,48 +894,6 @@ #endif }; -IN_PROC_BROWSER_TEST_F(IsClipboardPasteContentAllowedTest, BitmapAllowed) { - content::WebContents* contents = - browser()->tab_strip_model()->GetWebContentsAt(0); - ChromeContentBrowserClient::ClipboardPasteData clipboard_paste_data = - ChromeContentBrowserClient::ClipboardPasteData(std::string(), "allowed", - {}); - - client()->IsClipboardPasteContentAllowed( - contents, GURL("google.com"), ui::ClipboardFormatType::BitmapType(), - clipboard_paste_data, - base::BindOnce( - [](absl::optional<ChromeContentBrowserClient::ClipboardPasteData> - clipboard_paste_data) { - EXPECT_TRUE(clipboard_paste_data.has_value()); - EXPECT_EQ(clipboard_paste_data->image, "allowed"); - })); -} - -IN_PROC_BROWSER_TEST_F(IsClipboardPasteContentAllowedTest, BitmapBlocked) { - content::WebContents* contents = - browser()->tab_strip_model()->GetWebContentsAt(0); - ChromeContentBrowserClient::ClipboardPasteData clipboard_paste_data = - ChromeContentBrowserClient::ClipboardPasteData(std::string(), "blocked", - {}); - - client()->IsClipboardPasteContentAllowed( - contents, GURL("google.com"), ui::ClipboardFormatType::BitmapType(), - clipboard_paste_data, - base::BindOnce( - [](absl::optional<ChromeContentBrowserClient::ClipboardPasteData> - clipboard_paste_data) { -#if BUILDFLAG(ENTERPRISE_LOCAL_CONTENT_ANALYSIS) - EXPECT_FALSE(clipboard_paste_data.has_value()); -#else - // Platforms that don't support local content analysis shouldn't - // block anything, even when the policy is set to a local service - // provider value. - EXPECT_TRUE(clipboard_paste_data.has_value()); -#endif - })); -} - IN_PROC_BROWSER_TEST_F(IsClipboardPasteContentAllowedTest, TextAllowed) { content::WebContents* contents = browser()->tab_strip_model()->GetWebContentsAt(0);
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabMediator.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabMediator.java index 221f85a..94ebc565 100644 --- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabMediator.java +++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabMediator.java
@@ -104,7 +104,7 @@ // The link Back to Safety on the interstitial page will go to the // previous page. If there is no previous page, i.e. previous page is // NTP, the preview tab will be closed. - if (mIsOnErrorPage && UrlUtilities.isNTPUrl(url)) { + if (mIsOnErrorPage && UrlUtilities.isNtpUrl(url)) { mBottomSheetController.hideContent( mSheetContent, /* animate= */ true); mCurrentUrl = null;
diff --git a/chrome/browser/devtools/device/port_forwarding_browsertest.cc b/chrome/browser/devtools/device/port_forwarding_browsertest.cc index ed785f2..f42c06c8 100644 --- a/chrome/browser/devtools/device/port_forwarding_browsertest.cc +++ b/chrome/browser/devtools/device/port_forwarding_browsertest.cc
@@ -50,10 +50,9 @@ class Listener : public DevToolsAndroidBridge::PortForwardingListener { public: explicit Listener(Profile* profile) - : profile_(profile), - skip_empty_devices_(true) { - DevToolsAndroidBridge::Factory::GetForProfile(profile_)-> - AddPortForwardingListener(this); + : profile_(profile), skip_empty_devices_(true) { + DevToolsAndroidBridge::Factory::GetForProfile(profile_) + ->AddPortForwardingListener(this); } ~Listener() override { @@ -65,16 +64,19 @@ if (status.empty() && skip_empty_devices_) return; base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); + FROM_HERE, loop_->QuitWhenIdleClosure()); } void set_skip_empty_devices(bool skip_empty_devices) { skip_empty_devices_ = skip_empty_devices; } + void set_run_loop(base::RunLoop* loop) { loop_ = loop; } + private: Profile* profile_; bool skip_empty_devices_; + raw_ptr<base::RunLoop> loop_; }; }; @@ -82,7 +84,6 @@ IN_PROC_BROWSER_TEST_F(PortForwardingTest, DISABLED_LoadPageWithStyleAnsScript) { Profile* profile = browser()->profile(); - AndroidDeviceManager::DeviceProviders device_providers; device_providers.push_back( @@ -103,15 +104,16 @@ base::Value::Dict config; config.Set(forwarding_port, original_url.host() + ":" + original_url.port()); prefs->SetDict(prefs::kDevToolsPortForwardingConfig, std::move(config)); - + base::RunLoop loop1; Listener wait_for_port_forwarding(profile); - content::RunMessageLoop(); + wait_for_port_forwarding.set_run_loop(&loop1); + loop1.Run(); RemoteDebuggingServer::EnableTetheringForDebug(); - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), forwarding_url)); content::WebContents* wc = browser()->tab_strip_model()->GetWebContentsAt(0); + ASSERT_TRUE(content::WaitForLoadStop(wc)); ASSERT_EQ("Port forwarding test", content::EvalJs(wc, "document.title")) << "Document has not loaded."; @@ -123,9 +125,12 @@ << "CSS has not loaded."; // Test that disabling port forwarding is handled normally. + base::RunLoop loop2; wait_for_port_forwarding.set_skip_empty_devices(false); + wait_for_port_forwarding.set_run_loop(&loop2); prefs->SetBoolean(prefs::kDevToolsPortForwardingEnabled, false); - content::RunMessageLoop(); + + loop2.Run(); } class PortForwardingDisconnectTest : public PortForwardingTest { @@ -160,11 +165,11 @@ config.Set(forwarding_port, original_url.host() + ":" + original_url.port()); prefs->SetDict(prefs::kDevToolsPortForwardingConfig, std::move(config)); - std::unique_ptr<Listener> wait_for_port_forwarding(new Listener(profile)); - content::RunMessageLoop(); - base::RunLoop run_loop; + auto wait_for_port_forwarding = std::make_unique<Listener>(profile); + wait_for_port_forwarding->set_run_loop(&run_loop); + self_provider->set_release_callback_for_test(base::BindOnce( base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask), base::SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
diff --git a/chrome/browser/dips/dips_bounce_detector.cc b/chrome/browser/dips/dips_bounce_detector.cc index f352496..4e43ad7 100644 --- a/chrome/browser/dips/dips_bounce_detector.cc +++ b/chrome/browser/dips/dips_bounce_detector.cc
@@ -988,9 +988,15 @@ void DIPSWebContentsObserver::OnWorkerCreated( const blink::DedicatedWorkerToken& worker_token, int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) { + content::DedicatedWorkerCreator creator) { + const content::GlobalRenderFrameHostId* const render_frame_host_id = + absl::get_if<content::GlobalRenderFrameHostId>(&creator); + if (!render_frame_host_id) { + return; + } + content::RenderFrameHost* render_frame_host = - content::RenderFrameHost::FromID(ancestor_render_frame_host_id); + content::RenderFrameHost::FromID(*render_frame_host_id); if (!IsInPrimaryPage(render_frame_host)) { return;
diff --git a/chrome/browser/dips/dips_bounce_detector.h b/chrome/browser/dips/dips_bounce_detector.h index 0f1307c..77fd1d5 100644 --- a/chrome/browser/dips/dips_bounce_detector.h +++ b/chrome/browser/dips/dips_bounce_detector.h
@@ -434,14 +434,12 @@ // End SharedWorkerService.Observer overrides. // Start DedicatedWorkerService.Observer overrides: - void OnWorkerCreated( - const blink::DedicatedWorkerToken& worker_token, - int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override; + void OnWorkerCreated(const blink::DedicatedWorkerToken& worker_token, + int worker_process_id, + content::DedicatedWorkerCreator creator) override; void OnBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& worker_token, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override { - } + content::DedicatedWorkerCreator creator) override {} void OnFinalResponseURLDetermined( const blink::DedicatedWorkerToken& worker_token, const GURL& url) override {}
diff --git a/chrome/browser/dips/dips_bounce_detector_browsertest.cc b/chrome/browser/dips/dips_bounce_detector_browsertest.cc index 980cddc..2b0af214 100644 --- a/chrome/browser/dips/dips_bounce_detector_browsertest.cc +++ b/chrome/browser/dips/dips_bounce_detector_browsertest.cc
@@ -203,14 +203,12 @@ // End SharedWorkerService.Observer overrides. // Start DedicatedWorkerService.Observer overrides: - void OnWorkerCreated( - const blink::DedicatedWorkerToken& worker_token, - int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override; + void OnWorkerCreated(const blink::DedicatedWorkerToken& worker_token, + int worker_process_id, + content::DedicatedWorkerCreator creator) override; void OnBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& worker_token, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override { - } + content::DedicatedWorkerCreator creator) override {} void OnFinalResponseURLDetermined( const blink::DedicatedWorkerToken& worker_token, const GURL& url) override {} @@ -290,9 +288,11 @@ void WCOCallbackLogger::OnWorkerCreated( const blink::DedicatedWorkerToken& worker_token, int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) { + content::DedicatedWorkerCreator creator) { + const content::GlobalRenderFrameHostId& render_frame_host_id = + absl::get<content::GlobalRenderFrameHostId>(creator); content::RenderFrameHost* render_frame_host = - content::RenderFrameHost::FromID(ancestor_render_frame_host_id); + content::RenderFrameHost::FromID(render_frame_host_id); GURL scope = GetFirstPartyURL(render_frame_host).value_or(GURL()); log_.push_back(base::StringPrintf("OnDedicatedWorkerCreated(%s)",
diff --git a/chrome/browser/dips/dips_database.cc b/chrome/browser/dips/dips_database.cc index c3dc7ca..da429d6 100644 --- a/chrome/browser/dips/dips_database.cc +++ b/chrome/browser/dips/dips_database.cc
@@ -13,6 +13,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_restrictions.h" @@ -29,6 +30,10 @@ namespace { +BASE_FEATURE(kSqlWALModeOnDipsDatabase, + "SqlWALModeOnDipsDatabase", + base::FEATURE_DISABLED_BY_DEFAULT); + constexpr char kPrepopulatedKey[] = "prepopulated"; absl::optional<base::Time> ColumnOptionalTime(sql::Statement* statement, @@ -97,10 +102,10 @@ DIPSDatabase::DIPSDatabase(const absl::optional<base::FilePath>& db_path) : db_path_(db_path.value_or(base::FilePath())), - db_(std::make_unique<sql::Database>( - sql::DatabaseOptions{.exclusive_locking = true, - .page_size = 4096, - .cache_size = 32})) { + db_(std::make_unique<sql::Database>(sql::DatabaseOptions{ + .wal_mode = base::FeatureList::IsEnabled(kSqlWALModeOnDipsDatabase), + .page_size = 4096, + .cache_size = 32})) { DCHECK(base::FeatureList::IsEnabled(features::kDIPS)); base::AssertLongCPUWorkAllowed(); if (db_path.has_value()) { @@ -406,6 +411,8 @@ sql::InitStatus DIPSDatabase::InitImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + SCOPED_UMA_HISTOGRAM_TIMER("Privacy.DIPS.Database.Operation.InitTime"); + sql::InitStatus status = OpenDatabase(); if (status != sql::INIT_OK) { return status; @@ -549,6 +556,8 @@ // clang-format on DCHECK(db_->IsSQLValid(kWriteSql)); + SCOPED_UMA_HISTOGRAM_TIMER("Privacy.DIPS.Database.Operation.WriteTime"); + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kWriteSql)); statement.BindString(0, site); BindTimesOrNull(statement, storage_times, 1, 2); @@ -587,6 +596,8 @@ // clang-format on DCHECK(db_->IsSQLValid(kWriteSql)); + SCOPED_UMA_HISTOGRAM_TIMER("Privacy.DIPS.Database.Operation.WritePopupTime"); + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kWriteSql)); statement.BindString(0, opener_site); statement.BindString(1, popup_site); @@ -619,6 +630,8 @@ // clang-format on DCHECK(db_->IsSQLValid(kReadSql)); + SCOPED_UMA_HISTOGRAM_TIMER("Privacy.DIPS.Database.Operation.ReadTime"); + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kReadSql)); statement.BindString(0, site); @@ -717,6 +730,8 @@ // clang-format on DCHECK(db_->IsSQLValid(kReadSql)); + SCOPED_UMA_HISTOGRAM_TIMER("Privacy.DIPS.Database.Operation.ReadPopupTime"); + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kReadSql)); statement.BindString(0, opener_site); statement.BindString(1, popup_site); @@ -751,6 +766,10 @@ "AND last_popup_time>?"; // clang-format on DCHECK(db_->IsSQLValid(kReadSql)); + + SCOPED_UMA_HISTOGRAM_TIMER( + "Privacy.DIPS.Database.Operation.ReadRecentPopupsWithInteractionTime"); + sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kReadSql)); statement.BindTime(0, clock_->Now() - lookback); @@ -802,6 +821,9 @@ return {}; } + SCOPED_UMA_HISTOGRAM_TIMER( + "Privacy.DIPS.Database.Operation.GetSitesThatBouncedTime"); + ClearExpiredRows(); static constexpr char kBounceSql[] = // clang-format off @@ -830,6 +852,9 @@ return {}; } + SCOPED_UMA_HISTOGRAM_TIMER( + "Privacy.DIPS.Database.Operation.GetSitesThatBouncedWithStateTime"); + ClearExpiredRows(); static constexpr char kStatefulBounceSql[] = // clang-format off @@ -859,6 +884,9 @@ return {}; } + SCOPED_UMA_HISTOGRAM_TIMER( + "Privacy.DIPS.Database.Operation.GetSitesThatUsedStorageTime"); + ClearExpiredRows(); static constexpr char kStorageSql[] = // clang-format off @@ -887,6 +915,9 @@ return {}; } + SCOPED_UMA_HISTOGRAM_TIMER( + "Privacy.DIPS.Database.Operation.FilterSitesWithInteractionOrWaaTime"); + ClearExpiredRows(); sql::Statement statement(db_->GetUniqueStatement( @@ -1006,6 +1037,9 @@ if (sites.empty()) { return true; } + + SCOPED_UMA_HISTOGRAM_TIMER("Privacy.DIPS.Database.Operation.RemoveRowsTime"); + const std::string site_list = base::JoinString(std::vector<base::StringPiece>(sites.size(), "?"), ","); @@ -1087,6 +1121,9 @@ return false; } + SCOPED_UMA_HISTOGRAM_TIMER( + "Privacy.DIPS.Database.Operation.ClearTimestampsTime"); + ClearExpiredRows(); if ((type & DIPSEventRemovalType::kHistory) ==
diff --git a/chrome/browser/dips/dips_database_unittest.cc b/chrome/browser/dips/dips_database_unittest.cc index 6f21692..9bfa728 100644 --- a/chrome/browser/dips/dips_database_unittest.cc +++ b/chrome/browser/dips/dips_database_unittest.cc
@@ -1523,6 +1523,25 @@ sql::SqliteLoggedResultCode::kCorrupt, 1); } +TEST_F(DIPSDatabaseHistogramTest, PerformanceMetrics) { + histograms().ExpectTotalCount("Privacy.DIPS.Database.Operation.WriteTime", 0); + histograms().ExpectTotalCount("Privacy.DIPS.Database.Operation.ReadTime", 0); + + // Write an entry to the db. + db_->Write("url.test", {}, + /*interaction_times=*/ + {{Time::FromSecondsSinceUnixEpoch(1), + Time::FromSecondsSinceUnixEpoch(1)}}, + {}, {}, {}); + histograms().ExpectTotalCount("Privacy.DIPS.Database.Operation.ReadTime", 0); + histograms().ExpectTotalCount("Privacy.DIPS.Database.Operation.WriteTime", 1); + + // Read back the entry from the db. + db_->Read("site.test"); + histograms().ExpectTotalCount("Privacy.DIPS.Database.Operation.ReadTime", 1); + histograms().ExpectTotalCount("Privacy.DIPS.Database.Operation.WriteTime", 1); +} + class DIPSDatabaseMigrationTest : public testing::Test { public: DIPSDatabaseMigrationTest() {
diff --git a/chrome/browser/download/android/download_controller.cc b/chrome/browser/download/android/download_controller.cc index 65f614d..ac266f3 100644 --- a/chrome/browser/download/android/download_controller.cc +++ b/chrome/browser/download/android/download_controller.cc
@@ -16,7 +16,6 @@ #include "base/lazy_instance.h" #include "base/memory/raw_ptr.h" #include "base/metrics/field_trial_params.h" -#include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "base/synchronization/lock.h" #include "chrome/android/chrome_jni_headers/DownloadController_jni.h" @@ -81,9 +80,6 @@ return; if (!web_contents) { - DownloadController::RecordStoragePermission( - DownloadController::StoragePermissionType:: - STORAGE_PERMISSION_NO_WEB_CONTENTS); return; } @@ -163,14 +159,6 @@ bool granted) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (granted) { - DownloadController::RecordStoragePermission( - DownloadController::StoragePermissionType::STORAGE_PERMISSION_GRANTED); - } else { - DownloadController::RecordStoragePermission( - DownloadController::StoragePermissionType::STORAGE_PERMISSION_DENIED); - } - std::move(cb).Run(granted); } @@ -218,12 +206,6 @@ } // static -void DownloadController::RecordStoragePermission(StoragePermissionType type) { - UMA_HISTOGRAM_ENUMERATION("MobileDownload.StoragePermission", type, - STORAGE_PERMISSION_MAX); -} - -// static void DownloadController::CloseTabIfEmpty(content::WebContents* web_contents, download::DownloadItem* download) { if (!web_contents || !web_contents->GetController().IsInitialNavigation()) @@ -299,16 +281,11 @@ bool has_file_access_permission = Java_DownloadController_hasFileAccess(env, jwindow_android); if (has_file_access_permission) { - RecordStoragePermission( - StoragePermissionType::STORAGE_PERMISSION_REQUESTED); - RecordStoragePermission( - StoragePermissionType::STORAGE_PERMISSION_NO_ACTION_NEEDED); content::GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(std::move(cb), true)); return; } - RecordStoragePermission(StoragePermissionType::STORAGE_PERMISSION_REQUESTED); AcquirePermissionCallback callback(base::BindOnce( &OnRequestFileAccessResult, web_contents_getter, base::BindOnce(&OnStoragePermissionDecided, std::move(cb))));
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc index 5d4b413..c253b5c 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.cc +++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -1833,7 +1833,6 @@ bool storage_permission_granted, bool allow) { if (!storage_permission_granted) { - // UMA for this will be recorded in MobileDownload.StoragePermission. } else if (allow) { // Presumes all downloads initiated by navigation use this throttle and // nothing else does.
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc index 75bf88b..7df34f2 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
@@ -692,7 +692,6 @@ weak_ptr_factory_.GetWeakPtr())); PrepareRequest(BULK_DATA_ENTRY, request.get()); - request->set_content_type(data_.clipboard_mime_type); UploadTextForDeepScanning(std::move(request)); } } @@ -720,7 +719,6 @@ weak_ptr_factory_.GetWeakPtr())); PrepareRequest(BULK_DATA_ENTRY, request.get()); - request->set_content_type(data_.clipboard_mime_type); UploadImageForDeepScanning(std::move(request)); } }
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h index 8ba1bf9..a8e80121 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h
@@ -126,12 +126,6 @@ // analysis. ContentAnalysisRequest::Reason reason = ContentAnalysisRequest::UNKNOWN; - // Mime type of the contents of the clipboard. - // For pasted images, this represents the type of the bytes in `image`. - // For other clipboard data, this represents the type of the bytes in - // `text[0]`. - std::string clipboard_mime_type; - // The settings to use for the analysis of the data in this struct. AnalysisSettings settings; };
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc index df9b4f9c..8c96368 100644 --- a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc +++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -105,10 +105,11 @@ // Submit a request to the policy to read back some data, and call the // checker function when results are available. This will happen on the // database thread. + base::RunLoop run_loop; policy->ReadFilteredData( extension_id, type, api_name, page_url, arg_url, day, base::BindOnce(&CountingPolicyTest::CheckWrapper, std::move(checker), - base::RunLoop::QuitCurrentWhenIdleClosureDeprecated())); + run_loop.QuitClosure())); // Set up a timeout for receiving results; if we haven't received anything // when the timeout triggers then assume that the test is broken. @@ -119,7 +120,7 @@ // Wait for results; either the checker or the timeout callbacks should // cause the main loop to exit. - base::RunLoop().Run(); + run_loop.Run(); timeout.Cancel(); }
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc index 247626c..2186fca 100644 --- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc +++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -98,11 +98,11 @@ // Submit a request to the policy to read back some data, and call the // checker function when results are available. This will happen on the // database thread. + base::RunLoop run_loop; policy->ReadFilteredData( extension_id, type, api_name, page_url, arg_url, days_ago, base::BindOnce(&FullStreamUIPolicyTest::CheckWrapper, - std::move(checker), - base::RunLoop::QuitCurrentWhenIdleClosureDeprecated())); + std::move(checker), run_loop.QuitClosure())); // Set up a timeout for receiving results; if we haven't received anything // when the timeout triggers then assume that the test is broken. @@ -113,7 +113,7 @@ // Wait for results; either the checker or the timeout callbacks should // cause the main loop to exit. - base::RunLoop().Run(); + run_loop.Run(); timeout.Cancel(); } @@ -750,10 +750,11 @@ } policy->Flush(); - GetActivityLogTaskRunner()->PostTaskAndReply( - FROM_HERE, base::DoNothing(), - base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); - base::RunLoop().Run(); + base::RunLoop run_loop; + GetActivityLogTaskRunner()->PostTaskAndReply(FROM_HERE, base::DoNothing(), + run_loop.QuitClosure()); + + run_loop.Run(); CheckReadFilteredData( policy, "punky", Action::ACTION_ANY, "", "", "", -1,
diff --git a/chrome/browser/favicon/large_icon_service_factory.cc b/chrome/browser/favicon/large_icon_service_factory.cc index 7e04bd54..0da8485c 100644 --- a/chrome/browser/favicon/large_icon_service_factory.cc +++ b/chrome/browser/favicon/large_icon_service_factory.cc
@@ -21,7 +21,7 @@ namespace { -favicon::LargeFaviconProvider* GetLargeFaviconProvider( +favicon::LargeIconService* GetLargeIconService( content::BrowserContext* context) { return LargeIconServiceFactory::GetInstance()->GetForBrowserContext(context); } @@ -66,7 +66,7 @@ .Build()) { DependsOn(FaviconServiceFactory::GetInstance()); favicon::SetLargeFaviconProviderGetter( - base::BindRepeating(&GetLargeFaviconProvider)); + base::BindRepeating(&GetLargeIconService)); } LargeIconServiceFactory::~LargeIconServiceFactory() = default;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index f304c33..3df772e 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -6160,7 +6160,7 @@ { "name": "origin-agent-cluster-default", "owners": [ "vogelheim@chromium.org", "chrome-security-owp-team@google.com" ], - "expiry_milestone": 120 + "expiry_milestone": 130 }, { "name": "origin-keyed-processes-by-default", @@ -8415,11 +8415,6 @@ "expiry_milestone": -1 }, { - "name": "whats-new-ios", - "owners": [ "cheickcisse@google.com", "bling-flags@google.com" ], - "expiry_milestone": 111 - }, - { "name": "whats-new-ios-m116", "owners": [ "cheickcisse@google.com", "bling-flags@google.com" ], "expiry_milestone": 122
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/Pane.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/Pane.java index 74cc38a..aa8aaf8 100644 --- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/Pane.java +++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/Pane.java
@@ -18,6 +18,7 @@ int getPaneId(); /** Returns the {@link View} containing the contents of the Pane. */ + @NonNull View getRootView(); /**
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc index 5c4c7d9..a489a1c 100644 --- a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc +++ b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
@@ -103,11 +103,6 @@ EXPECT_EQ(expected_list_size, list->GetSourceCount()); } -ACTION(QuitMessageLoop) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); -} - // This is a helper class to abstract away some of the details of creating and // managing the life-cycle of an AppWindow class TestAppWindow : public content::WebContentsObserver { @@ -296,7 +291,7 @@ void InitializeAndVerify() { CreateDefaultList(); - + base::RunLoop loop; // The tabs in media source list are sorted in decreasing time order. The // latest one is listed first. However, tabs are added to TabStripModel in // increasing time order, the oldest one is added first. @@ -313,11 +308,11 @@ OnSourceThumbnailChanged(kDefaultSourceCount - 1 - i)); } EXPECT_CALL(observer_, OnSourceThumbnailChanged(0)) - .WillOnce(QuitMessageLoop()); + .WillOnce(base::test::RunClosure(loop.QuitClosure())); } list_->StartUpdating(&observer_); - base::RunLoop().Run(); + loop.Run(); for (int i = 0; i < kDefaultSourceCount; ++i) { EXPECT_EQ(list_->GetSource(i).id.type, @@ -357,15 +352,15 @@ TEST_P(TabDesktopMediaListTest, AddTab) { InitializeAndVerify(); - + base::RunLoop loop; AddWebcontents(10); EXPECT_CALL(observer_, OnSourceAdded(0)) .WillOnce(CheckListSize(list_.get(), kDefaultSourceCount + 1)); EXPECT_CALL(observer_, OnSourceThumbnailChanged(0)) - .WillOnce(QuitMessageLoop()); + .WillOnce(base::test::RunClosure(loop.QuitClosure())); - base::RunLoop().Run(); + loop.Run(); } TEST_P(TabDesktopMediaListTest, AddAppWindow) { @@ -387,7 +382,7 @@ TEST_P(TabDesktopMediaListTest, RemoveTab) { InitializeAndVerify(); - + base::RunLoop loop; TabStripModel* tab_strip_model = browser_->tab_strip_model(); ASSERT_TRUE(tab_strip_model); std::unique_ptr<WebContents> released_web_contents = @@ -397,14 +392,14 @@ EXPECT_CALL(observer_, OnSourceRemoved(0)) .WillOnce( testing::DoAll(CheckListSize(list_.get(), kDefaultSourceCount - 1), - QuitMessageLoop())); + base::test::RunClosure(loop.QuitClosure()))); - base::RunLoop().Run(); + loop.Run(); } TEST_P(TabDesktopMediaListTest, MoveTab) { InitializeAndVerify(); - + base::RunLoop loop; // Swap the two media sources by swap their time stamps. TabStripModel* tab_strip_model = browser_->tab_strip_model(); ASSERT_TRUE(tab_strip_model); @@ -421,14 +416,14 @@ EXPECT_CALL(observer_, OnSourceMoved(1, 0)) .WillOnce(testing::DoAll(CheckListSize(list_.get(), kDefaultSourceCount), - QuitMessageLoop())); + base::test::RunClosure(loop.QuitClosure()))); - base::RunLoop().Run(); + loop.Run(); } TEST_P(TabDesktopMediaListTest, UpdateTitle) { InitializeAndVerify(); - + base::RunLoop loop; // Change tab's title. TabStripModel* tab_strip_model = browser_->tab_strip_model(); ASSERT_TRUE(tab_strip_model); @@ -439,9 +434,10 @@ contents->UpdateTitleForEntry(controller.GetLastCommittedEntry(), u"New test tab"); - EXPECT_CALL(observer_, OnSourceNameChanged(0)).WillOnce(QuitMessageLoop()); + EXPECT_CALL(observer_, OnSourceNameChanged(0)) + .WillOnce(base::test::RunClosure(loop.QuitClosure())); - base::RunLoop().Run(); + loop.Run(); EXPECT_EQ(list_->GetSource(0).name, u"New test tab"); } @@ -449,6 +445,7 @@ TEST_P(TabDesktopMediaListTest, UpdateThumbnail) { InitializeAndVerify(); + base::RunLoop loop; // Change tab's favicon. TabStripModel* tab_strip_model = browser_->tab_strip_model(); ASSERT_TRUE(tab_strip_model); @@ -462,16 +459,16 @@ favicon_info; EXPECT_CALL(observer_, OnSourceThumbnailChanged(0)) - .WillOnce(QuitMessageLoop()); + .WillOnce(base::test::RunClosure(loop.QuitClosure())); - base::RunLoop().Run(); + loop.Run(); } // Test that a source which is set as the one being previewed is marked as being // visibly captured, so that it is still painted even when hidden. TEST_P(TabDesktopMediaListTest, SetPreviewMarksTabAsVisiblyCaptured) { InitializeAndVerify(); - + base::RunLoop loop; TabStripModel* tab_strip_model = browser_->tab_strip_model(); ASSERT_TRUE(tab_strip_model); WebContents* contents = @@ -482,7 +479,8 @@ EXPECT_TRUE(contents->IsBeingVisiblyCaptured()); - EXPECT_CALL(observer_, OnSourcePreviewChanged(0)).WillOnce(QuitMessageLoop()); + EXPECT_CALL(observer_, OnSourcePreviewChanged(0)) + .WillOnce(base::test::RunClosure(loop.QuitClosure())); - base::RunLoop().Run(); + loop.Run(); }
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.h b/chrome/browser/metrics/chrome_metrics_service_accessor.h index 0ef15f9..3f928ab 100644 --- a/chrome/browser/metrics/chrome_metrics_service_accessor.h +++ b/chrome/browser/metrics/chrome_metrics_service_accessor.h
@@ -100,6 +100,10 @@ class ExperimentManagerImpl; } +namespace SearchEngineChoiceClientSideTrial { +void RegisterSyntheticTrials(); +} + // This class limits and documents access to metrics service helper methods. // Since these methods are private, each user has to be explicitly declared // as a 'friend' below. @@ -154,6 +158,7 @@ friend class WebUITabStripFieldTrial; friend class feed::FeedServiceDelegateImpl; friend class FirstRunService; + friend void SearchEngineChoiceClientSideTrial::RegisterSyntheticTrials(); friend class browser_sync::DeviceInfoSyncClientImpl; friend class feed::WebFeedSubscriptionCoordinator; friend class HttpsFirstModeService;
diff --git a/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc b/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc index 210f9bf..6894aee 100644 --- a/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc +++ b/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc
@@ -279,7 +279,7 @@ IN_PROC_BROWSER_TEST_F(ModelExecutionDisabledBrowserTest, ModelExecutionDisabled) { proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_FALSE(model_execution_result_->has_value()); @@ -300,7 +300,7 @@ ModelExecutionDisabledInIncognito) { Browser* otr_browser = CreateIncognitoBrowser(browser()->profile()); proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request, otr_browser->profile()); EXPECT_TRUE(model_execution_result_.has_value()); @@ -314,7 +314,7 @@ IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest, ModelExecutionFailsNoUserSignIn) { proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_FALSE(model_execution_result_->has_value()); @@ -330,7 +330,7 @@ SetExpectedBearerAccessToken("Bearer access_token"); proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_TRUE(model_execution_result_->has_value()); @@ -346,7 +346,7 @@ SetResponseType(ModelExecutionRemoteResponseType::kUnsuccessful); proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_FALSE(model_execution_result_->has_value()); @@ -363,7 +363,7 @@ SetResponseType(ModelExecutionRemoteResponseType::kMalformed); proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_FALSE(model_execution_result_->has_value()); @@ -380,7 +380,7 @@ SetResponseType(ModelExecutionRemoteResponseType::kErrorFiltered); proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_FALSE(model_execution_result_->has_value()); @@ -396,7 +396,7 @@ SetResponseType(ModelExecutionRemoteResponseType::kUnsupportedLanguage); proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_FALSE(model_execution_result_->has_value()); @@ -428,7 +428,7 @@ SetExpectedBearerAccessToken("Bearer access_token"); proto::ComposeRequest request; - request.set_user_input("foo"); + request.mutable_generate_params()->set_user_input("foo"); ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, request); EXPECT_TRUE(model_execution_result_.has_value()); EXPECT_TRUE(model_execution_result_->has_value());
diff --git a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java index e0c5a66f..44967bb 100644 --- a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java +++ b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -439,7 +439,7 @@ return false; } - if (!url.isValid() || (!UrlUtilities.isHttpOrHttps(url) && !UrlUtilities.isNTPUrl(url))) { + if (!url.isValid() || (!UrlUtilities.isHttpOrHttps(url) && !UrlUtilities.isNtpUrl(url))) { Log.w( TAG, "Partner homepage must be HTTP(S) or NewTabPage. " + "Got invalid URL \"%s\"",
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 04ad9af..74544d1 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -62,6 +62,7 @@ #include "components/password_manager/content/browser/password_manager_log_router_factory.h" #include "components/password_manager/content/browser/password_requirements_service_factory.h" #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" +#include "components/password_manager/core/browser/features/password_features.h" #include "components/password_manager/core/browser/hsts_query.h" #include "components/password_manager/core/browser/http_auth_manager.h" #include "components/password_manager/core/browser/http_auth_manager_impl.h" @@ -793,11 +794,11 @@ return &httpauth_manager_; } -autofill::AutofillDownloadManager* -ChromePasswordManagerClient::GetAutofillDownloadManager() { +autofill::AutofillCrowdsourcingManager* +ChromePasswordManagerClient::GetAutofillCrowdsourcingManager() { if (auto* client = autofill::ContentAutofillClient::FromWebContents(web_contents())) { - return client->GetDownloadManager(); + return client->GetCrowdsourcingManager(); } return nullptr; } @@ -1095,6 +1096,24 @@ return; } + // In `kNudgePassword` experiment generated password is previewed when the + // popup is visible and any character typed by the user is treated as + // rejection. + if (password_manager::features::kPasswordGenerationExperimentVariationParam + .Get() == + password_manager::features::PasswordGenerationVariation::kNudgePassword) { + // TODO(crbug.com/1444051): Rewrite the AutomaticGenerationAvailable + // triggering instead of checking a boolean if the experiment is launched. + if (ui_data.input_field_empty) { + ShowPasswordGenerationPopup(PasswordGenerationType::kAutomatic, driver, + ui_data); + } else if (popup_controller_) { + popup_controller_->GeneratedPasswordRejected(); + } + + return; + } + ShowPasswordGenerationPopup(PasswordGenerationType::kAutomatic, driver, ui_data); #endif // BUILDFLAG(IS_ANDROID) @@ -1131,7 +1150,8 @@ /*is_generation_element_password_type=*/true, base::i18n::TextDirection(), password_manager::GetFormWithFrameAndFormMetaData( password_generation_driver_receivers_.GetCurrentTargetFrame(), - form_data)); + form_data), + /*input_field_empty=*/false); popup_controller_ = PasswordGenerationPopupControllerImpl::GetOrCreate( popup_controller_, element_bounds_in_screen_space, ui_data, driver->AsWeakPtr(), observer_, web_contents(),
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h index 3ff1e2e..ec7684f 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.h +++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -219,7 +219,8 @@ const password_manager::PasswordFeatureManager* GetPasswordFeatureManager() const override; password_manager::HttpAuthManager* GetHttpAuthManager() override; - autofill::AutofillDownloadManager* GetAutofillDownloadManager() override; + autofill::AutofillCrowdsourcingManager* GetAutofillCrowdsourcingManager() + override; bool IsCommittedMainFrameSecure() const override; const GURL& GetLastCommittedURL() const override; url::Origin GetLastCommittedOrigin() const override;
diff --git a/chrome/browser/pdf/BUILD.gn b/chrome/browser/pdf/BUILD.gn index c8e36d8..6b8b26f 100644 --- a/chrome/browser/pdf/BUILD.gn +++ b/chrome/browser/pdf/BUILD.gn
@@ -35,9 +35,11 @@ "//extensions/browser", "//extensions/common:common_constants", "//extensions/common/api", + "//mojo/public/cpp/bindings", "//pdf:buildflags", "//pdf:features", "//printing/buildflags", + "//third_party/blink/public/common:headers", "//ui/base", "//ui/gfx:color_utils", "//url",
diff --git a/chrome/browser/pdf/pdf_extension_accessibility_test.cc b/chrome/browser/pdf/pdf_extension_accessibility_test.cc index e09d937..34ccd79bf 100644 --- a/chrome/browser/pdf/pdf_extension_accessibility_test.cc +++ b/chrome/browser/pdf/pdf_extension_accessibility_test.cc
@@ -973,9 +973,6 @@ std::vector<std::string> actual_lines = base::SplitString(actual_contents, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - // TODO(b/1473176): Either keep the banner and status node in the output or - // modify `pdf_root` above to remove the banner and status nodes from the - // tree so that they are not in the format output. RemoveBannerAndStatusNodesFromFormatOutput(actual_lines, ax_inspect_type()); // Validate the dump against the expectation file.
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 9604ea7..d86b525e 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -3648,6 +3648,73 @@ EXPECT_EQ(1, content::EvalJs(guest_view->web_contents(), "1;").ExtractInt()); } +// PDF extension tests for the OOPIF PDF viewer. +class PDFExtensionOopifTest : public PDFExtensionTestWithoutOopifOverride { + public: + bool UseOopif() const override { return true; } +}; + +// Test that full page PDF can send and receive postMessage() messages from its +// embedder. +IN_PROC_BROWSER_TEST_F(PDFExtensionOopifTest, OopifPdfPostMessageFullPage) { + // Load a direct PDF URL full page. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/pdf/test.pdf"))); + + // `EnsurePDFHasLoaded()` uses postMessage() to check that the PDF has loaded, + // so calling it is sufficient to check that a postMessage() connection has + // been established. + ASSERT_TRUE(pdf_extension_test_util::EnsurePDFHasLoaded( + GetActiveWebContents()->GetPrimaryMainFrame())); +} + +// Test that an embed-embedded PDF can send and receive postMessage() messages +// to and from its embedder. +IN_PROC_BROWSER_TEST_F(PDFExtensionOopifTest, OopifPdfPostMessageEmbed) { + // Load the HTML containing an embed embedding a PDF. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/pdf/pdf_embed.html"))); + + // `EnsurePDFHasLoaded()` uses postMessage() to check that the PDF has loaded, + // so calling it is sufficient to check that a postMessage() connection has + // been established. + ASSERT_TRUE(pdf_extension_test_util::EnsurePDFHasLoaded( + GetActiveWebContents()->GetPrimaryMainFrame())); +} + +// Test that an iframe-embedded PDF can send and receive postMessage() messages +// from its embedder. +IN_PROC_BROWSER_TEST_F(PDFExtensionOopifTest, OopifPdfPostMessageIframe) { + // A promise that receives and sends postMessage() messages to the PDF iframe. + // The iframe must be accessed differently than the embed, so + // `EnsurePDFHasLoaded()` can't be used here. + const std::string kPostMessageIframe = R"( + new Promise(resolve => { + window.addEventListener('message', event => { + if (event.origin !== + 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai') { + return; + } + if (event.data.type === 'documentLoaded') { + resolve( + event.data.load_state === 'success'); + } else if (event.data.type === 'passwordPrompted') { + resolve(true); + } + }); + window.frames[0][0].postMessage({type: 'initialize'}, '*'); + }); + )"; + + // Load the HTML containing an iframe embedding a PDF. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/pdf/test-iframe.html"))); + + // Verify the pdf has loaded. + EXPECT_EQ(true, content::EvalJs(GetActiveWebContents()->GetPrimaryMainFrame(), + kPostMessageIframe)); +} + // TODO(crbug.com/1445746): Stop testing both modes after OOPIF PDF viewer // launches. INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(PDFExtensionTest);
diff --git a/chrome/browser/pdf/pdf_viewer_stream_manager.cc b/chrome/browser/pdf/pdf_viewer_stream_manager.cc index bff346a..a2bffaf 100644 --- a/chrome/browser/pdf/pdf_viewer_stream_manager.cc +++ b/chrome/browser/pdf/pdf_viewer_stream_manager.cc
@@ -4,11 +4,14 @@ #include "chrome/browser/pdf/pdf_viewer_stream_manager.h" +#include <stdint.h> + #include <memory> #include <tuple> #include <utility> #include "base/containers/contains.h" +#include "base/functional/bind.h" #include "base/memory/weak_ptr.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_handle.h" @@ -16,6 +19,11 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" +#include "extensions/common/api/mime_handler.mojom.h" +#include "extensions/common/mojom/guest_view.mojom.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/frame/frame_owner_element_type.h" #include "url/gurl.h" namespace pdf { @@ -38,6 +46,31 @@ return {frame_tree_node_id, content::GlobalRenderFrameHostId()}; } +// Gets the embedder host from the PDF content host's navigation handle. +content::RenderFrameHost* GetEmbedderHostFromPdfContentNavigation( + content::NavigationHandle* navigation_handle) { + // Since `navigation_handle` is for a PDF content frame, the parent frame is + // the PDF extension frame, and the grandparent frame is the embedder frame. + content::RenderFrameHost* extension_host = + navigation_handle->GetParentFrame(); + CHECK(extension_host); + + return extension_host->GetParent(); +} + +// Gets the `extensions::mojom::MimeHandlerViewContainerManager` from the +// `container_host`. +mojo::AssociatedRemote<extensions::mojom::MimeHandlerViewContainerManager> +GetMimeHandlerViewContainerManager(content::RenderFrameHost* container_host) { + CHECK(container_host); + + mojo::AssociatedRemote<extensions::mojom::MimeHandlerViewContainerManager> + container_manager; + container_host->GetRemoteAssociatedInterfaces()->GetInterface( + &container_manager); + return container_manager; +} + } // namespace bool PdfViewerStreamManager::EmbedderHostInfo::operator<( @@ -49,7 +82,12 @@ PdfViewerStreamManager::StreamInfo::StreamInfo( const std::string& embed_internal_id, std::unique_ptr<extensions::StreamContainer> stream_container) - : internal_id(embed_internal_id), stream(std::move(stream_container)) {} + : internal_id(embed_internal_id), stream(std::move(stream_container)) { + // Make sure 0 is never used because some APIs (particularly WebRequest) have + // special meaning for 0 IDs. + static int32_t next_instance_id = 0; + instance_id = ++next_instance_id; +} PdfViewerStreamManager::StreamInfo::~StreamInfo() = default; @@ -143,6 +181,12 @@ // If an embedder host is deleted, delete the associated `StreamInfo`. for (auto iter = stream_infos_.begin(); iter != stream_infos_.end();) { if (iter->first.frame_tree_node_id == frame_tree_node_id) { + StreamInfo* stream_info = iter->second.get(); + if (stream_info->container_manager) { + stream_info->container_manager->DestroyFrameContainer( + stream_info->instance_id); + } + iter = stream_infos_.erase(iter); } else { ++iter; @@ -158,11 +202,8 @@ void PdfViewerStreamManager::ReadyToCommitNavigation( content::NavigationHandle* navigation_handle) { - // Maybe register a PDF subresource override in the PDF content host, which - // would delete the associated `StreamInfo`. + // Maybe register a PDF subresource override in the PDF content host. if (MaybeRegisterPdfSubresourceOverride(navigation_handle)) { - // `MaybeRegisterPdfSubresourceOverride()` might delete `this`, so return - // immediately. return; } @@ -176,11 +217,22 @@ return; } - ClaimStreamInfo(embedder_host); + StreamInfo* claimed_stream_info = ClaimStreamInfo(embedder_host); + + // Set the internal ID to set up postMessage later, when the PDF content host + // finishes navigating. + auto container_manager = GetMimeHandlerViewContainerManager(embedder_host); + container_manager->SetInternalId(claimed_stream_info->internal_id); } void PdfViewerStreamManager::DidFinishNavigation( content::NavigationHandle* navigation_handle) { + // Maybe set up postMessage support after the PDF content host finishes + // navigating, which would delete the associated `StreamInfo`. + if (MaybeSetUpPostMessage(navigation_handle)) { + return; + } + // During PDF navigation, in the embedder host, an about:blank embed is // inserted in a synthetic HTML document as a placeholder for the PDF // extension. Navigate the about:blank embed to the PDF extension URL to load @@ -242,21 +294,35 @@ GetUnclaimedEmbedderHostInfo(frame_tree_node_id)); } -void PdfViewerStreamManager::ClaimStreamInfo( +PdfViewerStreamManager::StreamInfo* PdfViewerStreamManager::ClaimStreamInfo( content::RenderFrameHost* embedder_host) { auto unclaimed_embedder_info = GetUnclaimedEmbedderHostInfo(embedder_host->GetFrameTreeNodeId()); auto iter = stream_infos_.find(unclaimed_embedder_info); CHECK(iter != stream_infos_.end()); + PdfViewerStreamManager::StreamInfo* stream_info = iter->second.get(); + auto claimed_embedder_info = GetEmbedderHostInfo(embedder_host); stream_infos_[claimed_embedder_info] = std::move(iter->second); stream_infos_.erase(iter); + + return stream_info; } void PdfViewerStreamManager::DeleteStreamInfo( content::RenderFrameHost* embedder_host) { - CHECK(stream_infos_.erase(GetEmbedderHostInfo(embedder_host))); + auto iter = stream_infos_.find(GetEmbedderHostInfo(embedder_host)); + CHECK(iter != stream_infos_.end()); + + StreamInfo* stream_info = iter->second.get(); + if (stream_info->container_manager) { + stream_info->container_manager->DestroyFrameContainer( + stream_info->instance_id); + } + + stream_infos_.erase(iter); + if (stream_infos_.empty()) { web_contents()->RemoveUserData(UserDataKey()); // DO NOT add code past this point. RemoveUserData() deleted `this`. @@ -272,13 +338,10 @@ return false; } - // Since `navigation_handle` is for a PDF content frame, as checked by - // `NavigationHandle::IsPdf()`, the parent frame is the PDF extension frame, - // and the grandparent frame is the embedder frame. - content::RenderFrameHost* extension_host = - navigation_handle->GetParentFrame(); - CHECK(extension_host); - content::RenderFrameHost* embedder_host = extension_host->GetParent(); + // `navigation_handle` is for a PDF content frame, as checked by + // `NavigationHandle::IsPdf()`. + content::RenderFrameHost* embedder_host = + GetEmbedderHostFromPdfContentNavigation(navigation_handle); CHECK(embedder_host); auto* claimed_stream_info = GetClaimedStreamInfo(embedder_host); @@ -291,13 +354,68 @@ navigation_handle->RegisterSubresourceOverride( claimed_stream_info->stream->TakeTransferrableURLLoader()); - // TODO(crbug.com/1445746): The lifetime of the stream container needs to be - // extended to last the duration of the PDF viewer to support PDF saving. - DeleteStreamInfo(embedder_host); - // DO NOT add code past this point. `this` may have been deleted. return true; } +bool PdfViewerStreamManager::MaybeSetUpPostMessage( + content::NavigationHandle* navigation_handle) { + // Only set up postMessage if `navigation_handle` is for the PDF content + // frame. + if (!navigation_handle->IsPdf()) { + return false; + } + + // `navigation_handle` is for a PDF content frame, as checked by + // `NavigationHandle::IsPdf()`. + content::RenderFrameHost* embedder_host = + GetEmbedderHostFromPdfContentNavigation(navigation_handle); + CHECK(embedder_host); + + auto* claimed_stream_info = GetClaimedStreamInfo(embedder_host); + if (!claimed_stream_info) { + return false; + } + + // If `owner_type` is kEmbed or kObject, then the PDF is embedded onto another + // HTML page. `container_host` should be the PDF embedder host's parent. + // Otherwise, the PDF is full-page, in which `container_host` should be the + // PDF embedder host itself. + auto owner_type = embedder_host->GetFrameOwnerElementType(); + bool is_full_page = owner_type != blink::FrameOwnerElementType::kEmbed && + owner_type != blink::FrameOwnerElementType::kObject; + auto* container_host = + is_full_page ? embedder_host : embedder_host->GetParent(); + CHECK(container_host); + + auto container_manager = GetMimeHandlerViewContainerManager(container_host); + + // Set up beforeunload support for full page PDF viewer, which will also help + // set up postMessage support. + if (is_full_page) { + container_manager->CreateBeforeUnloadControl( + base::BindOnce(&PdfViewerStreamManager::SetUpBeforeUnloadControl, + weak_factory_.GetWeakPtr())); + } + + // Enable postMessage support. + // The first parameter for DidLoad() is + // mime_handler_view_guest_element_instance_id, which is used to identify and + // delete `extensions::MimeHandlerViewFrameContainer` objects. However, OOPIF + // PDF viewer doesn't have a guest element instance ID. Use the instance ID + // instead, which is a unique ID for `StreamInfo`. + container_manager->DidLoad(claimed_stream_info->instance_id, + claimed_stream_info->stream->original_url()); + claimed_stream_info->container_manager = std::move(container_manager); + + return true; +} + +void PdfViewerStreamManager::SetUpBeforeUnloadControl( + mojo::PendingRemote<extensions::mime_handler::BeforeUnloadControl> + before_unload_control_remote) { + // TODO(crbug.com/1445746): Currently a no-op. Support the beforeunload API. +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(PdfViewerStreamManager); } // namespace pdf
diff --git a/chrome/browser/pdf/pdf_viewer_stream_manager.h b/chrome/browser/pdf/pdf_viewer_stream_manager.h index 086e7dc..cd2ddf4 100644 --- a/chrome/browser/pdf/pdf_viewer_stream_manager.h +++ b/chrome/browser/pdf/pdf_viewer_stream_manager.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_PDF_PDF_VIEWER_STREAM_MANAGER_H_ #define CHROME_BROWSER_PDF_PDF_VIEWER_STREAM_MANAGER_H_ +#include <stdint.h> + #include <map> #include <memory> @@ -12,6 +14,9 @@ #include "base/memory/weak_ptr.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" +#include "extensions/common/mojom/guest_view.mojom.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace content { @@ -21,6 +26,9 @@ } // namespace content namespace extensions { +namespace mime_handler { +class BeforeUnloadControl; +} class StreamContainer; } // namespace extensions @@ -36,12 +44,13 @@ // 3. Observing for the RFH created by the PDF embedder RFH to load the PDF // extension URL. // 4. Observing for the PDF content RFH to register the stream as a subresource -// override for the final PDF commit navigation. +// override for the final PDF commit navigation and to set up postMessage +// support. // `PdfViewerStreamManager` is scoped to the `content::WebContents` it tracks, // but it may also delete itself if all PDF streams are no longer used. // `extensions::StreamContainer` objects are stored from // `PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse()` until -// the PDF navigation is complete. +// the PDF viewer is no longer in use. // Use `PdfViewerStreamManager::FromWebContents()` to get an instance. class PdfViewerStreamManager : public content::WebContentsObserver, @@ -115,8 +124,6 @@ // A unique ID for the PDF viewer instance. Used to set up postMessage // support for the full-page PDF viewer. - // TODO(crbug.com/1445746): Currently an unused field. Use it to set up - // postMessage. const std::string internal_id; // A container for the PDF stream. Holds data needed to load the PDF in the @@ -127,6 +134,14 @@ // to avoid navigating multiple about:blank child hosts to the PDF extension // URL. bool did_extension_navigate = false; + + // The container manager used to provide postMessage support. + mojo::AssociatedRemote<extensions::mojom::MimeHandlerViewContainerManager> + container_manager; + + // A unique ID for this instance. Used for postMessage support to identify + // `extensions::MimeHandlerViewFrameContainer` objects. + int32_t instance_id; }; friend class content::WebContentsUserData<PdfViewerStreamManager>; @@ -143,10 +158,10 @@ bool ContainsUnclaimedStreamInfo(int frame_tree_node_id) const; // Mark an unclaimed stream info with the same frame tree node ID as - // `embedder_host` as claimed by `embedder_host`. Callers must ensure such a - // stream info exists with `ContainsUnclaimedStreamInfo()` before calling - // this. Otherwise, a crash will occur. - void ClaimStreamInfo(content::RenderFrameHost* embedder_host); + // `embedder_host` as claimed by `embedder_host`. Returns a pointer to the + // claimed stream info. Callers must ensure such a stream info exists with + // `ContainsUnclaimedStreamInfo()` before calling this. + StreamInfo* ClaimStreamInfo(content::RenderFrameHost* embedder_host); // Deletes the stream info associated with `embedder_host`, and deletes // `this` if there are no remaining stream infos. @@ -158,8 +173,22 @@ bool MaybeRegisterPdfSubresourceOverride( content::NavigationHandle* navigation_handle); + // Intended to be called during the PDF content frame's 'DidFinishNavigation'. + // Sets up postMessage communication between the embedder frame and the PDF + // extension frame after the PDF has finished loading. + bool MaybeSetUpPostMessage(content::NavigationHandle* navigation_handle); + + // Sets up beforeunload API support for full-page PDF viewers. + // TODO(crbug.com/1445746): Currently a no-op. Support the beforeunload API. + void SetUpBeforeUnloadControl( + mojo::PendingRemote<extensions::mime_handler::BeforeUnloadControl> + before_unload_control_remote); + // Stores stream info by embedder host info. std::map<EmbedderHostInfo, std::unique_ptr<StreamInfo>> stream_infos_; + + // Needed to avoid use-after-free when setting up beforeunload API support. + base::WeakPtrFactory<PdfViewerStreamManager> weak_factory_{this}; }; } // namespace pdf
diff --git a/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc b/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc index 1769901..46a9a22 100644 --- a/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc +++ b/chrome/browser/pdf/pdf_viewer_stream_manager_unittest.cc
@@ -312,9 +312,10 @@ EXPECT_CALL(navigation_handle, RegisterSubresourceOverride).Times(1); manager->ReadyToCommitNavigation(&navigation_handle); - // There are no remaining streams, so `PdfViewerStreamManager` should be - // deleted after registering the subresource override. - EXPECT_FALSE(pdf_viewer_stream_manager()); + // The stream should persist after the PDF load to provide postMessage support + // and PDF saving. + ASSERT_EQ(manager, pdf_viewer_stream_manager()); + EXPECT_TRUE(manager->GetStreamContainer(embedder_host)); } // `PdfViewerStreamManager` should be able to handle registering multiple @@ -357,17 +358,15 @@ EXPECT_CALL(navigation_handle, RegisterSubresourceOverride).Times(2); manager->ReadyToCommitNavigation(&navigation_handle); - // The first subresource override shouldn't affect the other stream. - EXPECT_FALSE(manager->GetStreamContainer(main_rfh())); - EXPECT_TRUE(manager->GetStreamContainer(embedder_host2)); - navigation_handle.set_render_frame_host(pdf_host2); manager->ReadyToCommitNavigation(&navigation_handle); - // There are no remaining streams, so `PdfViewerStreamManager` should be - // deleted after registering the subresource override. - EXPECT_FALSE(pdf_viewer_stream_manager()); + // The streams should persist after the PDF load to provide postMessage + // support and PDF saving. + ASSERT_EQ(manager, pdf_viewer_stream_manager()); + EXPECT_TRUE(manager->GetStreamContainer(embedder_host1)); + EXPECT_TRUE(manager->GetStreamContainer(embedder_host2)); } // The initial load should claim the stream. If the top level frame is
diff --git a/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc index 60ebf02..239729ea9 100644 --- a/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc
@@ -486,24 +486,6 @@ "'documentPictureInPicture' in window")); } -// Make sure that we cannot set window bounds on the PiP window. -IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - CannotSetWindowRect) { - LoadTabAndEnterPictureInPicture(browser()); - auto* pip_web_contents = window_controller()->GetChildWebContents(); - ASSERT_NE(nullptr, pip_web_contents); - - auto* browser_view = static_cast<BrowserView*>( - BrowserWindow::FindBrowserWindowWithWebContents(pip_web_contents)); - const gfx::Rect bounds = browser_view->GetBounds(); - gfx::Rect different_bounds(bounds.x() + 10, bounds.y() + 10, - bounds.width() / 2, bounds.height() / 2); - ASSERT_NE(bounds, different_bounds); - static_cast<content::WebContentsDelegate*>(browser_view->browser()) - ->SetContentsBounds(pip_web_contents, different_bounds); - EXPECT_EQ(bounds, browser_view->GetBounds()); -} - // Make sure that inner bounds of document PiP windows are not smaller than the // allowed minimum size. IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 8d1f76b3..6b4daf9 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -232,6 +232,7 @@ // `search_engine_choice_service.h` includes `chrome/browser/ui/browser_list.h` // that can't be included on android. #if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) +#include "chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.h" #include "chrome/browser/search_engine_choice/search_engine_choice_service.h" #endif @@ -1665,6 +1666,7 @@ #if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) SearchEngineChoiceService::RegisterLocalStatePrefs(registry); + SearchEngineChoiceClientSideTrial::RegisterLocalStatePrefs(registry); #endif // Platform-specific and compile-time conditional individual preferences.
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragmentV4Test.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragmentV4Test.java index 1e84e61..ee48e7c 100644 --- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragmentV4Test.java +++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragmentV4Test.java
@@ -76,6 +76,7 @@ public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() .setBugComponent(RenderTestRule.Component.UI_SETTINGS_PRIVACY) + .setRevision(1) .build(); @Rule
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragmentV4Test.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragmentV4Test.java index ab24229..bd37131f 100644 --- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragmentV4Test.java +++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragmentV4Test.java
@@ -74,6 +74,7 @@ public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() .setBugComponent(RenderTestRule.Component.UI_SETTINGS_PRIVACY) + .setRevision(1) .build(); @Rule
diff --git a/chrome/browser/resources/ash/settings/common/app_management/actions.ts b/chrome/browser/resources/ash/settings/common/app_management/actions.ts index 3df339c..e26bb1f 100644 --- a/chrome/browser/resources/ash/settings/common/app_management/actions.ts +++ b/chrome/browser/resources/ash/settings/common/app_management/actions.ts
@@ -8,7 +8,7 @@ */ import {App} from 'chrome://resources/cr_components/app_management/app_management.mojom-webui.js'; -import {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; export interface AddAppAction extends Action { name: 'add-app';
diff --git a/chrome/browser/resources/ash/settings/common/app_management/store.ts b/chrome/browser/resources/ash/settings/common/app_management/store.ts index 44a7924..d4385bff 100644 --- a/chrome/browser/resources/ash/settings/common/app_management/store.ts +++ b/chrome/browser/resources/ash/settings/common/app_management/store.ts
@@ -10,7 +10,7 @@ import {App} from 'chrome://resources/cr_components/app_management/app_management.mojom-webui.js'; import {createEmptyState} from 'chrome://resources/cr_components/app_management/util.js'; -import {Store} from 'chrome://resources/js/store_ts.js'; +import {Store} from 'chrome://resources/js/store.js'; import {AppManagementActions} from './actions.js'; import {reduceAction} from './reducers.js';
diff --git a/chrome/browser/resources/ash/settings/crostini_page/crostini_settings_card.html b/chrome/browser/resources/ash/settings/crostini_page/crostini_settings_card.html index cf3d453..f6d6fb0 100644 --- a/chrome/browser/resources/ash/settings/crostini_page/crostini_settings_card.html +++ b/chrome/browser/resources/ash/settings/crostini_page/crostini_settings_card.html
@@ -1,9 +1,21 @@ -<style include="settings-shared"></style> +<style include="settings-shared"> + :host-context(body.revamp-wayfinding-enabled) + #crostiniRowIcon, + #bruschettaRowIcon { + margin-inline-end: 16px; + fill: var(--cros-sys-primary); + } +</style> <settings-card header-text="$i18n{crostiniPageTitle}"> <div id="crostini" class="settings-box two-line first" actionable$="[[prefs.crostini.enabled.value]]" on-click="onSubpageClick_"> + <template is="dom-if" if="[[isRevampWayfindingEnabled_]]"> + <iron-icon id="crostiniRowIcon" + icon="os-settings:about-linux"> + </iron-icon> + </template> <div class="start"> $i18n{crostiniPageLabel} <div class="secondary" id="secondaryText"> @@ -48,6 +60,11 @@ <div id="bruschetta" class="settings-box two-line" actionable$="[[prefs.bruschetta.installed.value]]" on-click="onBruschettaSubpageClick_"> + <template is="dom-if" if="[[isRevampWayfindingEnabled_]]"> + <iron-icon id="bruschettaRowIcon" + icon="os-settings:about-manage-develop-environment"> + </iron-icon> + </template> <div class="start"> $i18n{bruschettaPageLabel} <div class="secondary" id="bruschettaSecondaryText">
diff --git a/chrome/browser/resources/ash/settings/device_page/customize_button_select.ts b/chrome/browser/resources/ash/settings/device_page/customize_button_select.ts index c4098167..fcf7109 100644 --- a/chrome/browser/resources/ash/settings/device_page/customize_button_select.ts +++ b/chrome/browser/resources/ash/settings/device_page/customize_button_select.ts
@@ -55,10 +55,10 @@ * contains the following four. */ const modifierBitMaskToString: Map<number, string> = new Map([ - [Modifier.CONTROL, 'ctrl'], - [Modifier.SHIFT, 'shift'], - [Modifier.ALT, 'alt'], - [Modifier.META, 'meta'], + [Modifier.CONTROL, 'Ctrl'], + [Modifier.SHIFT, 'Shift'], + [Modifier.ALT, 'Alt'], + [Modifier.META, 'Meta'], ]); /** @@ -67,7 +67,12 @@ function getInputKeys(keyEvent: KeyEvent): string[] { const inputKeysArray: string[] = []; modifierBitMaskToString.forEach((modifierName: string, bitValue: number) => { - if ((keyEvent.modifiers & bitValue) !== 0) { + // Now if pressing a single modifier key like "shift", it will show + // "shift + shift" instead of a single "shift". + // Temporarily add a condition to check modifierName duplicating with + // keyDisplay until it's fixed in the key combination logics. + if ((keyEvent.modifiers & bitValue) !== 0 && + modifierName !== keyEvent.keyDisplay) { inputKeysArray.push(modifierName, '+'); } });
diff --git a/chrome/browser/resources/ash/settings/os_about_page/os_about_page.html b/chrome/browser/resources/ash/settings/os_about_page/os_about_page.html index 314f34d4..d49447b7 100644 --- a/chrome/browser/resources/ash/settings/os_about_page/os_about_page.html +++ b/chrome/browser/resources/ash/settings/os_about_page/os_about_page.html
@@ -29,6 +29,10 @@ text-align: center; } + :host-context(body.revamp-wayfinding-enabled) #updateRowIcon { + margin-inline-end: 16px; + } + /* TODO(crbug.com/986596): Don't use browser icons here. Fork them. */ iron-icon[icon='settings:check-circle'] { fill: var(--cros-icon-color-prominent); @@ -40,6 +44,19 @@ fill: var(--cros-icon-color-alert); } + iron-icon[icon='os-settings:about-update-complete'] { + fill: var(--cros-sys-positive); + } + iron-icon[icon='os-settings:about-update-warning'] { + fill: var(--cros-sys-warning); + } + iron-icon[icon='os-settings:about-update-error'] { + fill: var(--cros-sys-error); + } + :host-context(body.revamp-wayfinding-enabled) iron-icon[icon='cr20:domain'] { + fill: var(--cros-sys-primary); + } + #firmwareUpdateBadge { --iron-icon-fill-color: var(--cros-icon-color-secondary); } @@ -94,11 +111,23 @@ <div class="settings-box two-line"> <!-- Set the icon from the iconset (when it's obsolete/EOL and when update is done) or set the src (when it's updating). --> - <div class="icon-container" - hidden="[[!shouldShowIcons_(showUpdateStatus_)]]"> - <!-- TODO(crbug.com/986596): Don't use browser icons here. Fork - them. --> - <iron-icon + <template is="dom-if" if="[[!isRevampWayfindingEnabled_]]"> + <div class="icon-container" + hidden="[[!shouldShowIcons_(showUpdateStatus_)]]"> + <!-- TODO(crbug.com/986596): Don't use browser icons here. Fork + them. --> + <iron-icon + icon$="[[getUpdateStatusIcon_( + hasEndOfLife_, currentUpdateStatusEvent_)]]" + src="[[getThrobberSrcIfUpdating_( + isDarkModeActive_, + hasEndOfLife_, + currentUpdateStatusEvent_)]]"> + </iron-icon> + </div> + </template> + <template is="dom-if" if="[[isRevampWayfindingEnabled_]]"> + <iron-icon id="updateRowIcon" icon$="[[getUpdateStatusIcon_( hasEndOfLife_, currentUpdateStatusEvent_)]]" src="[[getThrobberSrcIfUpdating_( @@ -106,7 +135,7 @@ hasEndOfLife_, currentUpdateStatusEvent_)]]"> </iron-icon> - </div> + </template> <div class="start padded"> <div id="updateStatusMessage" hidden="[[!showUpdateStatus_]]"> <div id="updateStatusMessageInner" tabindex="-1" @@ -161,6 +190,7 @@ <cr-link-row id="aboutTPMFirmwareUpdate" class="hr" + start-icon="[[rowIcons_.powerWash]]" hidden$="[[!showTPMFirmwareUpdateLineItem_]]" label="$i18n{aboutTPMFirmwareUpdateTitle}" on-click="onTpmFirmwareUpdateClick_"> @@ -174,6 +204,7 @@ </cr-link-row> <template is="dom-if" if="[[hasInternetConnection_]]"> <cr-link-row class="hr" id="releaseNotesOnline" + start-icon="[[rowIcons_.releaseNotes]]" on-click="onReleaseNotesClick_" label="$i18n{aboutShowReleaseNotes}" sub-label="[[getShowReleaseNotesSublabel_()]]" @@ -183,6 +214,7 @@ </template> <template is="dom-if" if="[[!hasInternetConnection_]]"> <cr-link-row class="hr" id="releaseNotesOffline" + start-icon="[[rowIcons_.releaseNotes]]" on-click="onReleaseNotesClick_" label="$i18n{aboutShowReleaseNotes}" title="$i18n{aboutReleaseNotesOffline}" @@ -190,7 +222,9 @@ deep-link-focus-id$="[[Setting.kSeeWhatsNew]]"> </cr-link-row> </template> - <cr-link-row class="hr" id="help" on-click="onHelpClick_" + <cr-link-row class="hr" id="help" + start-icon="[[rowIcons_.help]]" + on-click="onHelpClick_" label="$i18n{aboutGetHelpUsingChromeOs}" sub-label="[[getHelpUsingChromeOsSublabel_()]]" external @@ -198,6 +232,7 @@ </cr-link-row> <if expr="_google_chrome"> <cr-link-row class="hr" id="reportIssue" + start-icon="[[rowIcons_.feedback]]" on-click="onReportIssueClick_" hidden="[[!prefs.feedback_allowed.value]]" label="[[getReportIssueLabel_()]]" @@ -207,6 +242,7 @@ </cr-link-row> </if> <cr-link-row class="hr" id="diagnostics" + start-icon="[[rowIcons_.diagnostics]]" on-click="onDiagnosticsClick_" label="$i18n{aboutDiagnostics}" sub-label="[[getDiagnosticsSublabel_()]]" @@ -214,6 +250,7 @@ deep-link-focus-id$="[[Setting.kDiagnostics]]"> </cr-link-row> <cr-link-row class="hr" id="firmwareUpdates" + start-icon="[[rowIcons_.firmwareUpdates]]" on-click="onFirmwareUpdatesClick_" label="$i18n{aboutFirmwareUpdates}" sub-label="[[getFirmwareSublabel_(firmwareUpdateCount_)]]" @@ -232,6 +269,7 @@ </div> </cr-link-row> <cr-link-row class="hr" id="detailedBuildInfoTrigger" + start-icon="[[rowIcons_.additionalDetails]]" on-click="onDetailedBuildInfoClick_" label="$i18n{aboutDetailedBuildInfo}" role-description="$i18n{subpageArrowRoleDescription}">
diff --git a/chrome/browser/resources/ash/settings/os_about_page/os_about_page.ts b/chrome/browser/resources/ash/settings/os_about_page/os_about_page.ts index d40b2b2..adf1462 100644 --- a/chrome/browser/resources/ash/settings/os_about_page/os_about_page.ts +++ b/chrome/browser/resources/ash/settings/os_about_page/os_about_page.ts
@@ -239,6 +239,33 @@ }, readOnly: true, }, + + rowIcons_: { + type: Object, + value() { + if (isRevampWayfindingEnabled()) { + return { + powerWash: 'os-settings:startup', + releaseNotes: 'os-settings:about-release-notes', + help: 'os-settings:about-help', + feedback: 'os-settings:about-feedback', + diagnostics: 'os-settings:about-diagnostics', + firmwareUpdates: 'os-settings:about-firmware-updates', + additionalDetails: 'os-settings:about-additional-details', + }; + } + + return { + powerWash: '', + releaseNotes: '', + help: '', + feedback: '', + diagnostics: '', + firmwareUpdates: '', + additionalDetails: '', + }; + }, + }, }; } @@ -267,6 +294,7 @@ private eolMessageWithMonthAndYear_: string; private hasInternetConnection_: boolean; private firmwareUpdateCount_: number; + private rowIcons_: Record<string, string>; private showCrostiniLicense_: boolean; private showUpdateStatus_: boolean; private showButtonContainer_: boolean; @@ -557,14 +585,20 @@ case UpdateStatus.FAILED_DOWNLOAD: case UpdateStatus.FAILED_HTTP: case UpdateStatus.FAILED: - return 'cr:error-outline'; + return this.isRevampWayfindingEnabled_ ? + 'os-settings:about-update-error' : + 'cr:error-outline'; case UpdateStatus.UPDATED: case UpdateStatus.NEARLY_UPDATED: // TODO(crbug.com/986596): Don't use browser icons here. Fork them. - return 'settings:check-circle'; + return this.isRevampWayfindingEnabled_ ? + 'os-settings:about-update-complete' : + 'settings:check-circle'; case UpdateStatus.DEFERRED: case UpdateStatus.UPDATE_TO_ROLLBACK_VERSION_DISALLOWED: - return 'cr:warning'; + return this.isRevampWayfindingEnabled_ ? + 'os-settings:about-update-warning' : + 'cr:warning'; default: return null; }
diff --git a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html index b21a0372..8ca1e4de 100644 --- a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html +++ b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html
@@ -1,8 +1,20 @@ -<style include="settings-shared"></style> +<style include="settings-shared"> + :host-context(body.revamp-wayfinding-enabled) + #disconnectGoogleDriveAccountToggle { + --cr-icon-button-margin-end: 16px; + --iron-icon-fill-color: var(--cros-sys-primary); + } + + #smbSharesIcon { + fill: var(--cros-sys-primary); + margin-inline-end: 16px; + } +</style> <settings-card header-text="$i18n{filesPageTitle}"> <template is="dom-if" if="[[!shouldShowGoogleDriveSettings_]]"> <settings-toggle-button id="disconnectGoogleDriveAccountToggle" + icon="[[rowIcons_.googleDrive]]" pref="{{prefs.gdata.disabled}}" label="$i18n{disconnectGoogleDriveAccount}" deep-link-focus-id$="[[Setting.kGoogleDriveConnection]]"> @@ -10,8 +22,7 @@ </template> <template is="dom-if" if="[[shouldShowGoogleDriveSettings_]]"> <cr-link-row id="googleDriveRow" - start-icon="settings20:google-drive" - class="hr" + start-icon="[[rowIcons_.googleDrive]]" on-click="onClickGoogleDrive_" label="$i18n{googleDriveLabel}" sub-label="[[computeGoogleDriveSublabel_(driveDisabled_, bulkPinningPrefEnabled_)]]" @@ -21,7 +32,7 @@ <template is="dom-if" if="[[shouldShowOfficeSettings_]]"> <cr-link-row id="oneDriveRow" - start-icon="settings20:onedrive" + start-icon="[[rowIcons_.oneDrive]]" class="hr" on-click="onClickOneDrive_" label="$i18n{oneDriveLabel}" @@ -40,6 +51,8 @@ <template is="dom-if" if="[[isRevampWayfindingEnabled_]]"> <template is="dom-if" if="[[shouldShowAddSmbButton_]]" restamp> <div id="addSmbSharesRow" class="settings-box two-line"> + <iron-icon id="smbSharesIcon" icon="[[rowIcons_.smbShares]]"> + </iron-icon> <div class="start"> <div class="settings-box-text"> <div> @@ -66,6 +79,7 @@ <template is="dom-if" if="[[computeShowSmbLinkRow_(shouldShowAddSmbButton_)]]" restamp> <cr-link-row id="smbSharesRow" + start-icon="[[rowIcons_.smbShares]]" class="hr" on-click="onClickSmbShares_" label="$i18n{smbSharesTitle}"
diff --git a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts index 0e80f68..95346ad 100644 --- a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts +++ b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts
@@ -85,6 +85,25 @@ }, }, + rowIcons_: { + type: Object, + value() { + if (isRevampWayfindingEnabled()) { + return { + googleDrive: 'os-settings:google-drive-revamp', + oneDrive: 'settings20:onedrive', + smbShares: 'os-settings:folder-shared', + }; + } + + return { + googleDrive: 'os-settings:google-drive', + oneDrive: 'settings20:onedrive', + smbShares: '', + }; + }, + }, + shouldShowGoogleDriveSettings_: { type: Boolean, value: () => { @@ -128,10 +147,11 @@ private bulkPinningPrefEnabled_: boolean; private driveDisabled_: boolean; private isBulkPinningEnabled_: boolean; - private isRevampWayfindingEnabled_: boolean; + private readonly isRevampWayfindingEnabled_: boolean; private oneDriveBrowserProxy_: OneDriveBrowserProxy|undefined; private oneDriveConnectionState_: OneDriveConnectionState; private oneDriveEmailAddress_: string|null; + private rowIcons_: Record<string, string>; private smbBrowserProxy_: SmbBrowserProxy; private shouldShowAddSmbButton_: boolean; private shouldShowAddSmbDialog_: boolean;
diff --git a/chrome/browser/resources/ash/settings/os_settings_icons.html b/chrome/browser/resources/ash/settings/os_settings_icons.html index f01f7b6..63bcef4b 100644 --- a/chrome/browser/resources/ash/settings/os_settings_icons.html +++ b/chrome/browser/resources/ash/settings/os_settings_icons.html
@@ -86,6 +86,40 @@ <path d="M10.6177 10.0898C10.4368 10.2188 10.2211 10.2832 9.97046 10.2832C9.61596 10.2832 9.34115 10.1462 9.146 9.87231C8.95085 9.59839 8.85327 9.24837 8.85327 8.82227C8.85327 8.39258 8.95353 8.0354 9.15405 7.75073C9.35457 7.46606 9.61059 7.32373 9.92212 7.32373C10.2587 7.32373 10.5273 7.46875 10.7278 7.75879C10.9283 8.04883 11.0286 8.45703 11.0286 8.9834V9.62256C10.9355 9.80518 10.7985 9.96094 10.6177 10.0898Z"></path> <path fill-rule="evenodd" clip-rule="evenodd" d="M10 2C5.584 2 2 5.584 2 10C2 14.416 5.584 18 10 18C14.416 18 18 14.416 18 10C18 5.584 14.416 2 10 2ZM11.0071 10.874C10.6025 11.2715 10.1298 11.4702 9.58911 11.4702C8.89803 11.4702 8.34481 11.233 7.92944 10.7585C7.51408 10.2841 7.3064 9.64405 7.3064 8.83838C7.3064 8.32633 7.41829 7.85637 7.64209 7.42847C7.86589 7.00057 8.1783 6.66756 8.57935 6.42944C8.98039 6.19132 9.43156 6.07227 9.93286 6.07227C10.4485 6.07227 10.9068 6.20117 11.3079 6.45898C11.7089 6.7168 12.0204 7.0874 12.2424 7.5708C12.4644 8.0542 12.5772 8.60742 12.5808 9.23047V9.80518C12.5808 11.1086 12.2568 12.1326 11.6086 12.8774C10.9605 13.6222 10.0421 14.0197 8.85327 14.0698L8.47192 14.0752V12.7808L8.81567 12.7754C10.1656 12.7145 10.8961 12.0807 11.0071 10.874Z"></path> </g> + <g id="about-update-complete" width="16" height="16" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M8 15.167a7.012 7.012 0 0 1-2.792-.563 7.165 7.165 0 0 1-2.27-1.52 7.731 7.731 0 0 1-1.542-2.292A7.012 7.012 0 0 1 .833 8c0-.986.188-1.917.563-2.792a7.46 7.46 0 0 1 1.542-2.27 6.996 6.996 0 0 1 2.27-1.542A7.012 7.012 0 0 1 8 .833c1.139 0 2.18.243 3.125.73A7.009 7.009 0 0 1 13.542 3.5V.875h1.583V6H10V4.417h2.083a4.944 4.944 0 0 0-1.791-1.354A5.314 5.314 0 0 0 8 2.563c-1.5 0-2.785.534-3.854 1.604C3.09 5.222 2.563 6.5 2.563 8s.527 2.785 1.583 3.854C5.216 12.91 6.5 13.438 8 13.438s2.778-.528 3.833-1.584c1.07-1.07 1.604-2.354 1.604-3.854h1.73c0 2-.695 3.694-2.084 5.083C11.694 14.473 10 15.167 8 15.167Zm2.042-4.292L7.208 8.042V4h1.584v3.375l2.375 2.375-1.125 1.125Z"></path> + </g> + <g id="about-update-warning" width="20" height="20" viewBox="0 0 20 20"> + <path fill-rule="evenodd" d="M.854 17.083 10 1.833l9.146 15.25H.854Zm2.917-1.645h12.458L10 5.063 3.77 15.438ZM10 14.479c.208 0 .389-.07.542-.208a.765.765 0 0 0 .229-.563.74.74 0 0 0-.23-.541.698.698 0 0 0-.541-.23.74.74 0 0 0-.542.23.698.698 0 0 0-.229.541c0 .209.07.39.209.542.152.153.34.23.562.23ZM9.25 12h1.5V8.063h-1.5V12Z"></path> + </g> + <g id="about-update-error" width="20" height="20" viewBox="0 0 20 20"> + <path fill-rule="evenodd" d="M10 14.167c.25 0 .458-.084.625-.25a.839.839 0 0 0 .27-.646c0-.25-.09-.459-.27-.625a.815.815 0 0 0-.625-.271c-.25 0-.465.09-.646.27a.848.848 0 0 0-.25.626c0 .25.084.465.25.646a.92.92 0 0 0 .646.25ZM9.125 11h1.75V5.896h-1.75V11ZM10 18.167a8.205 8.205 0 0 1-3.187-.625 8.59 8.59 0 0 1-2.605-1.75 8.589 8.589 0 0 1-1.75-2.604A8.204 8.204 0 0 1 1.833 10c0-1.139.209-2.201.625-3.187a8.327 8.327 0 0 1 1.75-2.584 8.112 8.112 0 0 1 2.605-1.75c1-.43 2.062-.646 3.187-.646 1.139 0 2.201.216 3.188.646.986.417 1.847 1 2.583 1.75a7.82 7.82 0 0 1 1.75 2.604c.43.986.646 2.042.646 3.167a7.974 7.974 0 0 1-.646 3.188c-.417.986-1 1.854-1.75 2.604a8.262 8.262 0 0 1-2.604 1.75 8.053 8.053 0 0 1-3.167.625Zm0-1.73c1.792 0 3.313-.625 4.563-1.875 1.25-1.25 1.874-2.77 1.874-4.562 0-1.792-.625-3.312-1.875-4.562-1.25-1.25-2.77-1.875-4.562-1.875-1.792 0-3.312.624-4.562 1.874C4.188 6.688 3.563 8.209 3.563 10c0 1.792.624 3.313 1.874 4.563 1.25 1.25 2.771 1.874 4.563 1.874Z"></path> + </g> + <g id="about-release-notes" width="18" height="18" viewBox="0 0 18 18"> + <path fill-rule="evenodd" d="m4.792 13.208 6.041-2.375 2.375-6.041-6.041 2.375-2.375 6.041ZM9 10a.896.896 0 0 1-.708-.27A1.035 1.035 0 0 1 8 9c0-.278.097-.514.292-.708A.964.964 0 0 1 9 8c.278 0 .514.097.708.292.195.194.292.43.292.708a.964.964 0 0 1-.292.708A.964.964 0 0 1 9 10Zm0 7.167a8.205 8.205 0 0 1-3.187-.625 8.59 8.59 0 0 1-2.605-1.75 8.589 8.589 0 0 1-1.75-2.604A8.204 8.204 0 0 1 .833 9c0-1.139.209-2.201.625-3.187a8.327 8.327 0 0 1 1.75-2.584 8.112 8.112 0 0 1 2.605-1.75c1-.43 2.062-.646 3.187-.646 1.139 0 2.201.216 3.188.646.986.417 1.847 1 2.583 1.75a7.82 7.82 0 0 1 1.75 2.604c.43.986.646 2.042.646 3.167a7.974 7.974 0 0 1-.646 3.188c-.417.986-1 1.854-1.75 2.604a8.262 8.262 0 0 1-2.604 1.75A8.053 8.053 0 0 1 9 17.167Zm0-1.73c1.792 0 3.313-.624 4.563-1.874 1.25-1.25 1.874-2.771 1.874-4.563 0-1.792-.624-3.312-1.874-4.562-1.25-1.25-2.771-1.875-4.563-1.875-1.792 0-3.312.624-4.562 1.874C3.188 5.688 2.563 7.209 2.563 9c0 1.792.624 3.313 1.874 4.563 1.25 1.25 2.771 1.874 4.563 1.874Z"></path> + </g> + <g id="about-help" width="16" height="16" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M7.98 12.5a.897.897 0 0 0 .687-.292.964.964 0 0 0 .291-.708.921.921 0 0 0-.291-.708.931.931 0 0 0-.688-.271c-.278 0-.52.09-.729.27a.922.922 0 0 0-.292.709c0 .278.098.514.292.708a.99.99 0 0 0 .73.292Zm-.75-2.854h1.478c0-.472.042-.806.125-1 .084-.195.299-.452.646-.771.278-.264.521-.549.73-.854.222-.32.333-.708.333-1.167 0-.75-.257-1.326-.771-1.729-.5-.417-1.097-.625-1.792-.625-.68 0-1.25.201-1.708.604-.445.39-.757.833-.938 1.334L6.667 6c.097-.236.236-.48.416-.73.195-.263.493-.395.896-.395s.688.111.854.333c.18.209.271.438.271.688 0 .278-.104.535-.312.77-.209.223-.41.431-.604.626-.445.43-.716.77-.813 1.02-.097.25-.146.695-.146 1.334Zm-4.667 5.52c-.487 0-.896-.166-1.23-.5a1.671 1.671 0 0 1-.5-1.229V2.563c0-.487.167-.896.5-1.23a1.67 1.67 0 0 1 1.23-.5h10.875c.486 0 .895.167 1.229.5.333.334.5.743.5 1.23v10.875c0 .486-.167.895-.5 1.229-.334.333-.743.5-1.23.5H2.563Zm0-1.729h10.875V2.563H2.563v10.875Zm0-10.874v10.875V2.563Z"></path> + </g> + <g id="about-feedback" width="18" height="18" viewBox="0 0 18 18"> + <path fill-rule="evenodd" d="M9 11.5a.79.79 0 0 0 .583-.23.756.756 0 0 0 .25-.582.756.756 0 0 0-.25-.584.756.756 0 0 0-.583-.25.823.823 0 0 0-.604.25.765.765 0 0 0-.23.563c0 .236.077.437.23.604.166.153.368.229.604.229Zm-.792-2.458h1.584V3.5H8.208v5.542ZM.833 17.167V2.562c0-.486.167-.895.5-1.229a1.67 1.67 0 0 1 1.23-.5h12.875c.486 0 .895.167 1.229.5.333.334.5.743.5 1.23v9.875c0 .486-.167.895-.5 1.229-.334.333-.743.5-1.23.5H3.834l-3 3Zm2.375-4.73h12.23V2.563H2.563v10.52l.645-.646Zm-.646 0V2.563v9.875Z"></path> + </g> + <g id="about-diagnostics" width="20" height="14" viewBox="0 0 20 14"> + <path fill-rule="evenodd" d="M7.542 13.125a1.34 1.34 0 0 1-.792-.25 1.391 1.391 0 0 1-.48-.646L4.5 7.875H.875v-1.75h4.813l1.854 4.625 3.646-9a1.34 1.34 0 0 1 1.27-.875c.292 0 .549.083.771.25.236.167.403.382.5.646L15.5 6.125h3.625v1.75h-4.792L12.458 3.25l-3.645 9a1.36 1.36 0 0 1-.5.625 1.25 1.25 0 0 1-.771.25Z"></path> + </g> + <g id="about-firmware-updates" width="18" height="14" viewBox="0 0 18 14"> + <path fill-rule="evenodd" d="M2.563 13.167c-.487 0-.896-.167-1.23-.5a1.671 1.671 0 0 1-.5-1.23V2.563c0-.487.167-.896.5-1.23a1.67 1.67 0 0 1 1.23-.5h4.312v1.73H2.563v8.875h12.875V2.563h-4.313V.833h4.313c.486 0 .895.167 1.229.5.333.334.5.743.5 1.23v8.875c0 .486-.167.895-.5 1.229-.334.333-.743.5-1.23.5H2.563Zm6.437-3L4.833 6l1.23-1.208 2.062 2.062V.834h1.75v6.02l2.063-2.062L13.167 6 9 10.167Z"></path> + </g> + <g id="about-additional-details" width="16" height="10" viewBox="0 0 16 10"> + <path fill-rule="evenodd" d="M.833 9.833V8.125h5.25v1.708H.833Zm0-3.958v-1.73h9.292v1.73H.833Zm0-3.98V.168h14.334v1.729H.833Z"></path> + </g> + <g id="about-linux" width="16" height="16" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M6.345 5.812c0 .47-.37.85-.828.85a.84.84 0 0 1-.827-.85c0-.47.37-.85.827-.85a.84.84 0 0 1 .828.85ZM10.483 6.662a.84.84 0 0 0 .827-.85.84.84 0 0 0-.827-.85.84.84 0 0 0-.828.85c0 .47.37.85.828.85ZM7.832 7.122a.384.384 0 0 1 .318 0l1.136.512a.398.398 0 0 1 .128.63L8.285 9.51a.386.386 0 0 1-.575 0L6.585 8.26a.4.4 0 0 1 .128-.629l1.12-.509Z"></path> + <path fill-rule="evenodd" d="M8 15.22c-.068 0-.136.051-.203.102l-.076.055c-.03.325-.274.623-1.652.623-1.693 0-1.674-.352-1.65-.815.004-.058.007-.117.007-.177 0-.082.016-.156.047-.221-1.96-.815-3.215-2.462-3.258-5.33-.198.104-.422.121-.682.024-.741-.278-.575-1.206-.303-2.034.226-.685.995-1.186 1.372-1.29C2.478 2.704 4.536 0 8 0c3.506 0 5.577 2.592 6.43 6.166.385.122 1.12.614 1.34 1.281.272.828.438 1.756-.303 2.034-.26.097-.484.08-.682-.023-.039 2.887-1.296 4.525-3.256 5.334.03.064.045.136.045.216 0 .06.004.12.007.177.024.463.043.815-1.65.815-1.388 0-1.626-.302-1.652-.63-.023-.015-.046-.032-.068-.048-.07-.05-.14-.102-.211-.102Zm0-1.662c3.657 0 4.975-1.602 4.975-5.148 0-2.943-1.199-5.645-3.189-6.097-.324-.073-.598.296-.882.678-.275.37-.558.751-.904.751-.353 0-.657-.398-.946-.775-.285-.373-.555-.725-.84-.654-1.999.504-3.19 3.31-3.19 6.097 0 3.346 1.32 5.149 4.976 5.149Z" clip-rule="evenodd"></path> + </g> + <g id="about-manage-develop-environment" width="18" height="16" viewBox="0 0 18 16"> + <path fill-rule="evenodd" d="M.833 3.917V2.563c0-.487.167-.896.5-1.23.348-.333.757-.5 1.23-.5h12.875c.486 0 .895.167 1.229.5.333.334.5.743.5 1.23v1.354h-1.73V2.563H2.563v1.354H.833Zm5.084 11.25v-2H2.563c-.473 0-.882-.167-1.23-.5a1.671 1.671 0 0 1-.5-1.23v-1.354h1.73v1.354h12.875v-1.354h1.729v1.354c0 .487-.167.896-.5 1.23-.334.333-.743.5-1.23.5h-3.354v2H5.917ZM3.063 7 5 5.063 3.875 3.938.833 7l3.042 3.063L5 8.937 3.063 7Zm11.875 0L13 8.938l1.125 1.104L17.167 7l-3.042-3.062L13 5.062 14.938 7Z"></path> + </g> <!-- Crostini Mascot icon for Settings drawer --> <g id="crostini-mascot" fill-rule="evenodd" viewBox="0 0 24 24"> @@ -133,6 +167,9 @@ <!-- Files section --> <g id="folder-outline"><path d="M16 5h-4l-2-2H4c-1.1 0-1.99.9-1.99 2L2 15c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 10H4V7h12v8z"></path></g> + <g id="folder-shared"> + <path fill-rule="evenodd" d="M10 14h6v-.354c0-.403-.306-.764-.917-1.084-.61-.319-1.305-.479-2.083-.479-.792 0-1.493.16-2.104.48-.597.305-.896.666-.896 1.083V14Zm3-2.917c.417 0 .77-.146 1.063-.437.291-.292.437-.646.437-1.063 0-.416-.146-.77-.438-1.062A1.447 1.447 0 0 0 13 8.083c-.417 0-.77.153-1.063.459a1.446 1.446 0 0 0-.437 1.062c0 .403.146.75.438 1.042.291.291.645.437 1.062.437Zm-9.438 5.084c-.472 0-.881-.167-1.229-.5a1.716 1.716 0 0 1-.5-1.23V5.563c0-.487.167-.896.5-1.23.348-.333.757-.5 1.23-.5h4.354L10 5.896h6.438c.486 0 .895.173 1.229.52.333.334.5.737.5 1.209v6.813c0 .472-.167.881-.5 1.229-.334.333-.743.5-1.23.5H3.563Zm0-1.73h12.876V7.625H9.27L7.208 5.562H3.562v8.875Zm0 0V5.563v8.875Z"></path> + </g> <!-- Keyboard shortcut banner icons --> <g id="keyboard-shortcut" viewBox="0 0 48 48"><path d="M11 17h26v20H11V17Z" fill="var(--cros-sys-illo-color1-2)"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 17a3 3 0 0 1 3-3h26a3 3 0 0 1 3 3v20a3 3 0 0 1-3 3H11a3 3 0 0 1-3-3V17Zm3 0v20h26V17H11Z" fill="var(--cros-sys-illo-color1-1)"/><path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 21a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1ZM18 33h12v2H18v-2Zm2.5-13a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1h-1Zm5 1a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1Zm7-1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1h-1Zm-7 8a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1Zm7-1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1h-1Zm-13 1a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1Zm-5-1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1h-1Z" fill="var(--cros-sys-illo-color1-1)"/><path fill-rule="evenodd" clip-rule="evenodd" d="M16 8a1 1 0 0 0-1 1v11.868h18V9a1 1 0 0 0-1-1H16Zm7.418 18.887L15 20.867h18l-8.418 6.019a1 1 0 0 1-1.164 0Z" fill="var(--cros-sys-illo-color1)"/><path d="m25 12 3 3-3 3" stroke="var(--cros-sys-illo-base)" stroke-width="2" stroke-linecap="square" stroke-linejoin="round"/><path d="M27 15h-6a1 1 0 0 0-1 1v3" stroke="var(--cros-sys-illo-base)" stroke-width="2" stroke-linejoin="round"/></g> @@ -268,6 +305,10 @@ <g id="set-date-time" viewBox="0 0 20 20"> <path fill-rule="evenodd" d="M4.563 7.5h10.875V5.562H4.562V7.5Zm0 0V5.562 7.5Zm0 10.667c-.487 0-.896-.167-1.23-.5a1.671 1.671 0 0 1-.5-1.23V5.563c0-.472.167-.875.5-1.208.348-.347.757-.52 1.23-.52H6v-2h1.625v2h4.75v-2H14v2h1.438c.472 0 .874.173 1.208.52.347.333.52.736.52 1.208v4.355a3.444 3.444 0 0 0-.833-.271 6.34 6.34 0 0 0-.895-.146V9H4.562v7.438h5.209c.083.319.194.625.333.916.153.278.327.549.521.813H4.562Zm10.52.833c-1.11 0-2.055-.389-2.833-1.167-.778-.777-1.167-1.722-1.167-2.833 0-1.111.39-2.056 1.167-2.833A3.927 3.927 0 0 1 15.104 11c1.097 0 2.035.389 2.813 1.167.777.777 1.166 1.722 1.166 2.833 0 1.111-.389 2.056-1.166 2.833-.778.778-1.723 1.167-2.834 1.167Zm1.146-2.104.771-.75-1.375-1.375v-1.813h-1.063v2.271l1.667 1.667Z"></path> </g> + <g id="restore"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 9V7H15.1979C14.1609 5.20627 12.2219 4 10 4C6.685 4 4 6.685 4 10C4 13.315 6.685 16 10 16C12.9739 16 15.4407 13.8392 15.9169 11.0011L17.9379 11.0005C17.4451 14.9449 14.0766 18 9.992 18C5.576 18 2 14.416 2 10C2 5.584 5.576 2 9.992 2C12.3857 2 14.5335 3.04926 16.0007 4.71184L16 3H18V9H12ZM10.5 6V10L13 12.5L11.5 14L8.5 11V6H10.5Z"></path></g> + <g id="restore-revamp"> + <path fill-rule="evenodd" d="M10 11.583a1.53 1.53 0 0 1-1.125-.458A1.575 1.575 0 0 1 8.417 10c0-.43.152-.799.458-1.104.32-.32.694-.48 1.125-.48.43 0 .799.16 1.104.48.32.305.48.673.48 1.104 0 .444-.16.82-.48 1.125a1.505 1.505 0 0 1-1.104.458Zm0 5.584c-1.986 0-3.68-.695-5.083-2.084C3.514 13.694 2.819 12 2.833 10h1.73c.027 1.514.562 2.799 1.604 3.854C7.222 14.91 8.5 15.438 10 15.438c1.514 0 2.799-.528 3.854-1.584 1.056-1.055 1.584-2.34 1.584-3.854 0-1.514-.528-2.799-1.584-3.854C12.8 5.09 11.514 4.563 10 4.563c-.778 0-1.52.166-2.23.5-.707.319-1.326.77-1.853 1.354H8V8H2.875V2.875h1.583V5.5c.68-.847 1.5-1.5 2.459-1.958A6.882 6.882 0 0 1 10 2.833c.986 0 1.917.188 2.792.563a6.996 6.996 0 0 1 2.27 1.542 7.165 7.165 0 0 1 1.521 2.27c.39.861.584 1.792.584 2.792 0 1-.195 1.938-.584 2.813a7.49 7.49 0 0 1-1.52 2.27 7.165 7.165 0 0 1-2.271 1.521 7.012 7.012 0 0 1-2.792.563Z"></path> + </g> <!-- General OS Settings icons --> <g id="account" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.6 9.8a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm4.8 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2ZM10 2c-4.416 0-8 3.584-8 8s3.584 8 8 8 8-3.584 8-8-3.584-8-8-8Zm0 14.4A6.409 6.409 0 0 1 3.6 10c0-.232.016-.464.04-.688a8.05 8.05 0 0 0 4.168-4.296 7.98 7.98 0 0 0 8.328 3.176c.168.568.264 1.176.264 1.808 0 3.528-2.872 6.4-6.4 6.4Z"/></g> @@ -292,6 +333,7 @@ <g id="fullscreen-magnifier" viewBox="0 0 20 20"><path d="M14 11V9h2V8h-2V6h-1v2h-2v1h2v2h1Z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M17.5 3h-15C1.6 3 1 3.7 1 4.556V15.5c0 .856.6 1.5 1.5 1.5h15c.9 0 1.5-.644 1.5-1.5v-11c0-.856-.6-1.5-1.5-1.5ZM17 15H3V5h14v10Z"></path></g> <g id="geolocation"><path d="M12 8C12 9.10457 11.1046 10 10 10C8.89543 10 8 9.10457 8 8C8 6.89543 8.89543 6 10 6C11.1046 6 12 6.89543 12 8Z" fill="#1B1B1F"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M16 8C16 10.2091 14 13.5425 10 18C6 13.5425 4 10.2091 4 8C4 4.68629 6.68629 2 10 2C13.3137 2 16 4.68629 16 8ZM10 4C7.79086 4 6 5.79086 6 8C6 9.32543 7.318 11.7149 10 14.9435C12.682 11.7149 14 9.32543 14 8C14 5.79086 12.2091 4 10 4Z" fill="#1B1B1F"></path></g> <g id="google-drive"><path fill-rule="evenodd" clip-rule="evenodd" d="M18.7333 12L13.0167 2H7.31665V2.00833L13.025 12H18.7333ZM8.27502 12.8334L5.41669 17.8334H16.35L19.2084 12.8334H8.27502ZM6.59167 3.26672L1.125 12.8334L3.98333 17.8251L9.45 8.26672C9.45 8.27506 6.59167 3.26672 6.59167 3.26672Z"></path></g> + <g id="google-drive-revamp"><path fill-rule="evenodd" d="M4.875 16.125h10.25l1.958-3.375-5.145-8.875H8.062L2.918 12.75l1.958 3.375Zm0 1.52c-.292 0-.556-.062-.792-.187a1.57 1.57 0 0 1-.541-.583L1.604 13.5a1.785 1.785 0 0 1-.208-.75c0-.278.07-.535.208-.77L6.73 3.124c.125-.236.306-.424.542-.563.25-.138.514-.208.792-.208h3.874c.264 0 .514.07.75.208.25.14.445.327.584.563l5.125 8.854c.11.236.166.493.166.771.014.264-.041.514-.166.75l-1.938 3.375c-.152.25-.347.444-.583.583a1.503 1.503 0 0 1-.75.188H4.875Zm1.292-3.624L5.604 13l3.667-6.417h1.458L14.396 13l-.563 1.02H6.167ZM7.646 12.5h4.708L10 8.396 7.646 12.5Z"></path></g> <g id="google-play"><path fill-rule="evenodd" clip-rule="evenodd" d="M16.8167 9.06658L14.2667 7.61658L11.8834 9.99991L14.2667 12.3832L16.8167 10.9332C17.275 10.6749 17.5 10.3416 17.5 9.99991C17.5 9.65824 17.275 9.32491 16.8167 9.06658ZM3.92498 2.04163C4.93332 3.04996 10.9417 9.05829 10.9417 9.05829L13.0666 6.93329L4.14998 1.88329C4.09165 1.84996 4.03332 1.82496 3.97498 1.79996C3.83332 1.74163 3.72498 1.84163 3.84998 1.97496C3.87498 1.99163 3.89998 2.01663 3.92498 2.04163ZM3.92501 17.9583C3.90001 17.9833 3.87501 18.0083 3.85834 18.025C3.73334 18.15 3.84168 18.2583 3.98334 18.2C4.04168 18.175 4.10001 18.15 4.15834 18.1166L13.0667 13.0667L10.9417 10.9417C10.9417 10.9417 4.94168 16.95 3.92501 17.9583ZM10 9.99995C10 9.99995 2.975 2.97495 2.81667 2.81662C2.65833 2.65828 2.5 2.75828 2.5 2.97495V17.025C2.5 17.2416 2.65833 17.3416 2.81667 17.1833C2.975 17.025 10 9.99995 10 9.99995Z"></path></g> <g id="hard-drive"><path d="M14 14C14 14.5523 13.5523 15 13 15C12.4477 15 12 14.5523 12 14C12 13.4477 12.4477 13 13 13C13.5523 13 14 13.4477 14 14Z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M5 2C3.89543 2 3 2.89543 3 4V16C3 17.1046 3.89543 18 5 18H15C16.1046 18 17 17.1046 17 16V4C17 2.89543 16.1046 2 15 2H5ZM5 16H15V12H5V16ZM5 10H15V4H5V10Z"></path></g> <g id="hotspot"><path d="M2 10.5C2 5.84343 5.808 2 10.5 2C15.192 2 19 5.84343 19 10.5C19 13.7534 17.2915 16.5158 15 18L14 16.5C15.9315 15.3233 17.3 13.1185 17.5 10.5C17.3 6.78713 14.257 3.71582 10.5 3.5C6.743 3.71582 3.7 6.78713 3.5 10.5C3.7 13.1185 5.0685 15.3233 7 16.5L6 18C3.7085 16.5158 2 13.7534 2 10.5Z"></path><path d="M15.5 10.5C15.5 7.78374 13.2583 5.5 10.5 5.5C7.74167 5.5 5.5 7.78374 5.5 10.5C5.5 12.4786 6.50833 14.1171 8 15L9 13.5C7.84167 12.9285 7.16667 11.8503 7 10.5C7.16667 8.71761 8.65833 7.19794 10.5 7C12.3417 7.19794 13.8333 8.71761 14 10.5C13.8333 11.8503 13.1583 12.9285 12 13.5L13 15C14.4917 14.1171 15.5 12.4786 15.5 10.5Z"></path><path d="M10.5 12C11.3284 12 12 11.3284 12 10.5C12 9.67157 11.3284 9 10.5 9C9.67157 9 9 9.67157 9 10.5C9 11.3284 9.67157 12 10.5 12Z"></path></g> @@ -312,7 +354,6 @@ <g id="print"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 3H15V7H16C17.1046 7 18 7.89543 18 9V14H15V17H5V14H2V9C2 7.89543 2.89543 7 4 7H5V3ZM13 5H7V7H13V5ZM16 10C16 10.5523 15.5523 11 15 11C14.4477 11 14 10.5523 14 10C14 9.44772 14.4477 9 15 9C15.5523 9 16 9.44772 16 10ZM7 12H13V15H7V12Z"></path></g> <g id="printer-add"><path fill-opacity=".3" d="M17.8734304,8.29826826 C17.2839707,8.10470383 16.6542128,8 16,8 C13.3875623,8 11.1650842,9.66961525 10.3414114,12 L7,12 L7,15 L10.0829584,15 C10.2034032,15.7179235 10.4513404,16.3926158 10.8026932,17 L5,17 L5,14 L2,14 L2,9 C2,7.8954305 2.8954305,7 4,7 L5,7 L5,3 L15,3 L15,7 L16,7 C16.8576527,7 17.5892179,7.53984453 17.8734304,8.29826826 Z M7,5 L7,7 L13,7 L13,5 L7,5 Z"></path><polygon points="17 13 19 13 19 15 17 15 17 17 15 17 15 15 13 15 13 13 15 13 15 11 17 11"></polygon></g> <g id="refresh"><path fill-rule="evenodd" clip-rule="evenodd" d="M10 3C6.136 3 3 6.136 3 10C3 13.864 6.136 17 10 17C12.1865 17 14.1399 15.9959 15.4239 14.4239L13.9984 12.9984C13.0852 14.2129 11.6325 15 10 15C7.24375 15 5 12.7563 5 10C5 7.24375 7.24375 5 10 5C11.6318 5 13.0839 5.78641 13.9972 7H11V9H17V3H15V5.10253C13.7292 3.80529 11.9581 3 10 3Z"></path></g> - <g id="restore"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 9V7H15.1979C14.1609 5.20627 12.2219 4 10 4C6.685 4 4 6.685 4 10C4 13.315 6.685 16 10 16C12.9739 16 15.4407 13.8392 15.9169 11.0011L17.9379 11.0005C17.4451 14.9449 14.0766 18 9.992 18C5.576 18 2 14.416 2 10C2 5.584 5.576 2 9.992 2C12.3857 2 14.5335 3.04926 16.0007 4.71184L16 3H18V9H12ZM10.5 6V10L13 12.5L11.5 14L8.5 11V6H10.5Z"></path></g> <g id="select-to-speak" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM7.778 11.368H6V8.632h1.778L10 6.352v7.297l-2.222-2.28ZM12 10c0-.807-.453-1.5-1.111-1.838v3.671A2.046 2.046 0 0 0 12 10Zm-1.111-3.06V6C12.67 6.415 14 8.048 14 10s-1.329 3.585-3.111 4v-.94c1.284-.392 2.222-1.614 2.222-3.06s-.938-2.668-2.222-3.06ZM5 7V5h2v1H6v1H5Zm10 6v2h-2v-1h1v-1h1Z"></path></g> <g id="social-group"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 3C9.425 3 11 4.575 11 6.5C11 8.425 9.425 10 7.5 10C5.575 10 4 8.425 4 6.5C4 4.575 5.575 3 7.5 3ZM7.5 5C6.67957 5 6 5.67957 6 6.5C6 7.32043 6.67957 8 7.5 8C8.32043 8 9 7.32043 9 6.5C9 5.67957 8.32043 5 7.5 5ZM13.9916 14.0859C13.7789 12.0336 9.60583 11 7.5 11C5.33875 11 1 12.0887 1 14.25V17H14V14.25L13.9916 14.0859ZM11.9947 14.3433C11.9867 14.3476 11.9693 14.3346 11.9329 14.3011L11.8432 14.2246C11.6159 14.0441 11.2636 13.85 10.8172 13.6713C9.79154 13.2607 8.42752 13 7.5 13C6.57248 13 5.20846 13.2607 4.18279 13.6713C3.73641 13.85 3.38414 14.0441 3.15679 14.2246L3.0671 14.3011C3.01855 14.3458 3.00384 14.3539 3 14.3335V15H12V14.3335L11.9947 14.3433ZM11.2717 9.77623C11.6543 9.92081 12.0683 10 12.5 10C14.425 10 16 8.425 16 6.5C16 4.575 14.425 3 12.5 3C12.0683 3 11.6543 3.07919 11.2717 3.22377C12.0361 4.10238 12.5 5.24886 12.5 6.5C12.5 7.75114 12.0361 8.89762 11.2717 9.77623ZM15.5 17H19V14.25L18.9916 14.0859C18.8063 12.2977 15.6141 11.2828 13.4026 11.0513C14.5583 11.7896 15.3634 12.7824 15.4896 14.0088L15.5 14.25V17Z"></path></g> <g id="stylus"><path fill-rule="evenodd" clip-rule="evenodd" d="M2 14.6662V18H5.32305L12.0225 11.3057L8.69053 7.97192L2 14.6662ZM15.6565 2.26452L17.7356 4.33592C18.0821 4.68263 18.091 5.2516 17.7445 5.59831L12.9732 10.3634L9.63234 7.02073L11.8803 4.77153L11.2317 4.12255L6.20266 9.15435L4.95874 7.90974L10.6186 2.25563C10.9651 1.90892 11.5426 1.91781 11.8803 2.26452L13.142 3.51803L14.4037 2.26452C14.7413 1.91781 15.31 1.91781 15.6565 2.26452Z"></path></g>
diff --git a/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts b/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts index 50810cc..83195c6 100644 --- a/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts +++ b/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts
@@ -715,7 +715,8 @@ case SearchResultIcon.kDockedMagnifier: return 'os-settings:docked-magnifier'; case SearchResultIcon.kDrive: - return 'os-settings:google-drive'; + return isRevampEnabled ? 'os-settings:google-drive-revamp' : + 'os-settings:google-drive'; case SearchResultIcon.kEthernet: return 'os-settings:settings-ethernet'; case SearchResultIcon.kFingerprint: @@ -771,12 +772,13 @@ return 'os-settings:print'; case SearchResultIcon.kReset: return isRevampEnabled ? 'os-settings:startup' : 'os-settings:restore'; + case SearchResultIcon.kRestore: + return isRevampEnabled ? 'os-settings:restore-revamp' : + 'os-settings:startup'; case SearchResultIcon.kSelectToSpeak: return 'os-settings:select-to-speak'; case SearchResultIcon.kShield: return 'cr:security'; - case SearchResultIcon.kStartup: - return 'os-settings:startup'; case SearchResultIcon.kStorage: return isRevampEnabled ? 'os-settings:storage' : 'os-settings:hard-drive';
diff --git a/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.html b/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.html index 0a255a2..d02f088 100644 --- a/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.html +++ b/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.html
@@ -1,7 +1,16 @@ -<style include="settings-shared"></style> +<style include="settings-shared"> + #restoreIcon { + fill: var(--cros-sys-primary); + margin-inline-end: 16px; + } +</style> <settings-card header-text="$i18n{onStartupSettingsCardTitle}"> - <div class="settings-box"> + <div class="settings-box first two-line"> + <template is="dom-if" if="[[isRevampWayfindingEnabled_]]"> + <iron-icon id="restoreIcon" icon="os-settings:restore-revamp"> + </iron-icon> + </template> <div class="start settings-box-text" aria-hidden="true"> $i18n{onStartupTitle} <div class="secondary">$i18n{onStartupDescription}</div>
diff --git a/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.ts b/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.ts index ded101a9..99242d1 100644 --- a/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.ts +++ b/chrome/browser/resources/ash/settings/system_preferences_page/startup_settings_card.ts
@@ -16,6 +16,7 @@ import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {DeepLinkingMixin} from '../common/deep_linking_mixin.js'; +import {isRevampWayfindingEnabled} from '../common/load_time_booleans.js'; import {RouteObserverMixin} from '../common/route_observer_mixin.js'; import {PrefsState} from '../common/types.js'; import {Setting} from '../mojom-webui/setting.mojom-webui.js'; @@ -50,6 +51,14 @@ value: () => new Set<Setting>([Setting.kRestoreAppsAndPages]), }, + isRevampWayfindingEnabled_: { + type: Boolean, + value() { + return isRevampWayfindingEnabled(); + }, + readOnly: true, + }, + /** * List of options for the on startup dropdown menu. */ @@ -68,6 +77,7 @@ } prefs: PrefsState; + private readonly isRevampWayfindingEnabled_: boolean; private readonly onStartupDropdownOptions_: Array<{value: number, name: string}>;
diff --git a/chrome/browser/resources/bookmarks/actions.ts b/chrome/browser/resources/bookmarks/actions.ts index 254f7ff..3dbf2c7 100644 --- a/chrome/browser/resources/bookmarks/actions.ts +++ b/chrome/browser/resources/bookmarks/actions.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.js'; -import {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {IncognitoAvailability, ROOT_NODE_ID} from './constants.js'; import {BookmarkNode, BookmarksPageState, NodeMap} from './types.js';
diff --git a/chrome/browser/resources/bookmarks/api_listener.ts b/chrome/browser/resources/bookmarks/api_listener.ts index 5bb0ac1..1686a5e 100644 --- a/chrome/browser/resources/bookmarks/api_listener.ts +++ b/chrome/browser/resources/bookmarks/api_listener.ts
@@ -4,7 +4,7 @@ import {assert} from 'chrome://resources/js/assert.js'; import {addWebUiListener, removeWebUiListener} from 'chrome://resources/js/cr.js'; -import {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {createBookmark, editBookmark, moveBookmark, refreshNodes, removeBookmark, reorderChildren, setCanEditBookmarks, setIncognitoAvailability} from './actions.js'; import {BrowserProxyImpl} from './browser_proxy.js';
diff --git a/chrome/browser/resources/bookmarks/reducers.ts b/chrome/browser/resources/bookmarks/reducers.ts index 31a5827..76b7e97 100644 --- a/chrome/browser/resources/bookmarks/reducers.ts +++ b/chrome/browser/resources/bookmarks/reducers.ts
@@ -10,7 +10,7 @@ */ import {assert} from 'chrome://resources/js/assert.js'; -import {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {ChangeFolderOpenAction, CreateBookmarkAction, EditBookmarkAction, FinishSearchAction, MoveBookmarkAction, RefreshNodesAction, RemoveBookmarkAction, ReorderChildrenAction, SelectFolderAction, SelectItemsAction, SetPrefAction, StartSearchAction, UpdateAnchorAction} from './actions.js'; import {BookmarkNode, BookmarksPageState, FolderOpenState, NodeMap, PreferencesState, SearchState, SelectionState} from './types.js';
diff --git a/chrome/browser/resources/bookmarks/store.ts b/chrome/browser/resources/bookmarks/store.ts index 54866a5..dfb4e7e 100644 --- a/chrome/browser/resources/bookmarks/store.ts +++ b/chrome/browser/resources/bookmarks/store.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 {Store as CrUiStore} from 'chrome://resources/js/store_ts.js'; +import {Store as CrUiStore} from 'chrome://resources/js/store.js'; import {reduceAction} from './reducers.js'; import {BookmarksPageState} from './types.js';
diff --git a/chrome/browser/resources/bookmarks/store_client_mixin.ts b/chrome/browser/resources/bookmarks/store_client_mixin.ts index 2c38dba..5f79a55 100644 --- a/chrome/browser/resources/bookmarks/store_client_mixin.ts +++ b/chrome/browser/resources/bookmarks/store_client_mixin.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {makeStoreClientMixin, StoreClientInterface} from 'chrome://resources/cr_elements/store_client/store_client.js'; -import {Action} from 'chrome://resources/js/store_ts.js'; +import {Action} from 'chrome://resources/js/store.js'; import {Store} from './store.js'; import {BookmarksPageState} from './types.js';
diff --git a/chrome/browser/resources/on_device_internals/app.html b/chrome/browser/resources/on_device_internals/app.html index fcf308a..54e6298 100644 --- a/chrome/browser/resources/on_device_internals/app.html +++ b/chrome/browser/resources/on_device_internals/app.html
@@ -59,6 +59,10 @@ margin-inline-start: 50px; } + .retracted { + background-color: var(--google-red-100); + } + .text { margin-inline-end: 50px; } @@ -141,6 +145,6 @@ <template is="dom-repeat" items="[[responses_]]"> <div class="session"> <div class="text">[[item.text]]</div> - <div class="response">[[item.response]]</div> + <div class$="[[responseClass_(item)]]">[[item.response]]</div> </div> </template>
diff --git a/chrome/browser/resources/on_device_internals/app.ts b/chrome/browser/resources/on_device_internals/app.ts index 26b0c819..bde25eb 100644 --- a/chrome/browser/resources/on_device_internals/app.ts +++ b/chrome/browser/resources/on_device_internals/app.ts
@@ -15,11 +15,12 @@ import {getTemplate} from './app.html.js'; import {BrowserProxy} from './browser_proxy.js'; -import {LoadModelResult, OnDeviceModelRemote, PerformanceClass, SessionRemote, StreamingResponderCallbackRouter} from './on_device_model.mojom-webui.js'; +import {LoadModelResult, OnDeviceModelRemote, PerformanceClass, ResponseStatus, SessionRemote, StreamingResponderCallbackRouter} from './on_device_model.mojom-webui.js'; interface Response { text: string; response: string; + retracted: boolean; } interface OnDeviceInternalsAppElement { @@ -208,15 +209,26 @@ 'currentResponse_.response', (this.currentResponse_?.response + text).trimStart()); }); - const onCompleteId = this.responseRouter_.onComplete.addListener(() => { - this.addResponse_(); - this.responseRouter_.removeListener(onResponseId); - this.responseRouter_.removeListener(onCompleteId); - }); - this.currentResponse_ = {text: this.text_, response: ''}; + const onCompleteId = this.responseRouter_.onComplete.addListener( + (status: ResponseStatus) => { + if (status === ResponseStatus.kRetracted && this.currentResponse_) { + this.currentResponse_.retracted = true; + } + this.addResponse_(); + this.responseRouter_.removeListener(onResponseId); + this.responseRouter_.removeListener(onCompleteId); + }); + this.currentResponse_ = {text: this.text_, response: '', retracted: false}; this.text_ = ''; } + private responseClass_(response: Response): string { + if (response.retracted) { + return 'response retracted'; + } + return 'response'; + } + private canExecute_(): boolean { return !this.currentResponse_ && this.model_ !== null; }
diff --git a/chrome/browser/resources/search_engine_choice/app.html b/chrome/browser/resources/search_engine_choice/app.html index eff9cbd..d42faea 100644 --- a/chrome/browser/resources/search_engine_choice/app.html +++ b/chrome/browser/resources/search_engine_choice/app.html
@@ -108,7 +108,7 @@ margin-left: 16px; } - cr-radio-group { + #choiceList { display: flex; flex-direction: column; gap: 1px; @@ -344,7 +344,7 @@ display: none; } - cr-radio-group { + #choiceList { --button-container-height: calc(var(--cr-button-height) + 2 * var(--submit-button-margins)); padding-bottom: var(--button-container-height); @@ -375,7 +375,7 @@ font-size: 1.0625rem; } - cr-radio-group { + #choiceList { overflow: unset; } } @@ -415,23 +415,24 @@ $i18n{subtitleInfoLink} </a> </p> - <cr-radio-group class="custom-scrollbar" selected="{{selectedChoice_}}"> + <cr-radio-group id="choiceList" class="custom-scrollbar" + selected="{{selectedChoice_}}"> <template is="dom-repeat" items="[[choiceList_]]"> - <cr-radio-button class="label-first" name="[[item.prepopulate_id]]"> + <cr-radio-button class="label-first" name="[[item.prepopulateId]]"> <div class="choice"> <div class="choice-icon" - style$="background-image: [[item.icon_path]];"></div> + style$="background-image: [[item.iconPath]];"></div> <template is="dom-if" if="[[!withMarketingSnippets_]]"> <div class="choice-title">[[item.name]]</div> </template> <template is="dom-if" if="[[withMarketingSnippets_]]"> <div class="choice-text"> - <cr-expand-button expanded="{{item.show_marketing_snippet}}" + <cr-expand-button expanded="{{item.showMarketingSnippet}}" no-hover> <div class="choice-title">[[item.name]]</div> </cr-expand-button> - <iron-collapse opened="[[item.show_marketing_snippet]]"> - $i18n{fallbackMarketingSnippet} + <iron-collapse opened="[[item.showMarketingSnippet]]"> + [[item.marketingSnippet]] </iron-collapse> </div> </template>
diff --git a/chrome/browser/resources/search_engine_choice/app.ts b/chrome/browser/resources/search_engine_choice/app.ts index efec79d..4d5c92e 100644 --- a/chrome/browser/resources/search_engine_choice/app.ts +++ b/chrome/browser/resources/search_engine_choice/app.ts
@@ -18,6 +18,7 @@ import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js'; import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; +import {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {getFaviconForPageURL} from 'chrome://resources/js/icon.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; @@ -34,6 +35,7 @@ searchEngineOmnibox: HTMLElement, submitButton: CrButtonElement, infoLink: HTMLElement, + choiceList: CrRadioGroupElement, }; } @@ -73,7 +75,8 @@ isSubmitDisabled_: { type: Boolean, - computed: 'isSubmitButtonDisabled_(selectedChoice_)', + computed: 'isSubmitButtonDisabled_(selectedChoice_, ' + + 'hasUserScrolledToTheBottom_)', }, fakeOmniboxText_: { @@ -92,6 +95,13 @@ return loadTimeData.getBoolean('withMarketingSnippets'); }, }, + + withForcedScroll_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('withForcedScroll'); + }, + }, }; } @@ -101,6 +111,8 @@ private fakeOmniboxIconPath_: string; private pageHandler_: PageHandlerRemote; private withMarketingSnippets_: boolean; + private hasUserScrolledToTheBottom_: boolean; + private withForcedScroll_: boolean; constructor() { super(); @@ -115,13 +127,13 @@ // `background-image` property because `getFaviconForPageURL` returns an // `image-set` and not a url. this.choiceList_.forEach((searchEngine: SearchEngineChoice) => { - if (searchEngine.prepopulate_id === 0) { + if (searchEngine.prepopulateId === 0) { // We get the favicon from the Favicon Service for custom search // engines. - searchEngine.icon_path = + searchEngine.iconPath = getFaviconForPageURL(searchEngine?.url!, false, '', 24); } else { - searchEngine.icon_path = 'url(' + searchEngine.icon_path + ')'; + searchEngine.iconPath = 'url(' + searchEngine.iconPath + ')'; } }); @@ -130,12 +142,26 @@ }); } + override ready() { + super.ready(); + + if (this.withForcedScroll_) { + this.$.choiceList.addEventListener( + 'scroll', this.onChoiceListScroll_.bind(this)); + } + } + private onLinkClicked_() { this.$.infoDialog.showModal(); this.pageHandler_.handleLearnMoreLinkClicked(); } + // The user needs to make a choice and scroll to the bottom of the list to be + // able to submit the selection. private isSubmitButtonDisabled_() { + if (this.withForcedScroll_ && !this.hasUserScrolledToTheBottom_) { + return true; + } return parseInt(this.selectedChoice_) === -1; } @@ -156,11 +182,11 @@ // Get the selected engine. const choice = this.choiceList_.find( - elem => elem.prepopulate_id === parseInt(selectedChoice)); + elem => elem.prepopulateId === parseInt(selectedChoice)); const searchEngineOmnibox = this.$.searchEngineOmnibox; const dummyOmnibox = this.$.dummyOmnibox; const fakeOmniboxText = this.i18n('fakeOmniboxText', choice?.name!); - const fakeOmniboxIconPath = choice?.icon_path!; + const fakeOmniboxIconPath = choice?.iconPath!; // We need to change the previous engine name to the new one and then start // the fade-in-animation when the fade-out-animation finishes running. @@ -207,6 +233,20 @@ searchEngineOmnibox.classList.add('fade-in-animation'); } } + + private onChoiceListScroll_() { + const scrollHeight = this.$.choiceList.scrollHeight; + const clientHeight = this.$.choiceList.clientHeight; + const scrollTop = this.$.choiceList.scrollTop; + + // We check for `< 1` so that we don't care about rounding issues. + if (Math.abs(scrollHeight - clientHeight - scrollTop) < 1) { + this.hasUserScrolledToTheBottom_ = true; + + this.$.choiceList.removeEventListener( + 'scroll', this.onChoiceListScroll_.bind(this)); + } + } } declare global {
diff --git a/chrome/browser/resources/search_engine_choice/browser_proxy.ts b/chrome/browser/resources/search_engine_choice/browser_proxy.ts index f294eb5..d4f7b70 100644 --- a/chrome/browser/resources/search_engine_choice/browser_proxy.ts +++ b/chrome/browser/resources/search_engine_choice/browser_proxy.ts
@@ -10,11 +10,12 @@ import {PageHandlerFactory, PageHandlerRemote} from './search_engine_choice.mojom-webui.js'; export interface SearchEngineChoice { - prepopulate_id: number; + prepopulateId: number; name: string; - icon_path: string; + iconPath: string; url: string; - show_marketing_snippet: boolean; + marketingSnippet: string; + showMarketingSnippet: boolean; } export class SearchEngineChoiceBrowserProxy {
diff --git a/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager.cc b/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager.cc index 1d02852..528a25f 100644 --- a/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager.cc +++ b/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager.cc
@@ -131,16 +131,26 @@ const bool success = gfx::PNGCodec::EncodeBGRASkBitmap( bitmap, /*discard_transparency=*/false, &encoded); if (success) { - base::ThreadPool::PostTaskAndReply( - FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, - base::BindOnce( - &WriteFileToPath, std::string(encoded.begin(), encoded.end()), - profile_->GetPath().AppendASCII( - id.ToString() + - chrome::kChromeUIUntrustedNewTabPageBackgroundFilename)), - base::BindOnce(&WallpaperSearchBackgroundManager:: - SetBackgroundToLocalResourceWithId, - weak_ptr_factory_.GetWeakPtr(), id)); + // Do not update theme image unless it is different from the current. + // Otherwise, we end up deleting the image file as part of the cleanup + // of the last theme. + absl::optional<CustomBackground> current_theme = + ntp_custom_background_service_->GetCustomBackground(); + if (!current_theme.has_value() || + !current_theme->local_background_id.has_value() || + current_theme->local_background_id.value() != id) { + base::ThreadPool::PostTaskAndReply( + FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, + base::BindOnce( + &WriteFileToPath, std::string(encoded.begin(), encoded.end()), + profile_->GetPath().AppendASCII( + id.ToString() + + chrome::kChromeUIUntrustedNewTabPageBackgroundFilename)), + base::BindOnce(&WallpaperSearchBackgroundManager:: + SetBackgroundToLocalResourceWithId, + weak_ptr_factory_.GetWeakPtr(), id)); + } + ntp_custom_background_service_->UpdateCustomLocalBackgroundColorAsync( gfx::Image::CreateFrom1xBitmap(bitmap)); }
diff --git a/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager_unittest.cc b/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager_unittest.cc index da4edec..fa96f67 100644 --- a/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager_unittest.cc +++ b/chrome/browser/search/background/wallpaper_search/wallpaper_search_background_manager_unittest.cc
@@ -175,6 +175,40 @@ EXPECT_EQ(SK_ColorRED, image_arg.ToSkBitmap()->getColor(0, 0)); } +// If the currently set wallpaper search image is set again, do not pass it +// through to SetBackgroundToLocalResourceWithId(). Otherwise, its image file +// could be deleted. +TEST_F(WallpaperSearchBackgroundManagerTest, + SetLocalBackgroundImage_DoNotReSetSameImage) { + gfx::Image image_arg; + ON_CALL(mock_ntp_custom_background_service(), + IsCustomBackgroundDisabledByPolicy) + .WillByDefault(testing::Return(false)); + EXPECT_CALL(mock_ntp_custom_background_service(), + SetBackgroundToLocalResourceWithId) + .Times(0); + EXPECT_CALL(mock_ntp_custom_background_service(), + UpdateCustomLocalBackgroundColorAsync) + .WillOnce(SaveArg<0>(&image_arg)); + + SkBitmap bitmap; + bitmap.allocN32Pixels(32, 32); + bitmap.eraseColor(SK_ColorRED); + + base::Token token = base::Token::CreateRandom(); + CustomBackground custom_background; + custom_background.local_background_id = token; + ON_CALL(mock_ntp_custom_background_service(), GetCustomBackground()) + .WillByDefault(Return(absl::make_optional(custom_background))); + wallpaper_search_background_manager().SelectLocalBackgroundImage(token, + bitmap); + + task_environment().RunUntilIdle(); + + // Check that the args were passed to |NtpCustomBackgroundService|. + EXPECT_EQ(SK_ColorRED, image_arg.ToSkBitmap()->getColor(0, 0)); +} + TEST_F(WallpaperSearchBackgroundManagerTest, SaveCurrentBackgroundToHistory) { base::Token token = base::Token::CreateRandom(); CustomBackground custom_background;
diff --git a/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.cc b/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.cc new file mode 100644 index 0000000..23c3aee5f --- /dev/null +++ b/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.cc
@@ -0,0 +1,204 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.h" + +#include "base/check_deref.h" +#include "base/check_is_test.h" +#include "base/feature_list.h" +#include "base/metrics/field_trial.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/metrics/chrome_metrics_service_accessor.h" +#include "chrome/common/channel_info.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" +#include "components/search_engines/search_engines_pref_names.h" +#include "components/search_engines/search_engines_switches.h" +#include "components/signin/public/base/signin_switches.h" +#include "components/version_info/channel.h" + +namespace SearchEngineChoiceClientSideTrial { +namespace { + +absl::optional<version_info::Channel> g_channel_for_testing; + +// Should match the trial name from Finch. +const char kTrialName[] = "WaffleStudy"; + +// Group names for the trial. +const char kEnabledGroup[] = "ClientSideEnabledForTaggedProfiles"; +const char kDisabledGroup[] = "ClientSideDisabled"; +const char kDefaultGroup[] = "Default"; + +// Probabilities for all field trial groups add up to kTotalGroupWeight. +constexpr base::FieldTrial::Probability kTotalGroupWeight = 1000; + +constexpr int kNonStableEnabledWeight = 500; +constexpr int kNonStableDisabledWeight = 500; +constexpr int kNonStableDefaultWeight = 0; +static_assert(kTotalGroupWeight == kNonStableEnabledWeight + + kNonStableDisabledWeight + + kNonStableDefaultWeight); + +constexpr int kStableEnabledWeight = 5; +constexpr int kStableDisabledWeight = 5; +constexpr int kStableDefaultWeight = 990; +static_assert(kTotalGroupWeight == kStableEnabledWeight + + kStableDisabledWeight + + kStableDefaultWeight); + +std::string PickTrialGroupWithoutActivation(base::FieldTrial& trial, + version_info::Channel channel) { + int enabled_weight; + int disabled_weight; + int default_weight; + switch (channel) { + case version_info::Channel::UNKNOWN: + case version_info::Channel::CANARY: + case version_info::Channel::DEV: + case version_info::Channel::BETA: + enabled_weight = kNonStableEnabledWeight; + disabled_weight = kNonStableDisabledWeight; + default_weight = kNonStableDefaultWeight; + break; + case version_info::Channel::STABLE: + enabled_weight = kStableEnabledWeight; + disabled_weight = kStableDisabledWeight; + default_weight = kStableDefaultWeight; + break; + } + DCHECK_EQ(kTotalGroupWeight, + enabled_weight + disabled_weight + default_weight); + + trial.AppendGroup(kEnabledGroup, enabled_weight); + trial.AppendGroup(kDisabledGroup, disabled_weight); + trial.AppendGroup(kDefaultGroup, default_weight); + + return trial.GetGroupNameWithoutActivation(); +} + +void SetUp(const base::FieldTrial::EntropyProvider& entropy_provider, + base::FeatureList& feature_list, + PrefService& local_state, + version_info::Channel channel) { + // Set up the trial and determine the group for the current client. + scoped_refptr<base::FieldTrial> trial = + base::FieldTrialList::FactoryGetFieldTrial( + kTrialName, kTotalGroupWeight, kDefaultGroup, entropy_provider); + + std::string group_name; + if (local_state.HasPrefPath(prefs::kSearchEnginesStudyGroup)) { + DVLOG(1) << "Continuing field trial setup with already set group " + << group_name; + group_name = local_state.GetString(prefs::kSearchEnginesStudyGroup); + } else { + group_name = PickTrialGroupWithoutActivation(*trial, channel); + DVLOG(1) << "Setting field trial with selected group " << group_name; + local_state.SetString(prefs::kSearchEnginesStudyGroup, group_name); + } + + // Set up the state of the features based on the obtained group. + base::FeatureList::OverrideState feature_state = + group_name == kEnabledGroup ? base::FeatureList::OVERRIDE_ENABLE_FEATURE + : base::FeatureList::OVERRIDE_DISABLE_FEATURE; + + if (feature_state == base::FeatureList::OVERRIDE_ENABLE_FEATURE) { + base::AssociateFieldTrialParams( + kTrialName, group_name, + {{switches::kSearchEngineChoiceTriggerForTaggedProfilesOnly.name, + "true"}}); + } + + feature_list.RegisterFieldTrialOverride( + switches::kSearchEngineChoiceTrigger.name, feature_state, trial.get()); + feature_list.RegisterFieldTrialOverride(switches::kSearchEngineChoice.name, + feature_state, trial.get()); + feature_list.RegisterFieldTrialOverride(switches::kSearchEngineChoiceFre.name, + feature_state, trial.get()); + + // Activate only after the overrides are completed. + trial->Activate(); + + // Can't call `RegisterSyntheticFieldTrial` here, it requires + // `g_browser_process` to be available, we are too early for this. +} + +} // namespace + +void RegisterLocalStatePrefs(PrefRegistrySimple* registry) { + registry->RegisterStringPref(prefs::kSearchEnginesStudyGroup, ""); +} + +void SetUpIfNeeded(const base::FieldTrial::EntropyProvider& entropy_provider, + base::FeatureList* feature_list, + PrefService* local_state) { +#if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_MAC) + // Platform not in scope for this client-side trial. + return; +#else + // Make sure that Finch, fieldtrial_testing_config and command line flags take + // precedence over features defined here. In particular, not detecting + // fieldtrial_testing_config triggers a DCHECK. + if (base::FieldTrialList::Find(kTrialName) || + feature_list->HasAssociatedFieldTrialByFeatureName( + switches::kSearchEngineChoiceTrigger.name)) { + DVLOG(1) << "Not setting up client-side trial for WaffleStudy, trial " + "already registered"; + return; + } + + // Skip setup if an associated feature is overriden, typically via the + // commandline or setup during tests. + if (feature_list->IsFeatureOverridden( + switches::kSearchEngineChoiceTrigger.name) || + feature_list->IsFeatureOverridden(switches::kSearchEngineChoice.name) || + feature_list->IsFeatureOverridden( + switches::kSearchEngineChoiceFre.name)) { + LOG(WARNING) << "Not setting up client-side trial for WaffleStudy, feature " + "already overridden."; + return; + } + + // Proceed with actually setting up the field trial. + SetUp(entropy_provider, CHECK_DEREF(feature_list), CHECK_DEREF(local_state), + g_channel_for_testing.value_or(chrome::GetChannel())); +#endif +} + +void SetUpForTesting(const base::FieldTrial::EntropyProvider& entropy_provider, + base::FeatureList& feature_list, + PrefService& local_state, + version_info::Channel channel) { + CHECK_IS_TEST(); + SetUp(entropy_provider, feature_list, local_state, channel); +} + +void RegisterSyntheticTrials() { + CHECK(g_browser_process); + auto enrolled_study_group = g_browser_process->local_state()->GetString( + prefs::kSearchEnginesStudyGroup); + if (enrolled_study_group.empty()) { + // The user was not enrolled or exited the study at some point. + return; + } + + if (enrolled_study_group == kDefaultGroup) { + // No need to register for the default group. + return; + } + + DVLOG(1) << "Registering synthetic field trial for group " + << enrolled_study_group; + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + kSyntheticTrialName, enrolled_study_group, + variations::SyntheticTrialAnnotationMode::kCurrentLog); +} + +ScopedChannelOverride CreateScopedChannelOverrideForTesting( + version_info::Channel channel) { + CHECK_IS_TEST(); + return ScopedChannelOverride(&g_channel_for_testing, channel); +} + +} // namespace SearchEngineChoiceClientSideTrial
diff --git a/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.h b/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.h new file mode 100644 index 0000000..237bc97f --- /dev/null +++ b/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.h
@@ -0,0 +1,56 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SEARCH_ENGINE_CHOICE_SEARCH_ENGINE_CHOICE_CLIENT_SIDE_TRIAL_H_ +#define CHROME_BROWSER_SEARCH_ENGINE_CHOICE_SEARCH_ENGINE_CHOICE_CLIENT_SIDE_TRIAL_H_ + +#include "base/metrics/field_trial.h" +#include "components/signin/public/base/signin_buildflags.h" + +#if !BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) +#error "Unsupported platform" +#endif + +namespace base { +class FeatureList; +} + +namespace version_info { +enum class Channel; +} + +class PrefService; +class PrefRegistrySimple; + +namespace SearchEngineChoiceClientSideTrial { + +inline constexpr char kSyntheticTrialName[] = "WaffleSynthetic"; + +void RegisterLocalStatePrefs(PrefRegistrySimple* registry); + +// Enrolls the client in a trial and overrides the SearchEngineChoice related +// features according the the selected group. +// Note: Does not perform the synthetic trial registration, it has to be done +// at a later time by calling `RegisterSyntheticTrials()`, as that requires +// `g_browser_process` to be fully initialized, which is typically not the +// case when this method is called. +void SetUpIfNeeded(const base::FieldTrial::EntropyProvider& entropy_provider, + base::FeatureList* feature_list, + PrefService* local_state); + +// Registers a synthetic trial name and group to annotate UMA records based on +// the client-side trial. +// Requires `g_browser_process` to be fully initialized. +void RegisterSyntheticTrials(); + +// Overrides the client channel value used when choosing in which group to +// assign this client. +using ScopedChannelOverride = + base::AutoReset<absl::optional<version_info::Channel>>; +ScopedChannelOverride CreateScopedChannelOverrideForTesting( + version_info::Channel channel); + +} // namespace SearchEngineChoiceClientSideTrial + +#endif // CHROME_BROWSER_SEARCH_ENGINE_CHOICE_SEARCH_ENGINE_CHOICE_CLIENT_SIDE_TRIAL_H_
diff --git a/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial_unittest.cc b/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial_unittest.cc new file mode 100644 index 0000000..6bada79 --- /dev/null +++ b/chrome/browser/search_engine_choice/search_engine_choice_client_side_trial_unittest.cc
@@ -0,0 +1,307 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/search_engine_choice/search_engine_choice_client_side_trial.h" + +#include "base/feature_list.h" +#include "base/files/file_path.h" +#include "base/run_loop.h" +#include "base/scoped_observation.h" +#include "base/strings/stringprintf.h" +#include "base/test/mock_entropy_provider.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "chrome/browser/first_run/first_run.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/base/scoped_testing_local_state.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/metrics/metrics_service.h" +#include "components/metrics/metrics_service_client.h" +#include "components/metrics/metrics_state_manager.h" +#include "components/metrics/test/test_enabled_state_provider.h" +#include "components/metrics/test/test_metrics_service_client.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "components/search_engines/search_engines_pref_names.h" +#include "components/search_engines/search_engines_switches.h" +#include "components/signin/public/base/signin_buildflags.h" +#include "components/signin/public/base/signin_switches.h" +#include "components/variations/active_field_trials.h" +#include "components/variations/synthetic_trial_registry.h" +#include "components/variations/synthetic_trials.h" +#include "components/variations/synthetic_trials_active_group_id_provider.h" +#include "components/variations/variations_crash_keys.h" +#include "components/version_info/channel.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if !BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) +#error "Unsupported platform" +#endif + +namespace { + +// TODO(b/313407392): Move the class to some utils file. +class ScopedTestingMetricsService { + public: + // Sets up a `metrics::MetricsService` instance and makes it available in its + // scope via `testing_browser_process->metrics_service()`. + // + // This service only supports feature related to the usage of synthetic field + // trials. + // + // Requires: + // - the local state prefs to be usable from `testing_browser_process` + // - a task runner to be available (see //docs/threading_and_tasks_testing.md) + explicit ScopedTestingMetricsService( + TestingBrowserProcess* testing_browser_process) + : browser_process_(testing_browser_process) { + CHECK(browser_process_); + + auto* local_state = browser_process_->local_state(); + CHECK(local_state) + << "Error: local state prefs are required. In a unit test, this can be " + "set up using base::test::ScopedTestingLocalState."; + + // The `SyntheticTrialsActiveGroupIdProvider` needs to be notified of + // changes from the registry for them to be used through the variations API. + synthetic_trial_registry_observation_.Observe(&synthetic_trial_registry_); + + metrics_service_client_.set_synthetic_trial_registry( + &synthetic_trial_registry_); + + metrics_state_manager_ = metrics::MetricsStateManager::Create( + local_state, &enabled_state_provider_, + /*backup_registry_key=*/std::wstring(), + /*user_data_dir=*/base::FilePath()); + + // Needs to be set up, will be updated at each synthetic trial change. + variations::InitCrashKeys(); + + // Required by `MetricsService` to record UserActions. We don't rely on + // these here, since we never make it start recording metrics, but the task + // runner is still required during the shutdown sequence. + base::SetRecordActionTaskRunner( + base::SingleThreadTaskRunner::GetCurrentDefault()); + + metrics_service_ = std::make_unique<metrics::MetricsService>( + metrics_state_manager_.get(), &metrics_service_client_, local_state); + + browser_process_->SetMetricsService(metrics_service_.get()); + } + + ~ScopedTestingMetricsService() { + // The scope is closing, undo the set up that was done in the constructor: + // `MetricsService` and other necessary parts like crash keys. + browser_process_->SetMetricsService(nullptr); + variations::ClearCrashKeysInstanceForTesting(); + + // Note: Clears all the synthetic trials, not juste the ones registered + // during the lifetime of this object. + variations::SyntheticTrialsActiveGroupIdProvider::GetInstance() + ->ResetForTesting(); + } + + metrics::MetricsService* Get() { return metrics_service_.get(); } + + private: + raw_ptr<TestingBrowserProcess> browser_process_ = nullptr; + + metrics::TestEnabledStateProvider enabled_state_provider_{/*consent=*/true, + /*enabled=*/true}; + + variations::SyntheticTrialRegistry synthetic_trial_registry_; + base::ScopedObservation<variations::SyntheticTrialRegistry, + variations::SyntheticTrialObserver> + synthetic_trial_registry_observation_{ + variations::SyntheticTrialsActiveGroupIdProvider::GetInstance()}; + + metrics::TestMetricsServiceClient metrics_service_client_; + std::unique_ptr<metrics::MetricsStateManager> metrics_state_manager_; + + std::unique_ptr<metrics::MetricsService> metrics_service_; +}; + +struct SearchEngineChoiceFieldTrialTestParams { + double entropy_value = 0.0; + version_info::Channel channel = version_info::Channel::UNKNOWN; + + bool expect_study_enabled = false; + bool expect_feature_enabled = false; +}; + +} // namespace + +class SearchEngineChoiceClientSideTrialTest + : public testing::Test, + public testing::WithParamInterface< + SearchEngineChoiceFieldTrialTestParams> { + public: + base::test::ScopedFeatureList& scoped_feature_list() { + return scoped_feature_list_; + } + + TestingPrefServiceSimple* local_state() { return testing_local_state_.Get(); } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + base::test::TaskEnvironment task_environment_; + + ScopedTestingLocalState testing_local_state_{ + TestingBrowserProcess::GetGlobal()}; + + // Needed for synthetic trial checks to work. + ScopedTestingMetricsService testing_metrics_service_{ + TestingBrowserProcess::GetGlobal()}; +}; + +TEST_P(SearchEngineChoiceClientSideTrialTest, SetUpIfNeeded) { + { + auto scoped_channel_override = SearchEngineChoiceClientSideTrial:: + CreateScopedChannelOverrideForTesting(GetParam().channel); + base::MockEntropyProvider low_entropy_provider{GetParam().entropy_value}; + auto feature_list = std::make_unique<base::FeatureList>(); + + SearchEngineChoiceClientSideTrial::SetUpIfNeeded( + low_entropy_provider, feature_list.get(), local_state()); + + // Substitute the existing feature list with the one with field trial + // configurations we are testing, so we can check the assertions. + scoped_feature_list().InitWithFeatureList(std::move(feature_list)); + } + + EXPECT_EQ(GetParam().expect_feature_enabled, + base::FeatureList::IsEnabled(switches::kSearchEngineChoiceTrigger)); + EXPECT_EQ(GetParam().expect_feature_enabled, + switches::kSearchEngineChoiceTriggerForTaggedProfilesOnly.Get()); + EXPECT_EQ(GetParam().expect_feature_enabled, + base::FeatureList::IsEnabled(switches::kSearchEngineChoice)); + EXPECT_EQ(GetParam().expect_feature_enabled, + base::FeatureList::IsEnabled(switches::kSearchEngineChoiceFre)); + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) + EXPECT_TRUE(base::FieldTrialList::IsTrialActive("WaffleStudy")); + + std::string expected_group_name = + GetParam().expect_study_enabled + ? GetParam().expect_feature_enabled + ? "ClientSideEnabledForTaggedProfiles" + : "ClientSideDisabled" + : "Default"; + + EXPECT_EQ(local_state()->GetString(prefs::kSearchEnginesStudyGroup), + expected_group_name); +#else + // No group is assigned on other platforms and nothing is added to prefs. + EXPECT_TRUE( + local_state()->GetString(prefs::kSearchEnginesStudyGroup).empty()); +#endif +} + +INSTANTIATE_TEST_SUITE_P( + , + SearchEngineChoiceClientSideTrialTest, + testing::Values( +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) + // `entropy_value` makes the group be assigned according to the + // specified weight of each group and the order in which they are + // declared. So for a split at 33% enabled, 33% disabled, 33% default + // a .4 entropy value should select the "disabled" group. + SearchEngineChoiceFieldTrialTestParams{ + .entropy_value = 0.01, + .channel = version_info::Channel::BETA, + // In the 50% treatment group + .expect_study_enabled = true, + .expect_feature_enabled = true}, + SearchEngineChoiceFieldTrialTestParams{ + .entropy_value = 0.6, + .channel = version_info::Channel::BETA, + // In the 50% control group + .expect_study_enabled = true, + .expect_feature_enabled = false}, + SearchEngineChoiceFieldTrialTestParams{ + .entropy_value = 0.0001, + .channel = version_info::Channel::STABLE, + // In the .5% treatment group + .expect_study_enabled = true, + .expect_feature_enabled = true}, + SearchEngineChoiceFieldTrialTestParams{ + .entropy_value = 0.009, + .channel = version_info::Channel::STABLE, + // In the .5% control group + .expect_study_enabled = true, + .expect_feature_enabled = false}, + SearchEngineChoiceFieldTrialTestParams{ + .entropy_value = 0.99, + .channel = version_info::Channel::STABLE, + // Not in the study (99%) + .expect_study_enabled = false, + .expect_feature_enabled = false} +#else + SearchEngineChoiceFieldTrialTestParams{ + .entropy_value = 0.01, + .channel = version_info::Channel::BETA, + // On other platforms we never enroll clients. + .expect_study_enabled = false, + .expect_feature_enabled = false} +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) + ), + + [](const ::testing::TestParamInfo<SearchEngineChoiceFieldTrialTestParams>& + params) { + return base::StringPrintf( + "%02.0fpctEntropy%s", params.param.entropy_value * 100, + version_info::GetChannelString(params.param.channel).data()); + }); + +TEST_F(SearchEngineChoiceClientSideTrialTest, + SetUpIfNeeded_SkipsIfFeatureOverridden) { + { + base::MockEntropyProvider low_entropy_provider{0.01}; + auto feature_list = std::make_unique<base::FeatureList>(); + feature_list->RegisterExtraFeatureOverrides( + {{std::cref(switches::kSearchEngineChoice), + base::FeatureList::OVERRIDE_ENABLE_FEATURE}}); + + SearchEngineChoiceClientSideTrial::SetUpIfNeeded( + low_entropy_provider, feature_list.get(), local_state()); + + // Substitute the existing feature list with the one with field trial + // configurations we are testing, so we can check the assertions. + scoped_feature_list().InitWithFeatureList(std::move(feature_list)); + } + + EXPECT_FALSE(base::FieldTrialList::IsTrialActive("WaffleStudy")); + + EXPECT_FALSE( + base::FeatureList::IsEnabled(switches::kSearchEngineChoiceTrigger)); + EXPECT_TRUE(base::FeatureList::IsEnabled(switches::kSearchEngineChoice)); + + EXPECT_FALSE(local_state()->HasPrefPath(prefs::kSearchEnginesStudyGroup)); +} + +TEST_F(SearchEngineChoiceClientSideTrialTest, + RegisterSyntheticTrials_ReadsPref) { + const char kStudyTestGroupName1[] = "group_name_1"; + EXPECT_FALSE(local_state()->HasPrefPath(prefs::kSearchEnginesStudyGroup)); + EXPECT_FALSE(variations::HasSyntheticTrial( + SearchEngineChoiceClientSideTrial::kSyntheticTrialName)); + + // `RegisterSyntheticTrials()` no-ops without some specific pref. + SearchEngineChoiceClientSideTrial::RegisterSyntheticTrials(); + EXPECT_FALSE(local_state()->HasPrefPath(prefs::kSearchEnginesStudyGroup)); + EXPECT_FALSE(variations::HasSyntheticTrial( + SearchEngineChoiceClientSideTrial::kSyntheticTrialName)); + + // With the pref, it will log it as synthetic trial group. + local_state()->SetString(prefs::kSearchEnginesStudyGroup, + kStudyTestGroupName1); + SearchEngineChoiceClientSideTrial::RegisterSyntheticTrials(); + EXPECT_TRUE(variations::HasSyntheticTrial( + SearchEngineChoiceClientSideTrial::kSyntheticTrialName)); + EXPECT_TRUE(variations::IsInSyntheticTrialGroup( + SearchEngineChoiceClientSideTrial::kSyntheticTrialName, + kStudyTestGroupName1)); +}
diff --git a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionUserData.java b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionUserData.java index 05f16fc..41f1437 100644 --- a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionUserData.java +++ b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionUserData.java
@@ -82,7 +82,7 @@ */ public void cacheSuggestions( Tab tab, GURL urlToTrack, String[] suggestionTexts, GURL[] suggestionUrls) { - if (tab == null || !UrlUtilities.isNTPUrl(tab.getUrl())) return; + if (tab == null || !UrlUtilities.isNtpUrl(tab.getUrl())) return; SearchResumptionUserData searchResumptionUserData = get(tab); if (searchResumptionUserData == null) { @@ -101,7 +101,7 @@ * @param suggestions: The suggestions fetched using Autocompelete API. */ public void cacheSuggestions(Tab tab, GURL urlToTrack, List<AutocompleteMatch> suggestions) { - if (tab == null || !UrlUtilities.isNTPUrl(tab.getUrl())) return; + if (tab == null || !UrlUtilities.isNtpUrl(tab.getUrl())) return; SearchResumptionUserData searchResumptionUserData = get(tab); if (searchResumptionUserData == null) {
diff --git a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc index 32462803..743ae52 100644 --- a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc +++ b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc
@@ -62,7 +62,7 @@ void PerProfileWorkerTaskTracker::OnWorkerCreated( const blink::DedicatedWorkerToken& worker_token, int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) { + content::DedicatedWorkerCreator creator) { auto* worker_process_host = content::RenderProcessHost::FromID(worker_process_id); DCHECK(worker_process_host); @@ -72,7 +72,7 @@ void PerProfileWorkerTaskTracker::OnBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& worker_token, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) { + content::DedicatedWorkerCreator creator) { DeleteWorkerTask(worker_token, &dedicated_worker_tasks_); }
diff --git a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h index 4e38294..a1663c7e 100644 --- a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h +++ b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
@@ -47,13 +47,12 @@ delete; // content::DedicatedWorkerService::Observer: - void OnWorkerCreated( - const blink::DedicatedWorkerToken& worker_token, - int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override; + void OnWorkerCreated(const blink::DedicatedWorkerToken& worker_token, + int worker_process_id, + content::DedicatedWorkerCreator creator) override; void OnBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& worker_token, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override; + content::DedicatedWorkerCreator creator) override; void OnFinalResponseURLDetermined( const blink::DedicatedWorkerToken& worker_token, const GURL& url) override;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index b8688724..7b6f70ee 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -4680,6 +4680,10 @@ "views/media_preview/camera_preview/camera_selector_combobox_model.h", "views/media_preview/camera_preview/camera_view_controller.cc", "views/media_preview/camera_preview/camera_view_controller.h", + "views/media_preview/camera_preview/video_stream_coordinator.cc", + "views/media_preview/camera_preview/video_stream_coordinator.h", + "views/media_preview/camera_preview/video_stream_view.cc", + "views/media_preview/camera_preview/video_stream_view.h", "views/media_preview/media_coordinator.cc", "views/media_preview/media_coordinator.h", "views/media_preview/media_view.cc", @@ -4687,7 +4691,10 @@ "views/media_preview/media_view_controller_base.cc", "views/media_preview/media_view_controller_base.h", ] - deps += [ "//services/video_capture/public/mojom" ] + deps += [ + "//components/capture_mode", + "//services/video_capture/public/mojom", + ] } if (enable_webui_certificate_viewer) {
diff --git a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc index e4abc8fe..06b4017 100644 --- a/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc +++ b/chrome/browser/ui/android/fast_checkout/ui_view_android_utils.cc
@@ -114,7 +114,9 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& jprofile, const std::string& locale) { - auto profile = std::make_unique<autofill::AutofillProfile>(); + AddressCountryCode country_code = AddressCountryCode(ConvertJavaStringToUTF8( + Java_FastCheckoutAutofillProfile_getCountryCode(env, jprofile))); + auto profile = std::make_unique<autofill::AutofillProfile>(country_code); // Only set the guid if it is an existing profile (Java guid not empty). // Otherwise, keep the generated one. std::string guid = ConvertJavaStringToUTF8( @@ -148,9 +150,6 @@ MaybeSetRawInfo( profile.get(), autofill::ADDRESS_HOME_SORTING_CODE, Java_FastCheckoutAutofillProfile_getSortingCode(env, jprofile)); - MaybeSetInfo(profile.get(), autofill::ADDRESS_HOME_COUNTRY, - Java_FastCheckoutAutofillProfile_getCountryCode(env, jprofile), - locale); MaybeSetRawInfo( profile.get(), autofill::PHONE_HOME_WHOLE_NUMBER, Java_FastCheckoutAutofillProfile_getPhoneNumber(env, jprofile));
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java index 8682165..7768314a5 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
@@ -144,6 +144,8 @@ * @param reportExceptionCallback A {@link Callback} to report exceptions. * @param backPressManager The {@link BackPressManager} for intercepting back press. * @param tabModelSelectorSupplier Supplier of the {@link TabModelSelector}. + * @param forcePhoneStyleOmnibox Whether a "phone-style" (full bleed, unrounded corners) omnibox + * suggestions list should be used even when the screen width is >600dp. */ public LocationBarCoordinator( View locationBarLayout, @@ -179,7 +181,8 @@ OmniboxSuggestionsDropdownScrollListener omniboxSuggestionsDropdownScrollListener, @Nullable OpenHistoryClustersDelegate openHistoryClustersDelegate, - @Nullable ObservableSupplier<TabModelSelector> tabModelSelectorSupplier) { + @Nullable ObservableSupplier<TabModelSelector> tabModelSelectorSupplier, + boolean forcePhoneStyleOmnibox) { mLocationBarLayout = (LocationBarLayout) locationBarLayout; mWindowDelegate = windowDelegate; mWindowAndroid = windowAndroid; @@ -193,7 +196,8 @@ mWindowAndroid, mWindowDelegate, autocompleteAnchorView, - mLocationBarLayout); + mLocationBarLayout, + forcePhoneStyleOmnibox); mUrlBar = mLocationBarLayout.findViewById(R.id.url_bar); // TODO(crbug.com/1151513): Inject LocaleManager instance to LocationBarCoordinator instead @@ -250,7 +254,8 @@ bookmarkState, omniboxActionDelegate, omniboxSuggestionsDropdownScrollListener, - openHistoryClustersDelegate); + openHistoryClustersDelegate, + forcePhoneStyleOmnibox); StatusView statusView = mLocationBarLayout.findViewById(R.id.location_bar_status); mStatusCoordinator = new StatusCoordinator(
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index 4ea5bcd..b7f0029 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -573,7 +573,7 @@ boolean isNtpOnPhone = mStatusCoordinator.isSearchEngineStatusIconVisible() - && UrlUtilities.isNTPUrl(mLocationBarDataProvider.getCurrentGurl()) + && UrlUtilities.isNtpUrl(mLocationBarDataProvider.getCurrentGurl()) && !isOnTablet; boolean isScrollingOnNtpOnPhone = !mUrlBar.hasFocus() && isNtpOnPhone;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java index 63f2505..74ea094 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
@@ -544,7 +544,7 @@ } if (currentTab != null) { - boolean isCurrentTabNtpUrl = UrlUtilities.isNTPUrl(currentTab.getUrl()); + boolean isCurrentTabNtpUrl = UrlUtilities.isNtpUrl(currentTab.getUrl()); if (currentTab.isNativePage() || isCurrentTabNtpUrl) { mOmniboxUma.recordNavigationOnNtp( url, transition, !currentTab.isIncognito() && isCurrentTabNtpUrl);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java index acb0cc1..182a994 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
@@ -121,12 +121,12 @@ static boolean sIsNtp; @Implementation - public static boolean isNTPUrl(GURL url) { + public static boolean isNtpUrl(GURL url) { return sIsNtp; } @Implementation - public static boolean isNTPUrl(String url) { + public static boolean isNtpUrl(String url) { return sIsNtp; } } @@ -1170,7 +1170,7 @@ anyBoolean()); doReturn(true).when(mTab).isNativePage(); ShadowUrlUtilities.sIsNtp = true; - assertTrue(UrlUtilities.isNTPUrl(mTab.getUrl())); + assertTrue(UrlUtilities.isNtpUrl(mTab.getUrl())); doReturn(false).when(mTab).isIncognito(); // Test navigating using omnibox. mMediator.loadUrl(TEST_URL, PageTransition.TYPED, 0, false); @@ -1186,7 +1186,7 @@ // This will run the function recordNavigationOnNtp with isNtp equal to false // making it unable to record the histogram. ShadowUrlUtilities.sIsNtp = false; - assertFalse(UrlUtilities.isNTPUrl(mTab.getUrl())); + assertFalse(UrlUtilities.isNtpUrl(mTab.getUrl())); // Test navigating using omnibox. mMediator.loadUrl(TEST_URL, PageTransition.TYPED, 0, false); verify(mOmniboxUma, times(1)).recordNavigationOnNtp(TEST_URL, PageTransition.TYPED, true);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java index 4c6d3de7..bbdc5ec 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java
@@ -41,6 +41,7 @@ private final @NonNull WindowDelegate mWindowDelegate; private final @NonNull View mAnchorView; private final @NonNull View mHorizontalAlignmentView; + private final boolean mForcePhoneStyleOmnibox; private final @NonNull Context mContext; // Reusable int array to pass to positioning methods that operate on a two element int array. // Keeping it as a member lets us avoid allocating a temp array every time. @@ -64,11 +65,13 @@ @NonNull WindowAndroid windowAndroid, @NonNull WindowDelegate windowDelegate, @NonNull View anchorView, - @NonNull View horizontalAlignmentView) { + @NonNull View horizontalAlignmentView, + boolean forcePhoneStyleOmnibox) { mWindowAndroid = windowAndroid; mWindowDelegate = windowDelegate; mAnchorView = anchorView; mHorizontalAlignmentView = horizontalAlignmentView; + mForcePhoneStyleOmnibox = forcePhoneStyleOmnibox; mContext = mAnchorView.getContext(); mContext.registerComponentCallbacks(this); Configuration configuration = mContext.getResources().getConfiguration(); @@ -95,6 +98,7 @@ @Override public boolean isTablet() { + if (mForcePhoneStyleOmnibox) return false; return mWindowWidthDp >= DeviceFormFactor.MINIMUM_TABLET_WIDTH_DP && DeviceFormFactor.isWindowOnTablet(mWindowAndroid); }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java index d20ef16..5bb7aa7 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java
@@ -100,7 +100,11 @@ doReturn(DIP_SCALE).when(mDisplay).getDipScale(); mImpl = new OmniboxSuggestionsDropdownEmbedderImpl( - mWindowAndroid, mWindowDelegate, mAnchorView, mHorizontalAlignmentView); + mWindowAndroid, + mWindowDelegate, + mAnchorView, + mHorizontalAlignmentView, + false); } @Test
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java index 55048aa..35e9d61 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
@@ -65,7 +65,7 @@ /** Returns whether supplied URL should be shown in the Omnibox/Suggestions list. */ public static boolean shouldShowUrl(GURL gurl, boolean isIncognito) { - return !(NativePage.isNativePageUrl(gurl, isIncognito) || UrlUtilities.isNTPUrl(gurl)); + return !(NativePage.isNativePageUrl(gurl, isIncognito) || UrlUtilities.isNtpUrl(gurl)); } public static UrlBarData forUrlAndText(
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java index 5188b37c..9b9150c 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -82,6 +82,7 @@ private OneshotSupplierImpl<OmniboxSuggestionsDropdownAdapter> mAdapterSupplier = new OneshotSupplierImpl<>(); private PreWarmingRecycledViewPool mRecycledViewPool; + private final boolean mForcePhoneStyleOmnibox; public AutocompleteCoordinator( @NonNull ViewGroup parent, @@ -99,11 +100,13 @@ @NonNull BookmarkState bookmarkState, @NonNull OmniboxActionDelegate omniboxActionDelegate, @NonNull OmniboxSuggestionsDropdownScrollListener scrollListener, - @NonNull OpenHistoryClustersDelegate openHistoryClustersDelegate) { + @NonNull OpenHistoryClustersDelegate openHistoryClustersDelegate, + boolean forcePhoneStyleOmnibox) { mParent = parent; mModalDialogManagerSupplier = modalDialogManagerSupplier; Context context = parent.getContext(); mContext = context; + mForcePhoneStyleOmnibox = forcePhoneStyleOmnibox; PropertyModel listModel = new PropertyModel(SuggestionListProperties.ALL_KEYS); ModelList listItems = new ModelList(); @@ -187,7 +190,9 @@ public void inflate() { OmniboxSuggestionsDropdown dropdown; try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { - dropdown = new OmniboxSuggestionsDropdown(context, mRecycledViewPool); + dropdown = + new OmniboxSuggestionsDropdown( + context, mRecycledViewPool, mForcePhoneStyleOmnibox); } dropdown.getViewGroup().setClipToPadding(false);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java index bac2a41..f79b3bbc 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
@@ -65,6 +65,7 @@ private int mListViewMaxHeight; private int mLastBroadcastedListViewMaxHeight; private @Nullable Callback<OmniboxAlignment> mOmniboxAlignmentObserver; + private final boolean mForcePhoneStyleOmnibox; /** * Interface that will receive notifications when the user is interacting with an item on the @@ -213,11 +214,15 @@ * * @param context Context used for contained views. */ - public OmniboxSuggestionsDropdown(@NonNull Context context, RecycledViewPool recycledViewPool) { + public OmniboxSuggestionsDropdown( + @NonNull Context context, + RecycledViewPool recycledViewPool, + boolean forcePhoneStyleOmnibox) { super(context, null, android.R.attr.dropDownListViewStyle); setFocusable(true); setFocusableInTouchMode(true); setRecycledViewPool(recycledViewPool); + mForcePhoneStyleOmnibox = forcePhoneStyleOmnibox; setId(R.id.omnibox_suggestions_dropdown); // By default RecyclerViews come with item animators. @@ -247,7 +252,8 @@ shouldShowModernizeVisualUpdate ? context.getColor(incognitoBgColorRes) : ChromeColors.getDefaultThemeColor(context, true); - if (OmniboxFeatures.shouldShowModernizeVisualUpdate(context) + if (!mForcePhoneStyleOmnibox + && OmniboxFeatures.shouldShowModernizeVisualUpdate(context) && DeviceFormFactor.isNonMultiDisplayContextOnTablet(context)) { setOutlineProvider( new RoundedCornerOutlineProvider(
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownUnitTest.java index ae4cd89..01e72a9c 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownUnitTest.java
@@ -124,7 +124,7 @@ new ContextThemeWrapper( ApplicationProvider.getApplicationContext(), R.style.Theme_BrowserUI_DayNight); - mDropdown = new OmniboxSuggestionsDropdown(mContext, mPool); + mDropdown = new OmniboxSuggestionsDropdown(mContext, mPool, false); mDropdown.setAdapter(mAdapter); mListener = mDropdown.getLayoutScrollListener(); } @@ -424,7 +424,7 @@ @SmallTest @LooperMode(Mode.PAUSED) public void testAlignmentProvider_changeDuringlayout() { - mDropdown = Mockito.spy(new OmniboxSuggestionsDropdown(mContext, mPool)); + mDropdown = Mockito.spy(new OmniboxSuggestionsDropdown(mContext, mPool, false)); mDropdown.setAdapter(mAdapter); mDropdown.setEmbedder(mEmbedder); mDropdown.onAttachedToWindow();
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java index bb2be1fb..f5d4786c 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsCoordinatorTest.java
@@ -108,7 +108,6 @@ @Mock private OptimizationGuideBridge.Natives mOptimizationGuideBridgeJniMock; @Mock private ObservableSupplierImpl<Tab> mTabProvider; - @Captor private ArgumentCaptor<Callback<Tab>> mTabCallbackCaptor; @Captor private ArgumentCaptor<EmptyTabObserver> mTabObserverCaptor; @Captor private ArgumentCaptor<BottomSheetObserver> mBottomUiObserverCaptor; @@ -223,6 +222,8 @@ () -> rootView()); }); doReturn(true).when(mIsPageInsightsHubEnabled).getAsBoolean(); + doReturn(mTab).when(mTabProvider).get(); + doReturn(JUnitTestGURLs.EXAMPLE_URL).when(mTab).getUrl(); mPageInsightsCoordinator = TestThreadUtils.runOnUiThreadBlocking( () -> @@ -246,10 +247,6 @@ .setShouldXsurfaceLog(true) .setShouldAttachGaiaToRequest(true) .build())); - doReturn(mTab).when(mTabProvider).get(); - doReturn(JUnitTestGURLs.EXAMPLE_URL).when(mTab).getUrl(); - verify(mTabProvider).addObserver(mTabCallbackCaptor.capture()); - mTabCallbackCaptor.getValue().onResult(mTab); verify(mTab).addObserver(mTabObserverCaptor.capture()); mTabObserverCaptor .getValue()
diff --git a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java index c47e696..b5b7976 100644 --- a/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java +++ b/chrome/browser/ui/android/page_insights/java/src/org/chromium/chrome/browser/page_insights/PageInsightsMediator.java
@@ -304,12 +304,15 @@ ChromeFeatureList.CCT_PAGE_INSIGHTS_HUB, PAGE_INSIGHTS_CAN_RETURN_TO_PEEK_AFTER_EXPANSION, false); - tabObservable.addObserver( - tab -> { - if (tab == null) return; - delayStartAutoTrigger(mAutoTriggerDelayMs); - tab.addObserver(this); - }); + if (tabObservable.get() != null) { + onTab(tabObservable.get()); + } else { + tabObservable.addObserver( + tab -> { + if (tab == null) return; + onTab(tab); + }); + } if (BackPressManager.isEnabled()) { BackPressHandler backPressHandler = bottomSheetController.getBottomSheetBackPressHandler(); @@ -348,6 +351,11 @@ } } + private void onTab(Tab tab) { + delayStartAutoTrigger(mAutoTriggerDelayMs); + tab.addObserver(this); + } + private boolean shouldHideContent() { // See if we need to hide the sheet content temporarily while another bottom UI is // launched. No need to hide if not in peek/full state or in scrolled-away state,
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java index dd2c34a..c43bbe6 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogTest.java
@@ -72,6 +72,7 @@ public final ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_FIRST_RUN) + .setRevision(1) .build(); @Mock private Listener mListenerMock;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java index d9aea38..9886d3b1 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java
@@ -157,7 +157,7 @@ protected boolean shouldShowButton(Tab tab) { if (!super.shouldShowButton(tab) || mIsTablet) return false; - if (UrlUtilities.isNTPUrl(tab.getUrl())) return false; + if (UrlUtilities.isNtpUrl(tab.getUrl())) return false; return true; }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java index 9f7f352..f960ba2b 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java
@@ -125,7 +125,7 @@ void handlePageLoadFinished(GURL url) { if (!mHomeButton.isShown()) return; if (mIsIncognitoSupplier.getAsBoolean()) return; - if (UrlUtilities.isNTPUrl(url)) return; + if (UrlUtilities.isNtpUrl(url)) return; if (mIsHomepageNonNtpSupplier.get()) return; if (mPromoShownOneshotSupplier.get() == null || mPromoShownOneshotSupplier.get()) return;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java index 1f6bbef8..5b07b3bd 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java
@@ -80,7 +80,7 @@ @Override public void onLoadProgressChanged(Tab tab, float progress) { if (tab.getUrl() == null - || UrlUtilities.isNTPUrl(tab.getUrl()) + || UrlUtilities.isNtpUrl(tab.getUrl()) || NativePage.isNativePageUrl( tab.getUrl(), tab.isIncognito())) { return;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java index d2a8168..68c655b 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/NavigationPopup.java
@@ -270,7 +270,7 @@ if (mDefaultFaviconHelper == null) mDefaultFaviconHelper = new DefaultFaviconHelper(); favicon = mDefaultFaviconHelper.getDefaultFaviconBitmap(mContext, pageUrl, true); } - if (UrlUtilities.isNTPUrl(pageUrl) && shouldUseIncognitoResources()) { + if (UrlUtilities.isNtpUrl(pageUrl) && shouldUseIncognitoResources()) { favicon = mDefaultFaviconHelper.getThemifiedBitmap( mContext, R.drawable.incognito_small, true);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 4cedfea..45068c1 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -2005,7 +2005,7 @@ private boolean hideShadowForRegularNtpTextureCapture() { return !isIncognito() - && UrlUtilities.isNTPUrl(getToolbarDataProvider().getCurrentGurl()) + && UrlUtilities.isNtpUrl(getToolbarDataProvider().getCurrentGurl()) && mNtpSearchBoxScrollFraction < 1.f; } @@ -2651,7 +2651,7 @@ } private boolean hideShadowForIncognitoNtp() { - return isIncognito() && UrlUtilities.isNTPUrl(getToolbarDataProvider().getCurrentGurl()); + return isIncognito() && UrlUtilities.isNtpUrl(getToolbarDataProvider().getCurrentGurl()); } private boolean hideShadowForInterstitial() {
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index ff6978a..fddb5d7 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -217,13 +217,13 @@ ->GetURLLoaderFactoryForBrowserProcess(); } -AutofillDownloadManager* ChromeAutofillClient::GetDownloadManager() { - if (!download_manager_) { +AutofillCrowdsourcingManager* ChromeAutofillClient::GetCrowdsourcingManager() { + if (!crowdsourcing_manager_) { // Lazy initialization to avoid virtual function calls in the constructor. - download_manager_ = std::make_unique<AutofillDownloadManager>( + crowdsourcing_manager_ = std::make_unique<AutofillCrowdsourcingManager>( this, GetChannel(), GetLogManager()); } - return download_manager_.get(); + return crowdsourcing_manager_.get(); } AutofillOptimizationGuide* ChromeAutofillClient::GetAutofillOptimizationGuide()
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index f975a0d..52c4d41 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -18,9 +18,9 @@ #include "chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h" #include "chrome/browser/ui/autofill/payments/autofill_progress_dialog_controller_impl.h" #include "components/autofill/content/browser/content_autofill_client.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_driver.h" #include "components/autofill/core/browser/country_type.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/browser/payments/legal_message_line.h" #include "components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h" @@ -105,7 +105,7 @@ version_info::Channel GetChannel() const override; bool IsOffTheRecord() override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; - AutofillDownloadManager* GetDownloadManager() override; + AutofillCrowdsourcingManager* GetCrowdsourcingManager() override; AutofillOptimizationGuide* GetAutofillOptimizationGuide() const override; AutofillMlPredictionModelHandler* GetAutofillMlPredictionModelHandler() override; @@ -341,7 +341,7 @@ // These members are initialized lazily in their respective getters. // Therefore, do not access the members directly. - std::unique_ptr<AutofillDownloadManager> download_manager_; + std::unique_ptr<AutofillCrowdsourcingManager> crowdsourcing_manager_; std::unique_ptr<payments::ChromePaymentsAutofillClient> payments_autofill_client_; std::unique_ptr<payments::PaymentsNetworkInterface>
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index c36f783..9656ae2 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -1775,7 +1775,7 @@ } void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) { - if (is_type_normal() || is_type_picture_in_picture()) { + if (is_type_normal()) { return; }
diff --git a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc index 5785775..daf9a6d 100644 --- a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc +++ b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc
@@ -301,6 +301,16 @@ } } + // In `kNudgePassword` Desktop experiment password is previewed straight away + // in offer generation state. +#if !BUILDFLAG(IS_ANDROID) + if (state == kOfferGeneration && + kPasswordGenerationExperimentVariationParam.Get() == + PasswordGenerationVariation::kNudgePassword) { + driver_->PreviewGenerationSuggestion(current_generated_password_); + } +#endif // !BUILDFLAG(IS_ANDROID) + if (observer_) observer_->OnPopupShown(state_); }
diff --git a/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc b/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc index 893813c9..9748eee 100644 --- a/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc +++ b/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc
@@ -38,11 +38,11 @@ using ::testing::Return; PasswordGenerationUIData CreatePasswordGenerationUIData() { - return PasswordGenerationUIData(gfx::RectF(100, 20), /*max_length=*/20, - u"element", autofill::FieldRendererId(100), - /*is_generation_element_password_type=*/true, - base::i18n::TextDirection(), - autofill::FormData()); + return PasswordGenerationUIData( + gfx::RectF(100, 20), /*max_length=*/20, u"element", + autofill::FieldRendererId(100), + /*is_generation_element_password_type=*/true, base::i18n::TextDirection(), + autofill::FormData(), /*input_field_empty=*/true); } class MockPasswordManagerDriver @@ -71,6 +71,7 @@ }; class MockPasswordGenerationPopupView : public PasswordGenerationPopupView { + public: MOCK_METHOD(bool, Show, (), (override)); MOCK_METHOD(void, Hide, (), (override)); MOCK_METHOD(void, UpdateState, (), (override)); @@ -335,6 +336,43 @@ EXPECT_CALL(*driver, FocusNextFieldAfterPasswords).Times(0); controller->EditPasswordClicked(); } + +TEST_F(PasswordGenerationPopupControllerImplTest, + PreviewsGeneratedPasswordOnShowInNudgePassword) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeaturesAndParameters( + {{password_manager::features::kPasswordGenerationExperiment, + {{"password_generation_variation", "nudge_password"}}}}, + {}); + + // The password generation helper is needed in the offer generation state and + // since the driver mock returns a raw pointer to it, we construct it first. + StubPasswordManagerClient client; + PasswordGenerationFrameHelper pw_generation_helper{&client, + /*driver=*/nullptr}; + + PasswordGenerationUIData ui_data = CreatePasswordGenerationUIData(); + auto driver = CreateDriver(); + ON_CALL(*driver, GetPasswordGenerationHelper) + .WillByDefault(Return(&pw_generation_helper)); + std::unique_ptr<content::WebContents> web_contents = CreateTestWebContents(); + base::WeakPtr<PasswordGenerationPopupControllerImpl> controller = + PasswordGenerationPopupControllerImpl::GetOrCreate( + /*previous=*/nullptr, ui_data.bounds, ui_data, driver->AsWeakPtr(), + /*observer=*/nullptr, web_contents.get(), main_rfh()); + + controller->SetViewForTesting(popup_view()); + // TODO(crbug.com/1444072): Rewrite controller_->Show() function to allow + // testing expectations when the view doesn't exist. SetViewForTesting + // prevents that currently, hence the update view flow is being called. + ON_CALL(*popup_view(), UpdateBoundsAndRedrawPopup) + .WillByDefault(Return(true)); + + // In the nudge password experiment suggestion is previewed on show. + EXPECT_CALL(*driver, PreviewGenerationSuggestion); + controller->Show( + PasswordGenerationPopupController::GenerationUIState::kOfferGeneration); +} #endif // !BUILDFLAG(IS_ANDROID) } // namespace password_manager
diff --git a/chrome/browser/ui/side_panel/companion/exps_registration_success_observer_unittest.cc b/chrome/browser/ui/side_panel/companion/exps_registration_success_observer_unittest.cc index 6f20fcb..2c2b8ed9 100644 --- a/chrome/browser/ui/side_panel/companion/exps_registration_success_observer_unittest.cc +++ b/chrome/browser/ui/side_panel/companion/exps_registration_success_observer_unittest.cc
@@ -174,6 +174,8 @@ } TEST_F(ExpsRegistrationSuccessObserverTest, MatchURL) { + SetupExpsObserver(); + std::vector<std::string> url_patterns; url_patterns.emplace_back("https://labs.google.com/search/experiment"); url_patterns.emplace_back("https://labs.google.com/search/otherexperiment");
diff --git a/chrome/browser/ui/views/autofill/autofill_bubble_utils.cc b/chrome/browser/ui/views/autofill/autofill_bubble_utils.cc index 1eb8463..1b0be95 100644 --- a/chrome/browser/ui/views/autofill/autofill_bubble_utils.cc +++ b/chrome/browser/ui/views/autofill/autofill_bubble_utils.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/autofill/autofill_bubble_utils.h" #include <memory> +#include <utility> #include "chrome/app/vector_icons/vector_icons.h" #include "components/strings/grit/components_strings.h" @@ -25,7 +26,7 @@ views::Button::PressedCallback callback) { std::unique_ptr<views::ImageButton> button = views::CreateVectorImageButtonWithNativeTheme( - callback, vector_icons::kEditIcon, kIconSize); + std::move(callback), vector_icons::kEditIcon, kIconSize); button->SetAccessibleName(l10n_util::GetStringUTF16( IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_EDIT_BUTTON_TOOLTIP)); button->SetTooltipText(l10n_util::GetStringUTF16(
diff --git a/chrome/browser/ui/views/autofill/payments/promo_code_label_view.cc b/chrome/browser/ui/views/autofill/payments/promo_code_label_view.cc index 71b6f9a..be7173d4 100644 --- a/chrome/browser/ui/views/autofill/payments/promo_code_label_view.cc +++ b/chrome/browser/ui/views/autofill/payments/promo_code_label_view.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/autofill/payments/promo_code_label_view.h" +#include <utility> + #include "base/strings/strcat.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -51,7 +53,7 @@ kPromoCodeLabelRightMarginPx)); copy_button_ = AddChildView(std::make_unique<views::MdTextButton>( - copy_button_pressed_callback, + std::move(copy_button_pressed_callback), l10n_util::GetStringUTF16(IDS_DISCOUNT_CODE_COPY_BUTTON_TEXT))); copy_button_->SetImageModel( views::Button::STATE_NORMAL,
diff --git a/chrome/browser/ui/views/bubble_menu_item_factory.cc b/chrome/browser/ui/views/bubble_menu_item_factory.cc index 08fbc98..52d49d2 100644 --- a/chrome/browser/ui/views/bubble_menu_item_factory.cc +++ b/chrome/browser/ui/views/bubble_menu_item_factory.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/bubble_menu_item_factory.h" #include <memory> +#include <utility> #include "chrome/browser/ui/views/controls/hover_button.h" #include "ui/base/models/image_model.h" @@ -39,7 +40,7 @@ const std::u16string& name, views::Button::PressedCallback callback, const ui::ImageModel& icon) { - auto button = std::make_unique<HoverButton>(callback, icon, name); + auto button = std::make_unique<HoverButton>(std::move(callback), icon, name); ConfigureBubbleMenuItem(button.get(), button_id); button->SetBorder(views::CreateEmptyBorder(kDefaultBorderInsets)); return button;
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc index 4e86322..4d6e2f1c 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/download/bubble/download_bubble_row_view.h" +#include <utility> + #include "base/files/file_path.h" #include "base/functional/callback.h" #include "base/time/time.h" @@ -103,7 +105,7 @@ explicit DownloadBubbleTransparentButton(PressedCallback callback, DownloadBubbleRowView* row_view) - : Button(callback), row_view_(row_view) { + : Button(std::move(callback)), row_view_(row_view) { views::InkDrop::Get(this)->SetMode(views::InkDropHost::InkDropMode::OFF); SetInstallFocusRingOnFocus(false); SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
diff --git a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc index fadaea1..77e73f76 100644 --- a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc +++ b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
@@ -1247,14 +1247,7 @@ // Scenario: starting a drag in left frame // Test coverage: dragstart DOM event, dragstart data passed to the OS. -// -// TODO(https://crbug.com/1444100): Re-enable the test once fixed. -#if BUILDFLAG(IS_CHROMEOS_LACROS) && defined(ADDRESS_SANITIZER) -#define MAYBE_DragStartInFrame DISABLED_DragStartInFrame -#else -#define MAYBE_DragStartInFrame DragStartInFrame -#endif -IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_DragStartInFrame) { +IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DragStartInFrame) { std::string frame_site = use_cross_site_subframe() ? "b.test" : "a.test"; ASSERT_TRUE(NavigateToTestPage("a.test")); ASSERT_TRUE(NavigateLeftFrame(frame_site, "image_source.html"));
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc index bb66c1c3..02a586f 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
@@ -312,7 +312,7 @@ // Site permissions button. views::Builder<HoverButton>( std::make_unique<HoverButton>( - site_permissions_button_callback, + std::move(site_permissions_button_callback), is_enterprise ? std::make_unique<views::ImageView>( ui::ImageModel::FromVectorIcon(
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.cc index deefa54c..9f74465 100644 --- a/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h" +#include <utility> + #include "base/containers/contains.h" #include "base/functional/bind.h" #include "base/metrics/histogram_functions.h" @@ -111,7 +113,7 @@ ExpandDeviceSelectorButton::ExpandDeviceSelectorButton(PressedCallback callback, SkColor foreground_color) - : ToggleImageButton(callback) { + : ToggleImageButton(std::move(callback)) { SetFocusBehavior(views::View::FocusBehavior::ALWAYS); SetBorder(views::CreateEmptyBorder(kDropdownButtonBorderInsets));
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc index aa355542..f423600 100644 --- a/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h" +#include <utility> + #include "base/memory/raw_ptr.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -49,7 +51,7 @@ DeviceEntryButton::DeviceEntryButton(PressedCallback callback, const gfx::VectorIcon* icon, const std::u16string& text) - : LabelButton(callback, text), icon_(icon) { + : LabelButton(std::move(callback), text), icon_(icon) { ConfigureInkDropForToolbar(this); views::InkDrop::Get(this)->SetBaseColorCallback(base::BindRepeating( &DeviceEntryButton::GetForegroundColor, base::Unretained(this)));
diff --git a/chrome/browser/ui/views/media_preview/DEPS b/chrome/browser/ui/views/media_preview/DEPS new file mode 100644 index 0000000..cda6711 --- /dev/null +++ b/chrome/browser/ui/views/media_preview/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/capture_mode", +]
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.cc b/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.cc index 464ffc8..f1adba40 100644 --- a/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.cc +++ b/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.cc
@@ -32,9 +32,17 @@ *camera_view, needs_borders, combobox_model_, base::BindRepeating(&CameraCoordinator::OnVideoSourceChanged, base::Unretained(this))); + + video_stream_coordinator_.emplace( + camera_view_controller_->GetLiveFeedContainer(), /*index=*/0); } -CameraCoordinator::~CameraCoordinator() = default; +CameraCoordinator::~CameraCoordinator() { + // As to guarantee that VideoSourceProvider outlive its VideoSource + // connection, it is passed in here to protect from destruction. + video_stream_coordinator_->StopAndCleanup( + camera_mediator_.TakeVideoSourceProvider()); +} void CameraCoordinator::OnVideoSourceInfosReceived( const std::vector<media::VideoCaptureDeviceInfo>& device_infos) { @@ -42,6 +50,8 @@ return; } + video_stream_coordinator_->SetPreviewVisibility(!device_infos.empty()); + std::vector<VideoSourceInfo> relevant_device_infos; relevant_device_infos.reserve(device_infos.size()); for (const auto& device_info : device_infos) { @@ -50,6 +60,7 @@ if (relevant_device_infos.empty()) { active_device_id_.clear(); + video_stream_coordinator_->Stop(); } camera_view_controller_->UpdateVideoSourceInfos( std::move(relevant_device_infos)); @@ -71,8 +82,8 @@ mojo::Remote<video_capture::mojom::VideoSource> video_source; camera_mediator_.BindVideoSource(device_info.id, video_source.BindNewPipeAndPassReceiver()); - // TODO(ahmedmoussa): `video_source` is to be passed to - // VideoStreamCoordiantor. Done in the following CL. + video_stream_coordinator_->ConnectToDevice(std::move(video_source), + device_info.supported_formats); } void CameraCoordinator::ResetViewController() {
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.h b/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.h index 28ff65e3..c280ad6 100644 --- a/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.h +++ b/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/views/media_preview/camera_preview/camera_mediator.h" #include "chrome/browser/ui/views/media_preview/camera_preview/camera_selector_combobox_model.h" #include "chrome/browser/ui/views/media_preview/camera_preview/camera_view_controller.h" +#include "chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.h" #include "ui/views/view_tracker.h" // Acts as a middle man between the ViewController and the Mediator. @@ -44,6 +45,7 @@ CameraSelectorComboboxModel combobox_model_; std::string active_device_id_; std::optional<CameraViewController> camera_view_controller_; + std::optional<VideoStreamCoordinator> video_stream_coordinator_; }; #endif // CHROME_BROWSER_UI_VIEWS_MEDIA_PREVIEW_CAMERA_PREVIEW_CAMERA_COORDINATOR_H_
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator_unittest.cc b/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator_unittest.cc index 3729d5e7..661e85c 100644 --- a/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator_unittest.cc +++ b/chrome/browser/ui/views/media_preview/camera_preview/camera_coordinator_unittest.cc
@@ -55,6 +55,7 @@ } void TearDown() override { + base::RunLoop().RunUntilIdle(); coordinator_.reset(); parent_view_.reset(); content::OverrideVideoCaptureServiceForTesting(nullptr);
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.cc b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.cc new file mode 100644 index 0000000..e37ab54 --- /dev/null +++ b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.cc
@@ -0,0 +1,191 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.h" + +#include <stdlib.h> + +#include <utility> + +#include "chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.h" +#include "content/public/browser/context_factory.h" +#include "media/capture/video_capture_types.h" +#include "ui/compositor/compositor.h" + +namespace { + +constexpr float kDefaultFrameRate = 24.0f; +constexpr float kDefaultAspectRatio = 16.0 / 9.0; +// Used to exclude vertical video. +constexpr float kLeastAcceptableAspectRatio = 0.99; + +float GetFrameAspectRatio(const gfx::Size& frame_size) { + return frame_size.width() / static_cast<float>(frame_size.height()); +} + +bool IsAcceptableFormat(const media::VideoCaptureFormat& format, + const float minimum_frame_rate, + const int view_width) { + return format.frame_rate >= minimum_frame_rate && + format.frame_size.width() >= view_width && + GetFrameAspectRatio(format.frame_size) >= kLeastAcceptableAspectRatio; +} + +// Returns true if `v2` suits more than `v1`. If both values are larger than or +// equal the `least_acceptable`, then the lower among the two values would be +// more suitable. On the other hand, if one or both the values are less than +// `least_acceptable`, then the higher among the two values would be more +// suitable. +bool SuitsMore(const float v1, const float v2, const float least_acceptable) { + const auto lower_v = std::min(v1, v2); + return lower_v >= least_acceptable ? v2 == lower_v : v1 == lower_v; +} + +// Returns true if `other` format is better than `cur` format. +// Better here means: (1) If one format is acceptable and the other is not, then +// the acceptable is better. (2) If both formats are acceptable or both are +// unacceptable, then check their frame rate, width, and aspect ratio in that +// order, and decide which suits more. +// For suits more definition, check `SuitsMore(..)`. +bool IsBetterFormat(const media::VideoCaptureFormat& cur, + const media::VideoCaptureFormat& other, + const int view_width, + const float minimum_frame_rate) { + const bool is_other_acceptable = + IsAcceptableFormat(other, minimum_frame_rate, view_width); + if (is_other_acceptable != + IsAcceptableFormat(cur, minimum_frame_rate, view_width)) { + return is_other_acceptable; + } + + if (cur.frame_rate != other.frame_rate) { + return SuitsMore(cur.frame_rate, other.frame_rate, minimum_frame_rate); + } + if (cur.frame_size.width() != other.frame_size.width()) { + return SuitsMore(cur.frame_size.width(), other.frame_size.width(), + view_width); + } + return SuitsMore(GetFrameAspectRatio(cur.frame_size), + GetFrameAspectRatio(other.frame_size), kDefaultAspectRatio); +} + +// Given a list of supported formats, return the least taxing acceptable format +// if exist. If no acceptable format exist, then return the closest that exist. +// For acceptable format definition, check `IsAcceptableFormat(...)`. +// For more info about formats comparison (i.e. to decide which is more +// taxable), check `IsBetterFormat(...)`. +media::VideoCaptureFormat GetClosestVideoFormat( + const std::vector<media::VideoCaptureFormat>& formats, + const int view_width, + const float minimum_frame_rate = kDefaultFrameRate) { + const media::VideoCaptureFormat* chosen_format = nullptr; + for (const auto& format : formats) { + if (!chosen_format || IsBetterFormat(*chosen_format, format, view_width, + minimum_frame_rate)) { + chosen_format = &format; + } + } + return chosen_format ? *chosen_format : media::VideoCaptureFormat(); +} + +} // namespace + +VideoStreamCoordinator::VideoStreamCoordinator(views::View& parent_view, + absl::optional<size_t> index) { + auto* video_stream_view = parent_view.AddChildViewAt( + std::make_unique<VideoStreamView>(kDefaultAspectRatio), + index.value_or(parent_view.children().size())); + + video_stream_view->SetVisible(false); + video_stream_view->SetRasterContextProvider( + content::GetContextFactory()->SharedMainThreadRasterContextProvider()); + + video_stream_view_tracker_.SetView(video_stream_view); +} + +VideoStreamCoordinator::~VideoStreamCoordinator() { + Stop(); +} + +void VideoStreamCoordinator::ConnectToDevice( + mojo::Remote<video_capture::mojom::VideoSource> video_source, + const std::vector<media::VideoCaptureFormat>& supported_formats) { + Stop(); + if (auto* view = GetVideoStreamView(); view) { + video_frame_handler_ = + std::make_unique<capture_mode::CameraVideoFrameHandler>( + content::GetContextFactory(), std::move(video_source), + GetClosestVideoFormat(supported_formats, view->width())); + + video_frame_handler_->StartHandlingFrames(/*delegate=*/this); + } +} + +// capture_mode::CameraVideoFrameHandler::Delegate implementation. +void VideoStreamCoordinator::OnCameraVideoFrame( + scoped_refptr<media::VideoFrame> frame) { + if (frame_received_callback_for_test_) { + frame_received_callback_for_test_.Run(); + } + + if (auto* view = GetVideoStreamView(); view) { + view->ScheduleFramePaint(std::move(frame)); + } +} + +void VideoStreamCoordinator::OnFatalErrorOrDisconnection() { + // When called, `video_frame_handler_` is no longer valid. + video_frame_handler_.reset(); + if (auto* view = GetVideoStreamView(); view) { + view->ClearFrame(); + } +} + +void VideoStreamCoordinator::StopAndCleanup( + mojo::Remote<video_capture::mojom::VideoSourceProvider> + video_source_provider) { + StopInternal(std::move(video_source_provider)); +} + +void VideoStreamCoordinator::Stop() { + StopInternal(); +} + +void VideoStreamCoordinator::StopInternal( + mojo::Remote<video_capture::mojom::VideoSourceProvider> + video_source_provider) { + if (video_frame_handler_) { + // Close frame handling and move the object to another thread to allow it + // to finish processing frames that are in progress. If this isn't done, + // then allocated buffers can be left dangling until the video stream is + // stopped. + auto* handler_ptr = video_frame_handler_.get(); + std::exchange(handler_ptr, nullptr) + ->Close(base::DoNothingWithBoundArgs(std::move(video_source_provider), + std::move(video_frame_handler_))); + } + + if (auto* view = GetVideoStreamView(); view) { + view->ClearFrame(); + } +} + +void VideoStreamCoordinator::SetPreviewVisibility(bool is_visible) { + if (auto* view = GetVideoStreamView(); view) { + view->SetVisible(is_visible); + } +} + +VideoStreamView* VideoStreamCoordinator::GetVideoStreamView() { + auto* view = video_stream_view_tracker_.view(); + return view ? static_cast<VideoStreamView*>(view) : nullptr; +} + +const media::VideoCaptureFormat +VideoStreamCoordinator::GetClosestVideoFormatForTest( // IN-TEST + const std::vector<media::VideoCaptureFormat>& formats, + const int view_width, + const float minimum_frame_rate) { + return GetClosestVideoFormat(formats, view_width, minimum_frame_rate); +}
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.h b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.h new file mode 100644 index 0000000..ba2ea45 --- /dev/null +++ b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.h
@@ -0,0 +1,82 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_MEDIA_PREVIEW_CAMERA_PREVIEW_VIDEO_STREAM_COORDINATOR_H_ +#define CHROME_BROWSER_UI_VIEWS_MEDIA_PREVIEW_CAMERA_PREVIEW_VIDEO_STREAM_COORDINATOR_H_ + +#include <stddef.h> + +#include <memory> +#include <optional> +#include <utility> +#include <vector> + +#include "base/functional/callback_forward.h" +#include "base/memory/scoped_refptr.h" +#include "components/capture_mode/camera_video_frame_handler.h" +#include "media/capture/video_capture_types.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/video_capture/public/mojom/video_source_provider.mojom.h" +#include "ui/views/view_tracker.h" + +class VideoStreamView; + +// Sets up, updates and maintains the lifetime of the VideoStreamView. +// The view controller layer would be very thin so it is combined with the +// coordinator for the VideoStreamView. +class VideoStreamCoordinator + : public capture_mode::CameraVideoFrameHandler::Delegate { + public: + // VideoStreamView is added to `parent_view` children list at `index`. + // If `index` is `nullopt`, then the view is added to the end of the list. + VideoStreamCoordinator(views::View& parent_view, std::optional<size_t> index); + VideoStreamCoordinator(const VideoStreamCoordinator&) = delete; + VideoStreamCoordinator& operator=(const VideoStreamCoordinator&) = delete; + ~VideoStreamCoordinator() override; + + // Initializes CameraVideoFrameHandler, and request to start receiving frames. + void ConnectToDevice( + mojo::Remote<video_capture::mojom::VideoSource> video_source, + const std::vector<media::VideoCaptureFormat>& supported_formats); + + // Stops active VideoSource connection. + void Stop(); + + // Stops active VideoSource connection. As to guarantee that + // VideoSourceProvider outlive its VideoSource connection, it is passed in + // here to protect from destruction. + void StopAndCleanup(mojo::Remote<video_capture::mojom::VideoSourceProvider> + video_source_provider); + + // Shows/Hides video stream preview. It does nothing if the view has already + // been closed. + void SetPreviewVisibility(bool is_visible); + + // capture_mode::CameraVideoFrameHandler::Delegate implementation. + void OnCameraVideoFrame(scoped_refptr<media::VideoFrame> frame) override; + void OnFatalErrorOrDisconnection() override; + + void SetFrameReceivedCallbackForTest(base::RepeatingClosure callback) { + frame_received_callback_for_test_ = std::move(callback); + } + + const media::VideoCaptureFormat GetClosestVideoFormatForTest( + const std::vector<media::VideoCaptureFormat>& formats, + const int view_width, + const float minimum_frame_rate); + + private: + void StopInternal(mojo::Remote<video_capture::mojom::VideoSourceProvider> + video_source_provider = {}); + + VideoStreamView* GetVideoStreamView(); + + views::ViewTracker video_stream_view_tracker_; + std::unique_ptr<capture_mode::CameraVideoFrameHandler> video_frame_handler_; + + // Runs when a new frame is received. Used for testing. + base::RepeatingClosure frame_received_callback_for_test_; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_MEDIA_PREVIEW_CAMERA_PREVIEW_VIDEO_STREAM_COORDINATOR_H_
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator_unittest.cc b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator_unittest.cc new file mode 100644 index 0000000..d8e0af15 --- /dev/null +++ b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator_unittest.cc
@@ -0,0 +1,205 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/media_preview/camera_preview/video_stream_coordinator.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "base/functional/callback_forward.h" +#include "base/run_loop.h" +#include "base/test/mock_callback.h" +#include "base/time/time.h" +#include "chrome/browser/ui/views/frame/test_with_browser_view.h" +#include "media/capture/video_capture_types.h" +#include "services/video_capture/public/cpp/mock_push_subscription.h" +#include "services/video_capture/public/cpp/mock_video_frame_handler.h" +#include "services/video_capture/public/cpp/mock_video_source.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Mock; +using testing::Sequence; + +namespace { + +media::mojom::VideoBufferHandlePtr GetBufferHandler( + const gfx::Size& frame_size) { + return media::mojom::VideoBufferHandle::NewUnsafeShmemRegion( + base::UnsafeSharedMemoryRegion::Create(media::VideoFrame::AllocationSize( + media::PIXEL_FORMAT_I420, frame_size))); +} + +} // namespace + +class VideoStreamCoordinatorTest : public TestWithBrowserView { + protected: + VideoStreamCoordinatorTest() + : video_source_receiver_(&mock_video_source_), + subscription_(&mock_subscription_), + video_frame_access_handler_receiver_( + &fake_video_frame_access_handler_) {} + + void SetUp() override { + TestWithBrowserView::SetUp(); + parent_view_ = std::make_unique<views::View>(); + coordinator_ = + std::make_unique<VideoStreamCoordinator>(*parent_view_, /*index=*/0); + } + + void TearDown() override { + coordinator_.reset(); + parent_view_.reset(); + TestWithBrowserView::TearDown(); + } + + static std::vector<media::VideoCaptureFormat> GetFormats() { + return {{{160, 120}, 15.0, media::PIXEL_FORMAT_I420}, + {{160, 120}, 30.0, media::PIXEL_FORMAT_NV12}, + {{640, 480}, 30.0, media::PIXEL_FORMAT_NV12}, + {{640, 480}, 30.0, media::PIXEL_FORMAT_I420}, + {{3840, 2160}, 30.0, media::PIXEL_FORMAT_Y16}, + {{844, 400}, 30.0, media::PIXEL_FORMAT_NV12}, + {{1280, 720}, 30.0, media::PIXEL_FORMAT_I420}}; + } + + void ExpectCreatePushSubscriptionCall(Sequence sequence) { + EXPECT_CALL(mock_video_source_, DoCreatePushSubscription(_, _, _, _, _)) + .InSequence(sequence) + .WillOnce([&](auto subscriber, const auto& requested_settings, + bool force_reopen_with_new_settings, auto subscription, + auto& callback) { + subscriber_.reset(); + subscriber_.Bind(std::move(subscriber)); + subscription_.reset(); + subscription_.Bind(std::move(subscription)); + current_settings_ = requested_settings; + + std::move(callback).Run( + video_capture::mojom::CreatePushSubscriptionResultCode:: + NewSuccessCode( + video_capture::mojom::CreatePushSubscriptionSuccessCode:: + kCreatedWithRequestedSettings), + requested_settings); + }); + } + + void ExpectActivateCall(Sequence sequence) { + EXPECT_CALL(mock_subscription_, Activate()) + .InSequence(sequence) + .WillOnce([&]() { + subscriber_->OnFrameAccessHandlerReady( + video_frame_access_handler_receiver_.BindNewPipeAndPassRemote()); + + start_time_ = base::Time::Now(); + const auto frame_duration = + base::Hertz(current_settings_.requested_format.frame_rate); + frame_timer_.Start(FROM_HERE, frame_duration, this, + &VideoStreamCoordinatorTest::OnNextFrame); + }); + } + + void OnNextFrame() { + const int buffer_id = g_next_buffer_id++; + subscriber_->OnNewBuffer( + buffer_id, + GetBufferHandler(current_settings_.requested_format.frame_size)); + + media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New(); + info->timestamp = base::Time::Now() - start_time_; + info->pixel_format = media::PIXEL_FORMAT_I420; + info->coded_size = current_settings_.requested_format.frame_size; + info->visible_rect = gfx::Rect(info->coded_size); + info->is_premapped = false; + subscriber_->OnFrameReadyInBuffer( + video_capture::mojom::ReadyFrameInBuffer::New(buffer_id, + /*frame_feedback_id=*/0, + std::move(info))); + } + + void ExpectCloseCall(Sequence sequence, base::RunLoop& run_loop) { + EXPECT_CALL(mock_subscription_, DoClose(_)) + .InSequence(sequence) + .WillOnce( + [&](video_capture::MockPushSubcription::CloseCallback& callback) { + std::move(callback).Run(); + video_frame_access_handler_receiver_.reset(); + video_source_receiver_.reset(); + run_loop.Quit(); + }); + } + + std::unique_ptr<views::View> parent_view_; + std::unique_ptr<VideoStreamCoordinator> coordinator_; + + video_capture::MockVideoSource mock_video_source_; + mojo::Receiver<video_capture::mojom::VideoSource> video_source_receiver_; + + media::VideoCaptureParams current_settings_; + + video_capture::MockPushSubcription mock_subscription_; + mojo::Receiver<video_capture::mojom::PushVideoStreamSubscription> + subscription_; + + mojo::Remote<video_capture::mojom::VideoFrameHandler> subscriber_; + + video_capture::FakeVideoFrameAccessHandler fake_video_frame_access_handler_; + mojo::Receiver<video_capture::mojom::VideoFrameAccessHandler> + video_frame_access_handler_receiver_; + + // The next ID to be used for a newly created buffer. + int g_next_buffer_id = 0; + + // The time at which this device started producing video frames. + base::Time start_time_; + + // The timer that invokes `OnNextFrame()` repeatedly depending on the frame + // rate requested. + base::RepeatingTimer frame_timer_; +}; + +TEST_F(VideoStreamCoordinatorTest, ConnectToFrameHandlerAndReceiveFrames) { + Sequence sequence; + ExpectCreatePushSubscriptionCall(sequence); + ExpectActivateCall(sequence); + + base::MockCallback<base::RepeatingClosure> callback; + EXPECT_CALL(callback, Run()).Times(9).InSequence(sequence); + EXPECT_CALL(callback, Run()).InSequence(sequence).WillOnce([this]() { + coordinator_->Stop(); + }); + + base::RunLoop run_loop; + ExpectCloseCall(sequence, run_loop); + + coordinator_->SetFrameReceivedCallbackForTest(callback.Get()); + + mojo::Remote<video_capture::mojom::VideoSource> video_source; + video_source_receiver_.Bind(video_source.BindNewPipeAndPassReceiver()); + coordinator_->ConnectToDevice(std::move(video_source), GetFormats()); + run_loop.Run(); +} + +TEST_F(VideoStreamCoordinatorTest, ChooseTheClosetFormat) { + const auto& formats = GetFormats(); + EXPECT_EQ(formats[0], + coordinator_->GetClosestVideoFormatForTest( + formats, /*view_width=*/130, /*minimum_frame_rate*/ 10)); + EXPECT_EQ(formats[3], + coordinator_->GetClosestVideoFormatForTest( + formats, /*view_width=*/300, /*minimum_frame_rate*/ 10)); + + EXPECT_EQ(formats[3], + coordinator_->GetClosestVideoFormatForTest( + formats, /*view_width=*/280, /*minimum_frame_rate*/ 30)); + EXPECT_EQ(formats[5], + coordinator_->GetClosestVideoFormatForTest( + formats, /*view_width=*/700, /*minimum_frame_rate*/ 30)); + + EXPECT_EQ(formats[3], coordinator_->GetClosestVideoFormatForTest( + formats, /*view_width=*/280, + /*minimum_frame_rate*/ 40)); +}
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.cc b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.cc new file mode 100644 index 0000000..f75af0c --- /dev/null +++ b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.cc
@@ -0,0 +1,92 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.h" + +#include <utility> + +#include "chrome/browser/ui/views/chrome_layout_provider.h" +#include "chrome/grit/generated_resources.h" +#include "media/base/video_transformation.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/compositor/compositor.h" +#include "ui/gfx/canvas.h" + +VideoStreamView::VideoStreamView(float default_aspect_ratio) + : current_aspect_ratio_(default_aspect_ratio), + rounded_radius_(ChromeLayoutProvider::Get()->GetCornerRadiusMetric( + views::ShapeContextTokens::kOmniboxExpandedRadius)) { + SetAccessibleName(l10n_util::GetStringUTF16( + IDS_MEDIA_PREVIEW_VIDEO_STREAM_ACCESSIBLE_NAME)); + SetAccessibleRole(ax::mojom::Role::kImage); + SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); +} + +VideoStreamView::~VideoStreamView() { + ClearFrame(); +} + +void VideoStreamView::ScheduleFramePaint( + scoped_refptr<media::VideoFrame> frame) { + latest_frame_ = std::move(frame); + + if (!has_updated_preferred_size_) { + if (latest_frame_) { + gfx::Size frame_size = latest_frame_->natural_size(); + current_aspect_ratio_ = + frame_size.width() / static_cast<float>(frame_size.height()); + } + PreferredSizeChanged(); + has_updated_preferred_size_ = true; + } + + SchedulePaint(); +} + +void VideoStreamView::ClearFrame() { + has_updated_preferred_size_ = false; + video_renderer_.ResetCache(); + latest_frame_.reset(); + PreferredSizeChanged(); + SchedulePaint(); +} + +void VideoStreamView::OnPaint(gfx::Canvas* canvas) { + if (!latest_frame_ || !raster_context_provider_) { + gfx::RectF base_rect(width(), height()); + canvas->DrawRoundRect(base_rect, rounded_radius_, cc::PaintFlags()); + return; + } + + if (features::IsChromeRefresh2023()) { + canvas->sk_canvas()->clipRRect( + SkRRect::MakeRectXY(SkRect::MakeIWH(width(), height()), rounded_radius_, + rounded_radius_), + /*do_anti_alias=*/true); + } + const gfx::RectF dest_rect(width(), height()); + cc::PaintFlags flags; + media::VideoTransformation transformation; + transformation.mirrored = true; + video_renderer_.Paint(std::move(latest_frame_), canvas->sk_canvas(), + dest_rect, flags, transformation, + raster_context_provider_.get()); +} + +int VideoStreamView::GetHeightForWidth(int w) const { + return w / current_aspect_ratio_; +} + +gfx::Size VideoStreamView::CalculatePreferredSize() const { + return gfx::Size(width(), GetHeightForWidth(width())); +} + +void VideoStreamView::OnBoundsChanged(const gfx::Rect& previous_bounds) { + has_updated_preferred_size_ = false; +} + +BEGIN_METADATA(VideoStreamView) +END_METADATA
diff --git a/chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.h b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.h new file mode 100644 index 0000000..0d465d3 --- /dev/null +++ b/chrome/browser/ui/views/media_preview/camera_preview/video_stream_view.h
@@ -0,0 +1,51 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_MEDIA_PREVIEW_CAMERA_PREVIEW_VIDEO_STREAM_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_MEDIA_PREVIEW_CAMERA_PREVIEW_VIDEO_STREAM_VIEW_H_ + +#include <utility> + +#include "base/memory/scoped_refptr.h" +#include "components/viz/common/gpu/raster_context_provider.h" +#include "media/base/video_frame.h" +#include "media/renderers/paint_canvas_video_renderer.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/view.h" + +// The camera live video feed view. +class VideoStreamView : public views::View { + METADATA_HEADER(VideoStreamView, views::View) + + public: + explicit VideoStreamView(float default_aspect_ratio); + VideoStreamView(const VideoStreamView&) = delete; + VideoStreamView& operator=(const VideoStreamView&) = delete; + ~VideoStreamView() override; + + void SetRasterContextProvider( + scoped_refptr<viz::RasterContextProvider> raster_context_provider) { + raster_context_provider_ = std::move(raster_context_provider); + } + + void ScheduleFramePaint(scoped_refptr<media::VideoFrame> frame); + void ClearFrame(); + + protected: + // views::View overrides + void OnPaint(gfx::Canvas* canvas) override; + int GetHeightForWidth(int w) const override; + gfx::Size CalculatePreferredSize() const override; + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + + private: + float current_aspect_ratio_; + bool has_updated_preferred_size_ = false; + const int rounded_radius_; + media::PaintCanvasVideoRenderer video_renderer_; + scoped_refptr<media::VideoFrame> latest_frame_; + scoped_refptr<viz::RasterContextProvider> raster_context_provider_; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_MEDIA_PREVIEW_CAMERA_PREVIEW_VIDEO_STREAM_VIEW_H_
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_sink_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_sink_view.cc index 09f15ce..4c40c318 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_sink_view.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_sink_view.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/media_router/cast_dialog_sink_view.h" +#include <utility> + #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/media/router/discovery/access_code/access_code_cast_feature.h" #include "chrome/browser/media/router/media_router_feature.h" @@ -52,7 +54,7 @@ views::Button::PressedCallback issue_pressed_callback) { if (sink.issue) { auto subtitle_button = std::make_unique<views::LabelButton>( - issue_pressed_callback, sink.GetStatusTextForDisplay()); + std::move(issue_pressed_callback), sink.GetStatusTextForDisplay()); subtitle_button->SetLabelStyle(views::style::STYLE_SECONDARY); subtitle_button->SetAccessibleName(sink.GetStatusTextForDisplay()); return subtitle_button; @@ -93,12 +95,12 @@ // |----------------------------------| // | | Button 1 | Button 2 | Buttons View // *----------------------------------* - AddChildView(CreateLabelView(sink, issue_pressed_callback)); - AddChildView( - CreateButtonsView(stop_pressed_callback, freeze_pressed_callback)); + AddChildView(CreateLabelView(sink, std::move(issue_pressed_callback))); + AddChildView(CreateButtonsView(std::move(stop_pressed_callback), + std::move(freeze_pressed_callback))); } else { - cast_sink_button_ = AddChildView( - std::make_unique<CastDialogSinkButton>(sink_pressed_callback, sink)); + cast_sink_button_ = AddChildView(std::make_unique<CastDialogSinkButton>( + std::move(sink_pressed_callback), sink)); } } @@ -129,8 +131,8 @@ // Create the wrapper so labels can stack. auto label_wrapper = std::make_unique<views::View>(); title_ = label_wrapper->AddChildView(CreateTitle(sink)); - subtitle_ = - label_wrapper->AddChildView(CreateSubtitle(sink, issue_pressed_callback)); + subtitle_ = label_wrapper->AddChildView( + CreateSubtitle(sink, std::move(issue_pressed_callback))); // Set wrapper properties. label_wrapper->SetLayoutManager(std::make_unique<views::FlexLayout>()) @@ -180,7 +182,7 @@ if (IsAccessCodeCastFreezeUiEnabled(profile_) && sink_.freeze_info.can_freeze) { auto freeze_button = std::make_unique<views::MdTextButton>( - freeze_pressed_callback, + std::move(freeze_pressed_callback), l10n_util::GetStringUTF16(sink_.freeze_info.is_frozen ? IDS_MEDIA_ROUTER_SINK_VIEW_RESUME : IDS_MEDIA_ROUTER_SINK_VIEW_PAUSE)); @@ -192,7 +194,7 @@ // Always create the stop button, since at this point we know the sink is // connected. auto stop_button = std::make_unique<views::MdTextButton>( - stop_pressed_callback, + std::move(stop_pressed_callback), l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_SINK_VIEW_STOP)); stop_button->SetStyle(ui::ButtonStyle::kText); stop_button->SetAccessibleName(GetStopButtonAccessibleName());
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc index a8d55f4e..159e7cd9 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -931,9 +931,7 @@ // Looks like the same problem as in the SelectAllOnClick(). // Tracked in: https://crbug.com/915591 // Test is also flaky on Linux: https://crbug.com/1157250 -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) #define MAYBE_HandleExternalProtocolURLs DISABLED_HandleExternalProtocolURLs #else #define MAYBE_HandleExternalProtocolURLs HandleExternalProtocolURLs
diff --git a/chrome/browser/ui/views/page_info/security_information_view.cc b/chrome/browser/ui/views/page_info/security_information_view.cc index 5405130..723755a 100644 --- a/chrome/browser/ui/views/page_info/security_information_view.cc +++ b/chrome/browser/ui/views/page_info/security_information_view.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/page_info/security_information_view.h" +#include <utility> + #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h" @@ -205,14 +207,14 @@ std::unique_ptr<views::MdTextButton> change_password_button; if (change_password_template) { change_password_button = std::make_unique<views::MdTextButton>( - change_password_callback, + std::move(change_password_callback), l10n_util::GetStringUTF16(change_password_template)); change_password_button->SetProminent(true); change_password_button->SetID( PageInfoViewFactory::VIEW_ID_PAGE_INFO_BUTTON_CHANGE_PASSWORD); } auto allowlist_password_reuse_button = std::make_unique<views::MdTextButton>( - password_reuse_callback, + std::move(password_reuse_callback), l10n_util::GetStringUTF16(IDS_PAGE_INFO_ALLOWLIST_PASSWORD_REUSE_BUTTON)); allowlist_password_reuse_button->SetID( PageInfoViewFactory::VIEW_ID_PAGE_INFO_BUTTON_ALLOWLIST_PASSWORD_REUSE);
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc index 88995b3..26e98ee 100644 --- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.h" #include <memory> +#include <utility> #include "base/check_op.h" #include "base/strings/strcat.h" @@ -204,7 +205,7 @@ views::Button::PressedCallback pressed_callback, const SkColor enabled_color, const SkColor disabled_color) - : views::ImageButton(pressed_callback) { + : views::ImageButton(std::move(pressed_callback)) { ConfigureVectorImageButton(this); views::InstallCircleHighlightPathGenerator(this); constexpr int kCloseButtonSize = 16;
diff --git a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc index f04d65e..7f9728f 100644 --- a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc +++ b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
@@ -238,7 +238,7 @@ METADATA_HEADER(PaymentRequestBackArrowButton); explicit PaymentRequestBackArrowButton( views::Button::PressedCallback back_arrow_callback) - : views::ImageButton(back_arrow_callback) { + : views::ImageButton(std::move(back_arrow_callback)) { ConfigureVectorImageButton(this); constexpr int kBackArrowSize = 16; SetSize(gfx::Size(kBackArrowSize, kBackArrowSize));
diff --git a/chrome/browser/ui/views/profiles/first_run_interactive_uitest.cc b/chrome/browser/ui/views/profiles/first_run_interactive_uitest.cc index bf1923c..4b32f29e 100644 --- a/chrome/browser/ui/views/profiles/first_run_interactive_uitest.cc +++ b/chrome/browser/ui/views/profiles/first_run_interactive_uitest.cc
@@ -247,13 +247,14 @@ public: FirstRunParameterizedInteractiveUiTest() { std::vector<base::test::FeatureRefAndParams> enabled_features_and_params; + std::vector<base::test::FeatureRef> disabled_features; enabled_features_and_params.push_back( {kForYouFre, {{kForYouFreWithDefaultBrowserStep.name, WithDefaultBrowserStep() ? "forced" : "no"}}}); -#if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) if (WithSearchEngineChoiceStep()) { +#if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) scoped_chrome_build_override_ = std::make_unique<base::AutoReset<bool>>( SearchEngineChoiceServiceFactory::ScopedChromeBuildOverrideForTesting( /*force_chrome_build=*/true)); @@ -261,9 +262,17 @@ enabled_features_and_params.push_back( {switches::kSearchEngineChoiceFre, {}}); enabled_features_and_params.push_back( - {switches::kSearchEngineChoice, {}}); - } + {switches::kSearchEngineChoice, { + { switches::kWithForcedScrollEnabled.name, + "true" } + }}); +#else + NOTREACHED_NORETURN(); #endif + } else { + disabled_features.push_back(switches::kSearchEngineChoice); + disabled_features.push_back(switches::kSearchEngineChoiceFre); + } if (WithPrivacySandboxEnabled()) { enabled_features_and_params.push_back( @@ -274,7 +283,7 @@ } scoped_feature_list_.InitWithFeaturesAndParameters( - enabled_features_and_params, {}); + enabled_features_and_params, disabled_features); } // FirstRunInteractiveUiTestBase: @@ -320,11 +329,9 @@ return GetParam().with_default_browser_step; } -#if BUILDFLAG(ENABLE_SEARCH_ENGINE_CHOICE) bool WithSearchEngineChoiceStep() const { return GetParam().with_search_engine_choice_step; } -#endif bool WithPrivacySandboxEnabled() const { return GetParam().with_privacy_sandbox_enabled; @@ -334,10 +341,19 @@ auto CompleteSearchEngineChoiceStep() { const DeepQuery first_search_engine = {"search-engine-choice-app", "cr-radio-button"}; + const DeepQuery searchEngineChoiceList{"search-engine-choice-app", + "#choiceList"}; return Steps( WaitForWebContentsNavigation( kWebContentsId, GURL(chrome::kChromeUISearchEngineChoiceURL)), PressJsButton(kWebContentsId, first_search_engine), + // Simulate scrolling to the bottom of the choice list. + ExecuteJsAt(kWebContentsId, searchEngineChoiceList, R"js( + element => { + element.scrollTop = element.scrollHeight - element.clientHeight; + element.dispatchEvent(new CustomEvent('scroll')); + } + )js"), WaitForButtonEnabled(kWebContentsId, kSubmitSearchEngineChoiceButton), PressJsButton(kWebContentsId, kSubmitSearchEngineChoiceButton)); }
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc index 721b25f3..7f6aea5 100644 --- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -98,7 +98,8 @@ ? gfx::Insets::VH(5 * vertical_spacing / 4, horizontal_spacing) : gfx::Insets::VH(vertical_spacing, horizontal_spacing); - auto button = CreateBubbleMenuItem(button_id, name, callback, icon); + auto button = + CreateBubbleMenuItem(button_id, name, std::move(callback), icon); button->SetBorder(views::CreateEmptyBorder(control_insets)); if (features::IsChromeRefresh2023()) { button->SetLabelStyle(views::style::STYLE_BODY_3_EMPHASIS);
diff --git a/chrome/browser/ui/views/tabs/tab_strip_control_button.cc b/chrome/browser/ui/views/tabs/tab_strip_control_button.cc index 84b1c9ad..e04b5b9 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_control_button.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_control_button.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/tabs/tab_strip_control_button.h" +#include <utility> + #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" @@ -62,7 +64,7 @@ const gfx::VectorIcon& icon, Edge flat_edge) : TabStripControlButton(tab_strip_controller, - callback, + std::move(callback), icon, std::u16string(), flat_edge) {} @@ -73,7 +75,7 @@ const std::u16string& text, Edge flat_edge) : TabStripControlButton(tab_strip_controller, - callback, + std::move(callback), kEmptyIcon, text, flat_edge) {}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller.cc b/chrome/browser/ui/views/toolbar/toolbar_controller.cc index 02a3cd4..43557a4 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_controller.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_controller.cc
@@ -142,18 +142,22 @@ {{kToolbarForwardButtonElementId, IDS_OVERFLOW_MENU_ITEM_TEXT_FORWARD, kToolbarForwardButtonElementId}, {kToolbarHomeButtonElementId, IDS_OVERFLOW_MENU_ITEM_TEXT_HOME, - kToolbarHomeButtonElementId}, + kToolbarHomeButtonElementId, /*is_section_end=*/true}, {kToolbarChromeLabsButtonElementId, IDS_OVERFLOW_MENU_ITEM_TEXT_LABS, - kToolbarChromeLabsButtonElementId, kToolbarChromeLabsBubbleElementId}, + kToolbarChromeLabsButtonElementId, /*is_section_end=*/false, + kToolbarChromeLabsBubbleElementId}, {kToolbarMediaButtonElementId, IDS_OVERFLOW_MENU_ITEM_TEXT_MEDIA_CONTROLS, - kToolbarMediaButtonElementId, kToolbarMediaBubbleElementId}, + kToolbarMediaButtonElementId, /*is_section_end=*/false, + kToolbarMediaBubbleElementId}, {kToolbarDownloadButtonElementId, IDS_OVERFLOW_MENU_ITEM_TEXT_DOWNLOADS, - kToolbarDownloadButtonElementId, kToolbarDownloadBubbleElementId}, + kToolbarDownloadButtonElementId, /*is_section_end=*/false, + kToolbarDownloadBubbleElementId}, {kToolbarNewTabButtonElementId, IDS_OVERFLOW_MENU_ITEM_TEXT_NEW_TAB, - kToolbarNewTabButtonElementId}, + kToolbarNewTabButtonElementId, /*is_section_end=*/true}, {kToolbarAvatarButtonElementId, IDS_OVERFLOW_MENU_ITEM_TEXT_PROFILE, - kToolbarAvatarButtonElementId, kToolbarAvatarBubbleElementId}}); + kToolbarAvatarButtonElementId, /*is_section_end=*/false, + kToolbarAvatarBubbleElementId}}); } std::vector<ui::ElementIdentifier> @@ -306,9 +310,21 @@ ToolbarController::CreateOverflowMenuModel() { CHECK(overflow_button_->GetVisible()); auto menu_model = std::make_unique<ui::SimpleMenuModel>(this); + + // True if the separator belonging to previous section has not been added yet. + bool pre_separator_pending = false; + for (size_t i = 0; i < responsive_elements_.size(); ++i) { - if (IsOverflowed(responsive_elements_[i].overflow_identifier)) { - menu_model->AddItem(i, GetMenuText(responsive_elements_[i])); + const auto& element = responsive_elements_[i]; + if (IsOverflowed(element.overflow_identifier)) { + if (pre_separator_pending && menu_model->GetItemCount() > 0) { + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); + } + menu_model->AddItem(i, GetMenuText(element)); + pre_separator_pending = false; + } + if (element.is_section_end) { + pre_separator_pending = true; } } return menu_model;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller.h b/chrome/browser/ui/views/toolbar/toolbar_controller.h index b7a0d2a..5d70d5ab 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_controller.h +++ b/chrome/browser/ui/views/toolbar/toolbar_controller.h
@@ -21,11 +21,32 @@ public: // Data structure to store information of responsive elements. struct ResponsiveElementInfo { + // Overflow menu structure: + // ------------------- + // | Forward | + // |-----------------| + // | Home | -> section end + // |=================| -> potential separator + // | Reading list | + // |-----------------| + // | Bookmarks | -> section end + // |=================| -> potential separator + // | Labs | + // |-----------------| + // | Cast | + // |-----------------| + // | Media controls | + // |-----------------| + // | Downloads | -> section end + // |=================| -> potential separator + // | Profile | + // |-----------------| + // The toolbar element that potentially overflows. ui::ElementIdentifier overflow_identifier; // Menu text when the element is overflow to the overflow menu. - int menu_text_id; + int menu_text_id = 0; // The toolbar button to be activated with menu text pressed. This is not // necessarily the same as the element that overflows. E.g. when the @@ -33,6 +54,9 @@ // `activate_identifier` should be kExtensionsMenuButtonElementId. ui::ElementIdentifier activate_identifier; + // True if current element is a section end in overflow menu structure. + bool is_section_end = false; + // Pop out button when `observed_identifier` is shown. End pop out when it's // hidden. absl::optional<ui::ElementIdentifier> observed_identifier;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc index b767efa..67b5987 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/views/toolbar/chrome_labs_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_controller.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/grit/generated_resources.h" #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "chrome/test/interaction/feature_engagement_initialized_observer.h" @@ -131,14 +132,17 @@ auto CheckMenuMatchesOverflowedElements() { return Steps(Check([this]() { const ui::SimpleMenuModel* menu = GetOverflowMenu(); - const auto overflowed_elements = GetOverflowedElements(); EXPECT_NE(menu, nullptr); EXPECT_GT(menu->GetItemCount(), size_t(0)); - EXPECT_EQ(menu->GetItemCount(), overflowed_elements.size()); - for (size_t i = 0; i < menu->GetItemCount(); ++i) { - if (menu->GetLabelAt(i).compare(toolbar_controller_->GetMenuText( - *overflowed_elements[i])) != 0) { - return false; + const auto& responsive_elements = + toolbar_controller_->responsive_elements_; + for (size_t i = 0; i < responsive_elements.size(); ++i) { + if (toolbar_controller_->IsOverflowed( + responsive_elements[i].overflow_identifier)) { + if (toolbar_controller_->GetMenuText(responsive_elements[i]) != + menu->GetLabelAt(menu->GetIndexOfCommandId(i).value())) { + return false; + } } } return true;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc index 44fd2456..f610b031 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc
@@ -98,7 +98,7 @@ MockToolbarController toolbar_controller( std::vector<ToolbarController::ResponsiveElementInfo>( - {{kDummyButton, 0, kDummyActivateView, kDummyObservedView}}), + {{kDummyButton, 0, kDummyActivateView, false, kDummyObservedView}}), std::vector<ui::ElementIdentifier>({kDummyButton}), 1, container_view(), overflow_button()); @@ -186,9 +186,9 @@ overflow_button_->SetVisible(false); toolbar_controller_ = std::make_unique<TestToolbarController>( std::vector<ToolbarController::ResponsiveElementInfo>( - {{kDummyButton1, 0, kDummyActivateView, kDummyObservedView}, - {kDummyButton2, 0, kDummyActivateView, kDummyObservedView}, - {kDummyButton3, 0, kDummyActivateView, kDummyObservedView}}), + {{kDummyButton1, 0, kDummyActivateView, false, kDummyObservedView}, + {kDummyButton2, 0, kDummyActivateView, true, kDummyObservedView}, + {kDummyButton3, 0, kDummyActivateView, true, kDummyObservedView}}), std::vector<ui::ElementIdentifier>( {kDummyButton3, kDummyButton2, kDummyButton1}), kElementFlexOrderStart, toolbar_container_view_, overflow_button_); @@ -241,6 +241,13 @@ GetOverflowedElements() { return toolbar_controller()->GetOverflowedElements(); } + const std::vector<ToolbarController::ResponsiveElementInfo>& + GetResponsiveElements() { + return toolbar_controller_->responsive_elements_; + } + bool IsOverflowed(const ToolbarController::ResponsiveElementInfo& element) { + return toolbar_controller_->IsOverflowed(element.overflow_identifier); + } private: std::unique_ptr<views::Widget> widget_; @@ -286,13 +293,156 @@ // Overflowed buttons should match overflow menu. EXPECT_TRUE(menu); - EXPECT_EQ(overflowed_buttons.size(), menu->GetItemCount()); - for (size_t i = 0; i < overflowed_buttons.size(); ++i) { - EXPECT_EQ(toolbar_controller()->GetMenuText(*overflowed_buttons[i]), - menu->GetLabelAt(i)); + const auto& responsive_elements = GetResponsiveElements(); + for (size_t i = 0; i < responsive_elements.size(); ++i) { + if (IsOverflowed(responsive_elements[i])) { + EXPECT_EQ(toolbar_controller()->GetMenuText(responsive_elements[i]), + menu->GetLabelAt(menu->GetIndexOfCommandId(i).value())); + } } } +TEST_F(ToolbarControllerUnitTest, MenuSeparator) { + // Set widget to be small enough to ensure all the buttons overflow. + widget()->SetSize(gfx::Size(1, 1)); + SetOverflowButtonVisible(toolbar_controller()->ShouldShowOverflowButton()); + + // All 3 buttons overflowed. + EXPECT_EQ(GetOverflowedElements().size(), static_cast<size_t>(3)); + const auto menu = toolbar_controller()->CreateOverflowMenuModel(); + EXPECT_TRUE(menu); + + // There is no separator between button1 and 2 because button1 is not a menu + // section end. + // There is a separator between button2 and button3 because + // 1) button2 is a section end; + // 2) the section button2 is in is valid; + // 3) the section button3 is in is valid. + // There is no separator after button3 because there is no valid next section. + EXPECT_EQ(menu->GetItemCount(), static_cast<size_t>(4)); + EXPECT_EQ(menu->GetTypeAt(0), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(0), u"DummyButton1"); + EXPECT_EQ(menu->GetTypeAt(1), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(1), u"DummyButton2"); + EXPECT_EQ(menu->GetTypeAt(2), ui::MenuModel::ItemType::TYPE_SEPARATOR); + EXPECT_EQ(menu->GetTypeAt(3), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(3), u"DummyButton3"); +} + +TEST_F(ToolbarControllerUnitTest, InValidFirstSectionAddsNoLeadingSeparator) { + std::unique_ptr<ToolbarController> test_controller = + std::make_unique<TestToolbarController>( + std::vector<ToolbarController::ResponsiveElementInfo>( + {{kDummyButton1, 0, kDummyActivateView, true}, + {kDummyButton2, 0, kDummyActivateView, true}, + {kDummyButton3, 0, kDummyActivateView, true}}), + std::vector<ui::ElementIdentifier>( + {kDummyButton3, kDummyButton2, kDummyButton1}), + kElementFlexOrderStart, toolbar_container_view(), + const_cast<views::View*>(overflow_button())); + + widget()->SetSize(kButtonSize); + SetOverflowButtonVisible(toolbar_controller()->ShouldShowOverflowButton()); + EXPECT_TRUE(overflow_button()->GetVisible()); + + views::View* button1 = test_buttons()[0]; + views::View* button2 = test_buttons()[1]; + views::View* button3 = test_buttons()[2]; + + // Button2 and 3 overflowed. + EXPECT_TRUE(button1->GetVisible()); + EXPECT_FALSE(button2->GetVisible()); + EXPECT_FALSE(button3->GetVisible()); + EXPECT_EQ(GetOverflowedElements().size(), static_cast<size_t>(2)); + const auto menu = test_controller->CreateOverflowMenuModel(); + EXPECT_TRUE(menu); + + // The first section (contains Button1) is invalid. It should not add a + // separator before Button2. + EXPECT_EQ(menu->GetItemCount(), static_cast<size_t>(3)); + EXPECT_EQ(menu->GetTypeAt(0), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(0), u"DummyButton2"); + EXPECT_EQ(menu->GetTypeAt(1), ui::MenuModel::ItemType::TYPE_SEPARATOR); + EXPECT_EQ(menu->GetTypeAt(2), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(2), u"DummyButton3"); +} + +TEST_F(ToolbarControllerUnitTest, InValidSectionInMiddleAddsNoExtraSeparator) { + std::unique_ptr<ToolbarController> test_controller = + std::make_unique<TestToolbarController>( + std::vector<ToolbarController::ResponsiveElementInfo>( + {{kDummyButton1, 0, kDummyActivateView, true}, + {kDummyButton2, 0, kDummyActivateView, true}, + {kDummyButton3, 0, kDummyActivateView, true}}), + std::vector<ui::ElementIdentifier>( + {kDummyButton1, kDummyButton3, kDummyButton2}), + kElementFlexOrderStart, toolbar_container_view(), + const_cast<views::View*>(overflow_button())); + + widget()->SetSize(kButtonSize); + SetOverflowButtonVisible(toolbar_controller()->ShouldShowOverflowButton()); + EXPECT_TRUE(overflow_button()->GetVisible()); + + views::View* button1 = test_buttons()[0]; + views::View* button2 = test_buttons()[1]; + views::View* button3 = test_buttons()[2]; + + // Button1 and 3 overflowed. + EXPECT_FALSE(button1->GetVisible()); + EXPECT_TRUE(button2->GetVisible()); + EXPECT_FALSE(button3->GetVisible()); + EXPECT_EQ(GetOverflowedElements().size(), static_cast<size_t>(2)); + const auto menu = test_controller->CreateOverflowMenuModel(); + EXPECT_TRUE(menu); + + // The second section (contains Button2) is invalid. It should not add a + // redundant separator. + EXPECT_EQ(menu->GetItemCount(), static_cast<size_t>(3)); + EXPECT_EQ(menu->GetTypeAt(0), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(0), u"DummyButton1"); + EXPECT_EQ(menu->GetTypeAt(1), ui::MenuModel::ItemType::TYPE_SEPARATOR); + EXPECT_EQ(menu->GetTypeAt(2), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(2), u"DummyButton3"); +} + +TEST_F(ToolbarControllerUnitTest, InValidLastSectionAddsNoTrailingSeparator) { + std::unique_ptr<ToolbarController> test_controller = + std::make_unique<TestToolbarController>( + std::vector<ToolbarController::ResponsiveElementInfo>( + {{kDummyButton1, 0, kDummyActivateView, true}, + {kDummyButton2, 0, kDummyActivateView, true}, + {kDummyButton3, 0, kDummyActivateView, true}}), + std::vector<ui::ElementIdentifier>( + {kDummyButton1, kDummyButton2, kDummyButton3}), + kElementFlexOrderStart, toolbar_container_view(), + const_cast<views::View*>(overflow_button())); + + widget()->SetSize(kButtonSize); + SetOverflowButtonVisible(toolbar_controller()->ShouldShowOverflowButton()); + EXPECT_TRUE(overflow_button()->GetVisible()); + + views::View* button1 = test_buttons()[0]; + views::View* button2 = test_buttons()[1]; + views::View* button3 = test_buttons()[2]; + + // Button1 and 2 overflowed. + EXPECT_FALSE(button1->GetVisible()); + EXPECT_FALSE(button2->GetVisible()); + EXPECT_TRUE(button3->GetVisible()); + EXPECT_EQ(GetOverflowedElements().size(), static_cast<size_t>(2)); + const auto menu = test_controller->CreateOverflowMenuModel(); + EXPECT_TRUE(menu); + + // The third section (contains Button3) is invalid. It should not add a + // redundant trailing separator. + EXPECT_EQ(menu->GetItemCount(), static_cast<size_t>(3)); + EXPECT_EQ(menu->GetTypeAt(0), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(0), u"DummyButton1"); + EXPECT_EQ(menu->GetTypeAt(1), ui::MenuModel::ItemType::TYPE_SEPARATOR); + EXPECT_EQ(menu->GetTypeAt(2), ui::MenuModel::ItemType::TYPE_COMMAND); + EXPECT_EQ(menu->GetLabelAt(2), u"DummyButton2"); +} + TEST_F(ToolbarControllerUnitTest, PopOutState) { auto& pop_out_state = toolbar_controller()->pop_out_state_for_testing(); EXPECT_FALSE(pop_out_state.at(kDummyButton1)->original_spec.has_value()); @@ -388,9 +538,9 @@ std::unique_ptr<ToolbarController> dummy_controller = std::make_unique<TestToolbarController>( std::vector<ToolbarController::ResponsiveElementInfo>( - {{kDummyButton1, 0, kDummyActivateView, kDummyObservedView}, - {kDummyButton2, 0, kDummyActivateView, kDummyObservedView}, - {kDummyButton3, 0, kDummyActivateView, kDummyObservedView}}), + {{kDummyButton1, 0, kDummyActivateView}, + {kDummyButton2, 0, kDummyActivateView}, + {kDummyButton3, 0, kDummyActivateView}}), std::vector<ui::ElementIdentifier>( {kDummyButton1, kDummyButton2, kDummyButton3}), kElementFlexOrderStart, toolbar_container_view(), @@ -448,13 +598,15 @@ const auto overflowed_buttons = GetOverflowedElements(); EXPECT_TRUE(menu); - EXPECT_EQ(overflowed_buttons.size(), menu->GetItemCount()); - for (size_t i = 0; i < overflowed_buttons.size(); ++i) { - EXPECT_EQ(ToolbarController::FindToolbarElementWithId( - toolbar_container_view(), - overflowed_buttons.at(i)->overflow_identifier) - ->GetEnabled(), - menu->IsEnabledAt(i)); + const auto& responsive_elements = GetResponsiveElements(); + for (size_t i = 0; i < responsive_elements.size(); ++i) { + if (IsOverflowed(responsive_elements[i])) { + EXPECT_EQ(ToolbarController::FindToolbarElementWithId( + toolbar_container_view(), + responsive_elements[i].overflow_identifier) + ->GetEnabled(), + menu->IsEnabledAt(menu->GetIndexOfCommandId(i).value())); + } } }
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc index cc876e4..49778b8 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/webid/account_selection_bubble_view.h" #include <algorithm> +#include <utility> #include "base/feature_list.h" #include "base/i18n/case_conversion.h" @@ -201,7 +202,7 @@ const std::u16string& text, AccountSelectionBubbleView* bubble_view, const content::IdentityProviderMetadata& idp_metadata) - : views::MdTextButton(callback, text), + : views::MdTextButton(std::move(callback), text), bubble_view_(bubble_view), brand_background_color_(idp_metadata.brand_background_color), brand_text_color_(idp_metadata.brand_text_color) {
diff --git a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc index f4ab6d3..0116e8e1 100644 --- a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc +++ b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc
@@ -29,6 +29,7 @@ #include "components/webapps/common/web_app_id.h" #include "content/public/common/content_features.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "third_party/blink/public/common/features_generated.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/encode/SkPngEncoder.h" @@ -41,7 +42,9 @@ IsolatedWebAppBrowserTestHarness::IsolatedWebAppBrowserTestHarness() { iwa_scoped_feature_list_.InitWithFeatures( - {features::kIsolatedWebApps, features::kIsolatedWebAppDevMode}, {}); + {features::kIsolatedWebApps, features::kIsolatedWebAppDevMode, + blink::features::kUnrestrictedUsb}, + {}); } IsolatedWebAppBrowserTestHarness::~IsolatedWebAppBrowserTestHarness() = default;
diff --git a/chrome/browser/ui/webui/ash/add_supervision/OWNERS b/chrome/browser/ui/webui/ash/add_supervision/OWNERS index 49c4b1cc..f335ce44 100644 --- a/chrome/browser/ui/webui/ash/add_supervision/OWNERS +++ b/chrome/browser/ui/webui/ash/add_supervision/OWNERS
@@ -1,5 +1,4 @@ -agawronska@chromium.org -courtneywong@chromium.org +file://chrome/browser/ash/child_accounts/OWNERS per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.cc b/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.cc index 78e957c..0802e06a 100644 --- a/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.cc +++ b/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.cc
@@ -94,12 +94,20 @@ : SystemWebDialogDelegate(GURL(chrome::kChromeUIBluetoothPairingURL), /*title=*/std::u16string()), dialog_id_(dialog_id) { - if (canonical_device_address.has_value()) - device_data_.Set("address", canonical_device_address.value()); + set_dialog_size(gfx::Size(SystemWebDialogDelegate::kDialogWidth, + kBluetoothPairingDialogHeight)); - device_data_.Set("shouldOmitLinks", - session_manager::SessionManager::Get()->session_state() != - session_manager::SessionState::ACTIVE); + base::Value::Dict device_data; + if (canonical_device_address.has_value()) { + device_data.Set("address", canonical_device_address.value()); + } + device_data.Set("shouldOmitLinks", + session_manager::SessionManager::Get()->session_state() != + session_manager::SessionState::ACTIVE); + + absl::optional<std::string> args = base::WriteJson(device_data); + CHECK(args.has_value()); + set_dialog_args(*args); } BluetoothPairingDialog::~BluetoothPairingDialog() = default; @@ -115,17 +123,6 @@ params->shadow_elevation = wm::kShadowElevationActiveWindow; } -void BluetoothPairingDialog::GetDialogSize(gfx::Size* size) const { - size->SetSize(SystemWebDialogDelegate::kDialogWidth, - kBluetoothPairingDialogHeight); -} - -std::string BluetoothPairingDialog::GetDialogArgs() const { - std::string data; - base::JSONWriter::Write(device_data_, &data); - return data; -} - // BluetoothPairingUI BluetoothPairingDialogUI::BluetoothPairingDialogUI(content::WebUI* web_ui)
diff --git a/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.h b/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.h index 56aa8bf..d73a2e6 100644 --- a/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.h +++ b/chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.h
@@ -8,7 +8,6 @@ #include <string> #include "base/strings/string_piece.h" -#include "base/values.h" #include "chrome/browser/ui/webui/ash/system_web_dialog_delegate.h" #include "chrome/common/webui_url_constants.h" #include "chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-forward.h" @@ -51,15 +50,9 @@ std::string Id() override; void AdjustWidgetInitParams(views::Widget::InitParams* params) override; - // ui::WebDialogDelegate - void GetDialogSize(gfx::Size* size) const override; - std::string GetDialogArgs() const override; - // The canonical Bluetooth address of a device when pairing a specific device, // otherwise |kChromeUIBluetoothPairingURL|. std::string dialog_id_; - - base::Value::Dict device_data_; }; class BluetoothPairingDialogUI;
diff --git a/chrome/browser/ui/webui/ash/edu_coexistence/OWNERS b/chrome/browser/ui/webui/ash/edu_coexistence/OWNERS index 68c7714..c125175 100644 --- a/chrome/browser/ui/webui/ash/edu_coexistence/OWNERS +++ b/chrome/browser/ui/webui/ash/edu_coexistence/OWNERS
@@ -1,3 +1 @@ -agawronska@chromium.org -courtneywong@chromium.org -yilkal@chromium.org +file://chrome/browser/ash/child_accounts/OWNERS
diff --git a/chrome/browser/ui/webui/ash/parent_access/OWNERS b/chrome/browser/ui/webui/ash/parent_access/OWNERS index 49c4b1cc..f335ce44 100644 --- a/chrome/browser/ui/webui/ash/parent_access/OWNERS +++ b/chrome/browser/ui/webui/ash/parent_access/OWNERS
@@ -1,5 +1,4 @@ -agawronska@chromium.org -courtneywong@chromium.org +file://chrome/browser/ash/child_accounts/OWNERS per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/ash/settings/pages/system_preferences/startup_section.cc b/chrome/browser/ui/webui/ash/settings/pages/system_preferences/startup_section.cc index 6a9cc3b..fa8e5e6 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/system_preferences/startup_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/system_preferences/startup_section.cc
@@ -29,7 +29,7 @@ static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_RESTORE_APPS_AND_PAGES, section_path, - mojom::SearchResultIcon::kStartup, + mojom::SearchResultIcon::kRestore, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kRestoreAppsAndPages}, @@ -95,7 +95,7 @@ } mojom::SearchResultIcon StartupSection::GetSectionIcon() const { - return mojom::SearchResultIcon::kStartup; + return mojom::SearchResultIcon::kRestore; } const char* StartupSection::GetSectionPath() const {
diff --git a/chrome/browser/ui/webui/ash/settings/search/mojom/search_result_icon.mojom b/chrome/browser/ui/webui/ash/settings/search/mojom/search_result_icon.mojom index ca4bb8e..bbace63 100644 --- a/chrome/browser/ui/webui/ash/settings/search/mojom/search_result_icon.mojom +++ b/chrome/browser/ui/webui/ash/settings/search/mojom/search_result_icon.mojom
@@ -50,9 +50,9 @@ kPower, kPrinter, kReset, + kRestore, kSelectToSpeak, kShield, - kStartup, kStorage, kStylus, kSwitchAccess,
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc index b909f94c..3b20247 100644 --- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc +++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc
@@ -44,7 +44,7 @@ std::ignore = GetService(); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock()}, - base::BindOnce(&on_device_model::LoadModelAssets, model_path), + base::BindOnce(&on_device_model::LoadModelAssets, model_path, model_path), base::BindOnce(&OnDeviceInternalsUI::OnModelAssetsLoaded, weak_ptr_factory_.GetWeakPtr(), std::move(model), std::move(callback)));
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h index dde3fc3e..b9963e16 100644 --- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h +++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h
@@ -10,6 +10,7 @@ #include "mojo/public/cpp/bindings/receiver_set.h" #include "services/on_device_model/public/cpp/model_assets.h" #include "services/on_device_model/public/mojom/on_device_model.mojom.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" #include "ui/webui/mojo_web_ui_controller.h" // A dev UI for testing the OnDeviceModelService.
diff --git a/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc b/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc index 638e6a57..188cdf1 100644 --- a/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc +++ b/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui.cc
@@ -40,10 +40,12 @@ const std::u16string icon_path = GetGeneratedIconPath( choice->keyword(), /*parent_directory_path=*/u"images/"); - choice_value.Set("prepopulate_id", choice->prepopulate_id()); + choice_value.Set("prepopulateId", choice->prepopulate_id()); choice_value.Set("name", choice->short_name()); - choice_value.Set("icon_path", icon_path); + choice_value.Set("iconPath", icon_path); choice_value.Set("url", choice->url()); + choice_value.Set("marketingSnippet", + search_engines::GetMarketingSnippetString(choice->data())); choice_value_list.Append(std::move(choice_value)); } std::string json_choice_list; @@ -88,8 +90,6 @@ IDS_SHORT_PRODUCT_LOGO_ALT_TEXT); source->AddLocalizedString("fakeOmniboxText", IDS_SEARCH_ENGINE_CHOICE_FAKE_OMNIBOX_TEXT); - source->AddLocalizedString("fallbackMarketingSnippet", - IDS_SEARCH_ENGINE_FALLBACK_MARKETING_SNIPPET); AddGeneratedIconResources(source, /*directory=*/"images/"); source->AddResourcePath("images/left_illustration.svg", @@ -108,6 +108,8 @@ source->AddString("choiceList", GetChoiceListJSON(profile_.get())); source->AddBoolean("withMarketingSnippets", switches::kWithSearchEngineMarketingSnippets.Get()); + source->AddBoolean("withForcedScroll", + switches::kWithForcedScrollEnabled.Get()); webui::SetupChromeRefresh2023(source);
diff --git a/chrome/browser/usb/chrome_usb_browsertest.cc b/chrome/browser/usb/chrome_usb_browsertest.cc index be9daa6..1b0e3722 100644 --- a/chrome/browser/usb/chrome_usb_browsertest.cc +++ b/chrome/browser/usb/chrome_usb_browsertest.cc
@@ -635,7 +635,8 @@ IN_PROC_BROWSER_TEST_F(IsolatedWebAppUsbBrowserTest, ClaimInterface) { // Verifies that non-IWA main frames and cross-origin iframes in an IWA can // access normal USB devices, but not devices from a protected class. IWA - // frames can access both. + // frames without usb-unrestricted permission can only access non-protected + // class too. GURL frame_url = https_server()->GetURL("/banners/isolated/simple.html"); auto* non_app_main_frame = ui_test_utils::NavigateToURL(browser(), frame_url); @@ -680,8 +681,9 @@ EXPECT_EQ("Success", EvalJs(app_frame, JsReplace(kClaimInterface, kPrinterProductId))); - EXPECT_EQ("Success", - EvalJs(app_frame, JsReplace(kClaimInterface, kSmartCardProductId))); + EXPECT_THAT( + EvalJs(app_frame, JsReplace(kClaimInterface, kSmartCardProductId)), + FailedWithSubstr("requested interface implements a protected class")); EXPECT_EQ("Success", EvalJs(non_app_main_frame, JsReplace(kClaimInterface, kPrinterProductId))); @@ -727,7 +729,7 @@ permissions_policy); auto* iframe = ChildFrameAt(app_frame, 0); - auto fake_device_info = CreateUsbDevice(device::mojom::kUsbSmartCardClass); + auto fake_device_info = CreateUsbDevice(kUsbPrinterClass); auto device_info = device_manager().AddDevice(std::move(fake_device_info)); chooser_context()->GrantDevicePermission(app_frame->GetLastCommittedOrigin(), *device_info); @@ -762,7 +764,7 @@ permissions_policy); auto* iframe = ChildFrameAt(app_frame, 0); - auto fake_device_info = CreateUsbDevice(device::mojom::kUsbSmartCardClass); + auto fake_device_info = CreateUsbDevice(kUsbPrinterClass); auto device_info = device_manager().AddDevice(std::move(fake_device_info)); chooser_context()->GrantDevicePermission(app_frame->GetLastCommittedOrigin(), *device_info); @@ -839,7 +841,7 @@ permissions_policy); auto* iframe = ChildFrameAt(app_frame, 0); - auto fake_device_info = CreateUsbDevice(device::mojom::kUsbSmartCardClass); + auto fake_device_info = CreateUsbDevice(kUsbPrinterClass); auto device_info = device_manager().AddDevice(std::move(fake_device_info)); chooser_context()->GrantDevicePermission(app_frame->GetLastCommittedOrigin(), *device_info); @@ -940,7 +942,7 @@ web_app::CreateIframe(app_frame, "child", app_url, permissions_policy); auto* iframe = ChildFrameAt(app_frame, 0); - auto fake_device_info = CreateUsbDevice(device::mojom::kUsbSmartCardClass); + auto fake_device_info = CreateUsbDevice(kUsbPrinterClass); auto device_info = device_manager().AddDevice(std::move(fake_device_info)); chooser_context()->GrantDevicePermission(app_frame->GetLastCommittedOrigin(), *device_info); @@ -995,6 +997,104 @@ EXPECT_EQ("Success", EvalJs(iframe, OpenAndClaimDeviceScript)); } +IN_PROC_BROWSER_TEST_F(IsolatedWebAppPermissionsPolicyBrowserTest, + PermissionsPolicy_Usb_Unrestricted_CrossOrigin_Iframe) { + std::unique_ptr<net::EmbeddedTestServer> isolated_web_app_dev_server = + CreateAndStartServer( + FILE_PATH_LITERAL("web_apps/unrestricted_usb_isolated_app")); + web_app::IsolatedWebAppUrlInfo url_info = InstallDevModeProxyIsolatedWebApp( + isolated_web_app_dev_server->GetOrigin()); + content::RenderFrameHost* app_frame = OpenApp(url_info.app_id()); + + // Create a fake device with protected class and grant permission. + auto fake_device_info = CreateUsbDevice(device::mojom::kUsbSmartCardClass); + auto device_info = device_manager().AddDevice(std::move(fake_device_info)); + chooser_context()->GrantDevicePermission(app_frame->GetLastCommittedOrigin(), + *device_info); + + // With "usb-unrestricted" permission, when main frame claims protected class + // device it should succeed. + EXPECT_EQ("Success", EvalJs(app_frame, OpenAndClaimDeviceScript)); + + GURL cross_origin_iframe_url = + https_server()->GetURL(kNonAppHost, "/banners/isolated/simple.html"); + + // Create a cross-origin Iframe without any permission and request to + // protected class device should be denied due to "usb" feature is not + // enabled on iframe's document. + web_app::CreateIframe(app_frame, "child0", cross_origin_iframe_url, ""); + auto* cross_origin_iframe0 = ChildFrameAt(app_frame, 0); + EXPECT_THAT( + EvalJs(cross_origin_iframe0, OpenAndClaimDeviceScript).ExtractString(), + testing::EndsWith("permissions policy.")); + + // Create a cross-origin Iframe with only "usb-unrestricted" permission, + // request to protected class device should be denied due to "usb" feature is + // not enabled on iframe's document. + web_app::CreateIframe(app_frame, "child1", cross_origin_iframe_url, + "usb-unrestricted"); + auto* cross_origin_iframe1 = ChildFrameAt(app_frame, 1); + EXPECT_THAT( + EvalJs(cross_origin_iframe1, OpenAndClaimDeviceScript).ExtractString(), + testing::EndsWith("permissions policy.")); + + // Create a cross-origin Iframe with only "usb" permission, request to + // protected class device should be denied due to "usb-unrestricted" is not + // enabled. + web_app::CreateIframe(app_frame, "child2", cross_origin_iframe_url, "usb"); + auto* cross_origin_iframe2 = ChildFrameAt(app_frame, 2); + EXPECT_THAT( + EvalJs(cross_origin_iframe2, OpenAndClaimDeviceScript).ExtractString(), + testing::EndsWith("requested interface implements a protected class.")); + + // Create a cross-origin Iframe with "usb + usb-unrestricted" and request to + // protected class device should be denied due to iframe's isolation level = + // 0. + web_app::CreateIframe(app_frame, "child3", cross_origin_iframe_url, + "usb; usb-unrestricted"); + auto* cross_origin_iframe3 = ChildFrameAt(app_frame, 3); + EXPECT_THAT( + EvalJs(cross_origin_iframe3, OpenAndClaimDeviceScript).ExtractString(), + testing::EndsWith("requested interface implements a protected class.")); +} + +IN_PROC_BROWSER_TEST_F(IsolatedWebAppPermissionsPolicyBrowserTest, + PermissionsPolicy_Usb_Unrestricted_Iframe) { + std::unique_ptr<net::EmbeddedTestServer> isolated_web_app_dev_server = + CreateAndStartServer( + FILE_PATH_LITERAL("web_apps/unrestricted_usb_isolated_app")); + web_app::IsolatedWebAppUrlInfo url_info = InstallDevModeProxyIsolatedWebApp( + isolated_web_app_dev_server->GetOrigin()); + content::RenderFrameHost* app_frame = OpenApp(url_info.app_id()); + + // Create a fake device with protected class and grant permission. + auto fake_device_info = CreateUsbDevice(device::mojom::kUsbSmartCardClass); + auto device_info = device_manager().AddDevice(std::move(fake_device_info)); + chooser_context()->GrantDevicePermission(app_frame->GetLastCommittedOrigin(), + *device_info); + + // With "usb + usb-unrestricted" permission, when main frame claims protected + // class device it should succeed. + EXPECT_EQ("Success", EvalJs(app_frame, OpenAndClaimDeviceScript)); + + // Create a same-origin iframe without any permissions in attribute, request + // to protected class device should still succeed due to "usb + + // usb-unrestricted" feature is inherited from main frame and same-origin + // iframe is still isolated. + web_app::CreateIframe(app_frame, "child0", GURL("empty.html"), ""); + auto* iframe0 = ChildFrameAt(app_frame, 0); + EXPECT_EQ("Success", EvalJs(iframe0, OpenAndClaimDeviceScript)); + + // Create a same-origin iframe with "usb-unrestricted" permissions disabled, + // request to protected class device should fail. + web_app::CreateIframe(app_frame, "child1", GURL("empty.html"), + "usb-unrestricted 'none'"); + auto* iframe1 = ChildFrameAt(app_frame, 1); + EXPECT_THAT( + EvalJs(iframe1, OpenAndClaimDeviceScript).ExtractString(), + testing::EndsWith("requested interface implements a protected class.")); +} + #if BUILDFLAG(ENABLE_EXTENSIONS) // Base Test fixture with kEnableWebUsbOnExtensionServiceWorker default // disabled.
diff --git a/chrome/browser/usb/chrome_usb_delegate.cc b/chrome/browser/usb/chrome_usb_delegate.cc index 1ed35d75..40ad0040 100644 --- a/chrome/browser/usb/chrome_usb_delegate.cc +++ b/chrome/browser/usb/chrome_usb_delegate.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/usb/usb_blocklist.h" #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/browser/usb/usb_chooser_controller.h" @@ -23,9 +24,11 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "components/permissions/object_permission_context_base.h" +#include "content/public/browser/isolated_context_util.h" #include "content/public/browser/page.h" #include "content/public/browser/render_frame_host.h" #include "services/device/public/mojom/usb_enumeration_options.mojom.h" +#include "third_party/blink/public/common/features_generated.h" #if BUILDFLAG(ENABLE_EXTENSIONS) #include "base/containers/fixed_flat_set.h" @@ -180,20 +183,13 @@ const url::Origin& origin, content::RenderFrameHost* frame, std::vector<uint8_t>& classes) { - // Isolated Apps have unrestricted access to any USB interface class. - if (frame && - frame->GetWebExposedIsolationLevel() >= - content::WebExposedIsolationLevel::kMaybeIsolatedApplication) { - // TODO(https://crbug.com/1236706): Should the list of interface classes the - // app expects to claim be encoded in the Web App Manifest? - classes.clear(); +#if BUILDFLAG(ENABLE_EXTENSIONS) + // We only adjust interfaces for extensions here. + if (origin.scheme() != extensions::kExtensionScheme) { return; } - -#if BUILDFLAG(ENABLE_EXTENSIONS) // Don't enforce protected interface classes for Chrome Apps since the // chrome.usb API has no such restriction. - if (origin.scheme() == extensions::kExtensionScheme) { auto* extension_registry = extensions::ExtensionRegistry::Get(browser_context); if (extension_registry) { @@ -204,7 +200,6 @@ return; } } - } #if BUILDFLAG(IS_CHROMEOS) // These extensions can claim the protected HID interface class (example: used @@ -248,14 +243,12 @@ "moklfjoegmpoolceggbebbmgbddlhdgp", }); - if (origin.scheme() == extensions::kExtensionScheme && - base::Contains(kHidPrivilegedExtensionIds, origin.host())) { + if (base::Contains(kHidPrivilegedExtensionIds, origin.host())) { base::Erase(classes, device::mojom::kUsbHidClass); } #endif // BUILDFLAG(IS_CHROMEOS) - if (origin.scheme() == extensions::kExtensionScheme && - base::Contains(kSmartCardPrivilegedExtensionIds, origin.host())) { + if (base::Contains(kSmartCardPrivilegedExtensionIds, origin.host())) { base::Erase(classes, device::mojom::kUsbSmartCardClass); } #endif // BUILDFLAG(ENABLE_EXTENSIONS) @@ -328,13 +321,30 @@ bool ChromeUsbDelegate::HasDevicePermission( content::BrowserContext* browser_context, + content::RenderFrameHost* frame, const url::Origin& origin, - const device::mojom::UsbDeviceInfo& device) { - if (IsDevicePermissionAutoGranted(origin, device)) + const device::mojom::UsbDeviceInfo& device_info) { + if (IsDevicePermissionAutoGranted(origin, device_info)) { return true; + } + + // Isolated context with permission to access the policy-controlled feature + // "usb-unrestricted" can bypass the USB blocklist. + bool is_usb_unrestricted = false; + if (base::FeatureList::IsEnabled(blink::features::kUnrestrictedUsb)) { + is_usb_unrestricted = + frame && + frame->IsFeatureEnabled( + blink::mojom::PermissionsPolicyFeature::kUsbUnrestricted) && + content::HasIsolatedContextCapability(frame); + } + + if (!is_usb_unrestricted && UsbBlocklist::Get().IsExcluded(device_info)) { + return false; + } return browser_context && GetChooserContext(browser_context) - ->HasDevicePermission(origin, device); + ->HasDevicePermission(origin, device_info); } void ChromeUsbDelegate::GetDevices(
diff --git a/chrome/browser/usb/chrome_usb_delegate.h b/chrome/browser/usb/chrome_usb_delegate.h index 566e02e0..0f8281c 100644 --- a/chrome/browser/usb/chrome_usb_delegate.h +++ b/chrome/browser/usb/chrome_usb_delegate.h
@@ -47,9 +47,11 @@ const device::mojom::UsbDeviceInfo* GetDeviceInfo( content::BrowserContext* browser_context, const std::string& guid) override; - bool HasDevicePermission(content::BrowserContext* browser_context, - const url::Origin& origin, - const device::mojom::UsbDeviceInfo& device) override; + bool HasDevicePermission( + content::BrowserContext* browser_context, + content::RenderFrameHost* frame, + const url::Origin& origin, + const device::mojom::UsbDeviceInfo& device_info) override; void GetDevices( content::BrowserContext* browser_context, blink::mojom::WebUsbService::GetDevicesCallback callback) override;
diff --git a/chrome/browser/usb/chrome_usb_delegate_unittest.cc b/chrome/browser/usb/chrome_usb_delegate_unittest.cc index 1218dcb..7911ea9 100644 --- a/chrome/browser/usb/chrome_usb_delegate_unittest.cc +++ b/chrome/browser/usb/chrome_usb_delegate_unittest.cc
@@ -1024,7 +1024,8 @@ EXPECT_FALSE(chrome_usb_delegate.CanRequestDevicePermission( /*browser_context=*/nullptr, origin)); EXPECT_FALSE(chrome_usb_delegate.HasDevicePermission( - /*browser_context=*/nullptr, origin, device::mojom::UsbDeviceInfo())); + /*browser_context=*/nullptr, /*frame=*/nullptr, origin, + device::mojom::UsbDeviceInfo())); EXPECT_EQ(nullptr, chrome_usb_delegate.GetDeviceInfo( /*browser_context=*/nullptr, base::Uuid::GenerateRandomV4().AsLowercaseString()));
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc index 1dcb161..9b9dcf6b 100644 --- a/chrome/browser/usb/usb_chooser_context.cc +++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -20,7 +20,6 @@ #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/usb/usb_blocklist.h" #include "chrome/browser/usb/web_usb_histograms.h" #include "chrome/grit/generated_resources.h" #include "components/content_settings/core/common/content_settings.h" @@ -516,8 +515,6 @@ bool UsbChooserContext::HasDevicePermission( const url::Origin& origin, const device::mojom::UsbDeviceInfo& device_info) { - if (UsbBlocklist::Get().IsExcluded(device_info)) - return false; if (usb_policy_allowed_devices_->IsDeviceAllowed(origin, device_info)) { return true;
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc index bc7e78b2..58aafad 100644 --- a/chrome/browser/usb/usb_chooser_controller.cc +++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -21,10 +21,12 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "components/strings/grit/components_strings.h" +#include "content/public/browser/isolated_context_util.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "services/device/public/cpp/usb/usb_utils.h" #include "services/device/public/mojom/usb_enumeration_options.mojom.h" +#include "third_party/blink/public/common/features_generated.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -272,8 +274,19 @@ return false; } - if (UsbBlocklist::Get().IsExcluded(device_info)) + bool is_usb_unrestricted = false; + if (base::FeatureList::IsEnabled(blink::features::kUnrestrictedUsb)) { + is_usb_unrestricted = + requesting_frame_ && + requesting_frame_->IsFeatureEnabled( + blink::mojom::PermissionsPolicyFeature::kUsbUnrestricted) && + content::HasIsolatedContextCapability(requesting_frame_); + } + // Isolated context with permission to access the policy-controlled feature + // "usb-unrestricted" can bypass the USB blocklist. + if (!is_usb_unrestricted && UsbBlocklist::Get().IsExcluded(device_info)) { return false; + } return true; }
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 18b365c..734647ab 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1701259184-389d0bec5ee3143b8568f5dcf03eaa13b5c56ede.profdata +chrome-android32-main-1701280711-9b97f76fcb8d08d9afa748fcc659c93d40e002c5.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index d5f650be..b3f7b76 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1701259184-57903b32eb4c7aa0f76f2cac574624ac2a604ff3.profdata +chrome-android64-main-1701280711-2764b0f647e441f0f7b85a745602672b42ca2445.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 0cc16fa0..971efc3 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1701266367-b4159cc76487839a28bfa5a638ef38b8c1f79966.profdata +chrome-mac-arm-main-1701273439-b3af7d5cd39986d000e24b087fdd88f9c56ba121.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index f0b1b0e..a8da208 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1701259184-dc35f20ec3b93f878a6d3f4a3e47e4d8d371f844.profdata +chrome-win32-main-1701269830-861308b97bff8eaa520690eac8c5fbfe5dcb1621.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 716a37c..a5af79e 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1701248368-fcf3783c91490c42746c61746fbf0364372a7676.profdata +chrome-win64-main-1701259184-7329774ee088b0317a0eec4d9134dc7a136057e1.profdata
diff --git a/chrome/chrome_repack_locales.gni b/chrome/chrome_repack_locales.gni index fdb87c7..c43aa58 100644 --- a/chrome/chrome_repack_locales.gni +++ b/chrome/chrome_repack_locales.gni
@@ -93,6 +93,10 @@ [ "${root_gen_dir}/chromeos/strings/chromeos_strings_" ] deps += [ "//chromeos/strings" ] } + if (!is_android) { + source_patterns += [ "${root_gen_dir}/components/strings/search_engine_descriptions_strings_" ] + deps += [ "//components/strings:search_engine_descriptions_strings" ] + } if (enable_extensions) { source_patterns += [ "${root_gen_dir}/extensions/strings/extensions_strings_" ]
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 8574638a..ad52289 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6537,7 +6537,10 @@ } if (enable_search_engine_choice) { - sources += [ "../browser/search_engine_choice/search_engine_choice_service_unittest.cc" ] + sources += [ + "../browser/search_engine_choice/search_engine_choice_client_side_trial_unittest.cc", + "../browser/search_engine_choice/search_engine_choice_service_unittest.cc", + ] } if (is_linux) { @@ -9851,10 +9854,15 @@ if (is_linux || is_win || is_mac) { sources += [ "../browser/ui/views/media_preview/camera_preview/camera_coordinator_unittest.cc", + "../browser/ui/views/media_preview/camera_preview/video_stream_coordinator_unittest.cc", "../browser/ui/views/media_preview/media_view_controller_base_unittest.cc", "../browser/ui/views/policy/enterprise_startup_dialog_unittest.cc", ] - deps += [ "//components/media_effects/test:test_support" ] + + deps += [ + "//components/media_effects/test:test_support", + "//services/video_capture/public/cpp:mocks", + ] } deps += [ "//components/enterprise:test_support" ]
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java index 56c5cb17..8ced6ce 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -210,7 +210,7 @@ ChromeTabUtils.waitForTabPageLoaded(tab, (String) null); if (tab != null - && UrlUtilities.isNTPUrl(ChromeTabUtils.getUrlStringOnUiThread(tab)) + && UrlUtilities.isNtpUrl(ChromeTabUtils.getUrlStringOnUiThread(tab)) && !getActivity().isInOverviewMode()) { NewTabPageTestUtils.waitForNtpLoaded(tab); }
diff --git a/chrome/test/data/web_apps/unrestricted_usb_isolated_app/256x256-green.png b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/256x256-green.png new file mode 100644 index 0000000..b644451 --- /dev/null +++ b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/256x256-green.png Binary files differ
diff --git a/chrome/test/data/web_apps/unrestricted_usb_isolated_app/empty.html b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/empty.html new file mode 100644 index 0000000..a006713 --- /dev/null +++ b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/empty.html
@@ -0,0 +1 @@ +Empty page.
diff --git a/chrome/test/data/web_apps/unrestricted_usb_isolated_app/index.html b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/index.html new file mode 100644 index 0000000..8223fb9c --- /dev/null +++ b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/index.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> +<html> +<head> + <title>Unrestricted USB Isolated App</title> +</head> +<body></body> +</html>
diff --git a/chrome/test/data/web_apps/unrestricted_usb_isolated_app/manifest.webmanifest b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/manifest.webmanifest new file mode 100644 index 0000000..78a744e --- /dev/null +++ b/chrome/test/data/web_apps/unrestricted_usb_isolated_app/manifest.webmanifest
@@ -0,0 +1,20 @@ +{ + "name": "Unrestricted USB Isolated App", + "version": "1.0.0", + "id": "/", + "scope": "/", + "start_url": "/index.html", + "display": "standalone", + "permissions_policy": { + "cross-origin-isolated": [ "*" ], + "usb": [ "*" ], + "usb-unrestricted": [ "*" ] + }, + "icons": [ + { + "src": "256x256-green.png", + "sizes": "256x256", + "type": "image/png" + } + ] +}
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 44795610..34ef91c 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -293,7 +293,7 @@ "test_mock.ts", "test_open_window_proxy.ts", "test_plural_string_proxy.ts", - "test_store_ts.ts", + "test_store.ts", "test_util.ts", "trusted_html.ts", ]
diff --git a/chrome/test/data/webui/bookmarks/test_store.ts b/chrome/test/data/webui/bookmarks/test_store.ts index d62c06974..9125d422 100644 --- a/chrome/test/data/webui/bookmarks/test_store.ts +++ b/chrome/test/data/webui/bookmarks/test_store.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {BookmarksPageState, createEmptyState, reduceAction, Store} from 'chrome://bookmarks/bookmarks.js'; -import {TestStore as CrUiTestStore} from 'chrome://webui-test/test_store_ts.js'; +import {TestStore as CrUiTestStore} from 'chrome://webui-test/test_store.js'; export class TestStore extends CrUiTestStore<BookmarksPageState> { constructor(data: any) {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_personalization_store.ts b/chrome/test/data/webui/chromeos/personalization_app/test_personalization_store.ts index ff14c193..55ce964 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/test_personalization_store.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/test_personalization_store.ts
@@ -8,7 +8,7 @@ */ import {Actions, emptyState, PersonalizationState, PersonalizationStore, reduce} from 'chrome://personalization/js/personalization_app.js'; -import {TestStore} from 'chrome://webui-test/test_store_ts.js'; +import {TestStore} from 'chrome://webui-test/test_store.js'; /** * Records actions and states observed during a test run. A Personalization App
diff --git a/chrome/test/data/webui/cr_elements/store_client_test.ts b/chrome/test/data/webui/cr_elements/store_client_test.ts index ec6b4c1f..eac0ce6 100644 --- a/chrome/test/data/webui/cr_elements/store_client_test.ts +++ b/chrome/test/data/webui/cr_elements/store_client_test.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {makeStoreClientMixin} from 'chrome://resources/cr_elements/store_client/store_client.js'; -import {Action, Store} from 'chrome://resources/js/store_ts.js'; +import {Action, Store} from 'chrome://resources/js/store.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
diff --git a/chrome/test/data/webui/js/store_test.ts b/chrome/test/data/webui/js/store_test.ts index d8e47b93..16f1c8cc 100644 --- a/chrome/test/data/webui/js/store_test.ts +++ b/chrome/test/data/webui/js/store_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 {Action, Store, StoreObserver} from 'chrome://resources/js/store_ts.js'; +import {Action, Store, StoreObserver} from 'chrome://resources/js/store.js'; import {assertDeepEquals, assertEquals, assertFalse} from 'chrome://webui-test/chai_assert.js'; interface TestState {
diff --git a/chrome/test/data/webui/search_engine_choice/search_engine_choice_js_browsertest.cc b/chrome/test/data/webui/search_engine_choice/search_engine_choice_js_browsertest.cc index ea69bf02..a2ae76c 100644 --- a/chrome/test/data/webui/search_engine_choice/search_engine_choice_js_browsertest.cc +++ b/chrome/test/data/webui/search_engine_choice/search_engine_choice_js_browsertest.cc
@@ -14,15 +14,16 @@ protected: SearchEngineChoiceJsBrowserTest() { set_test_loader_host(chrome::kChromeUISearchEngineChoiceHost); + scoped_feature_list_.InitAndEnableFeatureWithParameters( + switches::kSearchEngineChoice, + {{switches::kWithForcedScrollEnabled.name, "false"}}); } void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitchASCII(switches::kSearchEngineChoiceCountry, "BE"); } - private: - base::test::ScopedFeatureList scoped_feature_list_{ - switches::kSearchEngineChoice}; + base::test::ScopedFeatureList scoped_feature_list_; base::AutoReset<bool> scoped_chrome_build_override_ = SearchEngineChoiceServiceFactory::ScopedChromeBuildOverrideForTesting( /*force_chrome_build=*/true); @@ -32,3 +33,19 @@ SearchEngineChoiceTest) { RunTest("search_engine_choice/search_engine_choice_test.js", "mocha.run()"); } + +class SearchEngineChoiceJsBrowserTestWithForcedScroll + : public SearchEngineChoiceJsBrowserTest { + protected: + SearchEngineChoiceJsBrowserTestWithForcedScroll() { + scoped_feature_list_.Reset(); + scoped_feature_list_.InitAndEnableFeatureWithParameters( + switches::kSearchEngineChoice, + {{switches::kWithForcedScrollEnabled.name, "true"}}); + } +}; + +IN_PROC_BROWSER_TEST_F(SearchEngineChoiceJsBrowserTestWithForcedScroll, + SearchEngineChoiceTest) { + RunTest("search_engine_choice/search_engine_choice_test.js", "mocha.run()"); +}
diff --git a/chrome/test/data/webui/search_engine_choice/search_engine_choice_test.ts b/chrome/test/data/webui/search_engine_choice/search_engine_choice_test.ts index 8df6632..844e6f3 100644 --- a/chrome/test/data/webui/search_engine_choice/search_engine_choice_test.ts +++ b/chrome/test/data/webui/search_engine_choice/search_engine_choice_test.ts
@@ -4,6 +4,7 @@ import 'chrome://search-engine-choice/app.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {SearchEngineChoiceAppElement} from 'chrome://search-engine-choice/app.js'; import {SearchEngineChoiceBrowserProxy} from 'chrome://search-engine-choice/browser_proxy.js'; import {PageHandlerRemote} from 'chrome://search-engine-choice/search_engine_choice.mojom-webui.js'; @@ -30,13 +31,24 @@ testElement.remove(); }); - // Selects the first search engine from the list of search engine choices. - function selectChoice() { + // Selects the first search engine from the list of search engine choices and + // scrolls to the bottom of the list when the forced scroll feature is + // enabled. + async function selectChoice() { const radioButtons = testElement.shadowRoot!.querySelectorAll('cr-radio-button'); assertTrue(radioButtons.length > 0); radioButtons[0]!.click(); + + if (loadTimeData.getBoolean('withForcedScroll')) { + assertTrue(testElement.$.submitButton.disabled); + + const choiceList = testElement.$.choiceList; + choiceList.scrollTop = choiceList.scrollHeight - choiceList.clientHeight; + choiceList.dispatchEvent(new CustomEvent('scroll')); + await waitBeforeNextRender(testElement); + } } test('Submit button enabled on choice click', function() {
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/test_store.ts b/chrome/test/data/webui/settings/chromeos/app_management/test_store.ts index 49d0c2c..ab82606 100644 --- a/chrome/test/data/webui/settings/chromeos/app_management/test_store.ts +++ b/chrome/test/data/webui/settings/chromeos/app_management/test_store.ts
@@ -4,7 +4,7 @@ import {AppManagementActions, AppManagementPageState, AppManagementStore, reduceAction} from 'chrome://os-settings/os_settings.js'; import {createEmptyState} from 'chrome://resources/cr_components/app_management/util.js'; -import {TestStore} from 'chrome://webui-test/test_store_ts.js'; +import {TestStore} from 'chrome://webui-test/test_store.js'; export class TestAppManagementStore extends TestStore<AppManagementPageState, AppManagementActions> {
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/customize_button_select_test.ts b/chrome/test/data/webui/settings/chromeos/device_page/customize_button_select_test.ts index 6d988c6..713bf72 100644 --- a/chrome/test/data/webui/settings/chromeos/device_page/customize_button_select_test.ts +++ b/chrome/test/data/webui/settings/chromeos/device_page/customize_button_select_test.ts
@@ -95,7 +95,7 @@ assertEquals(getSelectedValue(), 'key combination'); assertTrue(select.get('remappedToKeyCombination_')); assertEquals(select.get('label_'), 'Key combination'); - assertDeepEquals(select.get('inputKeys_'), ['ctrl', '+', 'z']); + assertDeepEquals(select.get('inputKeys_'), ['Ctrl', '+', 'z']); // Switch to another button remapping. select.set( @@ -107,7 +107,7 @@ assertEquals(getSelectedValue(), 'key combination'); assertTrue(select.get('remappedToKeyCombination_')); assertEquals(select.get('label_'), 'Key combination'); - assertDeepEquals(select.get('inputKeys_'), ['ctrl', '+', 'v']); + assertDeepEquals(select.get('inputKeys_'), ['Ctrl', '+', 'v']); }); test('update dropdown will sent events', async () => {
diff --git a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js index 67a27d2..85e9e3a 100644 --- a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
@@ -37,6 +37,7 @@ 'chrome://resources/images/throbber_small_dark.svg'; setup(function() { + loadTimeData.overrideValues({isRevampWayfindingEnabled: false}); userActionRecorder = new FakeUserActionRecorder(); setUserActionRecorderForTesting(userActionRecorder);
diff --git a/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/main_view_test.ts b/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/main_view_test.ts index 220b31f6..030dc394 100644 --- a/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/main_view_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/main_view_test.ts
@@ -7,7 +7,7 @@ import {AppManagementMainViewElement} from 'chrome://os-settings/lazy_load.js'; import {AppManagementActions, AppManagementPageState, Router} from 'chrome://os-settings/os_settings.js'; import {assertEquals, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {TestStore} from 'chrome://webui-test/test_store_ts.js'; +import {TestStore} from 'chrome://webui-test/test_store.js'; import {FakePageHandler} from '../../app_management/fake_page_handler.js'; import {replaceBody, replaceStore, setupFakeHandler} from '../../app_management/test_util.js';
diff --git a/chrome/test/data/webui/test_store_ts.ts b/chrome/test/data/webui/test_store.ts similarity index 97% rename from chrome/test/data/webui/test_store_ts.ts rename to chrome/test/data/webui/test_store.ts index f536420..4d982ae 100644 --- a/chrome/test/data/webui/test_store_ts.ts +++ b/chrome/test/data/webui/test_store.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 {Action, Store} from 'chrome://resources/js/store_ts.js'; +import {Action, Store} from 'chrome://resources/js/store.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js'; import {assertTrue} from './chai_assert.js';
diff --git a/chrome/utility/safe_browsing/seven_zip_analyzer.cc b/chrome/utility/safe_browsing/seven_zip_analyzer.cc index 23214af..9a3f4422 100644 --- a/chrome/utility/safe_browsing/seven_zip_analyzer.cc +++ b/chrome/utility/safe_browsing/seven_zip_analyzer.cc
@@ -72,8 +72,6 @@ bool SevenZipAnalyzer::EntryDone(seven_zip::Result result, const seven_zip::EntryInfo& entry) { - base::UmaHistogramEnumeration("SBClientDownload.SevenZipEntryResult", result); - // Since unpacking an encrypted entry is expected to fail, allow all results // here for encrypted entries. if (result == seven_zip::Result::kSuccess || entry.is_encrypted) {
diff --git a/chromeos/ash/components/audio/audio_device_selection_test_base.cc b/chromeos/ash/components/audio/audio_device_selection_test_base.cc index 512d39f..019ba32 100644 --- a/chromeos/ash/components/audio/audio_device_selection_test_base.cc +++ b/chromeos/ash/components/audio/audio_device_selection_test_base.cc
@@ -81,6 +81,11 @@ } } +void AudioDeviceSelectionTestBase::SystemBootsWith( + const AudioNodeList& new_nodes) { + fake_cras_audio_client_->SetAudioNodesAndNotifyObserversForTesting(new_nodes); +} + uint64_t AudioDeviceSelectionTestBase::ActiveInputNodeId() { return active_node_observer_->GetActiveInputNodeId(); }
diff --git a/chromeos/ash/components/audio/audio_device_selection_test_base.h b/chromeos/ash/components/audio/audio_device_selection_test_base.h index 6a5541f..53d0046 100644 --- a/chromeos/ash/components/audio/audio_device_selection_test_base.h +++ b/chromeos/ash/components/audio/audio_device_selection_test_base.h
@@ -43,6 +43,8 @@ void Unplug(const AudioNode& node); void Select(const AudioNode& node); + void SystemBootsWith(const AudioNodeList& new_nodes); + uint64_t ActiveInputNodeId(); uint64_t ActiveOutputNodeId();
diff --git a/chromeos/ash/components/audio/audio_device_selection_unittest.cc b/chromeos/ash/components/audio/audio_device_selection_unittest.cc index a03dfcd..d7da293 100644 --- a/chromeos/ash/components/audio/audio_device_selection_unittest.cc +++ b/chromeos/ash/components/audio/audio_device_selection_unittest.cc
@@ -346,6 +346,28 @@ expected_system_not_switch_output_count); } +TEST_F(AudioDeviceSelectionTest, SystemBootsHistogramMetrics) { + AudioNode input_internal = NewInputNode("INTERNAL_MIC"); + AudioNode input_USB = NewInputNode("USB"); + AudioNode output_internal = NewOutputNode("INTERNAL_SPEAKER"); + AudioNode output_USB = NewOutputNode("USB"); + + uint16_t expected_system_switch_input_count = 0; + uint16_t expected_system_not_switch_input_count = 0; + uint16_t expected_system_switch_output_count = 0; + uint16_t expected_system_not_switch_output_count = 0; + + // System boots with multiple audio devices. + // Expect to record system has switched both input and output. + SystemBootsWith({input_internal, input_USB, output_internal, output_USB}); + + ExpectSystemDecisionHistogramCount(histogram_tester(), + ++expected_system_switch_input_count, + expected_system_not_switch_input_count, + ++expected_system_switch_output_count, + expected_system_not_switch_output_count); +} + TEST_F(AudioDeviceSelectionTest, DevicePrefEviction) { base::test::ScopedFeatureList features( ash::features::kRobustAudioDeviceSelectLogic);
diff --git a/chromeos/ash/components/cryptohome/userdataauth_util.cc b/chromeos/ash/components/cryptohome/userdataauth_util.cc index 6e2f6e08..71292d7 100644 --- a/chromeos/ash/components/cryptohome/userdataauth_util.cc +++ b/chromeos/ash/components/cryptohome/userdataauth_util.cc
@@ -72,6 +72,9 @@ ReplyToCryptohomeError(const absl::optional<CreatePersistentUserReply>&); template COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_CRYPTOHOME) CryptohomeErrorCode + ReplyToCryptohomeError(const absl::optional<RestoreDeviceKeyReply>&); +template COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_CRYPTOHOME) + CryptohomeErrorCode ReplyToCryptohomeError(const absl::optional<PrepareGuestVaultReply>&); template COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_CRYPTOHOME) CryptohomeErrorCode
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc index eb2ce093..4793c91 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
@@ -1041,6 +1041,48 @@ cryptohome::kAuthsessionInitialLifetime.InSeconds()); } +void FakeUserDataAuthClient::RestoreDeviceKey( + const ::user_data_auth::RestoreDeviceKeyRequest& request, + RestoreDeviceKeyCallback callback) { + ::user_data_auth::RestoreDeviceKeyReply reply; + ReplyOnReturn auto_reply(&reply, std::move(callback)); + RememberRequest<Operation::kRestoreDeviceKey>(request); + + if (auto error = TakeOperationError(Operation::kRestoreDeviceKey); + error != CryptohomeErrorCode::CRYPTOHOME_ERROR_NOT_SET) { + reply.set_error(error); + return; + } + + auto error = CryptohomeErrorCode::CRYPTOHOME_ERROR_NOT_SET; + auto* authenticated_auth_session = + GetAuthenticatedAuthSession(request.auth_session_id(), &error); + + if (authenticated_auth_session == nullptr) { + reply.set_error(error); + return; + } + + if (authenticated_auth_session->ephemeral) { + LOG(ERROR) << "Ephemeral AuthSession used with RestoreDeviceKey"; + reply.set_error(CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT); + return; + } + + const auto user_it = users_.find(authenticated_auth_session->account); + if (user_it == std::end(users_)) { + reply.set_error(CryptohomeErrorCode::CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND); + return; + } + + if (!authenticated_auth_session->authorized_auth_session_intent.Has( + user_data_auth::AUTH_INTENT_DECRYPT)) { + reply.set_error( + CryptohomeErrorCode::CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION); + return; + } +} + void FakeUserDataAuthClient::PreparePersistentVault( const ::user_data_auth::PreparePersistentVaultRequest& request, PreparePersistentVaultCallback callback) {
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h index 25dd328..c3578f9e 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h
@@ -36,6 +36,7 @@ kAuthenticateAuthFactor, kPrepareGuestVault, kPrepareEphemeralVault, + kRestoreDeviceKey, kCreatePersistentUser, kPreparePersistentVault, kPrepareVaultForMigration, @@ -243,6 +244,9 @@ void CreatePersistentUser( const ::user_data_auth::CreatePersistentUserRequest& request, CreatePersistentUserCallback callback) override; + void RestoreDeviceKey( + const ::user_data_auth::RestoreDeviceKeyRequest& request, + RestoreDeviceKeyCallback callback) override; void PreparePersistentVault( const ::user_data_auth::PreparePersistentVaultRequest& request, PreparePersistentVaultCallback callback) override; @@ -308,6 +312,7 @@ FUDAC_OPERATION_TYPES(kPrepareGuestVault, PrepareGuestVaultRequest); FUDAC_OPERATION_TYPES(kPrepareEphemeralVault, PrepareEphemeralVaultRequest); FUDAC_OPERATION_TYPES(kCreatePersistentUser, CreatePersistentUserRequest); + FUDAC_OPERATION_TYPES(kRestoreDeviceKey, RestoreDeviceKeyRequest); FUDAC_OPERATION_TYPES(kPreparePersistentVault, PreparePersistentVaultRequest); FUDAC_OPERATION_TYPES(kPrepareVaultForMigration, PrepareVaultForMigrationRequest);
diff --git a/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h index ab4e1909..62acf55 100644 --- a/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h
@@ -82,6 +82,11 @@ CreatePersistentUserCallback callback), (override)); MOCK_METHOD(void, + RestoreDeviceKey, + (const ::user_data_auth::RestoreDeviceKeyRequest& request, + RestoreDeviceKeyCallback callback), + (override)); + MOCK_METHOD(void, PreparePersistentVault, (const ::user_data_auth::PreparePersistentVaultRequest& request, PreparePersistentVaultCallback callback),
diff --git a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc index 9d93802..ee9ce557 100644 --- a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc +++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc
@@ -189,6 +189,14 @@ std::move(callback)); } + void RestoreDeviceKey( + const ::user_data_auth::RestoreDeviceKeyRequest& request, + RestoreDeviceKeyCallback callback) override { + CallProtoMethod(::user_data_auth::kRestoreDeviceKey, + ::user_data_auth::kUserDataAuthInterface, request, + std::move(callback)); + } + void PreparePersistentVault( const ::user_data_auth::PreparePersistentVaultRequest& request, PreparePersistentVaultCallback callback) override {
diff --git a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h index e02a084..942d8bae 100644 --- a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h
@@ -96,6 +96,8 @@ ::user_data_auth::PrepareEphemeralVaultReply>; using CreatePersistentUserCallback = chromeos::DBusMethodCallback<::user_data_auth::CreatePersistentUserReply>; + using RestoreDeviceKeyCallback = + chromeos::DBusMethodCallback<::user_data_auth::RestoreDeviceKeyReply>; using PreparePersistentVaultCallback = chromeos::DBusMethodCallback< ::user_data_auth::PreparePersistentVaultReply>; using PrepareVaultForMigrationCallback = chromeos::DBusMethodCallback< @@ -213,6 +215,13 @@ const ::user_data_auth::CreatePersistentUserRequest& request, CreatePersistentUserCallback callback) = 0; + // This will restore the filesystem keyset user directories needed to store + // keys and download policies. This will be called during lock screen if the + // device key is evicted. + virtual void RestoreDeviceKey( + const ::user_data_auth::RestoreDeviceKeyRequest& request, + RestoreDeviceKeyCallback callback) = 0; + // This makes available user directories for them to use. virtual void PreparePersistentVault( const ::user_data_auth::PreparePersistentVaultRequest& request,
diff --git a/chromeos/ash/components/growth/campaigns_manager.cc b/chromeos/ash/components/growth/campaigns_manager.cc index 7ae289a..3368b7b1 100644 --- a/chromeos/ash/components/growth/campaigns_manager.cc +++ b/chromeos/ash/components/growth/campaigns_manager.cc
@@ -35,7 +35,7 @@ absl::optional<base::Value> value(base::JSONReader::Read(campaigns_data)); if (!value || !value->is_dict()) { - LOG(ERROR) << "Failed to parse campaigns file: " << campaigns_data; + LOG(ERROR) << "Failed to parse campaigns file."; RecordCampaignsManagerError(CampaignsManagerError::kCampaignsParsingFail); return absl::nullopt; }
diff --git a/chromeos/ash/components/growth/campaigns_manager_unittest.cc b/chromeos/ash/components/growth/campaigns_manager_unittest.cc index ae24270..3e7ad516 100644 --- a/chromeos/ash/components/growth/campaigns_manager_unittest.cc +++ b/chromeos/ash/components/growth/campaigns_manager_unittest.cc
@@ -856,9 +856,51 @@ } TEST_F(CampaignsManagerTest, GetSchedulingCampaignInvalidTargeting) { - LoadComponentWithScheduling("test"); + base::HistogramTester histogram_tester; + + LoadComponentWithScheduling("1"); ASSERT_EQ(nullptr, campaigns_manager_->GetCampaignBySlot(Slot::kDemoModeApp)); + + histogram_tester.ExpectBucketCount( + kCampaignsManagerErrorHistogramName, + CampaignsManagerError::kInvalidSchedulingTargeting, + /*count=*/1); + + histogram_tester.ExpectBucketCount(kCampaignsManagerErrorHistogramName, + CampaignsManagerError::kInvalidCampaign, + /*count=*/1); + + histogram_tester.ExpectBucketCount(kCampaignsManagerErrorHistogramName, + CampaignsManagerError::kInvalidTargeting, + /*count=*/1); +} + +TEST_F(CampaignsManagerTest, GetSchedulingCampaignInvalidScheduling) { + base::HistogramTester histogram_tester; + + LoadComponentWithScheduling(R"([ + "test1", + "test2", + {"end": 1} + ])"); + + ASSERT_EQ(nullptr, campaigns_manager_->GetCampaignBySlot(Slot::kDemoModeApp)); + + // Verify that two of the scheduling is invalids. + histogram_tester.ExpectBucketCount(kCampaignsManagerErrorHistogramName, + CampaignsManagerError::kInvalidScheduling, + /*count=*/2); + + // There is a invalid campaign in the list of campaigns. + histogram_tester.ExpectBucketCount(kCampaignsManagerErrorHistogramName, + CampaignsManagerError::kInvalidCampaign, + /*count=*/1); + + // There is a campaign with invalid targeting in the list of campaigns. + histogram_tester.ExpectBucketCount(kCampaignsManagerErrorHistogramName, + CampaignsManagerError::kInvalidTargeting, + /*count=*/1); } } // namespace growth
diff --git a/chromeos/ash/components/growth/campaigns_model.cc b/chromeos/ash/components/growth/campaigns_model.cc index eaf8e7c..2e1c6fd2 100644 --- a/chromeos/ash/components/growth/campaigns_model.cc +++ b/chromeos/ash/components/growth/campaigns_model.cc
@@ -10,6 +10,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" +#include "chromeos/ash/components/growth/growth_metrics.h" namespace growth { namespace { @@ -210,12 +211,14 @@ auto* scheduling_dicts = GetListCriteria(kSchedulingTargetings); if (!scheduling_dicts) { LOG(ERROR) << "Invalid scheduling targetings"; - // TODO(b/309005344): Records invalid scheduling error. + RecordCampaignsManagerError( + CampaignsManagerError::kInvalidSchedulingTargeting); return schedulings; } for (auto& scheduling_dict : *scheduling_dicts) { if (!scheduling_dict.is_dict()) { + RecordCampaignsManagerError(CampaignsManagerError::kInvalidScheduling); continue; } schedulings.push_back(
diff --git a/chromeos/ash/components/growth/growth_metrics.h b/chromeos/ash/components/growth/growth_metrics.h index 0a0221be..c9f8e1ca 100644 --- a/chromeos/ash/components/growth/growth_metrics.h +++ b/chromeos/ash/components/growth/growth_metrics.h
@@ -5,12 +5,14 @@ #ifndef CHROMEOS_ASH_COMPONENTS_GROWTH_GROWTH_METRICS_H_ #define CHROMEOS_ASH_COMPONENTS_GROWTH_GROWTH_METRICS_H_ +#include "base/component_export.h" + namespace growth { // These enum values represent user-facing errors in the campaigns loading and // matching flow. Entries should not be renumbered and numeric values should // never be reused. Please keep in sync with "CampaignsManagerError" in -// src/tools/metrics/histograms/enums.xml. +// src/tools/metrics/histograms/metadata/ash/enums.xml. enum class CampaignsManagerError { kCampaignsComponentLoadFail = 0, kCampaignsFileLoadFail = 1, @@ -18,11 +20,16 @@ kUserPrefUnavailableAtMatching = 3, kInvalidCampaign = 4, kInvalidTargeting = 5, + kInvalidSchedulingTargeting = 6, + kInvalidScheduling = 7, + kDemoModeAppVersionUnavailable = 8, + kSerializingDemoModePayloadFail = 9, - kMaxValue = kInvalidTargeting, + kMaxValue = kSerializingDemoModePayloadFail, }; // Records errors encountered during the campaigns loading and matching flow. +COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_GROWTH) void RecordCampaignsManagerError(CampaignsManagerError error_code); } // namespace growth
diff --git a/chromeos/ash/components/login/auth/auth_session_authenticator.cc b/chromeos/ash/components/login/auth/auth_session_authenticator.cc index 07a77a5..e4504f3 100644 --- a/chromeos/ash/components/login/auth/auth_session_authenticator.cc +++ b/chromeos/ash/components/login/auth/auth_session_authenticator.cc
@@ -7,6 +7,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" #include "base/check.h" +#include "base/command_line.h" #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/functional/bind.h" @@ -415,8 +416,19 @@ } } + AuthSessionIntent intent = AuthSessionIntent::kVerifyOnly; + + // Full authentication is needed to restore keyset. It is only for + // non-ephemeral user sessions. + if (switches::ShouldRestoreKeyOnLockScreen() && !ephemeral) { + LOGIN_LOG(EVENT) + << "AuthenticateToUnlock starts AuthSession for decrypt to " + "restore keyset."; + intent = AuthSessionIntent::kDecrypt; + } + StartAuthSessionForLoggedIn( - ephemeral, std::move(user_context), AuthSessionIntent::kVerifyOnly, + ephemeral, std::move(user_context), intent, base::BindOnce(&AuthSessionAuthenticator::DoUnlock, weak_factory_.GetWeakPtr(), ephemeral)); } @@ -528,6 +540,11 @@ base::BindOnce(&AuthPerformer::AuthenticateUsingKnowledgeKey, auth_performer_->AsWeakPtr())); } + if (switches::ShouldRestoreKeyOnLockScreen() && !ephemeral) { + steps.push_back(base::BindOnce(&MountPerformer::RestoreEvictedVaultKey, + mount_performer_->AsWeakPtr())); + } + RunOperationChain(std::move(context), std::move(steps), std::move(success_callback), std::move(error_callback)); }
diff --git a/chromeos/ash/components/login/auth/auth_session_authenticator_unittest.cc b/chromeos/ash/components/login/auth/auth_session_authenticator_unittest.cc index c554ef9..aeab099 100644 --- a/chromeos/ash/components/login/auth/auth_session_authenticator_unittest.cc +++ b/chromeos/ash/components/login/auth/auth_session_authenticator_unittest.cc
@@ -10,7 +10,9 @@ #include <utility> #include "ash/constants/ash_features.h" +#include "ash/constants/ash_switches.h" #include "base/check.h" +#include "base/command_line.h" #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" @@ -61,6 +63,7 @@ using user_data_auth::PrepareGuestVaultReply; using user_data_auth::PreparePersistentVaultReply; using user_data_auth::RemoveReply; +using user_data_auth::RestoreDeviceKeyReply; using user_data_auth::StartAuthSessionReply; namespace ash { @@ -387,6 +390,44 @@ EXPECT_EQ(got_user_context.GetAuthSessionId(), kFirstAuthSessionId); } +// Test the `RestoreDeviceKey()` method for the key eviction on the user +// session. +TEST_P(AuthSessionAuthenticatorTest, RestoreDeviceKeyOnLockScreen) { + // Arrange. + + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kRestoreKeyOnLockScreen); + + CreateAuthenticator(); + auto user_context = std::make_unique<UserContext>( + user_manager::USER_TYPE_REGULAR, kAccountId); + user_context->SetKey(Key(kPassword)); + EXPECT_CALL(userdataauth(), + StartAuthSession(WithAccountIdAndFlags(AUTH_SESSION_FLAGS_NONE, + AUTH_INTENT_DECRYPT), + _)) + .WillOnce(ReplyWith(BuildStartReply( + kFirstAuthSessionId, /*user_exists=*/true, + /*factors=*/{PasswordFactor(kCryptohomeGaiaKeyLabel)}))); + EXPECT_CALL(userdataauth(), + AuthenticateAuthFactor( + AllOf(WithFirstAuthSessionId(), + WithPasswordFactorAuth(kCryptohomeGaiaKeyLabel)), + _)) + .WillOnce(ReplyWith(BuildAuthenticateFactorSuccessReply())); + EXPECT_CALL(userdataauth(), RestoreDeviceKey(WithFirstAuthSessionId(), _)) + .WillOnce(ReplyWith(RestoreDeviceKeyReply())); + + // Act. + authenticator().AuthenticateToUnlock(/*ephemeral=*/false, + std::move(user_context)); + const UserContext got_user_context = on_auth_success_future().Get(); + + // Assert. + EXPECT_EQ(got_user_context.GetAccountId(), kAccountId); + EXPECT_EQ(got_user_context.GetAuthSessionId(), kFirstAuthSessionId); +} + // Test the `CompleteLogin()` method in the existing regular user scenario. TEST_P(AuthSessionAuthenticatorTest, CompleteLoginRegularExisting) { // Arrange.
diff --git a/chromeos/ash/components/login/auth/mount_performer.cc b/chromeos/ash/components/login/auth/mount_performer.cc index 043bb3df..414b854 100644 --- a/chromeos/ash/components/login/auth/mount_performer.cc +++ b/chromeos/ash/components/login/auth/mount_performer.cc
@@ -51,6 +51,19 @@ std::move(context), std::move(callback))); } +void MountPerformer::RestoreEvictedVaultKey( + std::unique_ptr<UserContext> context, + AuthOperationCallback callback) { + user_data_auth::RestoreDeviceKeyRequest request; + LOGIN_LOG(EVENT) << "Restore evicted filesystem keyset"; + request.set_auth_session_id(context->GetAuthSessionId()); + + UserDataAuthClient::Get()->RestoreDeviceKey( + request, base::BindOnce(&MountPerformer::OnRestoreEvictedVaultKey, + weak_factory_.GetWeakPtr(), std::move(context), + std::move(callback))); +} + void MountPerformer::MountPersistentDirectory( std::unique_ptr<UserContext> context, AuthOperationCallback callback) { @@ -235,6 +248,23 @@ std::move(callback).Run(std::move(context), absl::nullopt); } +void MountPerformer::OnRestoreEvictedVaultKey( + std::unique_ptr<UserContext> context, + AuthOperationCallback callback, + absl::optional<user_data_auth::RestoreDeviceKeyReply> reply) { + auto error = user_data_auth::ReplyToCryptohomeError(reply); + bool is_success = !cryptohome::HasError(error); + AuthEventsRecorder::Get()->OnUserVaultPrepared( + AuthEventsRecorder::UserVaultType::kPersistent, is_success); + if (!is_success) { + LOGIN_LOG(ERROR) << "RestoreVaultKey failed with error " << error; + std::move(callback).Run(std::move(context), AuthenticationError{error}); + return; + } + CHECK(reply.has_value()); + std::move(callback).Run(std::move(context), absl::nullopt); +} + void MountPerformer::OnPreparePersistentVault( std::unique_ptr<UserContext> context, AuthOperationCallback callback,
diff --git a/chromeos/ash/components/login/auth/mount_performer.h b/chromeos/ash/components/login/auth/mount_performer.h index 5e968e96..f018147 100644 --- a/chromeos/ash/components/login/auth/mount_performer.h +++ b/chromeos/ash/components/login/auth/mount_performer.h
@@ -59,6 +59,11 @@ void MountPersistentDirectory(std::unique_ptr<UserContext> context, AuthOperationCallback callback); + // Restore evicted filesystem keyset for the user identified by auth session + // in `context`. Session should be authenticated. + void RestoreEvictedVaultKey(std::unique_ptr<UserContext> context, + AuthOperationCallback callback); + // Mounts persistent directory for the user identified by auth session in // `context` to perform dircrypto migration. // Session should be authenticated. @@ -107,6 +112,10 @@ std::unique_ptr<UserContext> context, AuthOperationCallback callback, absl::optional<user_data_auth::CreatePersistentUserReply> reply); + void OnRestoreEvictedVaultKey( + std::unique_ptr<UserContext> context, + AuthOperationCallback callback, + absl::optional<user_data_auth::RestoreDeviceKeyReply> reply); void OnPrepareGuestVault( std::unique_ptr<UserContext> context, AuthOperationCallback callback,
diff --git a/chromeos/assistant/internal b/chromeos/assistant/internal index 10ab734..610eee3 160000 --- a/chromeos/assistant/internal +++ b/chromeos/assistant/internal
@@ -1 +1 @@ -Subproject commit 10ab734474bc4ca9387c874f748cdd60c3b212f4 +Subproject commit 610eee397e5729aae646eb66551cd00df2228c6d
diff --git a/chromeos/crosapi/mojom/local_printer.mojom b/chromeos/crosapi/mojom/local_printer.mojom index 6c6167a..d7ae6c12 100644 --- a/chromeos/crosapi/mojom/local_printer.mojom +++ b/chromeos/crosapi/mojom/local_printer.mojom
@@ -271,8 +271,9 @@ // Used to specify which source(s) to observe print jobs from. [Stable, Extensible] enum PrintJobSource { - [Default] kAny, // reserved - kExtension, + [Default] kAny, // reserved + kExtension, + [MinVersion=1] kIsolatedWebApp, }; // This interface is used to notify Lacros about local printer events.
diff --git a/chromeos/profiles/arm-exp.afdo.newest.txt b/chromeos/profiles/arm-exp.afdo.newest.txt index 38710d9..66866ca9 100644 --- a/chromeos/profiles/arm-exp.afdo.newest.txt +++ b/chromeos/profiles/arm-exp.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-exp-121-6126.0-1701086572-benchmark-121.0.6152.0-r1-redacted.afdo.xz +chromeos-chrome-arm-exp-121-6126.0-1701086572-benchmark-121.0.6154.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt index 46ca3d0..5e2868f 100644 --- a/chromeos/profiles/arm.afdo.newest.txt +++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-none-121-6126.0-1701089735-benchmark-121.0.6153.0-r1-redacted.afdo.xz +chromeos-chrome-arm-none-121-6126.0-1701089735-benchmark-121.0.6154.0-r1-redacted.afdo.xz
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/chromeos/ui/frame/caption_buttons/frame_size_button.cc index 7455e2e..9c961f50 100644 --- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc +++ b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
@@ -139,6 +139,10 @@ // views::View: void OnPaint(gfx::Canvas* canvas) override { + if (!GetWidget()) { + return; + } + const double animation_value = animation_.GetCurrentValue(); if (animation_value == 0.0) { return; @@ -183,7 +187,7 @@ MultitaskMenuEntryType::kFrameSizeButtonHover; // The button `this` is associated with. Unowned. - raw_ptr<FrameSizeButton> button_; + const raw_ptr<FrameSizeButton> button_; }; BEGIN_METADATA(FrameSizeButton, PieAnimationView, views::View) @@ -317,9 +321,7 @@ } } - if (pie_animation_view_) { - pie_animation_view_->Stop(); - } + pie_animation_view_->Stop(); views::FrameCaptionButton::OnMouseReleased(event); } @@ -405,27 +407,22 @@ GetState() != views::Button::STATE_PRESSED) { // We want to continue the animation if the button was pressed while it was // already hovered, so only stop in other instances. - DCHECK(pie_animation_view_); pie_animation_view_->Stop(); } } void FrameSizeButton::Layout() { - if (pie_animation_view_) { - // Use the bounds of the inkdrop. - gfx::Rect bounds = GetLocalBounds(); - bounds.Inset(GetInkdropInsets(bounds.size())); - pie_animation_view_->SetBoundsRect(bounds); - } + // Use the bounds of the inkdrop for the pie animation. + gfx::Rect bounds = GetLocalBounds(); + bounds.Inset(GetInkdropInsets(bounds.size())); + pie_animation_view_->SetBoundsRect(bounds); views::FrameCaptionButton::Layout(); } void FrameSizeButton::OnDisplayTabletStateChanged(display::TabletState state) { if (state == display::TabletState::kEnteringTabletMode) { - if (pie_animation_view_) { - pie_animation_view_->Stop(); - } + pie_animation_view_->Stop(); long_tap_delay_timer_.Stop(); } } @@ -448,7 +445,6 @@ return; } - CHECK(pie_animation_view_); pie_animation_view_->Start(duration, entry_type); } @@ -559,9 +555,7 @@ void FrameSizeButton::SetButtonsToNormalMode( FrameSizeButtonDelegate::Animate animate) { in_snap_mode_ = false; - if (pie_animation_view_) { - pie_animation_view_->Stop(); - } + pie_animation_view_->Stop(); long_tap_delay_timer_.Stop(); delegate_->SetButtonsToNormal(animate); }
diff --git a/clank b/clank index 6af5e21..e4d96a4 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 6af5e217cc69a0ce9ad30b506c5e9be6897b5d46 +Subproject commit e4d96a442aa336f431e66b1a29d61da34f59bcb6
diff --git a/components/OWNERS b/components/OWNERS index 431c48c..fab04de 100644 --- a/components/OWNERS +++ b/components/OWNERS
@@ -45,6 +45,7 @@ per-file privacy_sandbox_strings.grdp=file://components/privacy_sandbox/OWNERS per-file reset_password_strings.grdp=file://components/safe_browsing/OWNERS per-file search_engine_choice_strings.grdp=file://chrome/browser/search_engine_choice/OWNERS +per-file search_engine_descriptions_strings.grd=file://chrome/browser/search_engine_choice/OWNERS per-file security_interstitials_strings.grdp=file://components/security_interstitials/OWNERS per-file send_tab_to_self_strings.grdp=file://components/send_tab_to_self/OWNERS per-file site_settings_strings.grdp=file://components/browser_ui/site_settings/OWNERS
diff --git a/components/android_autofill/browser/android_autofill_manager.cc b/components/android_autofill/browser/android_autofill_manager.cc index 641066b..0d51b11 100644 --- a/components/android_autofill/browser/android_autofill_manager.cc +++ b/components/android_autofill/browser/android_autofill_manager.cc
@@ -165,7 +165,7 @@ void AndroidAutofillManager::OnServerRequestError( FormSignature form_signature, - AutofillDownloadManager::RequestType request_type, + AutofillCrowdsourcingManager::RequestType request_type, int http_error) { if (auto* provider = GetAutofillProvider()) provider->OnServerQueryRequestError(this, form_signature);
diff --git a/components/android_autofill/browser/android_autofill_manager.h b/components/android_autofill/browser/android_autofill_manager.h index 798e9574..9ef74e9a 100644 --- a/components/android_autofill/browser/android_autofill_manager.h +++ b/components/android_autofill/browser/android_autofill_manager.h
@@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/notreached.h" #include "components/autofill/core/browser/autofill_manager.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/common/dense_set.h" namespace autofill { @@ -138,9 +139,10 @@ void OnAfterProcessParsedForms( const DenseSet<FormType>& form_types) override {} - void OnServerRequestError(FormSignature form_signature, - AutofillDownloadManager::RequestType request_type, - int http_error) override; + void OnServerRequestError( + FormSignature form_signature, + AutofillCrowdsourcingManager::RequestType request_type, + int http_error) override; private: // AutofillManager::Observer:
diff --git a/components/android_autofill/browser/autofill_provider.cc b/components/android_autofill/browser/autofill_provider.cc index da7073a..c1104f3 100644 --- a/components/android_autofill/browser/autofill_provider.cc +++ b/components/android_autofill/browser/autofill_provider.cc
@@ -11,17 +11,17 @@ namespace autofill { namespace { -bool g_is_download_manager_disabled_for_testing = false; +bool g_is_crowdsourcing_manager_disabled_for_testing = false; } // namespace WEB_CONTENTS_USER_DATA_KEY_IMPL(AutofillProvider); -bool AutofillProvider::is_download_manager_disabled_for_testing() { - return g_is_download_manager_disabled_for_testing; +bool AutofillProvider::is_crowdsourcing_manager_disabled_for_testing() { + return g_is_crowdsourcing_manager_disabled_for_testing; } -void AutofillProvider::set_is_download_manager_disabled_for_testing() { - g_is_download_manager_disabled_for_testing = true; +void AutofillProvider::set_is_crowdsourcing_manager_disabled_for_testing() { + g_is_crowdsourcing_manager_disabled_for_testing = true; } AutofillProvider::AutofillProvider(content::WebContents* web_contents)
diff --git a/components/android_autofill/browser/autofill_provider.h b/components/android_autofill/browser/autofill_provider.h index 8d25195..68cf34ab 100644 --- a/components/android_autofill/browser/autofill_provider.h +++ b/components/android_autofill/browser/autofill_provider.h
@@ -33,8 +33,8 @@ public: ~AutofillProvider() override; - static bool is_download_manager_disabled_for_testing(); - static void set_is_download_manager_disabled_for_testing(); + static bool is_crowdsourcing_manager_disabled_for_testing(); + static void set_is_crowdsourcing_manager_disabled_for_testing(); virtual void OnAskForValuesToFill( AndroidAutofillManager* manager,
diff --git a/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc b/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc index 93f4bf3..f430b2a 100644 --- a/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc +++ b/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc
@@ -49,9 +49,9 @@ } // namespace -static void JNI_AutofillProviderTestHelper_DisableDownloadServerForTesting( +static void JNI_AutofillProviderTestHelper_DisableCrowdsourcingForTesting( JNIEnv* env_md_ctx_st) { - AutofillProvider::set_is_download_manager_disabled_for_testing(); + AutofillProvider::set_is_crowdsourcing_manager_disabled_for_testing(); } static jboolean @@ -176,10 +176,10 @@ form_structures = autofill_manager->form_structures(); CHECK(!form_structures.empty()); const FormStructure& arbitary_form = *form_structures.begin()->second; - AutofillDownloadManager::Observer* observer = autofill_manager; + AutofillCrowdsourcingManager::Observer* observer = autofill_manager; observer->OnServerRequestError( arbitary_form.form_signature(), - AutofillDownloadManager::RequestType::REQUEST_QUERY, 400); + AutofillCrowdsourcingManager::RequestType::REQUEST_QUERY, 400); } } // namespace autofill
diff --git a/components/android_autofill/browser/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java b/components/android_autofill/browser/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java index 6e72c62..5cecb78c 100644 --- a/components/android_autofill/browser/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java +++ b/components/android_autofill/browser/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java
@@ -13,11 +13,11 @@ @JNINamespace("autofill") public class AutofillProviderTestHelper { /** - * Disable the download server for testing to avoid the server response affect the integration + * Disable crowdsourcing for testing to avoid that the server response affects the integration * tests. Must be called before WebContents is created. */ - public static void disableDownloadServerForTesting() { - AutofillProviderTestHelperJni.get().disableDownloadServerForTesting(); + public static void disableCrowdsourcingForTesting() { + AutofillProviderTestHelperJni.get().disableCrowdsourcingForTesting(); } /** Simulate the primary server type only. */ @@ -43,7 +43,7 @@ @NativeMethods interface Natives { - void disableDownloadServerForTesting(); + void disableCrowdsourcingForTesting(); boolean simulateMainFrameAutofillServerResponseForTesting( WebContents webContents, String[] fieldIds, int[] fieldTypes);
diff --git a/components/attribution_reporting/BUILD.gn b/components/attribution_reporting/BUILD.gn index ffd3f61..02cf968 100644 --- a/components/attribution_reporting/BUILD.gn +++ b/components/attribution_reporting/BUILD.gn
@@ -10,6 +10,7 @@ "registration_eligibility.mojom", "source_registration_error.mojom", "source_registration_time_config.mojom", + "summary_window_operator.mojom", "trigger_data_matching.mojom", "trigger_registration_error.mojom", ]
diff --git a/components/attribution_reporting/parsing_utils.cc b/components/attribution_reporting/parsing_utils.cc index ac39802..e4e0bb9 100644 --- a/components/attribution_reporting/parsing_utils.cc +++ b/components/attribution_reporting/parsing_utils.cc
@@ -6,9 +6,11 @@ #include <stdint.h> +#include <cmath> #include <sstream> #include <string> +#include "base/numerics/safe_conversions.h" #include "base/strings/abseil_string_number_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" @@ -189,4 +191,38 @@ } } +base::expected<uint32_t, mojom::SourceRegistrationError> ParseUint32( + const base::Value& value, + const mojom::SourceRegistrationError wrong_type_error, + const mojom::SourceRegistrationError out_of_range_error) { + // We use `base::Value::GetIfDouble()`, which coerces if the value is an + // integer, because not all `uint32_t` can be represented by 32-bit `int`. + // We use `std::modf` to check that the fractional part of the `double` is 0. + // + // Assumes that all `uint32_t` can be represented either by `int` or `double`, + // and that when represented internally by `base::Value` as an `int`, can be + // precisely represented by `double`. + // + // TODO(apaseltiner): Consider test coverage for all `uint32_t` values, or + // some kind of fuzzer. + absl::optional<double> double_value = value.GetIfDouble(); + if (double int_part; + !double_value.has_value() || std::modf(*double_value, &int_part) != 0) { + return base::unexpected(wrong_type_error); + } + + if (!base::IsValueInRangeForNumericType<uint32_t>(*double_value)) { + return base::unexpected(out_of_range_error); + } + + return static_cast<uint32_t>(*double_value); +} + +base::Value Uint32ToJson(uint32_t value) { + // All `uint32_t` can be represented exactly by `double`. + return base::IsValueInRangeForNumericType<int>(value) + ? base::Value(static_cast<int>(value)) + : base::Value(static_cast<double>(value)); +} + } // namespace attribution_reporting
diff --git a/components/attribution_reporting/parsing_utils.h b/components/attribution_reporting/parsing_utils.h index 3106ac1..9547d8cf 100644 --- a/components/attribution_reporting/parsing_utils.h +++ b/components/attribution_reporting/parsing_utils.h
@@ -86,6 +86,13 @@ base::StringPiece key, base::TimeDelta value); +base::expected<uint32_t, mojom::SourceRegistrationError> ParseUint32( + const base::Value&, + mojom::SourceRegistrationError wrong_type_error, + mojom::SourceRegistrationError out_of_range_error); + +base::Value Uint32ToJson(uint32_t); + } // namespace attribution_reporting #endif // COMPONENTS_ATTRIBUTION_REPORTING_PARSING_UTILS_H_
diff --git a/components/attribution_reporting/source_registration.cc b/components/attribution_reporting/source_registration.cc index f785975..b0db23f 100644 --- a/components/attribution_reporting/source_registration.cc +++ b/components/attribution_reporting/source_registration.cc
@@ -60,9 +60,9 @@ void RecordSourceRegistrationError(SourceRegistrationError error) { static_assert( SourceRegistrationError::kMaxValue == - SourceRegistrationError::kFilterDataKeyReserved, - "Bump version of Conversions.SourceRegistrationError8 histogram."); - base::UmaHistogramEnumeration("Conversions.SourceRegistrationError8", error); + SourceRegistrationError::kSummaryBucketsNonIncreasing, + "Bump version of Conversions.SourceRegistrationError9 histogram."); + base::UmaHistogramEnumeration("Conversions.SourceRegistrationError9", error); } SourceRegistration::SourceRegistration(mojo::DefaultConstruct::Tag tag)
diff --git a/components/attribution_reporting/source_registration_error.mojom b/components/attribution_reporting/source_registration_error.mojom index 52b87d25..24e74e9 100644 --- a/components/attribution_reporting/source_registration_error.mojom +++ b/components/attribution_reporting/source_registration_error.mojom
@@ -65,4 +65,14 @@ kExcessiveTriggerData = 46, kDuplicateTriggerData = 47, kInvalidTriggerDataForMatchingMode = 48, + + kSummaryWindowOperatorWrongType = 50, + kSummaryWindowOperatorUnknownValue = 51, + + kSummaryBucketsWrongType = 52, + kSummaryBucketsEmpty = 53, + kSummaryBucketsTooLong = 54, + kSummaryBucketsValueWrongType = 55, + kSummaryBucketsValueOutOfRange = 56, + kSummaryBucketsNonIncreasing = 57, };
diff --git a/components/attribution_reporting/source_registration_unittest.cc b/components/attribution_reporting/source_registration_unittest.cc index 8b8c240..627a35a 100644 --- a/components/attribution_reporting/source_registration_unittest.cc +++ b/components/attribution_reporting/source_registration_unittest.cc
@@ -323,7 +323,7 @@ }; static constexpr char kSourceRegistrationErrorMetric[] = - "Conversions.SourceRegistrationError8"; + "Conversions.SourceRegistrationError9"; for (const auto& test_case : kTestCases) { SCOPED_TRACE(test_case.desc);
diff --git a/components/attribution_reporting/summary_window_operator.mojom b/components/attribution_reporting/summary_window_operator.mojom new file mode 100644 index 0000000..b692fa95 --- /dev/null +++ b/components/attribution_reporting/summary_window_operator.mojom
@@ -0,0 +1,15 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module attribution_reporting.mojom; + +// Controls how event-level triggers contribute to a summary. +// Corresponds to +// https://wicg.github.io/attribution-reporting-api/#summary-window-operator +enum SummaryWindowOperator { + // The summary is incremented by 1. + kCount = 0, + // The summary is incremented by the trigger's value field. + kValueSum = 1, +};
diff --git a/components/attribution_reporting/test_utils.cc b/components/attribution_reporting/test_utils.cc index 0079eaa5..e75ee143 100644 --- a/components/attribution_reporting/test_utils.cc +++ b/components/attribution_reporting/test_utils.cc
@@ -105,6 +105,12 @@ << ", debug_reporting=" << item.debug_reporting << "}"; } +std::ostream& operator<<(std::ostream& out, const SummaryBuckets& buckets) { + base::Value::Dict dict; + buckets.Serialize(dict); + return out << dict; +} + std::ostream& operator<<(std::ostream& out, const TriggerSpec& spec) { return out << spec.ToJson(); }
diff --git a/components/attribution_reporting/test_utils.h b/components/attribution_reporting/test_utils.h index 9dd9583..6655f9a 100644 --- a/components/attribution_reporting/test_utils.h +++ b/components/attribution_reporting/test_utils.h
@@ -24,6 +24,7 @@ class DestinationSet; class EventReportWindows; class SuitableOrigin; +class SummaryBuckets; struct AggregatableDedupKey; struct EventTriggerData; @@ -61,6 +62,8 @@ std::ostream& operator<<(std::ostream&, const OsRegistrationItem&); +std::ostream& operator<<(std::ostream&, const SummaryBuckets&); + std::ostream& operator<<(std::ostream&, const TriggerSpec&); std::ostream& operator<<(std::ostream&, const TriggerSpecs&);
diff --git a/components/attribution_reporting/trigger_config.cc b/components/attribution_reporting/trigger_config.cc index 3ef5325..166bc25 100644 --- a/components/attribution_reporting/trigger_config.cc +++ b/components/attribution_reporting/trigger_config.cc
@@ -6,22 +6,26 @@ #include <stdint.h> -#include <cmath> #include <string> #include <utility> #include <vector> #include "base/check.h" #include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/feature_list.h" +#include "base/numerics/safe_conversions.h" #include "base/ranges/algorithm.h" #include "base/time/time.h" #include "base/types/expected.h" #include "base/types/expected_macros.h" #include "base/values.h" #include "components/attribution_reporting/features.h" +#include "components/attribution_reporting/max_event_level_reports.h" +#include "components/attribution_reporting/parsing_utils.h" #include "components/attribution_reporting/source_registration_error.mojom.h" #include "components/attribution_reporting/source_type.mojom.h" +#include "components/attribution_reporting/summary_window_operator.mojom.h" #include "components/attribution_reporting/trigger_data_matching.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -31,8 +35,11 @@ using ::attribution_reporting::mojom::SourceRegistrationError; using ::attribution_reporting::mojom::SourceType; +using ::attribution_reporting::mojom::SummaryWindowOperator; using ::attribution_reporting::mojom::TriggerDataMatching; +constexpr char kSummaryBuckets[] = "summary_buckets"; +constexpr char kSummaryWindowOperator[] = "summary_window_operator"; constexpr char kTriggerData[] = "trigger_data"; constexpr char kTriggerDataMatching[] = "trigger_data_matching"; constexpr char kTriggerSpecs[] = "trigger_specs"; @@ -40,6 +47,9 @@ constexpr char kTriggerDataMatchingExact[] = "exact"; constexpr char kTriggerDataMatchingModulus[] = "modulus"; +constexpr char kSummaryWindowOperatorCount[] = "count"; +constexpr char kSummaryWindowOperatorValueSum[] = "value_sum"; + // https://wicg.github.io/attribution-reporting-api/#max-distinct-trigger-data-per-source constexpr uint8_t kMaxTriggerDataPerSource = 32; @@ -78,29 +88,12 @@ } for (const base::Value& item : *list) { - // We use `base::Value::GetIfDouble()`, which coerces if the value is an - // integer, because trigger data values are `uint32_t`, but not all - // `uint32_t` can be represented by 32-bit `int`. We use `std::modf` to - // check that the fractional part of the `double` is 0. - // - // Assumes that all integers we care to support for trigger data (the full - // range of `uint32_t`) can be represented either by `int` or `double`, and - // that when represented internally by `base::Value` as an `int`, can be - // precisely represented by `double`. - // - // TODO(apaseltiner): Consider test coverage for all `uint32_t` values, or - // some kind of fuzzer. - absl::optional<double> double_value = item.GetIfDouble(); - if (double int_part; - !double_value.has_value() || std::modf(*double_value, &int_part) != 0) { - return SourceRegistrationError::kTriggerSpecTriggerDataValueWrongType; - } - - if (!base::IsValueInRangeForNumericType<uint32_t>(*double_value)) { - return SourceRegistrationError::kTriggerSpecTriggerDataValueOutOfRange; - } - - uint32_t trigger_data = static_cast<uint32_t>(*double_value); + ASSIGN_OR_RETURN( + uint32_t trigger_data, + ParseUint32( + item, + SourceRegistrationError::kTriggerSpecTriggerDataValueWrongType, + SourceRegistrationError::kTriggerSpecTriggerDataValueOutOfRange)); auto [_, inserted] = trigger_data_indices.try_emplace(trigger_data, spec_index); @@ -139,6 +132,13 @@ } } +bool AreSummaryBucketsValid(const base::flat_set<uint32_t>& starts) { + return !starts.empty() && + base::MakeStrictNum(starts.size()) <= + static_cast<int>(MaxEventLevelReports::Max()) && + *starts.begin() > 0; +} + } // namespace base::expected<TriggerDataMatching, SourceRegistrationError> @@ -345,16 +345,10 @@ } for (const auto& [trigger_data, index] : trigger_data_indices_) { - base::Value::List* trigger_data_list = - spec_list[index].GetDict().FindList(kTriggerData); - - if (base::IsValueInRangeForNumericType<int>(trigger_data)) { - trigger_data_list->Append(static_cast<int>(trigger_data)); - } else { - // This cast is safe because all `uint32_t` can be represented exactly by - // `double`. - trigger_data_list->Append(static_cast<double>(trigger_data)); - } + spec_list[index] + .GetDict() + .FindList(kTriggerData) + ->Append(Uint32ToJson(trigger_data)); } return spec_list; @@ -368,4 +362,108 @@ TriggerDataIndices::const_iterator it) : specs_(specs), it_(it) {} +base::expected<SummaryWindowOperator, SourceRegistrationError> +ParseSummaryWindowOperator(const base::Value::Dict& dict) { + const base::Value* value = dict.Find(kSummaryWindowOperator); + if (!value) { + return SummaryWindowOperator::kCount; + } + + const std::string* str = value->GetIfString(); + if (!str) { + return base::unexpected( + SourceRegistrationError::kSummaryWindowOperatorWrongType); + } else if (*str == kSummaryWindowOperatorCount) { + return SummaryWindowOperator::kCount; + } else if (*str == kSummaryWindowOperatorValueSum) { + return SummaryWindowOperator::kValueSum; + } else { + return base::unexpected( + SourceRegistrationError::kSummaryWindowOperatorUnknownValue); + } +} + +// static +base::expected<SummaryBuckets, SourceRegistrationError> SummaryBuckets::Parse( + const base::Value::Dict& dict, + MaxEventLevelReports max_event_level_reports) { + const base::Value* value = dict.Find(kSummaryBuckets); + if (!value) { + return SummaryBuckets(max_event_level_reports); + } + + const base::Value::List* list = value->GetIfList(); + if (!list) { + return base::unexpected(SourceRegistrationError::kSummaryBucketsWrongType); + } + + if (list->empty()) { + return base::unexpected(SourceRegistrationError::kSummaryBucketsEmpty); + } + + if (base::MakeStrictNum(list->size()) > + static_cast<int>(max_event_level_reports)) { + return base::unexpected(SourceRegistrationError::kSummaryBucketsTooLong); + } + + std::vector<uint32_t> starts; + starts.reserve(list->size()); + + uint32_t prev = 0; + + for (const base::Value& item : *list) { + ASSIGN_OR_RETURN( + uint32_t start, + ParseUint32(item, + SourceRegistrationError::kSummaryBucketsValueWrongType, + SourceRegistrationError::kSummaryBucketsValueOutOfRange)); + + if (start <= prev) { + return base::unexpected( + SourceRegistrationError::kSummaryBucketsNonIncreasing); + } + + starts.push_back(start); + prev = start; + } + + return SummaryBuckets( + base::flat_set<uint32_t>(base::sorted_unique, std::move(starts))); +} + +SummaryBuckets::SummaryBuckets( + const MaxEventLevelReports max_event_level_reports) { + std::vector<uint32_t> starts; + starts.reserve(max_event_level_reports); + for (int i = 1; i <= max_event_level_reports; ++i) { + starts.push_back(i); + } + starts_.replace(std::move(starts)); + CHECK(AreSummaryBucketsValid(starts_)); +} + +SummaryBuckets::SummaryBuckets(base::flat_set<uint32_t> starts) + : starts_(std::move(starts)) { + CHECK(AreSummaryBucketsValid(starts_)); +} + +SummaryBuckets::~SummaryBuckets() = default; + +SummaryBuckets::SummaryBuckets(const SummaryBuckets&) = default; + +SummaryBuckets& SummaryBuckets::operator=(const SummaryBuckets&) = default; + +SummaryBuckets::SummaryBuckets(SummaryBuckets&&) = default; + +SummaryBuckets& SummaryBuckets::operator=(SummaryBuckets&&) = default; + +void SummaryBuckets::Serialize(base::Value::Dict& dict) const { + base::Value::List list; + list.reserve(starts_.size()); + for (uint32_t start : starts_) { + list.Append(Uint32ToJson(start)); + } + dict.Set(kSummaryBuckets, std::move(list)); +} + } // namespace attribution_reporting
diff --git a/components/attribution_reporting/trigger_config.h b/components/attribution_reporting/trigger_config.h index 78c77c5..ebd500e 100644 --- a/components/attribution_reporting/trigger_config.h +++ b/components/attribution_reporting/trigger_config.h
@@ -14,12 +14,14 @@ #include "base/component_export.h" #include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/memory/raw_ref.h" #include "base/types/expected.h" #include "base/values.h" #include "components/attribution_reporting/event_report_windows.h" #include "components/attribution_reporting/source_registration_error.mojom-forward.h" #include "components/attribution_reporting/source_type.mojom-forward.h" +#include "components/attribution_reporting/summary_window_operator.mojom-forward.h" #include "components/attribution_reporting/trigger_data_matching.mojom-forward.h" namespace base { @@ -28,6 +30,44 @@ namespace attribution_reporting { +class MaxEventLevelReports; + +// Controls the bucketization of event-level triggers. +// Corresponds to +// https://wicg.github.io/attribution-reporting-api/#summary-bucket-list +class COMPONENT_EXPORT(ATTRIBUTION_REPORTING) SummaryBuckets { + public: + static base::expected<SummaryBuckets, mojom::SourceRegistrationError> Parse( + const base::Value::Dict&, + MaxEventLevelReports); + + // Represents `[1, 2, ... max_event_level_reports]`. + // `CHECK()`s that `max_event_level_reports` is positive. + explicit SummaryBuckets(MaxEventLevelReports max_event_level_reports); + + // `CHECK()`s that `starts` is valid: Must be non-empty, all values > 0, and + // length <= `MaxEventLevelReports::Max()`. + explicit SummaryBuckets(base::flat_set<uint32_t> starts); + + ~SummaryBuckets(); + + SummaryBuckets(const SummaryBuckets&); + SummaryBuckets& operator=(const SummaryBuckets&); + + SummaryBuckets(SummaryBuckets&&); + SummaryBuckets& operator=(SummaryBuckets&&); + + const base::flat_set<uint32_t>& starts() const { return starts_; } + + void Serialize(base::Value::Dict&) const; + + friend bool operator==(const SummaryBuckets&, + const SummaryBuckets&) = default; + + private: + base::flat_set<uint32_t> starts_; +}; + class COMPONENT_EXPORT(ATTRIBUTION_REPORTING) TriggerSpec { public: TriggerSpec(); @@ -205,6 +245,10 @@ COMPONENT_EXPORT(ATTRIBUTION_REPORTING) void Serialize(base::Value::Dict&, mojom::TriggerDataMatching); +COMPONENT_EXPORT(ATTRIBUTION_REPORTING) +base::expected<mojom::SummaryWindowOperator, mojom::SourceRegistrationError> +ParseSummaryWindowOperator(const base::Value::Dict&); + } // namespace attribution_reporting #endif // COMPONENTS_ATTRIBUTION_REPORTING_TRIGGER_CONFIG_H_
diff --git a/components/attribution_reporting/trigger_config_unittest.cc b/components/attribution_reporting/trigger_config_unittest.cc index 240d3334..6791ab0 100644 --- a/components/attribution_reporting/trigger_config_unittest.cc +++ b/components/attribution_reporting/trigger_config_unittest.cc
@@ -9,6 +9,7 @@ #include <limits> #include <utility> +#include "base/containers/flat_set.h" #include "base/test/gmock_expected_support.h" #include "base/test/scoped_feature_list.h" #include "base/test/values_test_util.h" @@ -17,8 +18,10 @@ #include "base/values.h" #include "components/attribution_reporting/event_report_windows.h" #include "components/attribution_reporting/features.h" +#include "components/attribution_reporting/max_event_level_reports.h" #include "components/attribution_reporting/source_registration_error.mojom.h" #include "components/attribution_reporting/source_type.mojom.h" +#include "components/attribution_reporting/summary_window_operator.mojom.h" #include "components/attribution_reporting/test_utils.h" #include "components/attribution_reporting/trigger_data_matching.mojom.h" #include "testing/gmock/include/gmock/gmock.h" @@ -29,6 +32,7 @@ using ::attribution_reporting::mojom::SourceRegistrationError; using ::attribution_reporting::mojom::SourceType; +using ::attribution_reporting::mojom::SummaryWindowOperator; using ::attribution_reporting::mojom::TriggerDataMatching; using ::base::test::ErrorIs; using ::base::test::ValueIs; @@ -605,5 +609,146 @@ } } +TEST(SummaryWindowOperatorTest, Parse) { + const struct { + const char* desc; + const char* json; + ::testing::Matcher< + base::expected<SummaryWindowOperator, SourceRegistrationError>> + matches; + } kTestCases[] = { + { + .desc = "missing", + .json = R"json({})json", + .matches = ValueIs(SummaryWindowOperator::kCount), + }, + { + .desc = "wrong_type", + .json = R"json({"summary_window_operator": 1})json", + .matches = + ErrorIs(SourceRegistrationError::kSummaryWindowOperatorWrongType), + }, + { + .desc = "invalid_value", + .json = R"json({"summary_window_operator": "COUNT"})json", + .matches = ErrorIs( + SourceRegistrationError::kSummaryWindowOperatorUnknownValue), + }, + { + .desc = "valid_count", + .json = R"json({"summary_window_operator": "count"})json", + .matches = ValueIs(SummaryWindowOperator::kCount), + }, + { + .desc = "valid_value_sum", + .json = R"json({"summary_window_operator": "value_sum"})json", + .matches = ValueIs(SummaryWindowOperator::kValueSum), + }, + }; + + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(test_case.desc); + + const base::Value::Dict dict = base::test::ParseJsonDict(test_case.json); + + EXPECT_THAT(ParseSummaryWindowOperator(dict), test_case.matches); + } +} + +TEST(SummaryBucketsTest, Parse) { + const struct { + const char* desc; + const char* json; + MaxEventLevelReports max_event_level_reports = MaxEventLevelReports::Max(); + ::testing::Matcher<base::expected<SummaryBuckets, SourceRegistrationError>> + matches; + } kTestCases[] = { + { + .desc = "missing", + .json = R"json({})json", + .max_event_level_reports = MaxEventLevelReports(5), + .matches = ValueIs( + Property(&SummaryBuckets::starts, ElementsAre(1, 2, 3, 4, 5))), + }, + { + .desc = "wrong_type", + .json = R"json({"summary_buckets": 1})json", + .matches = ErrorIs(SourceRegistrationError::kSummaryBucketsWrongType), + }, + { + .desc = "empty", + .json = R"json({"summary_buckets": []})json", + .matches = ErrorIs(SourceRegistrationError::kSummaryBucketsEmpty), + }, + { + .desc = "too_long", + .json = R"json({"summary_buckets": [1, 2, 3, 4]})json", + .max_event_level_reports = MaxEventLevelReports(3), + .matches = ErrorIs(SourceRegistrationError::kSummaryBucketsTooLong), + }, + { + .desc = "value_wrong_type", + .json = R"json({"summary_buckets": [0.1]})json", + .matches = + ErrorIs(SourceRegistrationError::kSummaryBucketsValueWrongType), + }, + { + .desc = "value_out_of_range", + .json = R"json({"summary_buckets": [-1]})json", + .matches = + ErrorIs(SourceRegistrationError::kSummaryBucketsValueOutOfRange), + }, + { + .desc = "value_zero", + .json = R"json({"summary_buckets": [0]})json", + .matches = + ErrorIs(SourceRegistrationError::kSummaryBucketsNonIncreasing), + }, + { + .desc = "non_increasing", + .json = R"json({"summary_buckets": [1, 3, 5, 2]})json", + .matches = + ErrorIs(SourceRegistrationError::kSummaryBucketsNonIncreasing), + }, + { + .desc = "duplicate", + .json = R"json({"summary_buckets": [1, 3, 3]})json", + .matches = + ErrorIs(SourceRegistrationError::kSummaryBucketsNonIncreasing), + }, + { + .desc = "valid", + .json = R"json({"summary_buckets": [1, 3, 5]})json", + .max_event_level_reports = MaxEventLevelReports(3), + .matches = + ValueIs(Property(&SummaryBuckets::starts, ElementsAre(1, 3, 5))), + }, + { + .desc = "valid_max_uint32", + .json = R"json({"summary_buckets": [4294967295]})json", + .matches = ValueIs( + Property(&SummaryBuckets::starts, ElementsAre(4294967295))), + }, + }; + + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(test_case.desc); + + const base::Value::Dict dict = base::test::ParseJsonDict(test_case.json); + + EXPECT_THAT(SummaryBuckets::Parse(dict, test_case.max_event_level_reports), + test_case.matches); + } +} + +TEST(SummaryBucketsTest, Serialize) { + base::Value::Dict dict; + SummaryBuckets({1, 3, 4294967295}).Serialize(dict); + + EXPECT_THAT(dict, base::test::IsJson(R"json({ + "summary_buckets": [1, 3, 4294967295] + })json")); +} + } // namespace } // namespace attribution_reporting
diff --git a/components/autofill/README.md b/components/autofill/README.md index dd16bdd..5391f87 100644 --- a/components/autofill/README.md +++ b/components/autofill/README.md
@@ -34,14 +34,14 @@ └─▲───────────────┘ │ │ │ │ ┌────────────────────────┐ ┌─┴────────────────────┐ - │ │AutofillExternalDelegate◄────────┤BrowserAutofillManager├───────┐ ┌───────────────┐ - │ │1 per RenderFrameHost │ owns 1│1 per RenderFrameHost │ votes│ │Autofill server│ - │ └──────────────────────┬─┘ └─▲──────────────────┬─┘ │ └─────────────▲─┘ - │ events│ │ events│ │ HTTP│ - │ │ │ │ ┌─▼───────────────────▼─┐ - ├────────────────────────┼────────────┼──────────────────┼───────►AutofillDownloadManager│ - │ │ │ │ │1 per WebContents │ - │ │ │ │ └─────────────────────▲─┘ + │ │AutofillExternalDelegate◄────────┤BrowserAutofillManager├─┐ ┌───────────────┐ + │ │1 per RenderFrameHost │ owns 1│1 per RenderFrameHost │ │ votes │Autofill server│ + │ └──────────────────────┬─┘ └─▲──────────────────┬─┘ │ └─────────────▲─┘ + │ events│ │ events│ │ HTTP│ + │ │ │ │ ┌─▼─────────────────────────▼─┐ + ├────────────────────────┼────────────┼──────────────────┼─►AutofillCrowsourcingdManager │ + │ │ │ │ │1 per WebContents │ + │ │ │ │ └───────────────────────────▲─┘ │ │ │ │ │ │ │ │ │ ┌──────────────┐ │ │ │ │ │ │FormStructure │ │ @@ -104,7 +104,6 @@ - [`autofill_client.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/autofill_client.h) - [`//android_webview/browser/aw_autofill_client.h`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/browser/aw_autofill_client.h) (WebView implementation) - [`//chrome/browser/ui/autofill/chrome_autofill_client.h`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/autofill/chrome_autofill_client.h) (Chrome implementation) - - [`autofill_download_manager.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/autofill_download_manager.h) - [`autofill_driver.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/autofill_driver.h) - [`../../content/browser/content_autofill_driver.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/autofill_driver.h) (non-iOS implementation) - [`../../ios/browser/autofill_driver_ios.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/ios/browser/autofill_driver_ios.h) (iOS implementation) @@ -113,6 +112,7 @@ - [`autofill_manager.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/autofill_manager.h) - [`browser_autofill_manager.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/browser_autofill_manager.h) (Chrome specialization) - [`//components/android_autofill/browser/android_autofill_manager.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/android_autofill/browser/android_autofill_manager.h) (WebView specialization) + - [`crowdsourcing/autofill_crowdsourcing_manager.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h) - [`data_model/`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/data_model) - [`autofill_profile.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/data_model/autofill_profile.h) - [`credit_card.h`](https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/browser/data_model/credit_card.h) @@ -269,8 +269,8 @@ `components/autofill/core/browser/form_parsing/regex_patterns.h` if `features::kAutofillParsingPatternProvider` is enabled. * Crowd sourcing - * `AutofillDownloadManager` is responsible for downloading field - classifications. + * `AutofillCrowdsourcingManager` is responsible for downloading field + classifications and uploading type votes. * Crowd sourcing is applied (for lookups and voting) for forms of any size but the server can handle small forms differently, see [`http://cs/IsSmallForm%20file:autofill`](http://cs/IsSmallForm%20file:autofill). @@ -427,10 +427,10 @@ `kAutofillUploadThrottlingPeriodInDays` days. In case `observed_submission == true`, the votes are generated on a background -thread and then passed to the `AutofillDownloadManager`. +thread and then passed to the `AutofillCrowdsourcingManager`. In case `observed_submission == false`, the votes are not directly passed to -the `AutofillDownloadManager`. Instead they are cached until the cache is +the `AutofillCrowdsourcingManager`. Instead they are cached until the cache is flushed. This enables us to override previous votes in case the user focuses and removes focus from a form multiple times while editing the fields' values. The cache is flushed on form submission.
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc index f529453..a9253ad 100644 --- a/components/autofill/content/renderer/password_generation_agent.cc +++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -454,7 +454,8 @@ is_generation_element_password_type, GetTextDirectionForElement( current_generation_item_->generation_element_), - current_generation_item_->form_data_); + current_generation_item_->form_data_, + current_generation_item_->generation_element_.Value().Utf16().empty()); std::move(callback).Run(std::move(password_generation_ui_data)); current_generation_item_->generation_popup_shown_ = true; } else { @@ -675,7 +676,8 @@ current_generation_item_->generation_element_), is_generation_element_password_type, GetTextDirectionForElement(current_generation_item_->generation_element_), - current_generation_item_->form_data_); + current_generation_item_->form_data_, + current_generation_item_->generation_element_.Value().Utf16().empty()); current_generation_item_->generation_popup_shown_ = true; GetPasswordGenerationDriver().AutomaticGenerationAvailable( password_generation_ui_data);
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 7fc5a50..520ee9f1 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -84,8 +84,6 @@ "autofill_credit_card_policy_handler.h", "autofill_data_util.cc", "autofill_data_util.h", - "autofill_download_manager.cc", - "autofill_download_manager.h", "autofill_driver.h", "autofill_driver_router.cc", "autofill_driver_router.h", @@ -117,6 +115,8 @@ "contact_info_sync_util.cc", "contact_info_sync_util.h", "country_type.h", + "crowdsourcing/autofill_crowdsourcing_manager.cc", + "crowdsourcing/autofill_crowdsourcing_manager.h", "data_model/address.cc", "data_model/address.h", "data_model/autofill_data_model.cc", @@ -783,6 +783,8 @@ "browser_autofill_manager_test_api.h", "browser_autofill_manager_test_delegate.cc", "browser_autofill_manager_test_delegate.h", + "crowdsourcing/mock_autofill_crowdsourcing_manager.cc", + "crowdsourcing/mock_autofill_crowdsourcing_manager.h", "data_model/autofill_structured_address_test_utils.cc", "data_model/autofill_structured_address_test_utils.h", "data_model/test_autofill_data_model.cc", @@ -994,7 +996,6 @@ "autofill_address_util_unittest.cc", "autofill_credit_card_policy_handler_unittest.cc", "autofill_data_util_unittest.cc", - "autofill_download_manager_unittest.cc", "autofill_experiments_unittest.cc", "autofill_external_delegate_unittest.cc", "autofill_feedback_data_unittest.cc", @@ -1009,6 +1010,7 @@ "autofill_type_unittest.cc", "browser_autofill_manager_unittest.cc", "contact_info_sync_util_unittest.cc", + "crowdsourcing/autofill_crowdsourcing_manager_unittest.cc", "data_model/address_unittest.cc", "data_model/autofill_data_model_unittest.cc", "data_model/autofill_i18n_api_unittest.cc",
diff --git a/components/autofill/core/browser/autofill_client.cc b/components/autofill/core/browser/autofill_client.cc index 3053f190..f565986 100644 --- a/components/autofill/core/browser/autofill_client.cc +++ b/components/autofill/core/browser/autofill_client.cc
@@ -47,7 +47,7 @@ return false; } -AutofillDownloadManager* AutofillClient::GetDownloadManager() { +AutofillCrowdsourcingManager* AutofillClient::GetCrowdsourcingManager() { return nullptr; }
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h index ba0dfe7..6f6122c 100644 --- a/components/autofill/core/browser/autofill_client.h +++ b/components/autofill/core/browser/autofill_client.h
@@ -77,7 +77,7 @@ class AutocompleteHistoryManager; class AutofillAblationStudy; class AutofillComposeDelegate; -class AutofillDownloadManager; +class AutofillCrowdsourcingManager; class AutofillDriver; struct AutofillErrorDialogContext; class AutofillMlPredictionModelHandler; @@ -412,9 +412,9 @@ virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() = 0; - // Returns the AutofillDownloadManager for communication with the Autofill - // crowdsourcing server. - virtual AutofillDownloadManager* GetDownloadManager(); + // Returns the AutofillCrowdsourcingManager for communication with the + // Autofill server. + virtual AutofillCrowdsourcingManager* GetCrowdsourcingManager(); // Gets the PersonalDataManager instance associated with the original Chrome // profile.
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index ade8714..e247c05 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -421,9 +421,9 @@ LogAutofillTypePredictionsAvailable(log_manager_, queryable_forms); // Query the server if at least one of the forms was parsed. - if (!queryable_forms.empty() && client().GetDownloadManager()) { + if (!queryable_forms.empty() && client().GetCrowdsourcingManager()) { NotifyObservers(&Observer::OnBeforeLoadedServerPredictions); - if (!client().GetDownloadManager()->StartQueryRequest( + if (!client().GetCrowdsourcingManager()->StartQueryRequest( queryable_forms, driver().IsolationInfo(), GetWeakPtr())) { NotifyObservers(&Observer::OnAfterLoadedServerPredictions); }
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index 58cb38f..8add9c9 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -24,9 +24,9 @@ #include "base/types/pass_key.h" #include "base/types/strong_alias.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_driver.h" #include "components/autofill/core/browser/autofill_trigger_details.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/metrics/autofill_metrics.h" #include "components/autofill/core/common/dense_set.h" #include "components/autofill/core/common/form_data.h" @@ -61,7 +61,7 @@ // // It is owned by the AutofillDriver. class AutofillManager - : public AutofillDownloadManager::Observer, + : public AutofillCrowdsourcingManager::Observer, public translate::TranslateDriver::LanguageDetectionObserver { public: // Observer of AutofillManager events. @@ -72,7 +72,8 @@ // OnBeforeFoo() may be called without a corresponding OnAfterFoo() call are: // - if the number of cached forms exceeds `kAutofillManagerMaxFormCacheSize`; // - if this AutofillManager has been destroyed or reset in the meantime. - // - if the request in AutofillDownloadManager was not successful (i.e. no 2XX + // - if the request in AutofillCrowdsourcingManager was not successful (i.e. + // no 2XX // response code or a null response body). // // TODO(crbug.com/1476488): Consider moving events that are specific to BAM to @@ -479,7 +480,8 @@ // ParseFormsAsync(), and then unwrap the vector again. // - Let OnFormsSeen() take a single FormData. That simplifies also // ContentAutofillDriver and AutofillDriverRouter a bit, but then the - // AutofillDownloadManager needs to collect forms to send a batch query. + // AutofillCrowdsourcingManager needs to collect forms to send a batch + // query. // - Let all other events take a FormGlobalId instead of a FormData and fire // OnFormsSeen() before these events if necessary. void ParseFormsAsync( @@ -506,7 +508,7 @@ private: friend class AutofillManagerTestApi; - // AutofillDownloadManager::Observer: + // AutofillCrowdsourcingManager::Observer: void OnLoadedServerPredictions( std::string response, const std::vector<FormSignature>& queried_form_signatures) override;
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 4fd3753..08f266e 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -14,6 +14,7 @@ #include "components/autofill/core/browser/autofill_manager.h" #include "components/autofill/core/browser/autofill_manager_test_api.h" #include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/mock_autofill_manager_observer.h" #include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/test_autofill_driver.h" @@ -31,52 +32,24 @@ #include "components/autofill/core/browser/ml_model/autofill_ml_prediction_model_handler.h" #endif -using testing::_; -using testing::AtLeast; -using testing::ElementsAre; -using testing::Eq; -using testing::Field; -using testing::Invoke; -using testing::NiceMock; -using testing::Pair; -using testing::Property; -using testing::Ref; -using testing::Return; -using testing::UnorderedElementsAreArray; -using testing::VariantWith; - namespace autofill { -using FieldTypeSource = AutofillManager::Observer::FieldTypeSource; - namespace { -class MockAutofillDownloadManager : public AutofillDownloadManager { - public: - explicit MockAutofillDownloadManager(AutofillClient* client) - : AutofillDownloadManager(client, - /*api_key=*/"", - /*log_manager=*/nullptr) {} - - MockAutofillDownloadManager(const MockAutofillDownloadManager&) = delete; - MockAutofillDownloadManager& operator=(const MockAutofillDownloadManager&) = - delete; - - MOCK_METHOD(bool, - StartQueryRequest, - (const std::vector<FormStructure*>&, - net::IsolationInfo, - base::WeakPtr<Observer>), - (override)); -}; - -class MockAutofillClient : public TestAutofillClient { - public: - MockAutofillClient() = default; - MockAutofillClient(const MockAutofillClient&) = delete; - MockAutofillClient& operator=(const MockAutofillClient&) = delete; - ~MockAutofillClient() override = default; -}; +using ::testing::_; +using ::testing::AtLeast; +using ::testing::ElementsAre; +using ::testing::Eq; +using ::testing::Field; +using ::testing::Invoke; +using ::testing::NiceMock; +using ::testing::Pair; +using ::testing::Property; +using ::testing::Ref; +using ::testing::Return; +using ::testing::UnorderedElementsAreArray; +using ::testing::VariantWith; +using FieldTypeSource = AutofillManager::Observer::FieldTypeSource; class MockAutofillDriver : public TestAutofillDriver { public: @@ -286,12 +259,12 @@ driver_.reset(); } - void SetUpObserverAndDownloadManager(bool successful_request) { - auto download_manager = - std::make_unique<MockAutofillDownloadManager>(&client_); - ON_CALL(*download_manager, StartQueryRequest) + void SetUpObserverAndCrowdsourcingManager(bool successful_request) { + auto crowdsourcing_manager = + std::make_unique<MockAutofillCrowdsourcingManager>(&client_); + ON_CALL(*crowdsourcing_manager, StartQueryRequest) .WillByDefault(Return(successful_request)); - client_.set_download_manager(std::move(download_manager)); + client_.set_crowdsourcing_manager(std::move(crowdsourcing_manager)); manager_->AddObserver(&observer_); } @@ -299,7 +272,7 @@ base::test::ScopedFeatureList scoped_feature_list_async_parse_form_; base::test::TaskEnvironment task_environment_; test::AutofillUnitTestEnvironment autofill_test_environment_; - NiceMock<MockAutofillClient> client_; + TestAutofillClient client_; std::unique_ptr<MockAutofillDriver> driver_; std::unique_ptr<MockAutofillManager> manager_; MockAutofillManagerObserver observer_; @@ -320,12 +293,12 @@ class AutofillManagerTest_OnLoadedServerPredictionsObserver : public AutofillManagerTest { public: - void SetUpObserverAndDownloadManager(bool successful_request) { - auto download_manager = - std::make_unique<MockAutofillDownloadManager>(&client_); - ON_CALL(*download_manager, StartQueryRequest) + void SetUpObserverAndCrowdsourcingManager(bool successful_request) { + auto crowdsourcing_manager = + std::make_unique<MockAutofillCrowdsourcingManager>(&client_); + ON_CALL(*crowdsourcing_manager, StartQueryRequest) .WillByDefault(Return(successful_request)); - client_.set_download_manager(std::move(download_manager)); + client_.set_crowdsourcing_manager(std::move(crowdsourcing_manager)); manager_->AddObserver(&observer_); } }; @@ -552,7 +525,7 @@ TEST_F( AutofillManagerTest_OnLoadedServerPredictionsObserver, OnFormsSeen_SuccessfulQueryRequest_NotifiesBeforeLoadedServerPredictionsObserver) { - SetUpObserverAndDownloadManager(/*successful_request=*/true); + SetUpObserverAndCrowdsourcingManager(/*successful_request=*/true); std::vector<FormData> forms = CreateTestForms(1); EXPECT_CALL(observer_, OnBeforeLoadedServerPredictions(Ref(*manager_))); @@ -570,7 +543,7 @@ TEST_F( AutofillManagerTest_OnLoadedServerPredictionsObserver, OnFormsSeen_FailedQueryRequest_NotifiesBothLoadedServerPredictionsObservers) { - SetUpObserverAndDownloadManager(/*successful_request=*/false); + SetUpObserverAndCrowdsourcingManager(/*successful_request=*/false); std::vector<FormData> forms = CreateTestForms(1); EXPECT_CALL(observer_, OnBeforeLoadedServerPredictions(Ref(*manager_))); @@ -588,7 +561,7 @@ TEST_F( AutofillManagerTest_OnLoadedServerPredictionsObserver, OnLoadedServerPredictions_EmptyQueriedFormSignatures_NotifiesAfterLoadedServerPredictionsObserver) { - SetUpObserverAndDownloadManager(/*successful_request=*/true); + SetUpObserverAndCrowdsourcingManager(/*successful_request=*/true); std::vector<FormData> forms = CreateTestForms(1); EXPECT_CALL(observer_, OnBeforeLoadedServerPredictions(Ref(*manager_))); @@ -608,7 +581,7 @@ TEST_F( AutofillManagerTest_OnLoadedServerPredictionsObserver, OnLoadedServerPredictions_NonEmptyQueriedFormSignatures_NotifiesAfterLoadedServerPredictionsObserver) { - SetUpObserverAndDownloadManager(/*successful_request=*/true); + SetUpObserverAndCrowdsourcingManager(/*successful_request=*/true); std::vector<FormData> forms = CreateTestForms(1); EXPECT_CALL(observer_, OnBeforeLoadedServerPredictions(Ref(*manager_)));
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc index 7b035dd92..e5f6ff50 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -561,24 +561,50 @@ } } -// Creates a specific granular filling label when the `last_filling_granularity` -// for a certain form was group filling. This is done to give users feedback -// about the filling behaviour. -std::optional<Suggestion::Text> GetGranularFillingLabel( +// Returns the number of occurrences of a certain `Suggestion::main_text` and +// its granular filling label. Used to decide whether or not a differentiating +// label should be added. If the concatenation of `Suggestion::main_text` and +// its respective granular filling label is unique, there is no need for a +// differentiating label. +std::map<std::u16string, size_t> +GetNumberOfSuggestionMainTextAndGranularFillingLabelOcurrences( + base::span<const Suggestion> suggestions, + base::span<const std::u16string> suggestions_granular_filling_labels) { + CHECK_EQ(suggestions_granular_filling_labels.size(), suggestions.size()); + // Count the occurrences of the concatenation between `Suggestion::main_text` + // and its granular filling label. + std::map<std::u16string, size_t> main_text_and_granular_filling_label_count; + for (size_t i = 0; i < suggestions.size(); ++i) { + ++main_text_and_granular_filling_label_count + [suggestions[i].main_text.value + + suggestions_granular_filling_labels[i]]; + } + return main_text_and_granular_filling_label_count; +} + +// Creates a specific granular filling label when the +// `last_filling_granularity` for a certain form was group filling. This is done +// to give users feedback about the filling behaviour. Returns an empty string +// when no granular filling label needs to be applied. +std::u16string GetGranularFillingLabel( absl::optional<ServerFieldTypeSet> optional_last_targeted_fields, - FieldTypeGroup triggering_field_type_group) { + ServerFieldType triggering_field_type) { if (!optional_last_targeted_fields || !AreFieldsGranularFillingGroup(*optional_last_targeted_fields)) { - return absl::nullopt; + return std::u16string(); } - switch (triggering_field_type_group) { + // TODO(crbug.com/1459990): Depending on the `optional_last_targeted_fields` + // and the `triggering_field_type`, add specific profile information. Such as + // ADDRESS_HOME_LINE1 when group filling and the `triggering_field_type` is + // not `ADDRESS_HOME_LINE1` nor `ADDRESS_HOME_LINE2`. + switch (GroupTypeOfServerFieldType(triggering_field_type)) { case FieldTypeGroup::kName: - return Suggestion::Text(l10n_util::GetStringUTF16( - IDS_AUTOFILL_FILL_NAME_GROUP_POPUP_OPTION_SELECTED)); + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_FILL_NAME_GROUP_POPUP_OPTION_SELECTED); case FieldTypeGroup::kCompany: case FieldTypeGroup::kAddress: - return Suggestion::Text(l10n_util::GetStringUTF16( - IDS_AUTOFILL_FILL_ADDRESS_GROUP_POPUP_OPTION_SELECTED)); + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_FILL_ADDRESS_GROUP_POPUP_OPTION_SELECTED); case FieldTypeGroup::kNoGroup: case FieldTypeGroup::kPhone: case FieldTypeGroup::kEmail: @@ -589,18 +615,15 @@ case FieldTypeGroup::kUnfillable: case FieldTypeGroup::kBirthdateField: case FieldTypeGroup::kIban: - return absl::nullopt; + return std::u16string(); } + return std::u16string(); } -// Returns for each profile in `profiles` label `Suggestion::Text`s to be used -// as a secondary text in the corresponding suggestion bubble. The last label in -// the label's vector is used to differentiate profiles, while the others are a -// granular filling specific label and an optional separator label ("-"), which -// exists when both a granular filling and a differentiating label exists. The -// Granular filling label is added depending on `optional_last_targeted_fields` -// and the `trigger_field_type`. See `GetProfileSuggestionLabels()` for details. -std::vector<std::vector<Suggestion::Text>> GetProfileSuggestionLabels( +// Returns for each profile in `profiles` a differentiating label string to be +// used as a secondary text in the corresponding suggestion bubble. +// `field_types` the types of the fields that will be filled by the suggestion. +std::vector<std::u16string> GetProfileSuggestionLabels( const std::vector<const AutofillProfile*>& profiles, const ServerFieldTypeSet& field_types, ServerFieldType trigger_field_type, @@ -639,32 +662,90 @@ nullptr); } - std::optional<Suggestion::Text> granular_filling_label = - base::FeatureList::IsEnabled(features::kAutofillGranularFillingAvailable) - ? GetGranularFillingLabel( - optional_last_targeted_fields, - GroupTypeOfServerFieldType(trigger_field_type)) - : absl::nullopt; - // Creates a list of `Suggestion::Text` to be used as labels. + return differentiating_labels; +} + +// For each profile in `profiles`, returns a vector of `Suggestion::labels` to +// be applied. Takes into account the `last_targeted_fields` and the +// `trigger_field_type` to add specific granular filling labels. Optionally adds +// a differentiating label if the Suggestion::main_text + granular filling label +// is not unique. +std::vector<std::vector<Suggestion::Text>> +CreateSuggestionLabelsWithGranularFillingDetails( + base::span<const Suggestion> suggestions, + const std::vector<const AutofillProfile*>& profiles, + const ServerFieldTypeSet& field_types, + absl::optional<ServerFieldTypeSet> last_targeted_fields, + ServerFieldType trigger_field_type, + const std::string& app_locale) { + // Get a granular filling label to be applied to each suggestion. + const std::vector<std::u16string> granular_filling_labels( + suggestions.size(), + GetGranularFillingLabel(last_targeted_fields, trigger_field_type)); + + const std::vector<std::u16string> differentiating_labels = + GetProfileSuggestionLabels(profiles, field_types, trigger_field_type, + last_targeted_fields, app_locale); + + const std::map<std::u16string, size_t> + main_text_and_granular_filling_label_count = + GetNumberOfSuggestionMainTextAndGranularFillingLabelOcurrences( + suggestions, granular_filling_labels); + std::vector<std::vector<Suggestion::Text>> suggestions_labels; - for (const std::u16string& differentiating_label : differentiating_labels) { - suggestions_labels.emplace_back(); - // Add granular filling specific labels if it exists. - if (granular_filling_label) { - suggestions_labels.back().emplace_back( - std::move(*granular_filling_label)); - // Add a separator if the `differentiating_label` is not empty. - // This will lead to a suggestion rendered as: - // "Fill address - Sansa Stark". - if (!differentiating_label.empty()) { - suggestions_labels.back().emplace_back(u"-"); - } + suggestions_labels.reserve(suggestions.size()); + for (size_t i = 0; i < suggestions.size(); ++i) { + const std::u16string& granular_filling_label = granular_filling_labels[i]; + const std::u16string& differentiating_label = differentiating_labels[i]; + + if (granular_filling_label.empty() && differentiating_label.empty()) { + // No labels to be added. + suggestions_labels.emplace_back(); + continue; } - if (!differentiating_label.empty()) { + + if (granular_filling_label.empty() && !differentiating_label.empty()) { + // If only a differentiating label exists, add it and continue. + // _________________________ + // | Jon snow | + // | Winterfel | + // |_________________________| + suggestions_labels.push_back({Suggestion::Text(differentiating_label)}); + continue; + } + + if (!granular_filling_label.empty() && differentiating_label.empty()) { + // If only a granular filling label label exists, add and continue. + // _________________________ + // | Jon snow | + // | Fill address | + // |_________________________| + suggestions_labels.push_back({Suggestion::Text(granular_filling_label)}); + continue; + } + + // Both labels exist, add the granular filling label first. + suggestions_labels.push_back({Suggestion::Text(granular_filling_label)}); + + // Check whether main_text + differentiating is unique. + auto main_text_and_granular_filling_label_count_iterator = + main_text_and_granular_filling_label_count.find( + suggestions[i].main_text.value + granular_filling_label); + CHECK(main_text_and_granular_filling_label_count_iterator != + main_text_and_granular_filling_label_count.end()); + const bool needs_differentiating_label = + main_text_and_granular_filling_label_count_iterator->second > 1; + if (needs_differentiating_label) { + // if main_text + differentiating labels is not unique, add the + // differentiating label. + // _________________________________ + // | 81274 | + // | Fill address - Winterfel | + // |_________________________________| + suggestions_labels.back().emplace_back(u"-"); suggestions_labels.back().emplace_back(differentiating_label); } } - return suggestions_labels; } @@ -672,8 +753,8 @@ // suggestion bubble, and deduplicates suggestions having the same main text // and label. For each vector in `labels`, the last value is used to // differentiate profiles, while the others are granular filling specific -// labels, see `GetGranularFillingLabel()`. In the case where `labels` is empty, -// we have no differentiating label for the profile. +// labels, see `GetGranularFillingLabel()`. In the case where `labels` is +// empty, we have no differentiating label for the profile. void AssignLabelsAndDeduplicate( std::vector<Suggestion>& suggestions, const std::vector<std::vector<Suggestion::Text>>& labels, @@ -971,8 +1052,9 @@ AssignLabelsAndDeduplicate( suggestions, - GetProfileSuggestionLabels(profiles, field_types, trigger_field_type, - last_targeted_fields, app_locale), + CreateSuggestionLabelsWithGranularFillingDetails( + suggestions, profiles, field_types, last_targeted_fields, + trigger_field_type, app_locale), app_locale); // Add devtools test addresses suggestion if it exists. A suggestion will
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc index 50af355..acd7edc 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
@@ -1130,9 +1130,34 @@ const AutofillProfile profile_ = test::GetFullProfile(); }; +// Test that the differentiating label is added when the suggestion main text +// and granular filling label are not unique across suggestions. TEST_F( AutofillChildrenSuggestionsGenenarationTest, CreateSuggestionsFromProfiles_GroupFillingLabels_AddFillAddressAndDifferentiatingLabel) { + AutofillProfile profile_1 = test::GetFullProfile(); + profile_1.SetRawInfo(ADDRESS_HOME_ZIP, u"1234"); + + AutofillProfile profile_2 = test::GetFullProfile(); + profile_2.SetRawInfo(ADDRESS_HOME_ZIP, u"4321"); + + // `profile_1` and `profile_2` have the same `ADDRESS_HOME_LINE1`, which + // will lead to the necessity of a differentiating label (`ADDRESS_HOME_ZIP`). + std::vector<Suggestion> suggestions = + suggestion_generator()->CreateSuggestionsFromProfiles( + {&profile_1, &profile_2}, {ADDRESS_HOME_LINE1, ADDRESS_HOME_ZIP}, + GetServerFieldTypesOfGroup(FieldTypeGroup::kName), ADDRESS_HOME_LINE1, + /*trigger_field_max_length=*/0); + + ASSERT_EQ(suggestions.size(), 2u); + EXPECT_EQ(suggestions[0].labels, + std::vector<std::vector<Suggestion::Text>>( + {{Suggestion::Text(u"Fill full address"), + Suggestion::Text(u"-"), Suggestion::Text(u"1234")}})); +} + +TEST_F(AutofillChildrenSuggestionsGenenarationTest, + CreateSuggestionsFromProfiles_GroupFillingLabels_AddOnlyFillAddress) { std::vector<Suggestion> suggestions = CreateSuggestionWithChildrenFromProfile( profile(), /*last_targeted_fields=*/ @@ -1142,8 +1167,7 @@ ASSERT_EQ(suggestions.size(), 1u); EXPECT_EQ(suggestions[0].labels, std::vector<std::vector<Suggestion::Text>>( - {{Suggestion::Text(u"Fill full address"), - Suggestion::Text(u"-"), Suggestion::Text(u"John H. Doe")}})); + {{Suggestion::Text(u"Fill full address")}})); } // When there is no differentiating label, we add only the granular filling @@ -1161,20 +1185,30 @@ {{Suggestion::Text(u"Fill full name")}})); } +// Test that the differentiating label is added when the suggestion main text +// and granular filling label are not unique across suggestions. TEST_F( AutofillChildrenSuggestionsGenenarationTest, CreateSuggestionsFromProfiles_GroupFillingLabels_AddFillNameAndDifferentiatingLabel) { - std::vector<Suggestion> suggestions = CreateSuggestionWithChildrenFromProfile( - profile(), - /*last_targeted_fields=*/ - GetServerFieldTypesOfGroup(FieldTypeGroup::kName), NAME_FIRST, - /*field_types=*/{ADDRESS_HOME_CITY}); + AutofillProfile profile_1 = test::GetFullProfile(); + profile_1.SetRawInfo(NAME_FULL, u"Cersei Lannister"); - ASSERT_EQ(suggestions.size(), 1u); + AutofillProfile profile_2 = test::GetFullProfile(); + profile_2.SetRawInfo(NAME_FULL, u"Cersei Baratheon"); + + // `profile_1` and `profile_2` have the same `NAME_FIRST`, which will lead to + // the necessity of a differentiating label (`NAME_FULL`). + std::vector<Suggestion> suggestions = + suggestion_generator()->CreateSuggestionsFromProfiles( + {&profile_1, &profile_2}, {NAME_FIRST, NAME_MIDDLE}, + GetServerFieldTypesOfGroup(FieldTypeGroup::kName), NAME_FIRST, + /*trigger_field_max_length=*/0); + + ASSERT_EQ(suggestions.size(), 2u); EXPECT_EQ(suggestions[0].labels, std::vector<std::vector<Suggestion::Text>>( {{Suggestion::Text(u"Fill full name"), Suggestion::Text(u"-"), - Suggestion::Text(u"Elysium")}})); + Suggestion::Text(u"Cersei Lannister")}})); } TEST_F(AutofillChildrenSuggestionsGenenarationTest,
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index c1c9d6b..2a7840e 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -621,12 +621,13 @@ credit_card_form_event_logger_->OnDestroyed(); // We don't flush the `queued_vote_uploads_` here because that would trigger - // network requests in the AutofillDownloadManager, which are managed with - // by SimpleURLLoaders owned by the AutofillDownloadManager. Destroying the - // BrowserAutofillManager destroys the AutofillDownloadManager and its - // SimpleURLLoaders, which would immediately cancel the uploads. - // As a consequence of this, votes are lost if the user generates blur votes - // and closes the tab before the votes are sent (due to a navigation). + // network requests in the AutofillCrowdsourcingManager, which are managed + // with by SimpleURLLoaders owned by the AutofillCrowdsourcingManager. + // Destroying the BrowserAutofillManager destroys the + // AutofillCrowdsourcingManager and its SimpleURLLoaders, which would + // immediately cancel the uploads. As a consequence of this, votes are lost if + // the user generates blur votes and closes the tab before the votes are sent + // (due to a navigation). } base::WeakPtr<AutofillManager> BrowserAutofillManager::GetWeakPtr() { @@ -2058,7 +2059,7 @@ client().GetUkmRecorder(), source_id, *submitted_form, submission_time); } - if (!client().GetDownloadManager()) { + if (!client().GetCrowdsourcingManager()) { return; } @@ -2074,7 +2075,7 @@ non_empty_types.insert(CREDIT_CARD_VERIFICATION_CODE); } - client().GetDownloadManager()->StartUploadRequest( + client().GetCrowdsourcingManager()->StartUploadRequest( *submitted_form, was_autofilled, non_empty_types, /*login_form_signature=*/std::string(), observed_submission, client().GetPrefs(), GetWeakPtr());
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc index ba3e36d4..ed24393 100644 --- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc +++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -32,12 +32,12 @@ #include "build/chromeos_buildflags.h" #include "components/autofill/core/browser/autocomplete_history_manager.h" #include "components/autofill/core/browser/autofill_compose_delegate.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_form_test_utils.h" #include "components/autofill/core/browser/autofill_suggestion_generator.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/browser_autofill_manager.h" #include "components/autofill/core/browser/browser_autofill_manager_test_api.h" +#include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/form_structure_test_api.h" @@ -104,29 +104,11 @@ #include "url/gurl.h" #include "url/url_canon.h" -using base::UTF8ToUTF16; -using testing::_; -using testing::AllOf; -using testing::AnyOf; -using testing::AtLeast; -using testing::Contains; -using testing::DoAll; -using testing::Each; -using testing::ElementsAre; -using testing::Eq; -using testing::Field; -using testing::HasSubstr; -using testing::Matcher; -using testing::NiceMock; -using testing::Not; -using testing::Property; -using testing::Return; -using testing::SaveArg; -using testing::UnorderedElementsAre; -using testing::VariantWith; - namespace autofill { +namespace { + +using ::base::UTF8ToUTF16; using mojom::SubmissionIndicatorEvent; using mojom::SubmissionSource; using test::CreateTestAddressFormData; @@ -135,8 +117,26 @@ using test::CreateTestPersonalInformationFormData; using test::CreateTestSelectField; using test::CreateTestSelectOrSelectListField; - -namespace { +using ::testing::_; +using ::testing::AllOf; +using ::testing::AnyNumber; +using ::testing::AnyOf; +using ::testing::AtLeast; +using ::testing::Contains; +using ::testing::DoAll; +using ::testing::Each; +using ::testing::ElementsAre; +using ::testing::Eq; +using ::testing::Field; +using ::testing::HasSubstr; +using ::testing::Matcher; +using ::testing::NiceMock; +using ::testing::Not; +using ::testing::Property; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::UnorderedElementsAre; +using ::testing::VariantWith; const std::string kArbitraryNickname = "Grocery Card"; const std::u16string kArbitraryNickname16 = u"Grocery Card"; @@ -294,48 +294,6 @@ MOCK_METHOD(AutofillComposeDelegate*, GetComposeDelegate, (), (override)); }; -class MockAutofillDownloadManager : public AutofillDownloadManager { - public: - explicit MockAutofillDownloadManager(AutofillClient* client) - : AutofillDownloadManager(client, - /*api_key=*/"", - /*log_manager=*/nullptr) {} - - MockAutofillDownloadManager(const MockAutofillDownloadManager&) = delete; - MockAutofillDownloadManager& operator=(const MockAutofillDownloadManager&) = - delete; - - MOCK_METHOD(bool, - StartUploadRequest, - (const FormStructure&, - bool, - const ServerFieldTypeSet&, - const std::string&, - bool, - PrefService*, - base::WeakPtr<Observer>), - (override)); - - bool StartQueryRequest(const std::vector<FormStructure*>& forms, - net::IsolationInfo isolation_info, - base::WeakPtr<Observer> observer) override { - last_queried_forms_ = forms; - return true; - } - - // Verify that the last queried forms equal |expected_forms|. - void VerifyLastQueriedForms(const std::vector<FormData>& expected_forms) { - ASSERT_EQ(expected_forms.size(), last_queried_forms_.size()); - for (size_t i = 0; i < expected_forms.size(); ++i) { - EXPECT_EQ(last_queried_forms_[i]->global_id().renderer_id, - expected_forms[i].global_id().renderer_id); - } - } - - private: - std::vector<FormStructure*> last_queried_forms_; -}; - class MockTouchToFillDelegate : public TouchToFillDelegate { public: MockTouchToFillDelegate() = default; @@ -544,6 +502,12 @@ } } +// Returns a matcher that checks a `FormStructure`'s renderer id. +auto FormStructureHasRendererId(FormRendererId form_renderer_id) { + return Property(&FormStructure::global_id, + Field(&FormGlobalId::renderer_id, form_renderer_id)); +} + class MockAutofillDriver : public TestAutofillDriver { public: MockAutofillDriver() = default; @@ -632,8 +596,9 @@ ON_CALL(*single_field_form_fill_router(), OnGetSingleFieldSuggestions) .WillByDefault(Return(true)); - autofill_client_.set_download_manager( - std::make_unique<MockAutofillDownloadManager>(&autofill_client_)); + autofill_client_.set_crowdsourcing_manager( + std::make_unique<NiceMock<MockAutofillCrowdsourcingManager>>( + &autofill_client_)); browser_autofill_manager_->set_touch_to_fill_delegate( std::make_unique<NiceMock<MockTouchToFillDelegate>>()); @@ -1193,9 +1158,9 @@ } protected: - MockAutofillDownloadManager* download_manager() { - return static_cast<MockAutofillDownloadManager*>( - autofill_client_.GetDownloadManager()); + MockAutofillCrowdsourcingManager* crowdsourcing_manager() { + return static_cast<MockAutofillCrowdsourcingManager*>( + autofill_client_.GetCrowdsourcingManager()); } TestAutofillExternalDelegate* external_delegate() { return static_cast<TestAutofillExternalDelegate*>( @@ -1402,13 +1367,6 @@ TEST_F(BrowserAutofillManagerTest, OnFormsSeen_DifferentFormStructures) { // Set up our form data. FormData form = CreateTestAddressFormData(); - base::HistogramTester histogram_tester; - FormsSeen({form}); - histogram_tester.ExpectUniqueSample("Autofill.UserHappiness", - 0 /* FORMS_LOADED */, 1); - download_manager()->VerifyLastQueriedForms({form}); - - // Different form structure. FormData form2; form2.host_frame = test::MakeLocalFrameToken(); form2.unique_renderer_id = test::MakeFormRendererId(); @@ -1422,10 +1380,26 @@ FormControlType::kInputText), CreateTestFormField("Email", "email", "", FormControlType::kInputText)}; + EXPECT_CALL(*crowdsourcing_manager(), StartQueryRequest).Times(AnyNumber()); + EXPECT_CALL( + *crowdsourcing_manager(), + StartQueryRequest( + ElementsAre(FormStructureHasRendererId(form.unique_renderer_id)), _, + _)); + EXPECT_CALL( + *crowdsourcing_manager(), + StartQueryRequest( + ElementsAre(FormStructureHasRendererId(form2.unique_renderer_id)), _, + _)); + + base::HistogramTester histogram_tester; + FormsSeen({form}); + histogram_tester.ExpectUniqueSample("Autofill.UserHappiness", + 0 /* FORMS_LOADED */, 1); + FormsSeen({form2}); histogram_tester.ExpectUniqueSample("Autofill.UserHappiness", 0 /* FORMS_LOADED */, 2); - download_manager()->VerifyLastQueriedForms({form2}); } // Tests that only fields from `field_types_to_fill` are filled. @@ -3566,10 +3540,15 @@ // If the password manager is enabled, that's enough to parse the form. { base::HistogramTester histogram_tester; + EXPECT_CALL(*crowdsourcing_manager(), StartQueryRequest).Times(AnyNumber()); + EXPECT_CALL( + *crowdsourcing_manager(), + StartQueryRequest( + ElementsAre(FormStructureHasRendererId(form.unique_renderer_id)), _, + _)); FormsSeen({form}); histogram_tester.ExpectUniqueSample("Autofill.UserHappiness", 0 /* FORMS_LOADED */, 1); - download_manager()->VerifyLastQueriedForms({form}); } } @@ -10738,7 +10717,7 @@ BrowserAutofillManagerTest::SetUp(); // All uploads should be expected explicitly. - EXPECT_CALL(*download_manager(), StartUploadRequest).Times(0); + EXPECT_CALL(*crowdsourcing_manager(), StartUploadRequest).Times(0); form_.name = u"MyForm"; form_.url = GURL("https://myform.com/form.html"); @@ -10775,7 +10754,7 @@ // Ensure that vote is submitted after form submission. EXPECT_CALL( - *download_manager(), + *crowdsourcing_manager(), StartUploadRequest(AllOf(SignatureIs(CalculateFormSignature(form_)), UploadedAutofillTypesAre(expected_vote_types)), _, _, _, /*observed_submission=*/true, _, _)) @@ -10808,7 +10787,7 @@ ServerFieldType::NAME_LAST_SECOND}}, }; EXPECT_CALL( - *download_manager(), + *crowdsourcing_manager(), StartUploadRequest(AllOf(SignatureIs(first_form_signature), UploadedAutofillTypesAre(expected_vote_types)), _, _, _, /*observed_submission=*/false, _, _)) @@ -10833,7 +10812,7 @@ {u"zip", {ServerFieldType::EMPTY_TYPE}}, }; EXPECT_CALL( - *download_manager(), + *crowdsourcing_manager(), StartUploadRequest(AllOf(SignatureIs(second_form_signature), UploadedAutofillTypesAre(expected_vote_types)), _, _, _, @@ -10853,7 +10832,7 @@ {u"lastname", {ServerFieldType::EMPTY_TYPE}}, }; EXPECT_CALL( - *download_manager(), + *crowdsourcing_manager(), StartUploadRequest(AllOf(SignatureIs(CalculateFormSignature(form_)), UploadedAutofillTypesAre(expected_vote_types)), _, _, _, /*observed_submission=*/false, _, _)) @@ -10880,7 +10859,7 @@ browser_autofill_manager_->OnFocusNoLongerOnForm(true); EXPECT_CALL( - *download_manager(), + *crowdsourcing_manager(), StartUploadRequest(AllOf(SignatureIs(CalculateFormSignature(form_)), UploadedAutofillTypesAre(expected_vote_types)), _, _, _, /*observed_submission=*/true, _, _))
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc similarity index 91% rename from components/autofill/core/browser/autofill_download_manager.cc rename to components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc index 2148953..e7dc3c1 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/autofill_download_manager.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include <algorithm> #include <utility> @@ -66,7 +66,7 @@ {3314445, 3314448}, {3314854, 3314883}, }; -const size_t kAutofillDownloadManagerMaxFormCacheSize = 16; +const size_t kAutofillCrowdsourcingManagerMaxFormCacheSize = 16; const size_t kMaxFieldsPerQueryRequest = 100; const net::BackoffEntry::Policy kAutofillBackoffPolicy = { @@ -168,25 +168,27 @@ }); } -const char* RequestTypeToString(AutofillDownloadManager::RequestType type) { +const char* RequestTypeToString(AutofillCrowdsourcingManager::RequestType type) +{ switch (type) { - case AutofillDownloadManager::REQUEST_QUERY: + case AutofillCrowdsourcingManager::REQUEST_QUERY: return "Query"; - case AutofillDownloadManager::REQUEST_UPLOAD: + case AutofillCrowdsourcingManager::REQUEST_UPLOAD: return "Upload"; } NOTREACHED_NORETURN(); } -std::string GetMetricName(AutofillDownloadManager::RequestType request_type, +std::string GetMetricName( + AutofillCrowdsourcingManager::RequestType request_type, std::string_view suffix) { return base::StrCat( {"Autofill.", RequestTypeToString(request_type), ".", suffix}); } net::NetworkTrafficAnnotationTag GetNetworkTrafficAnnotation( - const AutofillDownloadManager::RequestType& request_type) { - if (request_type == AutofillDownloadManager::REQUEST_QUERY) { + const AutofillCrowdsourcingManager::RequestType& request_type) { + if (request_type == AutofillCrowdsourcingManager::REQUEST_QUERY) { return net::DefineNetworkTrafficAnnotation("autofill_query", R"( semantics { sender: "Autofill" @@ -239,7 +241,7 @@ })"); } - DCHECK_EQ(request_type, AutofillDownloadManager::REQUEST_UPLOAD); + DCHECK_EQ(request_type, AutofillCrowdsourcingManager::REQUEST_UPLOAD); return net::DefineNetworkTrafficAnnotation("autofill_upload", R"( semantics { sender: "Autofill" @@ -417,7 +419,7 @@ base::Time last_reset = pref_service->GetTime(prefs::kAutofillUploadEventsLastResetTimestamp); if ((now - last_reset) > throttle_reset_period) { - AutofillDownloadManager::ClearUploadHistory(pref_service); + AutofillCrowdsourcingManager::ClearUploadHistory(pref_service); } // Get the key for the upload bucket and extract the current bitfield value. @@ -468,14 +470,14 @@ // * GetAPIMethodUrl(REQUEST_QUERY, "1234", "GET") will return "/v1/pages/1234". // * GetAPIMethodUrl(REQUEST_QUERY, "1234", "POST") will return "/v1/pages:get". // * GetAPIMethodUrl(REQUEST_UPLOAD, "", "POST") will return "/v1/forms:vote". -std::string GetAPIMethodUrl(AutofillDownloadManager::RequestType type, +std::string GetAPIMethodUrl(AutofillCrowdsourcingManager::RequestType type, base::StringPiece resource_id, base::StringPiece method) { const char* api_method_url = [&] { switch (type) { - case AutofillDownloadManager::REQUEST_QUERY: + case AutofillCrowdsourcingManager::REQUEST_QUERY: return method == "POST" ? "/v1/pages:get" : "/v1/pages"; - case AutofillDownloadManager::REQUEST_UPLOAD: + case AutofillCrowdsourcingManager::REQUEST_UPLOAD: return "/v1/forms:vote"; } NOTREACHED_NORETURN(); @@ -489,9 +491,9 @@ // Gets HTTP body payload for API POST request. absl::optional<std::string> GetAPIBodyPayload( std::string payload, - AutofillDownloadManager::RequestType type) { + AutofillCrowdsourcingManager::RequestType type) { // Don't do anything for payloads not related to Query. - if (type != AutofillDownloadManager::REQUEST_QUERY) { + if (type != AutofillCrowdsourcingManager::REQUEST_QUERY) { return std::move(payload); } // Wrap query payload in a request proto to interface with API Query method. @@ -534,7 +536,7 @@ } // namespace -struct AutofillDownloadManager::FormRequestData { +struct AutofillCrowdsourcingManager::FormRequestData { base::WeakPtr<Observer> observer; std::vector<FormSignature> form_signatures; RequestType request_type; @@ -544,24 +546,24 @@ }; ScopedActiveAutofillExperiments::ScopedActiveAutofillExperiments() { - AutofillDownloadManager::ResetActiveExperiments(); + AutofillCrowdsourcingManager::ResetActiveExperiments(); } ScopedActiveAutofillExperiments::~ScopedActiveAutofillExperiments() { - AutofillDownloadManager::ResetActiveExperiments(); + AutofillCrowdsourcingManager::ResetActiveExperiments(); } std::vector<variations::VariationID>* - AutofillDownloadManager::active_experiments_ = nullptr; + AutofillCrowdsourcingManager::active_experiments_ = nullptr; -AutofillDownloadManager::AutofillDownloadManager(AutofillClient* client, +AutofillCrowdsourcingManager::AutofillCrowdsourcingManager(AutofillClient* client, version_info::Channel channel, LogManager* log_manager) - : AutofillDownloadManager(client, + : AutofillCrowdsourcingManager(client, GetAPIKeyForUrl(channel), log_manager) {} -AutofillDownloadManager::AutofillDownloadManager(AutofillClient* client, +AutofillCrowdsourcingManager::AutofillCrowdsourcingManager(AutofillClient* client, const std::string& api_key, LogManager* log_manager) : client_(client), @@ -569,18 +571,18 @@ log_manager_(log_manager), autofill_server_url_(GetAutofillServerURL()), throttle_reset_period_(GetThrottleResetPeriod()), - max_form_cache_size_(kAutofillDownloadManagerMaxFormCacheSize), + max_form_cache_size_(kAutofillCrowdsourcingManagerMaxFormCacheSize), loader_backoff_(&kAutofillBackoffPolicy) {} -AutofillDownloadManager::~AutofillDownloadManager() = default; +AutofillCrowdsourcingManager::~AutofillCrowdsourcingManager() = default; -bool AutofillDownloadManager::IsEnabled() const { +bool AutofillCrowdsourcingManager::IsEnabled() const { return autofill_server_url_.is_valid() && base::FeatureList::IsEnabled( features::test::kAutofillServerCommunication); } -bool AutofillDownloadManager::StartQueryRequest( +bool AutofillCrowdsourcingManager::StartQueryRequest( const std::vector<FormStructure*>& forms, net::IsolationInfo isolation_info, base::WeakPtr<Observer> observer) { @@ -619,7 +621,7 @@ FormRequestData request_data = { .observer = observer, .form_signatures = std::move(queried_form_signatures), - .request_type = AutofillDownloadManager::REQUEST_QUERY, + .request_type = AutofillCrowdsourcingManager::REQUEST_QUERY, .isolation_info = std::move(isolation_info), .payload = std::move(payload).value(), }; @@ -642,7 +644,7 @@ return StartRequest(std::move(request_data)); } -bool AutofillDownloadManager::StartUploadRequest( +bool AutofillCrowdsourcingManager::StartUploadRequest( const FormStructure& form, bool form_was_autofilled, const ServerFieldTypeSet& available_field_types, @@ -689,7 +691,7 @@ FormRequestData request_data = { .observer = observer, .form_signatures = {form.form_signature()}, - .request_type = AutofillDownloadManager::REQUEST_UPLOAD, + .request_type = AutofillCrowdsourcingManager::REQUEST_UPLOAD, .isolation_info = absl::nullopt, .payload = std::move(payload).value(), }; @@ -714,7 +716,7 @@ return all_succeeded; } -void AutofillDownloadManager::ClearUploadHistory(PrefService* pref_service) { +void AutofillCrowdsourcingManager::ClearUploadHistory(PrefService* pref_service) { if (pref_service) { pref_service->ClearPref(prefs::kAutofillUploadEvents); pref_service->SetTime(prefs::kAutofillUploadEventsLastResetTimestamp, @@ -722,19 +724,19 @@ } } -size_t AutofillDownloadManager::GetPayloadLength( +size_t AutofillCrowdsourcingManager::GetPayloadLength( base::StringPiece payload) const { return payload.length(); } -std::tuple<GURL, std::string> AutofillDownloadManager::GetRequestURLAndMethod( +std::tuple<GURL, std::string> AutofillCrowdsourcingManager::GetRequestURLAndMethod( const FormRequestData& request_data) const { // ID of the resource to add to the API request URL. Nothing will be added if // |resource_id| is empty. std::string resource_id; std::string method = "POST"; - if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY) { + if (request_data.request_type == AutofillCrowdsourcingManager::REQUEST_QUERY) { if (GetPayloadLength(request_data.payload) <= kMaxQueryGetSize) { resource_id = request_data.payload; method = "GET"; @@ -756,7 +758,7 @@ return std::make_tuple(std::move(url), std::move(method)); } -bool AutofillDownloadManager::StartRequest(FormRequestData request_data) { +bool AutofillCrowdsourcingManager::StartRequest(FormRequestData request_data) { // REQUEST_UPLOADs take no IsolationInfo because Password Manager uploads when // RenderFrameHostImpl::DidCommitNavigation() is called, in which case // AutofillDriver::IsolationInfo() may crash because there is no committing @@ -764,7 +766,7 @@ // information about the response is passed to the renderer, or is otherwise // visible to a page. See crbug/1176635#c22. DCHECK( - (request_data.request_type == AutofillDownloadManager::REQUEST_UPLOAD) == + (request_data.request_type == AutofillCrowdsourcingManager::REQUEST_UPLOAD) == !request_data.isolation_info); // Get the URL and method to use for this request. @@ -772,7 +774,7 @@ // Track the URL length for GET queries because the URL length can be in the // thousands when rich metadata is enabled. - if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY && + if (request_data.request_type == AutofillCrowdsourcingManager::REQUEST_QUERY && method == "GET") { base::UmaHistogramCounts100000("Autofill.Query.GetUrlLength", request_url.spec().length()); @@ -843,13 +845,13 @@ url_loaders_.push_back(std::move(simple_loader)); raw_simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( client_->GetURLLoaderFactory().get(), - base::BindOnce(&AutofillDownloadManager::OnSimpleLoaderComplete, + base::BindOnce(&AutofillCrowdsourcingManager::OnSimpleLoaderComplete, base::Unretained(this), std::move(--url_loaders_.end()), std::move(request_data), AutofillTickClock::NowTicks())); return true; } -void AutofillDownloadManager::CacheQueryRequest( +void AutofillCrowdsourcingManager::CacheQueryRequest( const std::vector<FormSignature>& forms_in_query, const std::string& query_data) { for (auto it = cached_forms_.begin(); it != cached_forms_.end(); ++it) { @@ -866,7 +868,7 @@ cached_forms_.pop_back(); } -bool AutofillDownloadManager::CheckCacheForQueryRequest( +bool AutofillCrowdsourcingManager::CheckCacheForQueryRequest( const std::vector<FormSignature>& forms_in_query, std::string* query_data) const { for (const auto& [signatures, cached_data] : cached_forms_) { @@ -880,7 +882,7 @@ } // static -int AutofillDownloadManager::GetMaxServerAttempts() { +int AutofillCrowdsourcingManager::GetMaxServerAttempts() { // This value is constant for the life of the browser, so we cache it // statically on first use to avoid re-parsing the param on each retry // opportunity. @@ -889,7 +891,7 @@ return max_attempts; } -void AutofillDownloadManager::OnSimpleLoaderComplete( +void AutofillCrowdsourcingManager::OnSimpleLoaderComplete( std::list<std::unique_ptr<network::SimpleURLLoader>>::iterator it, FormRequestData request_data, base::TimeTicks request_start, @@ -926,7 +928,7 @@ if (!success) { std::string error_message = (response_body != nullptr) ? *response_body : ""; - DVLOG(1) << "AutofillDownloadManager: " + DVLOG(1) << "AutofillCrowdsourcingManager: " << RequestTypeToString(request_data.request_type) << " request has failed with net error " << simple_loader->NetError() << " and HTTP response code " @@ -960,7 +962,7 @@ base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, base::BindOnce( - base::IgnoreResult(&AutofillDownloadManager::StartRequest), + base::IgnoreResult(&AutofillCrowdsourcingManager::StartRequest), weak_factory_.GetWeakPtr(), std::move(request_data)), backoff); return; @@ -978,7 +980,7 @@ return; } case REQUEST_UPLOAD: - DVLOG(1) << "AutofillDownloadManager: upload request has succeeded."; + DVLOG(1) << "AutofillCrowdsourcingManager: upload request has succeeded."; if (request_data.observer) { request_data.observer->OnUploadedPossibleFieldTypes(); } @@ -987,7 +989,7 @@ NOTREACHED_NORETURN(); } -void AutofillDownloadManager::InitActiveExperiments() { +void AutofillCrowdsourcingManager::InitActiveExperiments() { auto* variations_ids_provider = variations::VariationsIdsProvider::GetInstance(); DCHECK(variations_ids_provider != nullptr); @@ -1012,7 +1014,7 @@ } // static -void AutofillDownloadManager::ResetActiveExperiments() { +void AutofillCrowdsourcingManager::ResetActiveExperiments() { delete active_experiments_; active_experiments_ = nullptr; }
diff --git a/components/autofill/core/browser/autofill_download_manager.h b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h similarity index 85% rename from components/autofill/core/browser/autofill_download_manager.h rename to components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h index 8768e76..bfa546f 100644 --- a/components/autofill/core/browser/autofill_download_manager.h +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h
@@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DOWNLOAD_MANAGER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DOWNLOAD_MANAGER_H_ +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_CROWDSOURCING_AUTOFILL_CROWDSOURCING_MANAGER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_CROWDSOURCING_AUTOFILL_CROWDSOURCING_MANAGER_H_ #include <stddef.h> #include <list> -#include <map> #include <memory> #include <string> #include <tuple> -#include <utility> #include <vector> #include "base/compiler_specific.h" @@ -38,7 +36,7 @@ class AutofillClient; class LogManager; -constexpr size_t kMaxQueryGetSize = 10240; // 10 KiB +inline constexpr size_t kMaxQueryGetSize = 10240; // 10 KiB // A helper to make sure that tests which modify the set of active autofill // experiments do not interfere with one another. @@ -47,15 +45,15 @@ ~ScopedActiveAutofillExperiments(); }; -// Handles getting and updating Autofill heuristics. -class AutofillDownloadManager { +// Obtains Autofill server predictions and upload votes for generating them. +class AutofillCrowdsourcingManager { public: enum RequestType { REQUEST_QUERY, REQUEST_UPLOAD, }; - // An interface used to notify clients of AutofillDownloadManager. + // An interface used to notify clients of AutofillCrowdsourcingManager. class Observer { public: // Called when field type predictions are successfully received from the @@ -82,14 +80,14 @@ virtual ~Observer() = default; }; - // `client` owns (and hence survives) this AutofillDownloadManager. + // `client` owns (and hence survives) this AutofillCrowdsourcingManager. // `channel` determines the value for the the Google-API-key HTTP header and // whether raw metadata uploading is enabled. - AutofillDownloadManager(AutofillClient* client, + AutofillCrowdsourcingManager(AutofillClient* client, version_info::Channel channel, LogManager* log_manager); - virtual ~AutofillDownloadManager(); + virtual ~AutofillCrowdsourcingManager(); // Starts a query request to Autofill servers. The observer is called with the // list of the fields of all requested forms. @@ -127,7 +125,7 @@ static void ClearUploadHistory(PrefService* pref_service); protected: - AutofillDownloadManager(AutofillClient* client, + AutofillCrowdsourcingManager(AutofillClient* client, const std::string& api_key, LogManager* log_manager); @@ -137,13 +135,13 @@ virtual size_t GetPayloadLength(base::StringPiece payload) const; private: - friend class AutofillDownloadManagerTest; + friend class AutofillCrowdsourcingManagerTest; friend struct ScopedActiveAutofillExperiments; - FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, QueryAndUploadTest); - FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, BackoffLogic_Upload); - FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, BackoffLogic_Query); - FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, RetryLimit_Upload); - FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, RetryLimit_Query); + FRIEND_TEST_ALL_PREFIXES(AutofillCrowdsourcingManagerTest, QueryAndUploadTest); + FRIEND_TEST_ALL_PREFIXES(AutofillCrowdsourcingManagerTest, BackoffLogic_Upload); + FRIEND_TEST_ALL_PREFIXES(AutofillCrowdsourcingManagerTest, BackoffLogic_Query); + FRIEND_TEST_ALL_PREFIXES(AutofillCrowdsourcingManagerTest, RetryLimit_Upload); + FRIEND_TEST_ALL_PREFIXES(AutofillCrowdsourcingManagerTest, RetryLimit_Query); struct FormRequestData; typedef std::list<std::pair<std::vector<FormSignature>, std::string>> @@ -202,7 +200,7 @@ const std::string api_key_; // Access to leave log messages for chrome://autofill-internals, may be null. - const raw_ptr<LogManager> log_manager_; // WEAK + const raw_ptr<LogManager> log_manager_; // The autofill server URL root: scheme://host[:port]/path excluding the // final path component for the request and the query params. @@ -224,9 +222,9 @@ // Used for exponential backoff of requests. net::BackoffEntry loader_backoff_; - base::WeakPtrFactory<AutofillDownloadManager> weak_factory_{this}; + base::WeakPtrFactory<AutofillCrowdsourcingManager> weak_factory_{this}; }; } // namespace autofill -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DOWNLOAD_MANAGER_H_ +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_CROWDSOURCING_AUTOFILL_CROWDSOURCING_MANAGER_H_
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc similarity index 93% rename from components/autofill/core/browser/autofill_download_manager_unittest.cc rename to components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc index 58d074f..5c62e6e 100644 --- a/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/core/browser/autofill_download_manager.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include <stddef.h> @@ -153,17 +153,17 @@ return true; } -class AutofillDownloadManagerWithCustomPayloadSize - : public AutofillDownloadManager { +class AutofillCrowdsourcingManagerWithCustomPayloadSize + : public AutofillCrowdsourcingManager { public: - AutofillDownloadManagerWithCustomPayloadSize(AutofillClient* client, + AutofillCrowdsourcingManagerWithCustomPayloadSize(AutofillClient* client, const std::string& api_key, size_t length) - : AutofillDownloadManager(client, + : AutofillCrowdsourcingManager(client, api_key, /*log_manager=*/nullptr), length_(length) {} - ~AutofillDownloadManagerWithCustomPayloadSize() override = default; + ~AutofillCrowdsourcingManagerWithCustomPayloadSize() override = default; protected: size_t GetPayloadLength(base::StringPiece payload) const override { @@ -176,15 +176,15 @@ } // namespace -// This tests AutofillDownloadManager. AutofillDownloadManagerTest implements -// AutofillDownloadManager::Observer and creates an instance of -// AutofillDownloadManager. Then it records responses to different initiated +// This tests AutofillCrowdsourcingManager. AutofillCrowdsourcingManagerTest implements +// AutofillCrowdsourcingManager::Observer and creates an instance of +// AutofillCrowdsourcingManager. Then it records responses to different initiated // requests, which are verified later. To mock network requests // TestURLLoaderFactory is used, which creates SimpleURLLoaders that do not // go over the wire, but allow calling back HTTP responses directly. // The responses in test are out of order and verify: successful query request, // successful upload request, failed upload request. -class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer, +class AutofillCrowdsourcingManagerTest : public AutofillCrowdsourcingManager::Observer, public ::testing::Test { public: enum ResponseType { @@ -201,42 +201,42 @@ std::string response; }; - class TestAutofillDownloadManager : public AutofillDownloadManager { + class TestAutofillCrowdsourcingManager : public AutofillCrowdsourcingManager { public: - explicit TestAutofillDownloadManager(AutofillClient* client, + explicit TestAutofillCrowdsourcingManager(AutofillClient* client, std::string api_key = "") - : AutofillDownloadManager(client, + : AutofillCrowdsourcingManager(client, /*api_key=*/std::move(api_key), /*log_manager=*/nullptr) {} }; - AutofillDownloadManagerTest() + AutofillCrowdsourcingManagerTest() : test_shared_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)), - download_manager_(&client_, + crowdsourcing_manager_(&client_, /*api_key=*/"", /*log_manager=*/nullptr), pref_service_(test::PrefServiceForTesting()) { client_.set_shared_url_loader_factory(test_shared_loader_factory_); } - base::WeakPtr<AutofillDownloadManagerTest> GetWeakPtr() { + base::WeakPtr<AutofillCrowdsourcingManagerTest> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } void LimitCache(size_t cache_size) { - download_manager_.set_max_form_cache_size(cache_size); + crowdsourcing_manager_.set_max_form_cache_size(cache_size); } bool StartQueryRequest( const std::vector<std::unique_ptr<FormStructure>>& form_structures) { - return download_manager_.StartQueryRequest( + return crowdsourcing_manager_.StartQueryRequest( ToRawPointerVector(form_structures), driver_.IsolationInfo(), weak_ptr_factory_.GetWeakPtr()); } - // AutofillDownloadManager::Observer implementation. + // AutofillCrowdsourcingManager::Observer implementation. void OnLoadedServerPredictions( std::string response_xml, const std::vector<FormSignature>& form_signatures) override { @@ -253,13 +253,13 @@ } void OnServerRequestError(FormSignature form_signature, - AutofillDownloadManager::RequestType request_type, + AutofillCrowdsourcingManager::RequestType request_type, int http_error) override { ResponseData response; response.signature = base::NumberToString(form_signature.value()); response.error = http_error; response.type_of_response = - request_type == AutofillDownloadManager::REQUEST_QUERY + request_type == AutofillCrowdsourcingManager::REQUEST_QUERY ? REQUEST_QUERY_FAILED : REQUEST_UPLOAD_FAILED; responses_.push_back(response); @@ -274,14 +274,14 @@ network::TestURLLoaderFactory test_url_loader_factory_; TestAutofillClient client_; TestAutofillDriver driver_; - AutofillDownloadManager download_manager_; + AutofillCrowdsourcingManager crowdsourcing_manager_; std::unique_ptr<PrefService> pref_service_; private: - base::WeakPtrFactory<AutofillDownloadManagerTest> weak_ptr_factory_{this}; + base::WeakPtrFactory<AutofillCrowdsourcingManagerTest> weak_ptr_factory_{this}; }; -TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) { +TEST_F(AutofillCrowdsourcingManagerTest, QueryAndUploadTest) { FormData form; FormFieldData field; @@ -371,13 +371,13 @@ } // Make download manager. - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( &client_, "dummykey", /*log_manager=*/nullptr); // Request with id 0. base::HistogramTester histogram; - EXPECT_TRUE(download_manager.StartQueryRequest( + EXPECT_TRUE(crowdsourcing_manager.StartQueryRequest( ToRawPointerVector(form_structures), driver_.IsolationInfo(), GetWeakPtr())); histogram.ExpectUniqueSample("Autofill.ServerQueryResponse", @@ -393,16 +393,16 @@ EXPECT_EQ(api_key_header_value, "dummykey"); // Request with id 1. - EXPECT_TRUE(download_manager.StartUploadRequest( + EXPECT_TRUE(crowdsourcing_manager.StartUploadRequest( *(form_structures[0]), true, ServerFieldTypeSet(), std::string(), true, pref_service_.get(), GetWeakPtr())); // Request with id 2. - EXPECT_TRUE(download_manager.StartUploadRequest( + EXPECT_TRUE(crowdsourcing_manager.StartUploadRequest( *(form_structures[1]), false, ServerFieldTypeSet(), std::string(), true, pref_service_.get(), GetWeakPtr())); // Request with id 3. Upload request with a non-empty additional password form // signature. - EXPECT_TRUE(download_manager.StartUploadRequest( + EXPECT_TRUE(crowdsourcing_manager.StartUploadRequest( *(form_structures[2]), false, ServerFieldTypeSet(), "42", true, pref_service_.get(), GetWeakPtr())); @@ -448,7 +448,7 @@ net::HTTP_OK, 1); // Check Request 1. - EXPECT_EQ(AutofillDownloadManagerTest::UPLOAD_SUCCESSFULL, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::UPLOAD_SUCCESSFULL, responses_.front().type_of_response); EXPECT_EQ(0, responses_.front().error); EXPECT_EQ(std::string(), responses_.front().signature); @@ -457,7 +457,7 @@ responses_.pop_front(); // Check Request 2. - EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_UPLOAD_FAILED, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::REQUEST_UPLOAD_FAILED, responses_.front().type_of_response); EXPECT_EQ(net::HTTP_NOT_FOUND, responses_.front().error); EXPECT_EQ(form_structures[1]->FormSignatureAsStr(), @@ -468,7 +468,7 @@ // Check Request 0. EXPECT_EQ(responses_.front().type_of_response, - AutofillDownloadManagerTest::QUERY_SUCCESSFULL); + AutofillCrowdsourcingManagerTest::QUERY_SUCCESSFULL); EXPECT_EQ(0, responses_.front().error); EXPECT_EQ(std::string(), responses_.front().signature); EXPECT_EQ(responses[0], responses_.front().response); @@ -482,7 +482,7 @@ form_structures.push_back(std::make_unique<FormStructure>(form)); // Request with id 4, not successful. - EXPECT_TRUE(download_manager.StartQueryRequest( + EXPECT_TRUE(crowdsourcing_manager.StartQueryRequest( ToRawPointerVector(form_structures), driver_.IsolationInfo(), GetWeakPtr())); request = test_url_loader_factory_.GetPendingRequest(4); @@ -496,7 +496,7 @@ net::HTTP_INTERNAL_SERVER_ERROR, 1); // Check Request 4. - EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_QUERY_FAILED, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::REQUEST_QUERY_FAILED, responses_.front().type_of_response); EXPECT_EQ(net::HTTP_INTERNAL_SERVER_ERROR, responses_.front().error); // Expected response on non-query request is an empty string. @@ -504,7 +504,7 @@ responses_.pop_front(); // Request with id 5. Let's pretend we hit the cache. - EXPECT_TRUE(download_manager.StartQueryRequest( + EXPECT_TRUE(crowdsourcing_manager.StartQueryRequest( ToRawPointerVector(form_structures), driver_.IsolationInfo(), GetWeakPtr())); histogram.ExpectBucketCount("Autofill.ServerQueryResponse", @@ -520,12 +520,12 @@ // Check Request 5. EXPECT_EQ(responses_.front().type_of_response, - AutofillDownloadManagerTest::QUERY_SUCCESSFULL); + AutofillCrowdsourcingManagerTest::QUERY_SUCCESSFULL); responses_.pop_front(); histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_HIT, 1); } -TEST_F(AutofillDownloadManagerTest, QueryAPITest) { +TEST_F(AutofillCrowdsourcingManagerTest, QueryAPITest) { // Build the form structures that we want to query. FormData form; FormFieldData field; @@ -543,12 +543,12 @@ std::vector<std::unique_ptr<FormStructure>> form_structures; form_structures.push_back(std::make_unique<FormStructure>(form)); - TestAutofillDownloadManager download_manager(&client_, "dummykey"); + TestAutofillCrowdsourcingManager crowdsourcing_manager(&client_, "dummykey"); // Start the query request and look if it is successful. No response was // received yet. base::HistogramTester histogram; - EXPECT_TRUE(download_manager.StartQueryRequest( + EXPECT_TRUE(crowdsourcing_manager.StartQueryRequest( ToRawPointerVector(form_structures), driver_.IsolationInfo(), GetWeakPtr())); @@ -617,13 +617,13 @@ // to be called back from the observer and some histograms be incremented. EXPECT_EQ(1U, responses_.size()); EXPECT_EQ(responses_.front().type_of_response, - AutofillDownloadManagerTest::QUERY_SUCCESSFULL); + AutofillCrowdsourcingManagerTest::QUERY_SUCCESSFULL); histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 1); histogram.ExpectBucketCount("Autofill.Query.HttpResponseOrErrorCode", net::HTTP_OK, 1); } -TEST_F(AutofillDownloadManagerTest, QueryAPITestWhenTooLongUrl) { +TEST_F(AutofillCrowdsourcingManagerTest, QueryAPITestWhenTooLongUrl) { // Build the form structures that we want to query. FormData form; FormFieldData field; @@ -638,13 +638,13 @@ form_structures.push_back(std::move(form_structure)); } - AutofillDownloadManagerWithCustomPayloadSize download_manager( + AutofillCrowdsourcingManagerWithCustomPayloadSize crowdsourcing_manager( &client_, "dummykey", kMaxQueryGetSize + 1); // Start the query request and look if it is successful. No response was // received yet. base::HistogramTester histogram; - EXPECT_TRUE(download_manager.StartQueryRequest( + EXPECT_TRUE(crowdsourcing_manager.StartQueryRequest( ToRawPointerVector(form_structures), driver_.IsolationInfo(), GetWeakPtr())); @@ -710,7 +710,7 @@ // to be called back from the observer and some histograms be incremented. EXPECT_EQ(1U, responses_.size()); EXPECT_EQ(responses_.front().type_of_response, - AutofillDownloadManagerTest::QUERY_SUCCESSFULL); + AutofillCrowdsourcingManagerTest::QUERY_SUCCESSFULL); histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 1); histogram.ExpectBucketCount("Autofill.Query.HttpResponseOrErrorCode", net::HTTP_OK, 1); @@ -723,7 +723,7 @@ // We expect the download manager to do the following things: // * Use the right API canonical URL when uploading. // * Serialize the upload proto content using the API upload request proto. -TEST_F(AutofillDownloadManagerTest, UploadToAPITest) { +TEST_F(AutofillCrowdsourcingManagerTest, UploadToAPITest) { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeatures( // Enabled @@ -752,8 +752,8 @@ fs_field->host_form_signature = form_structure.form_signature(); std::unique_ptr<PrefService> pref_service = test::PrefServiceForTesting(); - TestAutofillDownloadManager download_manager(&client_, "dummykey"); - EXPECT_TRUE(download_manager.StartUploadRequest( + TestAutofillCrowdsourcingManager crowdsourcing_manager(&client_, "dummykey"); + EXPECT_TRUE(crowdsourcing_manager.StartUploadRequest( form_structure, true, ServerFieldTypeSet(), "", true, pref_service.get(), GetWeakPtr())); @@ -790,7 +790,7 @@ // histograms be incremented. EXPECT_EQ(1U, responses_.size()); // Request should be upload and successful. - EXPECT_EQ(AutofillDownloadManagerTest::UPLOAD_SUCCESSFULL, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::UPLOAD_SUCCESSFULL, responses_.front().type_of_response); // We expect the request to be OK and corresponding response code to be // counted. @@ -798,7 +798,7 @@ net::HTTP_OK, 1); } -TEST_F(AutofillDownloadManagerTest, BackoffLogic_Query) { +TEST_F(AutofillCrowdsourcingManagerTest, BackoffLogic_Query) { FormData form; FormFieldData field; field.label = u"address"; @@ -842,7 +842,7 @@ "", network::URLLoaderCompletionStatus(net::OK)); EXPECT_EQ(1U, responses_.size()); - EXPECT_LT(download_manager_.loader_backoff_.GetTimeUntilRelease(), + EXPECT_LT(crowdsourcing_manager_.loader_backoff_.GetTimeUntilRelease(), base::Milliseconds(1100)); base::RunLoop run_loop; base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( @@ -859,7 +859,7 @@ "<html></html>", network::URLLoaderCompletionStatus(net::OK)); EXPECT_EQ(2U, responses_.size()); - EXPECT_LT(download_manager_.loader_backoff_.GetTimeUntilRelease(), + EXPECT_LT(crowdsourcing_manager_.loader_backoff_.GetTimeUntilRelease(), base::Milliseconds(2100)); // There should not be an additional retry. @@ -871,7 +871,7 @@ EXPECT_EQ(2, buckets[0].count); } -TEST_F(AutofillDownloadManagerTest, BackoffLogic_Upload) { +TEST_F(AutofillCrowdsourcingManagerTest, BackoffLogic_Upload) { FormData form; FormFieldData field; field.label = u"address"; @@ -900,7 +900,7 @@ fs_field->host_form_signature = form_structure->form_signature(); // Request with id 0. - EXPECT_TRUE(download_manager_.StartUploadRequest( + EXPECT_TRUE(crowdsourcing_manager_.StartUploadRequest( *form_structure, true, ServerFieldTypeSet(), std::string(), true, pref_service_.get(), GetWeakPtr())); @@ -911,7 +911,7 @@ request, network::CreateURLResponseHead(net::HTTP_INTERNAL_SERVER_ERROR), "", network::URLLoaderCompletionStatus(net::OK)); EXPECT_EQ(1U, responses_.size()); - EXPECT_LT(download_manager_.loader_backoff_.GetTimeUntilRelease(), + EXPECT_LT(crowdsourcing_manager_.loader_backoff_.GetTimeUntilRelease(), base::Milliseconds(1100)); base::RunLoop run_loop; base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( @@ -919,7 +919,7 @@ run_loop.Run(); // Check that it was a failure. - EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_UPLOAD_FAILED, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::REQUEST_UPLOAD_FAILED, responses_.front().type_of_response); EXPECT_EQ(net::HTTP_INTERNAL_SERVER_ERROR, responses_.front().error); EXPECT_EQ(form_structure->FormSignatureAsStr(), responses_.front().signature); @@ -933,7 +933,7 @@ request, ""); // Check success of response. - EXPECT_EQ(AutofillDownloadManagerTest::UPLOAD_SUCCESSFULL, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::UPLOAD_SUCCESSFULL, responses_.front().type_of_response); EXPECT_EQ(0, responses_.front().error); EXPECT_EQ(std::string(), responses_.front().signature); @@ -944,7 +944,7 @@ // Validate no retry on sending a bad request. form_structure->set_submission_source(SubmissionSource::XHR_SUCCEEDED); base::HistogramTester histogram; - EXPECT_TRUE(download_manager_.StartUploadRequest( + EXPECT_TRUE(crowdsourcing_manager_.StartUploadRequest( *form_structure, true, ServerFieldTypeSet(), std::string(), true, pref_service_.get(), GetWeakPtr())); request = test_url_loader_factory_.GetPendingRequest(2); @@ -960,7 +960,7 @@ EXPECT_EQ(1, buckets[0].count); } -TEST_F(AutofillDownloadManagerTest, RetryLimit_Query) { +TEST_F(AutofillCrowdsourcingManagerTest, RetryLimit_Query) { FormData form; FormFieldData field; field.label = u"address"; @@ -993,7 +993,7 @@ AutofillMetrics::QUERY_SENT, 1); const auto kTimeDeltaMargin = base::Milliseconds(100); - const int max_attempts = download_manager_.GetMaxServerAttempts(); + const int max_attempts = crowdsourcing_manager_.GetMaxServerAttempts(); int attempt = 0; while (true) { auto* request = test_url_loader_factory_.GetPendingRequest(attempt); @@ -1007,7 +1007,7 @@ EXPECT_EQ(1U, responses_.size()); const auto& response = responses_.front(); - EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_QUERY_FAILED, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::REQUEST_QUERY_FAILED, response.type_of_response); EXPECT_EQ(net::HTTP_INTERNAL_SERVER_ERROR, response.error); responses_.pop_front(); @@ -1018,7 +1018,7 @@ base::RunLoop run_loop; base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, run_loop.QuitClosure(), - download_manager_.loader_backoff_.GetTimeUntilRelease() + + crowdsourcing_manager_.loader_backoff_.GetTimeUntilRelease() + kTimeDeltaMargin); run_loop.Run(); } @@ -1036,7 +1036,7 @@ EXPECT_EQ(max_attempts, buckets[0].count); } -TEST_F(AutofillDownloadManagerTest, RetryLimit_Upload) { +TEST_F(AutofillCrowdsourcingManagerTest, RetryLimit_Upload) { FormData form; FormFieldData field; field.label = u"address"; @@ -1068,11 +1068,11 @@ fs_field->host_form_signature = form_structure->form_signature(); // Request with id 0. - EXPECT_TRUE(download_manager_.StartUploadRequest( + EXPECT_TRUE(crowdsourcing_manager_.StartUploadRequest( *form_structure, true, ServerFieldTypeSet(), std::string(), true, pref_service_.get(), GetWeakPtr())); - const int max_attempts = download_manager_.GetMaxServerAttempts(); + const int max_attempts = crowdsourcing_manager_.GetMaxServerAttempts(); int attempt = 0; while (true) { auto* request = test_url_loader_factory_.GetPendingRequest(attempt); @@ -1087,7 +1087,7 @@ // Check that it was a failure. ASSERT_EQ(1U, responses_.size()); const auto& response = responses_.front(); - EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_UPLOAD_FAILED, + EXPECT_EQ(AutofillCrowdsourcingManagerTest::REQUEST_UPLOAD_FAILED, response.type_of_response); EXPECT_EQ(net::HTTP_INTERNAL_SERVER_ERROR, response.error); responses_.pop_front(); @@ -1100,7 +1100,7 @@ base::RunLoop run_loop; base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, run_loop.QuitClosure(), - download_manager_.loader_backoff_.GetTimeUntilRelease() + + crowdsourcing_manager_.loader_backoff_.GetTimeUntilRelease() + kTimeDeltaMargin); run_loop.Run(); } @@ -1118,7 +1118,7 @@ EXPECT_EQ(max_attempts, buckets[0].count); } -TEST_F(AutofillDownloadManagerTest, QueryTooManyFieldsTest) { +TEST_F(AutofillCrowdsourcingManagerTest, QueryTooManyFieldsTest) { // Create a query that contains too many fields for the server. std::vector<FormData> forms(21); std::vector<std::unique_ptr<FormStructure>> form_structures; @@ -1137,7 +1137,7 @@ EXPECT_FALSE(StartQueryRequest(form_structures)); } -TEST_F(AutofillDownloadManagerTest, QueryNotTooManyFieldsTest) { +TEST_F(AutofillCrowdsourcingManagerTest, QueryNotTooManyFieldsTest) { // Create a query that contains a lot of fields, but not too many for the // server. std::vector<FormData> forms(25); @@ -1157,7 +1157,7 @@ EXPECT_TRUE(StartQueryRequest(form_structures)); } -TEST_F(AutofillDownloadManagerTest, CacheQueryTest) { +TEST_F(AutofillCrowdsourcingManagerTest, CacheQueryTest) { FormData form; FormFieldData field; @@ -1310,7 +1310,7 @@ }; class AutofillServerCommunicationTest - : public AutofillDownloadManager::Observer, + : public AutofillCrowdsourcingManager::Observer, public testing::TestWithParam<ServerCommuncationMode> { protected: void SetUp() override { @@ -1378,7 +1378,7 @@ variations_ids_provider->ResetForTesting(); } - // AutofillDownloadManager::Observer implementation. + // AutofillCrowdsourcingManager::Observer implementation. void OnLoadedServerPredictions( std::string /* response_xml */, const std::vector<FormSignature>& /*form_signatures */) override { @@ -1449,9 +1449,9 @@ run_loop_ = std::make_unique<base::RunLoop>(); ScopedActiveAutofillExperiments scoped_active_autofill_experiments; - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); - bool succeeded = download_manager.StartQueryRequest( + bool succeeded = crowdsourcing_manager.StartQueryRequest( ToRawPointerVector(form_structures), driver_->IsolationInfo(), weak_ptr_factory_.GetWeakPtr()); if (succeeded) @@ -1469,9 +1469,9 @@ run_loop_ = std::make_unique<base::RunLoop>(); ScopedActiveAutofillExperiments scoped_active_autofill_experiments; - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); - bool succeeded = download_manager.StartUploadRequest( + bool succeeded = crowdsourcing_manager.StartUploadRequest( form, form_was_autofilled, available_field_types, login_form_signature, observed_submission, pref_service_.get(), weak_ptr_factory_.GetWeakPtr()); @@ -1503,9 +1503,9 @@ } // namespace TEST_P(AutofillServerCommunicationTest, IsEnabled) { - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); - EXPECT_EQ(download_manager.IsEnabled(), GetParam() != DISABLED); + EXPECT_EQ(crowdsourcing_manager.IsEnabled(), GetParam() != DISABLED); } TEST_P(AutofillServerCommunicationTest, Query) { @@ -1542,7 +1542,7 @@ field.form_control_type = FormControlType::kInputText; form.fields.push_back(field); - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); EXPECT_EQ(GetParam() != DISABLED, SendUploadRequest(FormStructure(form), true, {}, "", true)); @@ -1810,7 +1810,7 @@ form.fields.push_back(field); // Setup the form structures to query. - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); std::vector<std::unique_ptr<FormStructure>> form_structures; form_structures.push_back(std::make_unique<FormStructure>(form)); @@ -1894,7 +1894,7 @@ field.placeholder = u"field-placeholder"; form.fields.push_back(field); - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); FormStructure form_structure(form); form_structure.set_current_page_language(LanguageCode("fr")); @@ -1976,7 +1976,7 @@ field.form_control_type = FormControlType::kInputText; form.fields.push_back(field); - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); FormStructure form_structure(form); for (int i = 0; i <= static_cast<int>(SubmissionSource::kMaxValue); ++i) { @@ -2036,7 +2036,7 @@ field.form_control_type = FormControlType::kInputText; form.fields.push_back(field); - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); FormStructure form_structure(form); FormStructure small_form_structure(small_form); @@ -2123,7 +2123,7 @@ field.form_control_type = FormControlType::kInputText; form.fields.push_back(field); - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); SubmissionSource submission_source = SubmissionSource::FORM_SUBMISSION; @@ -2182,7 +2182,7 @@ field.form_control_type = FormControlType::kInputText; form.fields.push_back(field); - AutofillDownloadManager download_manager( + AutofillCrowdsourcingManager crowdsourcing_manager( client_.get(), version_info::Channel::UNKNOWN, nullptr); SubmissionSource submission_source = SubmissionSource::FORM_SUBMISSION; @@ -2198,7 +2198,7 @@ EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); // Clear the upload throttling history. - AutofillDownloadManager::ClearUploadHistory(pref_service_.get()); + AutofillCrowdsourcingManager::ClearUploadHistory(pref_service_.get()); EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); // Two uploads were sent.
diff --git a/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.cc b/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.cc new file mode 100644 index 0000000..64ce056 --- /dev/null +++ b/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.cc
@@ -0,0 +1,19 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h" + +#include <vector> + +namespace autofill { + +MockAutofillCrowdsourcingManager::MockAutofillCrowdsourcingManager( + AutofillClient* client) + : AutofillCrowdsourcingManager(client, + /*api_key=*/"", + /*log_manager=*/nullptr) {} + +MockAutofillCrowdsourcingManager::~MockAutofillCrowdsourcingManager() = default; + +} // namespace autofill
diff --git a/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h b/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h new file mode 100644 index 0000000..a7d9d6d --- /dev/null +++ b/components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h
@@ -0,0 +1,49 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_CROWDSOURCING_MOCK_AUTOFILL_CROWDSOURCING_MANAGER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_CROWDSOURCING_MOCK_AUTOFILL_CROWDSOURCING_MANAGER_H_ + +#include <vector> + +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace autofill { + +// Note that this is not a pure mock - it overrides the full +// `AutofillCrowdsourcingManager` and only mocks `StartQueryRequest` and +// `StartUploadRequest`. +class MockAutofillCrowdsourcingManager : public AutofillCrowdsourcingManager { + public: + explicit MockAutofillCrowdsourcingManager(AutofillClient* client); + ~MockAutofillCrowdsourcingManager() override; + + MockAutofillCrowdsourcingManager(const MockAutofillCrowdsourcingManager&) = + delete; + MockAutofillCrowdsourcingManager& operator=( + const MockAutofillCrowdsourcingManager&) = delete; + + MOCK_METHOD(bool, + StartQueryRequest, + (const std::vector<FormStructure*>&, + net::IsolationInfo, + base::WeakPtr<Observer>), + (override)); + + MOCK_METHOD(bool, + StartUploadRequest, + (const FormStructure&, + bool, + const ServerFieldTypeSet&, + const std::string&, + bool, + PrefService*, + base::WeakPtr<Observer>), + (override)); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_CROWDSOURCING_MOCK_AUTOFILL_CROWDSOURCING_MANAGER_H_
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc index c90ec1e..9a23e6c 100644 --- a/components/autofill/core/browser/form_data_importer.cc +++ b/components/autofill/core/browser/form_data_importer.cc
@@ -224,10 +224,10 @@ fetched_card_instrument_id_.reset(); bool iban_prompt_potentially_shown = false; - if (extracted_data.iban_import_candidate.has_value() && + if (extracted_data.extracted_iban.has_value() && payment_methods_autofill_enabled) { iban_prompt_potentially_shown = - ProcessIbanImportCandidate(*extracted_data.iban_import_candidate); + ProcessIbanImportCandidate(*extracted_data.extracted_iban); } // If a prompt for credit cards or IBANs is potentially shown, do not allow @@ -310,7 +310,7 @@ #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) if (payment_methods_autofill_enabled) { - extracted_form_data.iban_import_candidate = ExtractIban(submitted_form); + extracted_form_data.extracted_iban = ExtractIban(submitted_form); } #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) @@ -339,7 +339,7 @@ if (!extracted_form_data.extracted_credit_card && num_complete_address_profiles == 0 && - !extracted_form_data.iban_import_candidate) { + !extracted_form_data.extracted_iban) { personal_data_manager_->MarkObserversInsufficientFormDataForImport(); } return extracted_form_data; @@ -765,8 +765,8 @@ } bool FormDataImporter::ProcessIbanImportCandidate( - const Iban& iban_import_candidate) { - return iban_save_manager_->AttemptToOfferSave(iban_import_candidate); + const Iban& extracted_iban) { + return iban_save_manager_->AttemptToOfferSave(extracted_iban); } absl::optional<CreditCard> FormDataImporter::ExtractCreditCard(
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h index c6956d4..79c8055 100644 --- a/components/autofill/core/browser/form_data_importer.h +++ b/components/autofill/core/browser/form_data_importer.h
@@ -93,8 +93,8 @@ ExtractCreditCardFromFormResult ExtractCreditCardFromForm( const FormStructure& form); - // Tries to initiate the saving of `iban_import_candidate` if applicable. - bool ProcessIbanImportCandidate(const Iban& iban_import_candidate); + // Tries to initiate the saving of `extracted_iban` if applicable. + bool ProcessIbanImportCandidate(const Iban& extracted_iban); // Cache the last four of the fetched virtual card so we don't offer saving // them. @@ -226,7 +226,7 @@ address_profile_import_candidates; // IBAN extracted from the form, which is a candidate for importing. Present // if an IBAN is found in the form. - absl::optional<Iban> iban_import_candidate; + absl::optional<Iban> extracted_iban; }; // Scans the given `form` for extractable Autofill data.
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc index d2f8a1f0..30c91ca 100644 --- a/components/autofill/core/browser/form_data_importer_unittest.cc +++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -699,9 +699,9 @@ bool payment_methods_autofill_enabled) { ExtractedFormData extracted_data = form_data_importer().ExtractFormData( form, profile_autofill_enabled, payment_methods_autofill_enabled); - return extracted_data.iban_import_candidate && + return extracted_data.extracted_iban && form_data_importer().ProcessIbanImportCandidate( - extracted_data.iban_import_candidate.value()); + extracted_data.extracted_iban.value()); } void ExtractAddressProfilesAndVerifyExpectation( @@ -3031,7 +3031,7 @@ auto extracted_data = ExtractFormDataAndProcessAddressCandidates( form_structure, /*profile_autofill_enabled=*/true, /*payment_methods_autofill_enabled=*/true); - ASSERT_FALSE(extracted_data.iban_import_candidate); + ASSERT_FALSE(extracted_data.extracted_iban); } TEST_F(FormDataImporterTest, ExtractFormData_SubmittingIbanFormUpdatesPref) { @@ -3077,7 +3077,7 @@ /*payment_methods_autofill_enabled=*/true); // IBAN candidate is empty as the value is invalid. - ASSERT_FALSE(extracted_data.iban_import_candidate); + ASSERT_FALSE(extracted_data.extracted_iban); } TEST_F(FormDataImporterTest, @@ -3089,7 +3089,7 @@ auto extracted_data = ExtractFormDataAndProcessAddressCandidates( form_structure, /*profile_autofill_enabled=*/true, /*payment_methods_autofill_enabled=*/true); - EXPECT_TRUE(extracted_data.iban_import_candidate); + EXPECT_TRUE(extracted_data.extracted_iban); } TEST_F(FormDataImporterTest, ExtractFormData_ImportIbanRecordType_LocalIban) { @@ -3116,7 +3116,7 @@ auto extracted_data = ExtractFormDataAndProcessAddressCandidates( form_structure, /*profile_autofill_enabled=*/true, /*payment_methods_autofill_enabled=*/true); - EXPECT_TRUE(extracted_data.iban_import_candidate); + EXPECT_TRUE(extracted_data.extracted_iban); } #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) @@ -3940,10 +3940,10 @@ #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) TEST_F(FormDataImporterTest, ProcessIbanImportCandidate_ShouldOfferLocalSave_NewIban) { - Iban iban_import_candidate = test::GetLocalIban(); + Iban extracted_iban = test::GetLocalIban(); EXPECT_TRUE( - form_data_importer().ProcessIbanImportCandidate(iban_import_candidate)); + form_data_importer().ProcessIbanImportCandidate(extracted_iban)); } TEST_F(FormDataImporterTest,
diff --git a/components/autofill/core/browser/form_parsing/address_field.cc b/components/autofill/core/browser/form_parsing/address_field.cc index 605912b1..17bfe95 100644 --- a/components/autofill/core/browser/form_parsing/address_field.cc +++ b/components/autofill/core/browser/form_parsing/address_field.cc
@@ -146,8 +146,10 @@ // Ignore "Address Lookup" field. http://crbug.com/427622 if (ParseField(scanner, kAddressLookupRe, address_patterns, nullptr, {log_manager, "kAddressLookupRe"}) || - ParseField(scanner, kAddressNameIgnoredRe, address_ignore_patterns, - nullptr, {log_manager, "kAddressNameIgnoreRe"})) { + // This pattern fully migrated to the MatchPattern mechanism. There + // is no regular expression in autofill_regex_constants.h anymore. + ParseField(scanner, kNoLegacyPattern, address_ignore_patterns, nullptr, + {log_manager, "kAddressNameIgnoreRe"})) { continue; // Ignore email addresses. } else if (ParseFieldSpecifics(
diff --git a/components/autofill/core/browser/form_parsing/address_field_unittest.cc b/components/autofill/core/browser/form_parsing/address_field_unittest.cc index ae40c75..36f1427 100644 --- a/components/autofill/core/browser/form_parsing/address_field_unittest.cc +++ b/components/autofill/core/browser/form_parsing/address_field_unittest.cc
@@ -340,12 +340,20 @@ } // Tests that address name is not misclassified as address. -TEST_P(AddressFieldTest, NotParseAddressName) { +TEST_P(AddressFieldTest, NotParseAddressName_TR) { AddTextFormFieldData("address", "Adres Başlığı", UNKNOWN_TYPE); ClassifyAndVerify(ParseResult::NOT_PARSED, GeoIpCountryCode("TR"), LanguageCode("tr")); } +// Tests that an address name does not lead to a classification even if the +// field mentions the word city. +TEST_P(AddressFieldTest, NotParseAddressName_BR) { + AddTextFormFieldData("-", "nombre de la dirección, city", UNKNOWN_TYPE); + ClassifyAndVerify(ParseResult::NOT_PARSED, GeoIpCountryCode("BR"), + LanguageCode("es")); +} + // Tests that the address components sequence in a label is classified // as |ADDRESS_HOME_LINE1|. TEST_P(AddressFieldTest, ParseAddressComponentsSequenceAsAddressLine1) {
diff --git a/components/autofill/core/browser/form_parsing/form_field.cc b/components/autofill/core/browser/form_parsing/form_field.cc index 0fa7aed..718f7a1 100644 --- a/components/autofill/core/browser/form_parsing/form_field.cc +++ b/components/autofill/core/browser/form_parsing/form_field.cc
@@ -410,7 +410,11 @@ raw_ptr<AutofillField>* match, const RegExLogging& logging, MatchingPattern (*projection)(const MatchingPattern&)) { - return base::FeatureList::IsEnabled(features::kAutofillParsingPatternProvider) + return (base::FeatureList::IsEnabled( + features::kAutofillParsingPatternProvider) || + // Some patterns may not exist as an old-school regex because they + // require negative matching. + pattern == kNoLegacyPattern) ? ParseFieldSpecificsWithNewPatterns(scanner, patterns, match, logging, projection) : ParseFieldSpecificsWithLegacyPattern(scanner, pattern,
diff --git a/components/autofill/core/browser/form_parsing/form_field.h b/components/autofill/core/browser/form_parsing/form_field.h index fd80541..145ed37d 100644 --- a/components/autofill/core/browser/form_parsing/form_field.h +++ b/components/autofill/core/browser/form_parsing/form_field.h
@@ -27,6 +27,11 @@ class AutofillScanner; class LogManager; +// When kNoLegacyPattern is passed to ParseField/ParseFieldSpecifics as the +// pattern, the functions always default to the MatchPatternRefs, regardless +// of the status of features::kAutofillParsingPatternProvider. +inline constexpr std::u16string_view kNoLegacyPattern = u"no-legacy-pattern"; + // This helper struct allows passing information into ParseField() and // ParseFieldSpecifics() that can be used to create a log entry in // chrome://autofill-internals explaining which regular expressions @@ -150,7 +155,10 @@ std::vector<std::u16string>* groups = nullptr); // Attempts to parse a form field with the given pattern. Returns true on - // success and fills |match| with a pointer to the field. + // success and fills `match` with a pointer to the field. + // When `kNoLegacyPattern` is passed as the `pattern`, the functions always + // default to `patterns`, regardless of the status of + // `features::kAutofillParsingPatternProvider`. static bool ParseField(AutofillScanner* scanner, base::StringPiece16 pattern, base::span<const MatchPatternRef> patterns, @@ -158,6 +166,9 @@ const RegExLogging& logging = {}); // TODO(crbug/1142936): Remove `projection` if it's not needed anymore. + // When `kNoLegacyPattern` is passed as the `pattern`, the functions always + // default to `patterns`, regardless of the status of + // `features::kAutofillParsingPatternProvider`. static bool ParseFieldSpecifics( AutofillScanner* scanner, base::StringPiece16 pattern,
diff --git a/components/autofill/core/browser/form_parsing/form_field_unittest.cc b/components/autofill/core/browser/form_parsing/form_field_unittest.cc index a97133f..85d0f68 100644 --- a/components/autofill/core/browser/form_parsing/form_field_unittest.cc +++ b/components/autofill/core/browser/form_parsing/form_field_unittest.cc
@@ -32,8 +32,9 @@ protected: // Parses all added fields using `ParseFormFields`. // Returns the number of fields parsed. - int ParseFormFields(GeoIpCountryCode client_country = GeoIpCountryCode("")) { - FormField::ParseFormFields(list_, client_country, LanguageCode(""), + int ParseFormFields(GeoIpCountryCode client_country = GeoIpCountryCode(""), + LanguageCode language = LanguageCode("")) { + FormField::ParseFormFields(list_, client_country, language, /*is_form_tag=*/true, GetActivePatternSource().value(), field_candidates_map_, @@ -384,4 +385,17 @@ TestClassificationExpectations(); } +// Tests that an email field is recognized even though it matches the pattern +// nombre.*dirección, which is used to detect address name/type patterns. +TEST_P(FormFieldTest, ParseStandaloneEmailSimilarToAddressName) { + AddTextFormFieldData("-", + "nombre de usuario o dirección de correo electrónico", + EMAIL_ADDRESS); + AddTextFormFieldData("city", "City", ADDRESS_HOME_CITY); + AddTextFormFieldData("state", "State", ADDRESS_HOME_STATE); + AddTextFormFieldData("zip", "Zip", ADDRESS_HOME_ZIP); + EXPECT_EQ(4, ParseFormFields(GeoIpCountryCode("BR"), LanguageCode("es"))); + TestClassificationExpectations(); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/form_parsing/internal_resources b/components/autofill/core/browser/form_parsing/internal_resources index a28833de..f4dc712 160000 --- a/components/autofill/core/browser/form_parsing/internal_resources +++ b/components/autofill/core/browser/form_parsing/internal_resources
@@ -1 +1 @@ -Subproject commit a28833de8a3c64abc9afc0158b79b14cf2ff8348 +Subproject commit f4dc712c172a20560d4b834b8d42bdf751ec0bef
diff --git a/components/autofill/core/browser/form_parsing/name_field.cc b/components/autofill/core/browser/form_parsing/name_field.cc index 063b1c6..e7aac14 100644 --- a/components/autofill/core/browser/form_parsing/name_field.cc +++ b/components/autofill/core/browser/form_parsing/name_field.cc
@@ -173,7 +173,9 @@ bool should_ignore = ParseField(scanner, kNameIgnoredRe, name_ignored_patterns, nullptr, {log_manager, "kNameIgnoredRe"}) || - ParseField(scanner, kAddressNameIgnoredRe, address_name_ignored_patterns, + // This pattern fully migrated to the MatchPattern mechanism. There + // is no regular expression in autofill_regex_constants.h anymore. + ParseField(scanner, kNoLegacyPattern, address_name_ignored_patterns, nullptr, {log_manager, "kAddressNameIgnoredRe"}); scanner->Rewind(); if (should_ignore) @@ -240,9 +242,10 @@ while (!scanner->IsEnd()) { // Skip over address label fields, which can have misleading names // e.g. "title" or "name". - if (ParseField(scanner, kAddressNameIgnoredRe, - address_name_ignored_patterns, nullptr, - {log_manager, "kAddressNameIgnoredRe"})) { + // This pattern fully migrated to the MatchPattern mechanism. There is no + // regular expression in autofill_regex_constants.h anymore. + if (ParseField(scanner, kNoLegacyPattern, address_name_ignored_patterns, + nullptr, {log_manager, "kAddressNameIgnoredRe"})) { continue; } @@ -347,7 +350,9 @@ bool should_ignore = ParseField(scanner, kNameIgnoredRe, name_ignored_patterns, nullptr, {log_manager, "kNameIgnoredRe"}) || - ParseField(scanner, kAddressNameIgnoredRe, address_name_ignored_patterns, + // This pattern fully migrated to the MatchPattern mechanism. There is no + // regular expression in autofill_regex_constants.h anymore. + ParseField(scanner, kNoLegacyPattern, address_name_ignored_patterns, nullptr, {log_manager, "kAddressNameIgnoredRe"}); scanner->Rewind(); @@ -445,9 +450,10 @@ while (!scanner->IsEnd()) { // Skip over address label fields, which can have misleading names // e.g. "title" or "name". - if (ParseField(scanner, kAddressNameIgnoredRe, - address_name_ignored_patterns, nullptr, - {log_manager, "kAddressNameIgnoredRe"})) { + // This pattern fully migrated to the MatchPattern mechanism. There is no + // regular expression in autofill_regex_constants.h anymore. + if (ParseField(scanner, kNoLegacyPattern, address_name_ignored_patterns, + nullptr, {log_manager, "kAddressNameIgnoredRe"})) { continue; }
diff --git a/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json b/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json index 402b962..2567cdf 100644 --- a/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json +++ b/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json
@@ -218,38 +218,47 @@ "ADDRESS_NAME_IGNORED": { "en": [ { - "positive_pattern": "address.*nickname|address.*label", + "positive_pattern": "(?:address|location).*(?:nickname|label|type)", "positive_score": 1.1, - "negative_pattern": null, + "negative_pattern": "e.?mail|re.?type|typed", "match_field_attributes": ["LABEL", "NAME"], - "match_field_input_types": ["TEXT"] + "match_field_input_types": ["TEXT", "SELECT", "SEARCH"] + } + ], + "es": [ + { + "positive_pattern": "(?:alias|identificador|nombre).*dirección", + "positive_score": 1.1, + "negative_pattern": "e.?mail|correo|apellido|nombres", + "match_field_attributes": ["LABEL", "NAME"], + "match_field_input_types": ["TEXT", "SELECT", "SEARCH"] } ], "tr": [ { - "positive_pattern": "adres ([İi]sim|başlığı|adı)", + "positive_pattern": "adres (?:[İi]sim|başlığı|adı)", "positive_score": 1.1, "negative_pattern": null, "match_field_attributes": ["LABEL", "NAME"], - "match_field_input_types": ["TEXT"] + "match_field_input_types": ["TEXT", "SELECT", "SEARCH"] } ], "pt": [ { - "positive_pattern": "identificação do endereço", + "positive_pattern": "(?:tipo|nome|apelido|identificação|título).*(?:endereço|local da entrega)", "positive_score": 1.1, - "negative_pattern": null, + "negative_pattern": "e.?mail|eletrónico|usuário|nomes", "match_field_attributes": ["LABEL", "NAME"], - "match_field_input_types": ["TEXT"] + "match_field_input_types": ["TEXT", "SELECT", "SEARCH"] } ], "id": [ { - "positive_pattern": "(label|judul|nama) alamat", + "positive_pattern": "(?:label|judul|nama) alamat", "positive_score": 1.1, "negative_pattern": null, "match_field_attributes": ["LABEL", "NAME"], - "match_field_input_types": ["TEXT"] + "match_field_input_types": ["TEXT", "SELECT", "SEARCH"] } ] },
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc index 5226954f..657b543 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -22,7 +22,6 @@ #include "base/time/clock.h" #include "base/time/time.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h"
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc index 0c91dc0..72543bf8 100644 --- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
@@ -27,7 +27,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "components/autofill/core/browser/autocomplete_history_manager.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h"
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc index b73f865..bcbf5809 100644 --- a/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
@@ -28,7 +28,6 @@ #include "base/values.h" #include "build/build_config.h" #include "components/autofill/core/browser/autocomplete_history_manager.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h"
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 07f7226..ee73df96 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -31,9 +31,9 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h" #include "components/autofill/core/browser/data_model/credit_card_art_image.h" @@ -482,7 +482,7 @@ } if (!deletion_info.is_from_expiration() && deletion_info.IsAllHistory()) { - AutofillDownloadManager::ClearUploadHistory(pref_service_); + AutofillCrowdsourcingManager::ClearUploadHistory(pref_service_); } if (profile_save_strike_database_) {
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h index b5fb8eb7..4655675 100644 --- a/components/autofill/core/browser/test_autofill_client.h +++ b/components/autofill/core/browser/test_autofill_client.h
@@ -19,9 +19,9 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "components/autofill/core/browser/autofill_client.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/country_type.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/browser/logging/log_router.h" #include "components/autofill/core/browser/logging/text_log_receiver.h" @@ -106,8 +106,8 @@ bool IsOffTheRecord() override { return is_off_the_record_; } - AutofillDownloadManager* GetDownloadManager() override { - return download_manager_.get(); + AutofillCrowdsourcingManager* GetCrowdsourcingManager() override { + return crowdsourcing_manager_.get(); } scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() @@ -713,9 +713,9 @@ is_off_the_record_ = is_off_the_record; } - void set_download_manager( - std::unique_ptr<AutofillDownloadManager> download_manager) { - download_manager_ = std::move(download_manager); + void set_crowdsourcing_manager( + std::unique_ptr<AutofillCrowdsourcingManager> crowdsourcing_manager) { + crowdsourcing_manager_ = std::move(crowdsourcing_manager); } void set_shared_url_loader_factory( @@ -829,7 +829,7 @@ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_); - std::unique_ptr<AutofillDownloadManager> download_manager_; + std::unique_ptr<AutofillCrowdsourcingManager> crowdsourcing_manager_; // Populated if credit card local save or upload was offered. absl::optional<AutofillClient::SaveCreditCardOptions>
diff --git a/components/autofill/core/common/autofill_regex_constants.h b/components/autofill/core/common/autofill_regex_constants.h index 3f708be..8c28e6d 100644 --- a/components/autofill/core/common/autofill_regex_constants.h +++ b/components/autofill/core/common/autofill_regex_constants.h
@@ -15,11 +15,6 @@ u"province|region|other" u"|provincia" // es u"|bairro|suburb"; // pt-BR, pt-PT -inline constexpr char16_t kAddressNameIgnoredRe[] = - u"address.*nickname|address.*label" - u"|adres ([İi]sim|başlığı|adı)" // tr - u"|identificação do endereço" // pt-BR, pt-PT - u"|(label|judul|nama) alamat"; // id inline constexpr char16_t kCompanyRe[] = u"company|business|organization|organisation" u"|(?<!con)firma|firmenname" // de-DE
diff --git a/components/autofill/core/common/mojom/autofill_types.mojom b/components/autofill/core/common/mojom/autofill_types.mojom index d86b653..6661efbc 100644 --- a/components/autofill/core/common/mojom/autofill_types.mojom +++ b/components/autofill/core/common/mojom/autofill_types.mojom
@@ -475,6 +475,7 @@ bool is_generation_element_password_type; mojo_base.mojom.TextDirection text_direction; FormData form_data; + bool input_field_empty; }; // autofill::ParsingResult
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc index 75cff76..7384b1f 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
@@ -414,6 +414,7 @@ out->max_length = data.max_length(); out->is_generation_element_password_type = data.is_generation_element_password_type(); + out->input_field_empty = data.input_field_empty(); return data.ReadGenerationElementId(&out->generation_element_id) && data.ReadGenerationElement(&out->generation_element) &&
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h index f4dde9d..a262e465 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
@@ -634,6 +634,11 @@ return r.form_data; } + static bool input_field_empty( + const autofill::password_generation::PasswordGenerationUIData& r) { + return r.input_field_empty; + } + static bool Read( autofill::mojom::PasswordGenerationUIDataDataView data, autofill::password_generation::PasswordGenerationUIData* out);
diff --git a/components/autofill/core/common/password_generation_util.cc b/components/autofill/core/common/password_generation_util.cc index d78d3bc..1bde086 100644 --- a/components/autofill/core/common/password_generation_util.cc +++ b/components/autofill/core/common/password_generation_util.cc
@@ -19,14 +19,16 @@ FieldRendererId generation_element_id, bool is_generation_element_password_type, base::i18n::TextDirection text_direction, - const FormData& form_data) + const FormData& form_data, + bool input_field_empty) : bounds(bounds), max_length(max_length), generation_element(generation_element), generation_element_id(generation_element_id), is_generation_element_password_type(is_generation_element_password_type), text_direction(text_direction), - form_data(form_data) {} + form_data(form_data), + input_field_empty(input_field_empty) {} PasswordGenerationUIData::PasswordGenerationUIData() = default; PasswordGenerationUIData::PasswordGenerationUIData(
diff --git a/components/autofill/core/common/password_generation_util.h b/components/autofill/core/common/password_generation_util.h index 5f3083a..b8e84c9 100644 --- a/components/autofill/core/common/password_generation_util.h +++ b/components/autofill/core/common/password_generation_util.h
@@ -123,7 +123,8 @@ FieldRendererId generation_element_id, bool is_generation_element_password_type, base::i18n::TextDirection text_direction, - const FormData& form_data); + const FormData& form_data, + bool input_field_empty); PasswordGenerationUIData(); PasswordGenerationUIData(const PasswordGenerationUIData& rhs); PasswordGenerationUIData(PasswordGenerationUIData&& rhs); @@ -153,6 +154,9 @@ // The form associated with the password field. FormData form_data; + + // Whether the password input field is empty. + bool input_field_empty; }; void LogPasswordGenerationEvent(PasswordGenerationEvent event);
diff --git a/components/component_updater/component_installer.h b/components/component_updater/component_installer.h index e87cbfc30..fe597860 100644 --- a/components/component_updater/component_installer.h +++ b/components/component_updater/component_installer.h
@@ -170,7 +170,7 @@ bool GetInstalledFile(const std::string& file, base::FilePath* installed_file) override; - // Only user-level component installations can be uninstalled. + // Components bundled with installations of Chrome cannot be uninstalled. bool Uninstall() override; private:
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java index fbf7636..45b6f56 100644 --- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java +++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java
@@ -266,15 +266,15 @@ } /** - * This variation of #isNTPUrl is for already parsed URLs, not for direct use on user-provided - * url input. Do not do isNTPUrl(new GURL(user_string)), as this will not handle legacy schemes - * like about: correctly. You should use {@link #isNTPUrl(String)} instead, or call - * {@link UrlFormatter#fixupUrl(String)} to create the GURL instead. + * This variation of #isNtpUrl is for already parsed URLs, not for direct use on user-provided + * url input. Do not do isNtpUrl(new GURL(user_string)), as this will not handle legacy schemes + * like about: correctly. You should use {@link #isNtpUrl(String)} instead, or call {@link + * UrlFormatter#fixupUrl(String)} to create the GURL instead. * * @param gurl The GURL to check whether it is for the NTP. * @return Whether the passed in URL is used to render the NTP. */ - public static boolean isNTPUrl(GURL gurl) { + public static boolean isNtpUrl(GURL gurl) { if (!gurl.isValid() || !isInternalScheme(gurl)) return false; return UrlConstants.NTP_HOST.equals(gurl.getHost()); } @@ -282,36 +282,37 @@ /** * @param url The URL to check whether it is for the NTP. * @return Whether the passed in URL is used to render the NTP. - * @deprecated For URLs coming from c++, those URLs should passed around in Java as a GURL. - * For URLs created in Java, coming from third parties or users, those URLs should be - * parsed into a GURL at their source using {@link UrlFormatter#fixupUrl(String)}. + * @deprecated For URLs coming from c++, those URLs should passed around in Java as a GURL. For + * URLs created in Java, coming from third parties or users, those URLs should be parsed + * into a GURL at their source using {@link UrlFormatter#fixupUrl(String)}. */ @Deprecated - public static boolean isNTPUrl(String url) { + public static boolean isNtpUrl(String url) { // Also handle the legacy chrome://newtab and about:newtab URLs since they will redirect to // chrome-native://newtab natively. if (TextUtils.isEmpty(url)) return false; // We need to fixup the URL to handle about: schemes and transform them into the equivalent // chrome:// scheme so that GURL parses the host correctly. GURL gurl = UrlFormatter.fixupUrl(url); - return isNTPUrl(gurl); + return isNtpUrl(gurl); } /** - * Returns whether the url matches an NTP URL exactly. This is used to support features - * showing the omnibox before native is loaded. Prefer using {@see #isNTPUrl(GURL gurl)} when - * native is loaded. + * Returns whether the url matches an NTP URL exactly. This is used to support features showing + * the omnibox before native is loaded. Prefer using {@see #isNtpUrl(GURL gurl)} when native is + * loaded. + * * @param url The current URL to compare. * @return Whether the given URL matches the NTP urls exactly. */ - public static boolean isCanonicalizedNTPUrl(String url) { + public static boolean isCanonicalizedNtpUrl(String url) { // TODO(crbug.com/1267266): Let callers check if the library is initialized and make them // call this method only before native is initialized. // After native initialization, the homepage url could become // "chrome://newtab/#most_visited" on carrier phones. Simply comparing the text of the URL - // returns a wrong result, but isNTPUrl(url) which checks the host of the URL works. See + // returns a wrong result, but isNtpUrl(url) which checks the host of the URL works. See // https://crbug.com/1266625. - if (LibraryLoader.getInstance().isInitialized()) return isNTPUrl(url); + if (LibraryLoader.getInstance().isInitialized()) return isNtpUrl(url); return TextUtils.equals(url, UrlConstants.NTP_URL) || TextUtils.equals(url, UrlConstants.NTP_NON_NATIVE_URL) || TextUtils.equals(url, UrlConstants.NTP_ABOUT_URL);
diff --git a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlConstantsTest.java b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlConstantsTest.java index 99bbfa1..4546bfc7 100644 --- a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlConstantsTest.java +++ b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlConstantsTest.java
@@ -37,6 +37,6 @@ Assert.assertTrue(ntpGurl.isValid()); Assert.assertEquals(ntpGurl.getHost(), UrlConstants.NTP_HOST); Assert.assertEquals(ntpGurl.getScheme(), UrlConstants.CHROME_SCHEME); - Assert.assertTrue(UrlUtilities.isNTPUrl(UrlConstants.ntpGurl())); + Assert.assertTrue(UrlUtilities.isNtpUrl(UrlConstants.ntpGurl())); } }
diff --git a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java index 91613e7..f285d212 100644 --- a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java +++ b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
@@ -195,32 +195,32 @@ @Test @SmallTest public void testIsNtpUrlString() { - Assert.assertTrue(UrlUtilities.isNTPUrl("chrome-native://newtab")); - Assert.assertTrue(UrlUtilities.isNTPUrl("chrome://newtab")); - Assert.assertTrue(UrlUtilities.isNTPUrl("about:newtab")); + Assert.assertTrue(UrlUtilities.isNtpUrl("chrome-native://newtab")); + Assert.assertTrue(UrlUtilities.isNtpUrl("chrome://newtab")); + Assert.assertTrue(UrlUtilities.isNtpUrl("about:newtab")); - Assert.assertFalse(UrlUtilities.isNTPUrl("http://www.example.com")); - Assert.assertFalse(UrlUtilities.isNTPUrl("chrome://history")); - Assert.assertFalse(UrlUtilities.isNTPUrl("chrome-native://newtabz")); - Assert.assertFalse(UrlUtilities.isNTPUrl("newtab")); - Assert.assertFalse(UrlUtilities.isNTPUrl("")); + Assert.assertFalse(UrlUtilities.isNtpUrl("http://www.example.com")); + Assert.assertFalse(UrlUtilities.isNtpUrl("chrome://history")); + Assert.assertFalse(UrlUtilities.isNtpUrl("chrome-native://newtabz")); + Assert.assertFalse(UrlUtilities.isNtpUrl("newtab")); + Assert.assertFalse(UrlUtilities.isNtpUrl("")); } @Test @SmallTest public void testIsNtpUrlGurl() { - Assert.assertTrue(UrlUtilities.isNTPUrl(new GURL("chrome-native://newtab"))); - Assert.assertTrue(UrlUtilities.isNTPUrl(new GURL("chrome://newtab"))); + Assert.assertTrue(UrlUtilities.isNtpUrl(new GURL("chrome-native://newtab"))); + Assert.assertTrue(UrlUtilities.isNtpUrl(new GURL("chrome://newtab"))); // Note that this intentionally differs from UrlUtilities#isNTPUrl(String) (see comments on // method). - Assert.assertFalse(UrlUtilities.isNTPUrl(new GURL("about:newtab"))); + Assert.assertFalse(UrlUtilities.isNtpUrl(new GURL("about:newtab"))); - Assert.assertFalse(UrlUtilities.isNTPUrl(new GURL("http://www.example.com"))); - Assert.assertFalse(UrlUtilities.isNTPUrl(new GURL("chrome://history"))); - Assert.assertFalse(UrlUtilities.isNTPUrl(new GURL("chrome-native://newtabz"))); - Assert.assertFalse(UrlUtilities.isNTPUrl(new GURL("newtab"))); - Assert.assertFalse(UrlUtilities.isNTPUrl(new GURL(""))); + Assert.assertFalse(UrlUtilities.isNtpUrl(new GURL("http://www.example.com"))); + Assert.assertFalse(UrlUtilities.isNtpUrl(new GURL("chrome://history"))); + Assert.assertFalse(UrlUtilities.isNtpUrl(new GURL("chrome-native://newtabz"))); + Assert.assertFalse(UrlUtilities.isNtpUrl(new GURL("newtab"))); + Assert.assertFalse(UrlUtilities.isNtpUrl(new GURL(""))); } @Test
diff --git a/components/favicon/android/large_icon_bridge.cc b/components/favicon/android/large_icon_bridge.cc index 8d8ccce8..0ccfed9 100644 --- a/components/favicon/android/large_icon_bridge.cc +++ b/components/favicon/android/large_icon_bridge.cc
@@ -11,8 +11,7 @@ #include "base/functional/bind.h" #include "components/favicon/android/jni_headers/LargeIconBridge_jni.h" #include "components/favicon/content/large_favicon_provider_getter.h" -#include "components/favicon/core/core_favicon_service.h" -#include "components/favicon/core/large_favicon_provider.h" +#include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" #include "content/public/browser/android/browser_context_handle.h" @@ -80,10 +79,11 @@ if (!browser_context) return false; - LargeFaviconProvider* favicon_provider = + LargeIconService* large_icon_service = GetLargeFaviconProvider(browser_context); - if (!favicon_provider) + if (!large_icon_service) { return false; + } favicon_base::LargeIconCallback callback_runner = base::BindOnce( &OnLargeIconAvailable, ScopedJavaGlobalRef<jobject>(env, j_callback)); @@ -92,7 +92,7 @@ // Use desired_size = 0 for getting the icon from the cache (so that // the icon is not poorly rescaled by LargeIconService). - favicon_provider->GetLargeIconRawBitmapOrFallbackStyleForPageUrl( + large_icon_service->GetLargeIconRawBitmapOrFallbackStyleForPageUrl( *url, min_source_size_px, desired_source_size_px, std::move(callback_runner), &cancelable_task_tracker_);
diff --git a/components/favicon/content/large_favicon_provider_getter.cc b/components/favicon/content/large_favicon_provider_getter.cc index 0f258de..30bd22d0 100644 --- a/components/favicon/content/large_favicon_provider_getter.cc +++ b/components/favicon/content/large_favicon_provider_getter.cc
@@ -22,8 +22,7 @@ } // static -LargeFaviconProvider* GetLargeFaviconProvider( - content::BrowserContext* context) { +LargeIconService* GetLargeFaviconProvider(content::BrowserContext* context) { return GetGetter()->Run(context); }
diff --git a/components/favicon/content/large_favicon_provider_getter.h b/components/favicon/content/large_favicon_provider_getter.h index a0ec041..2bde313 100644 --- a/components/favicon/content/large_favicon_provider_getter.h +++ b/components/favicon/content/large_favicon_provider_getter.h
@@ -13,17 +13,17 @@ namespace favicon { -class LargeFaviconProvider; +class LargeIconService; using LargeFaviconProviderGetter = - base::RepeatingCallback<LargeFaviconProvider*(content::BrowserContext*)>; + base::RepeatingCallback<LargeIconService*(content::BrowserContext*)>; // Sets a callback that returns the LargeIconProvider for a given // BrowserContext. This allows code in //components, such as LargeIconBridge, to // obtain an implementation of LargeIconProvider even though the // implementation's factory is unique to each embedder. void SetLargeFaviconProviderGetter(const LargeFaviconProviderGetter& getter); -LargeFaviconProvider* GetLargeFaviconProvider(content::BrowserContext* context); +LargeIconService* GetLargeFaviconProvider(content::BrowserContext* context); } // namespace favicon
diff --git a/components/favicon/core/BUILD.gn b/components/favicon/core/BUILD.gn index a6a10a9..08af08b 100644 --- a/components/favicon/core/BUILD.gn +++ b/components/favicon/core/BUILD.gn
@@ -24,7 +24,6 @@ "history_ui_favicon_request_handler.h", "history_ui_favicon_request_handler_impl.cc", "history_ui_favicon_request_handler_impl.h", - "large_favicon_provider.h", "large_icon_service.h", "large_icon_service_impl.cc", "large_icon_service_impl.h",
diff --git a/components/favicon/core/large_favicon_provider.h b/components/favicon/core/large_favicon_provider.h deleted file mode 100644 index 4c79a517..0000000 --- a/components/favicon/core/large_favicon_provider.h +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2020 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_FAVICON_CORE_LARGE_FAVICON_PROVIDER_H_ -#define COMPONENTS_FAVICON_CORE_LARGE_FAVICON_PROVIDER_H_ - -#include "base/task/cancelable_task_tracker.h" -#include "components/favicon_base/favicon_callback.h" -#include "components/favicon_base/favicon_types.h" - -class GURL; - -namespace favicon { - -// An interface used to look up large favicons. It's used by LargeIconBridge and -// LargeIconService, and embedders provide an implementation via -// SetLargeFaviconProviderGetter(), allowing code in //components to access the -// provider for a given BrowserContext. -class LargeFaviconProvider { - public: - // Requests the best large icon for the page at |page_url|. - // Case 1. An icon exists whose size is >= MAX(|min_source_size_in_pixel|, - // |desired_size_in_pixel|): - // - If |desired_size_in_pixel| == 0: returns icon as is. - // - Else: returns the icon resized to |desired_size_in_pixel|. - // Case 2. An icon exists whose size is >= |min_source_size_in_pixel| and < - // |desired_size_in_pixel|: - // - Same as 1 with the biggest icon. - // Case 3. An icon exists whose size is < |min_source_size_in_pixel|: - // - Extracts dominant color of smaller image, returns a fallback icon style - // that has a matching background. - // Case 4. No icon exists. - // - Returns the default fallback icon style. - // For cases 3 and 4, this function returns the style of the fallback icon - // instead of rendering an icon so clients can render the icon themselves. - virtual base::CancelableTaskTracker::TaskId - GetLargeIconRawBitmapOrFallbackStyleForPageUrl( - const GURL& page_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, - favicon_base::LargeIconCallback callback, - base::CancelableTaskTracker* tracker) = 0; - - // Behaves the same as GetLargeIconRawBitmapOrFallbackStyleForPageUrl(), only - // returns the large icon (if available) decoded. - virtual base::CancelableTaskTracker::TaskId - GetLargeIconImageOrFallbackStyleForPageUrl( - const GURL& page_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, - favicon_base::LargeIconImageCallback callback, - base::CancelableTaskTracker* tracker) = 0; - - // Requests the best large icon raw bitmap for the page at |page_url|. - // If there are several icons cached in the favicon database for |page_url| - // which are > |minimum_size_in_pixels|, selects an icon to return based on an - // LargeFaviconProvider-hard-coded ordering of preference for certain - // IconTypes. If no icon is larger than |minimum_size_in_pixels|, the largest - // one will be returned. - virtual base::CancelableTaskTracker::TaskId GetLargeIconRawBitmapForPageUrl( - const GURL& page_url, - int min_source_size_in_pixel, - favicon_base::FaviconRawBitmapCallback callback, - base::CancelableTaskTracker* tracker) = 0; -}; - -} // namespace favicon - -#endif // COMPONENTS_FAVICON_CORE_LARGE_FAVICON_PROVIDER_H_
diff --git a/components/favicon/core/large_icon_service.h b/components/favicon/core/large_icon_service.h index 18b34238..3f3a267 100644 --- a/components/favicon/core/large_icon_service.h +++ b/components/favicon/core/large_icon_service.h
@@ -6,7 +6,6 @@ #define COMPONENTS_FAVICON_CORE_LARGE_ICON_SERVICE_H_ #include "base/task/cancelable_task_tracker.h" -#include "components/favicon/core/large_favicon_provider.h" #include "components/favicon_base/favicon_callback.h" #include "components/keyed_service/core/keyed_service.h" @@ -20,11 +19,56 @@ // The large icon service provides methods to access large icons. The actual // implementation of this uses Google's favicon service. -class LargeIconService : public KeyedService, public LargeFaviconProvider { +class LargeIconService : public KeyedService { public: LargeIconService(const LargeIconService&) = delete; LargeIconService& operator=(const LargeIconService&) = delete; + // Requests the best large icon for the page at |page_url|. + // Case 1. An icon exists whose size is >= MAX(|min_source_size_in_pixel|, + // |desired_size_in_pixel|): + // - If |desired_size_in_pixel| == 0: returns icon as is. + // - Else: returns the icon resized to |desired_size_in_pixel|. + // Case 2. An icon exists whose size is >= |min_source_size_in_pixel| and < + // |desired_size_in_pixel|: + // - Same as 1 with the biggest icon. + // Case 3. An icon exists whose size is < |min_source_size_in_pixel|: + // - Extracts dominant color of smaller image, returns a fallback icon style + // that has a matching background. + // Case 4. No icon exists. + // - Returns the default fallback icon style. + // For cases 3 and 4, this function returns the style of the fallback icon + // instead of rendering an icon so clients can render the icon themselves. + virtual base::CancelableTaskTracker::TaskId + GetLargeIconRawBitmapOrFallbackStyleForPageUrl( + const GURL& page_url, + int min_source_size_in_pixel, + int desired_size_in_pixel, + favicon_base::LargeIconCallback callback, + base::CancelableTaskTracker* tracker) = 0; + + // Behaves the same as GetLargeIconRawBitmapOrFallbackStyleForPageUrl(), only + // returns the large icon (if available) decoded. + virtual base::CancelableTaskTracker::TaskId + GetLargeIconImageOrFallbackStyleForPageUrl( + const GURL& page_url, + int min_source_size_in_pixel, + int desired_size_in_pixel, + favicon_base::LargeIconImageCallback callback, + base::CancelableTaskTracker* tracker) = 0; + + // Requests the best large icon raw bitmap for the page at |page_url|. + // If there are several icons cached in the favicon database for |page_url| + // which are > |minimum_size_in_pixels|, selects an icon to return based on an + // LargeIconService-hard-coded ordering of preference for certain + // IconTypes. If no icon is larger than |minimum_size_in_pixels|, the largest + // one will be returned. + virtual base::CancelableTaskTracker::TaskId GetLargeIconRawBitmapForPageUrl( + const GURL& page_url, + int min_source_size_in_pixel, + favicon_base::FaviconRawBitmapCallback callback, + base::CancelableTaskTracker* tracker) = 0; + // Behaves the same as GetLargeIconRawBitmapOrFallbackStyleForPageUrl, except // uses icon URL instead of page URL. virtual base::CancelableTaskTracker::TaskId @@ -89,7 +133,6 @@ // GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache()). This // postpones the automatic eviction of the favicon from the database. virtual void TouchIconFromGoogleServer(const GURL& icon_url) = 0; - protected: LargeIconService() {} };
diff --git a/components/gwp_asan/client/lightweight_detector/shared_state.h b/components/gwp_asan/client/lightweight_detector/shared_state.h index a5ba7840..c8fc77a 100644 --- a/components/gwp_asan/client/lightweight_detector/shared_state.h +++ b/components/gwp_asan/client/lightweight_detector/shared_state.h
@@ -41,7 +41,7 @@ static void Init(Args&&... args) { DCHECK(!Holder::initialized_); Holder::initialized_ = true; - new (Get()) T(std::forward<Args>(args)...); + new (Holder::buffer_) T(std::forward<Args>(args)...); } ALWAYS_INLINE static T* Get() {
diff --git a/components/history/core/browser/features.cc b/components/history/core/browser/features.cc index 27867af..ab10dcc 100644 --- a/components/history/core/browser/features.cc +++ b/components/history/core/browser/features.cc
@@ -78,7 +78,7 @@ BASE_FEATURE(kPopulateVisitedLinkDatabase, "PopulateVisitedLinkDatabase", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kSyncSegmentsData, "SyncSegmentsData",
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc index 7fd03bd..8efad1e 100644 --- a/components/history/core/browser/history_backend_unittest.cc +++ b/components/history/core/browser/history_backend_unittest.cc
@@ -5426,9 +5426,8 @@ // Set-up the parameterized testing to depend on the flag value. is_database_enabled_ = (GetParam() == TestMode::kPopulateVisitedLinkDatabaseEnabled); - if (is_database_enabled_) { - scoped_feature_list_.InitAndEnableFeature(kPopulateVisitedLinkDatabase); - } + scoped_feature_list_.InitWithFeatureState(kPopulateVisitedLinkDatabase, + is_database_enabled_); // Init the transition types for AddPageVisit. link_transition_ = ui::PageTransitionFromInt( ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_START |
diff --git a/components/live_caption/views/caption_bubble.cc b/components/live_caption/views/caption_bubble.cc index c761d9f..571a7214 100644 --- a/components/live_caption/views/caption_bubble.cc +++ b/components/live_caption/views/caption_bubble.cc
@@ -635,9 +635,8 @@ base::Unretained(this))); #endif - views::Button::PressedCallback expand_or_collapse_callback = - base::BindRepeating(&CaptionBubble::ExpandOrCollapseButtonPressed, - base::Unretained(this)); + base::RepeatingClosure expand_or_collapse_callback = base::BindRepeating( + &CaptionBubble::ExpandOrCollapseButtonPressed, base::Unretained(this)); auto expand_button = BuildImageButton(expand_or_collapse_callback, IDS_LIVE_CAPTION_BUBBLE_EXPAND); expand_button->SetVisible(!is_expanded_); @@ -657,7 +656,7 @@ base::Unretained(this)), IDS_LIVE_CAPTION_BUBBLE_CLOSE); - views::Button::PressedCallback pin_or_unpin_callback = base::BindRepeating( + base::RepeatingClosure pin_or_unpin_callback = base::BindRepeating( &CaptionBubble::PinOrUnpinButtonPressed, base::Unretained(this)); auto pin_button = BuildImageButton(pin_or_unpin_callback, IDS_LIVE_CAPTION_BUBBLE_PIN);
diff --git a/components/media_message_center/media_notification_view_modern_impl.cc b/components/media_message_center/media_notification_view_modern_impl.cc index 2334e370..7398303e 100644 --- a/components/media_message_center/media_notification_view_modern_impl.cc +++ b/components/media_message_center/media_notification_view_modern_impl.cc
@@ -4,6 +4,8 @@ #include "components/media_message_center/media_notification_view_modern_impl.h" +#include <utility> + #include "base/containers/contains.h" #include "base/metrics/histogram_macros.h" #include "base/ranges/algorithm.h" @@ -85,7 +87,7 @@ public: METADATA_HEADER(MediaButton); MediaButton(PressedCallback callback, int icon_size, gfx::Size button_size) - : ImageButton(callback), icon_size_(icon_size) { + : ImageButton(std::move(callback)), icon_size_(icon_size) { SetHasInkDropActionOnClick(true); views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), button_size.height() / 2);
diff --git a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc index e83f0c2c..ea58a6d 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc +++ b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc
@@ -33,9 +33,8 @@ } // namespace NoStatePrefetchURLLoaderThrottle::NoStatePrefetchURLLoaderThrottle( - const std::string& histogram_prefix, mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler) - : histogram_prefix_(histogram_prefix), canceler_(std::move(canceler)) { + : canceler_(std::move(canceler)) { DCHECK(canceler_); } @@ -131,7 +130,6 @@ std::vector<std::string>* /* to_be_removed_headers */, net::HttpRequestHeaders* /* modified_headers */, net::HttpRequestHeaders* /* modified_cors_exempt_headers */) { - redirect_count_++; std::string follow_only_when_prerender_shown_header; if (response_head.headers) { @@ -153,16 +151,6 @@ } } -void NoStatePrefetchURLLoaderThrottle::WillProcessResponse( - const GURL& response_url, - network::mojom::URLResponseHead* response_head, - bool* defer) { - bool is_main_resource = - blink::IsRequestDestinationFrame(request_destination_); - RecordPrefetchRedirectCount(histogram_prefix_, is_main_resource, - redirect_count_); -} - void NoStatePrefetchURLLoaderThrottle::OnTimedOut() { delegate_->CancelWithError(net::ERR_ABORTED); }
diff --git a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.h b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.h index e93dc59..5f12354 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.h +++ b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.h
@@ -21,7 +21,6 @@ public base::SupportsWeakPtr<NoStatePrefetchURLLoaderThrottle> { public: NoStatePrefetchURLLoaderThrottle( - const std::string& histogram_prefix, mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler); ~NoStatePrefetchURLLoaderThrottle() override; @@ -46,16 +45,10 @@ std::vector<std::string>* to_be_removed_headers, net::HttpRequestHeaders* modified_headers, net::HttpRequestHeaders* modified_cors_exempt_headers) override; - void WillProcessResponse(const GURL& response_url, - network::mojom::URLResponseHead* response_head, - bool* defer) override; void OnTimedOut(); - std::string histogram_prefix_; - bool deferred_ = false; - int redirect_count_ = 0; network::mojom::RequestDestination request_destination_; mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler_;
diff --git a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc index 475a9f1..fec6273 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc +++ b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc
@@ -44,8 +44,8 @@ mojo::MakeSelfOwnedReceiver(std::make_unique<FakeCanceler>(), pending_remote.InitWithNewPipeAndPassReceiver()); std::unique_ptr<NoStatePrefetchURLLoaderThrottle> no_state_prefetch_throttle = - std::make_unique<NoStatePrefetchURLLoaderThrottle>("PREFIX", - std::move(pending_remote)); + std::make_unique<NoStatePrefetchURLLoaderThrottle>( + std::move(pending_remote)); bool destruction_closure_called = false; no_state_prefetch_throttle->set_destruction_closure( base::BindLambdaForTesting([&]() { destruction_closure_called = true; })); @@ -60,8 +60,8 @@ mojo::MakeSelfOwnedReceiver(std::make_unique<FakeCanceler>(), pending_remote.InitWithNewPipeAndPassReceiver()); std::unique_ptr<NoStatePrefetchURLLoaderThrottle> no_state_prefetch_throttle = - std::make_unique<NoStatePrefetchURLLoaderThrottle>("PREFIX", - std::move(pending_remote)); + std::make_unique<NoStatePrefetchURLLoaderThrottle>( + std::move(pending_remote)); base::RunLoop run_loop; scoped_refptr<base::SequencedTaskRunner> current_task_runner = base::SequencedTaskRunner::GetCurrentDefault();
diff --git a/components/no_state_prefetch/common/no_state_prefetch_utils.cc b/components/no_state_prefetch/common/no_state_prefetch_utils.cc index 3e94f5b..e440777 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_utils.cc +++ b/components/no_state_prefetch/common/no_state_prefetch_utils.cc
@@ -62,16 +62,4 @@ return std::string("Prerender.") + prefix_type + std::string("_") + name; } -void RecordPrefetchRedirectCount(const std::string& histogram_prefix, - bool is_main_resource, - int redirect_count) { - const int kMaxRedirectCount = 10; - std::string histogram_base_name = base::StringPrintf( - "NoStatePrefetch%sResourceRedirects", is_main_resource ? "Main" : "Sub"); - std::string histogram_name = - ComposeHistogramName(histogram_prefix, histogram_base_name); - base::UmaHistogramExactLinear(histogram_name, redirect_count, - kMaxRedirectCount); -} - } // namespace prerender
diff --git a/components/no_state_prefetch/common/no_state_prefetch_utils.h b/components/no_state_prefetch/common/no_state_prefetch_utils.h index 3d1de76b..03acd0b 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_utils.h +++ b/components/no_state_prefetch/common/no_state_prefetch_utils.h
@@ -26,12 +26,6 @@ std::string ComposeHistogramName(const std::string& prefix_type, const std::string& name); -// Called when a NoStatePrefetch resource has been loaded. This is called only -// once per resource, when all redirects have been resolved. -void RecordPrefetchRedirectCount(const std::string& histogram_prefix, - bool is_main_resource, - int redirect_count); - } // namespace prerender #endif // COMPONENTS_NO_STATE_PREFETCH_COMMON_NO_STATE_PREFETCH_UTILS_H_
diff --git a/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc b/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc index f01755c..5c808b09 100644 --- a/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc +++ b/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc
@@ -46,8 +46,8 @@ render_frame->GetBrowserInterfaceBroker()->GetInterface( canceler.InitWithNewPipeAndPassReceiver()); - auto throttle = std::make_unique<NoStatePrefetchURLLoaderThrottle>( - helper->histogram_prefix(), std::move(canceler)); + auto throttle = + std::make_unique<NoStatePrefetchURLLoaderThrottle>(std::move(canceler)); helper->AddThrottle(*throttle); return throttle; }
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 515a1dd3..aa73314 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
@@ -100,7 +100,7 @@ TEST_F(ModelExecutionManagerTest, ExecuteModelEmptyAccessToken) { proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); base::RunLoop run_loop; model_execution_manager()->ExecuteModel( proto::MODEL_EXECUTION_FEATURE_COMPOSE, request, @@ -118,7 +118,7 @@ TEST_F(ModelExecutionManagerTest, ExecuteModelWithUserSignIn) { proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); base::RunLoop run_loop; identity_test_env()->MakePrimaryAccountAvailable( "test_email", signin::ConsentLevel::kSignin); @@ -159,7 +159,7 @@ base::HistogramTester histogram_tester; proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); base::RunLoop run_loop; identity_test_env()->MakePrimaryAccountAvailable( "test_email", signin::ConsentLevel::kSignin); @@ -207,7 +207,7 @@ proto::MODEL_EXECUTION_FEATURE_COMPOSE); // Message is added through AddContext(). proto::ComposeRequest request; - request.set_user_input("some test"); + request.mutable_generate_params()->set_user_input("some test"); session->AddContext(request); // ExecuteModel() uses empty message. session->ExecuteModel( @@ -234,9 +234,9 @@ auto session = model_execution_manager()->StartSession( proto::MODEL_EXECUTION_FEATURE_COMPOSE); proto::ComposeRequest request; - request.set_user_input("first test"); + request.mutable_generate_params()->set_user_input("first test"); session->AddContext(request); - request.set_user_input("second test"); + request.mutable_generate_params()->set_user_input("second test"); session->AddContext(request); // ExecuteModel() uses empty message. session->ExecuteModel( @@ -264,10 +264,10 @@ proto::MODEL_EXECUTION_FEATURE_COMPOSE); // First message is added through AddContext(). proto::ComposeRequest request; - request.set_user_input("test_message"); + request.mutable_generate_params()->set_user_input("test_message"); session->AddContext(request); // ExecuteModel() adds a different message. - request.set_user_input("other test"); + request.mutable_generate_params()->set_user_input("other test"); session->ExecuteModel( request, base::BindRepeating( [](base::RunLoop* run_loop,
diff --git a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc index 4c7ae599..f9d873c 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc
@@ -245,12 +245,8 @@ auto* input_substitutions = input_config->add_input_context_substitutions(); input_substitutions->set_string_template("this is ignored"); auto* substitution = input_config->add_execute_substitutions(); - substitution->set_string_template("hello this is a test: %s %s %s"); + substitution->set_string_template("hello this is a test: %s %s"); substitution->set_should_ignore_input_context(true); - auto* proto_field = substitution->add_substitutions() - ->add_candidates() - ->mutable_proto_field(); - proto_field->add_proto_descriptors()->set_tag_number(2); auto* proto_field2 = substitution->add_substitutions() ->add_candidates() ->mutable_proto_field(); @@ -264,7 +260,6 @@ UpdateInterpreterWithConfig(config); proto::ComposeRequest request; - request.set_user_input("this is my input"); request.mutable_page_metadata()->set_page_title("nested"); request.mutable_generate_params()->set_user_input("inner type"); auto result = interpreter()->ConstructInputString( @@ -272,8 +267,7 @@ /*want_input_context=*/false); ASSERT_TRUE(result.has_value()); - EXPECT_EQ(result->input_string, - "hello this is a test: this is my input nested inner type"); + EXPECT_EQ(result->input_string, "hello this is a test: nested inner type"); EXPECT_TRUE(result->should_ignore_input_context); } @@ -294,7 +288,6 @@ UpdateInterpreterWithConfig(config); proto::ComposeRequest request; - request.set_user_input("this is my input"); request.mutable_page_metadata()->set_page_title("nested"); auto result = interpreter()->ConstructInputString( proto::MODEL_EXECUTION_FEATURE_COMPOSE, request, @@ -313,11 +306,11 @@ "optimization_guide.proto.ComposeRequest"); auto* execute_substitution = input_config->add_execute_substitutions(); execute_substitution->set_string_template("hello this is a test: %s %s"); - execute_substitution->add_substitutions() - ->add_candidates() - ->mutable_proto_field() - ->add_proto_descriptors() - ->set_tag_number(2); + auto* substitution1_proto_field = execute_substitution->add_substitutions() + ->add_candidates() + ->mutable_proto_field(); + substitution1_proto_field->add_proto_descriptors()->set_tag_number(8); + substitution1_proto_field->add_proto_descriptors()->set_tag_number(1); auto* substitution2 = execute_substitution->add_substitutions(); auto* arg1 = substitution2->add_candidates(); auto* proto_field1 = arg1->mutable_proto_field(); @@ -328,11 +321,13 @@ proto::CONDITION_EVALUATION_TYPE_OR); auto* arg1_c1 = arg1_conditions->add_conditions(); auto* arg1_c1_proto_field = arg1_c1->mutable_proto_field(); - arg1_c1_proto_field->add_proto_descriptors()->set_tag_number(4); + arg1_c1_proto_field->add_proto_descriptors()->set_tag_number(8); + arg1_c1_proto_field->add_proto_descriptors()->set_tag_number(2); arg1_c1->set_operator_type(proto::OPERATOR_TYPE_EQUAL_TO); arg1_c1->mutable_value()->set_int32_value(1); auto* arg1_c2 = arg1_conditions->add_conditions(); - arg1_c2->mutable_proto_field()->add_proto_descriptors()->set_tag_number(4); + arg1_c2->mutable_proto_field()->add_proto_descriptors()->set_tag_number(8); + arg1_c2->mutable_proto_field()->add_proto_descriptors()->set_tag_number(2); arg1_c2->set_operator_type(proto::OPERATOR_TYPE_EQUAL_TO); arg1_c1->mutable_value()->set_int32_value(2); auto* arg2 = substitution2->add_candidates(); @@ -344,11 +339,13 @@ proto::CONDITION_EVALUATION_TYPE_OR); auto* arg2_c1 = arg2_conditions->add_conditions(); auto* arg2_c1_proto_field = arg2_c1->mutable_proto_field(); - arg2_c1_proto_field->add_proto_descriptors()->set_tag_number(5); + arg2_c1_proto_field->add_proto_descriptors()->set_tag_number(8); + arg2_c1_proto_field->add_proto_descriptors()->set_tag_number(3); arg2_c1->set_operator_type(proto::OPERATOR_TYPE_EQUAL_TO); arg2_c1->mutable_value()->set_int32_value(1); auto* arg2_c2 = arg2_conditions->add_conditions(); - arg2_c2->mutable_proto_field()->add_proto_descriptors()->set_tag_number(5); + arg2_c2->mutable_proto_field()->add_proto_descriptors()->set_tag_number(8); + arg2_c2->mutable_proto_field()->add_proto_descriptors()->set_tag_number(3); arg2_c2->set_operator_type(proto::OPERATOR_TYPE_EQUAL_TO); arg2_c1->mutable_value()->set_int32_value(2); @@ -361,16 +358,17 @@ proto::CONDITION_EVALUATION_TYPE_AND); auto* c1 = es2_conditions->add_conditions(); auto* c1_proto_field = c1->mutable_proto_field(); - c1_proto_field->add_proto_descriptors()->set_tag_number(4); + c1_proto_field->add_proto_descriptors()->set_tag_number(8); + c1_proto_field->add_proto_descriptors()->set_tag_number(2); c1->set_operator_type(proto::OPERATOR_TYPE_NOT_EQUAL_TO); c1->mutable_value()->set_int32_value(0); UpdateInterpreterWithConfig(config); proto::ComposeRequest request; - request.set_user_input("this is my input"); + request.mutable_rewrite_params()->set_previous_response("this is my input"); + request.mutable_rewrite_params()->set_length(proto::COMPOSE_LONGER); request.mutable_page_metadata()->set_page_title("title"); request.mutable_page_metadata()->set_page_url("url"); - request.set_length(proto::COMPOSE_LONGER); auto result = interpreter()->ConstructInputString( proto::MODEL_EXECUTION_FEATURE_COMPOSE, request, /*want_input_context=*/false); @@ -439,7 +437,7 @@ fc->set_feature(proto::MODEL_EXECUTION_FEATURE_COMPOSE); auto* oc = fc->mutable_output_config(); oc->set_proto_type("optimization_guide.proto.ComposeRequest"); - oc->mutable_proto_field()->add_proto_descriptors()->set_tag_number(4); + oc->mutable_proto_field()->add_proto_descriptors()->set_tag_number(7); UpdateInterpreterWithConfig(config); auto maybe_metadata = interpreter()->ConstructOutputMetadata(
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc index 9612b94..5e69969 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
@@ -18,6 +18,7 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "services/on_device_model/public/cpp/model_assets.h" #include "services/on_device_model/public/mojom/on_device_model.mojom.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" namespace optimization_guide { @@ -139,7 +140,8 @@ LaunchService(); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock()}, - base::BindOnce(&on_device_model::LoadModelAssets, model_path_), + base::BindOnce(&on_device_model::LoadModelAssets, model_path_, + model_path_), base::BindOnce(&OnDeviceModelServiceController::OnModelAssetsLoaded, weak_ptr_factory_.GetWeakPtr(), model_remote_.BindNewPipeAndPassReceiver()));
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller.h b/components/optimization_guide/core/model_execution/on_device_model_service_controller.h index cfabb819..dd5cec1 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_service_controller.h +++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller.h
@@ -18,6 +18,7 @@ #include "components/optimization_guide/proto/model_execution.pb.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/on_device_model/public/mojom/on_device_model.mojom.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace base {
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 b18c291..11587e3 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
@@ -87,7 +87,7 @@ remote->OnResponse("Context: " + context + "\n"); } remote->OnResponse("Input: " + input->text + "\n"); - remote->OnComplete(); + remote->OnComplete(on_device_model::mojom::ResponseStatus::kOk); } void AddContextInternal( @@ -251,26 +251,26 @@ // Execute call prefixes with execute:. auto& substitution = *input_config.add_execute_substitutions(); substitution.set_string_template("execute:%s%s"); - substitution.add_substitutions() - ->add_candidates() - ->mutable_proto_field() - ->add_proto_descriptors() - ->set_tag_number(2); - auto* proto_field = substitution.add_substitutions() - ->add_candidates() - ->mutable_proto_field(); - proto_field->add_proto_descriptors()->set_tag_number(3); - proto_field->add_proto_descriptors()->set_tag_number(1); + auto* proto_field1 = substitution.add_substitutions() + ->add_candidates() + ->mutable_proto_field(); + proto_field1->add_proto_descriptors()->set_tag_number(7); + proto_field1->add_proto_descriptors()->set_tag_number(1); + auto* proto_field2 = substitution.add_substitutions() + ->add_candidates() + ->mutable_proto_field(); + proto_field2->add_proto_descriptors()->set_tag_number(3); + proto_field2->add_proto_descriptors()->set_tag_number(1); // Context call prefixes with context:. auto& context_substitution = *input_config.add_input_context_substitutions(); context_substitution.set_string_template("ctx:%s"); - context_substitution.add_substitutions() - ->add_candidates() - ->mutable_proto_field() - ->add_proto_descriptors() - ->set_tag_number(2); + auto* context_proto_field = context_substitution.add_substitutions() + ->add_candidates() + ->mutable_proto_field(); + context_proto_field->add_proto_descriptors()->set_tag_number(7); + context_proto_field->add_proto_descriptors()->set_tag_number(1); auto& output_config = *config.mutable_output_config(); output_config.set_proto_type(proto::ComposeResponse().GetTypeName()); @@ -289,7 +289,7 @@ void AddContext(OptimizationGuideModelExecutor::Session& session, std::string_view input) { proto::ComposeRequest request; - request.set_user_input(std::string(input)); + request.mutable_generate_params()->set_user_input(std::string(input)); session.AddContext(request); }
diff --git a/components/optimization_guide/core/model_execution/session_impl.cc b/components/optimization_guide/core/model_execution/session_impl.cc index a46e809..8edbb87 100644 --- a/components/optimization_guide/core/model_execution/session_impl.cc +++ b/components/optimization_guide/core/model_execution/session_impl.cc
@@ -206,7 +206,8 @@ SendResponse(/*is_complete=*/false); } -void SessionImpl::OnComplete() { +void SessionImpl::OnComplete(on_device_model::mojom::ResponseStatus status) { + // TODO(b/302395507): Handle a retracted response. base::UmaHistogramMediumTimes( base::StrCat( {"OptimizationGuide.ModelExecution.OnDeviceResponseCompleteTime.",
diff --git a/components/optimization_guide/core/model_execution/session_impl.h b/components/optimization_guide/core/model_execution/session_impl.h index c679947a..cbb70a8 100644 --- a/components/optimization_guide/core/model_execution/session_impl.h +++ b/components/optimization_guide/core/model_execution/session_impl.h
@@ -49,7 +49,7 @@ // on_device_model::mojom::StreamingResponder: void OnResponse(const std::string& response) override; - void OnComplete() override; + void OnComplete(on_device_model::mojom::ResponseStatus status) override; // Returns true if the on-device model should be used. bool ShouldUseOnDeviceModel() const;
diff --git a/components/optimization_guide/core/model_quality/model_quality_logs_uploader_service_unittest.cc b/components/optimization_guide/core/model_quality/model_quality_logs_uploader_service_unittest.cc index b34ea00b..668ca2b 100644 --- a/components/optimization_guide/core/model_quality/model_quality_logs_uploader_service_unittest.cc +++ b/components/optimization_guide/core/model_quality/model_quality_logs_uploader_service_unittest.cc
@@ -41,7 +41,7 @@ proto::ComposeLoggingData compose_logging_data; proto::ComposeRequest request; - request.set_user_input("a user typed this"); + request.mutable_generate_params()->set_user_input("a user typed this"); proto::ComposeResponse response; response.set_output("compose response");
diff --git a/components/optimization_guide/proto/features/compose.proto b/components/optimization_guide/proto/features/compose.proto index b43408f..7c958218 100644 --- a/components/optimization_guide/proto/features/compose.proto +++ b/components/optimization_guide/proto/features/compose.proto
@@ -97,6 +97,8 @@ // Stores all data associated with a single call to the model execution run for // compose. message ComposeRequest { + reserved 1, 2, 4, 5, 6; + message GenerateParams { // User written input text. string user_input = 1; @@ -116,22 +118,8 @@ RewriteParams rewrite_params = 8; } - // Purely the user input text. - string user_input = 2 [deprecated = true]; - // Contains information scraped from the page. ComposePageMetadata page_metadata = 3; - - // Stores the tone selection that the user chose. - ComposeTone tone = 4 [deprecated = true]; - - // Stores the length selection that the user chose. - ComposeLength length = 5 [deprecated = true]; - - // The previous Compose responses, which may be used when the user is - // selecting a different tone or length. Specified only for responses where - // the user prompt (and page context) stay the same. - repeated ComposePriorResponse previous_responses = 6 [deprecated = true]; } // Stores the response text from the model execution run.
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index 3ffe20a..0e5b391 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -19,8 +19,8 @@ #include "base/test/task_environment.h" #include "base/test/test_mock_time_task_runner.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/randomized_encoder.h" @@ -68,47 +68,47 @@ #include "components/webauthn/android/webauthn_cred_man_delegate.h" #endif // BUILDFLAG(IS_ANDROID) -using autofill::AutofillUploadContents; -using autofill::FieldPropertiesFlags; -using autofill::FieldRendererId; -using autofill::FieldSignature; -using autofill::FormData; -using autofill::FormFieldData; -using autofill::FormRendererId; -using autofill::FormSignature; -using autofill::FormStructure; -using autofill::IsMostRecentSingleUsernameCandidate; -using autofill::NOT_USERNAME; -using autofill::PasswordFormFillData; -using autofill::PasswordFormGenerationData; -using autofill::ServerFieldType; -using autofill::ServerFieldTypeSet; -using autofill::SINGLE_USERNAME; -using autofill::SINGLE_USERNAME_FORGOT_PASSWORD; -using autofill::UNKNOWN_TYPE; -using autofill::password_generation::PasswordGenerationType; -using base::TestMockTimeTaskRunner; -using signin::GaiaIdHash; -using testing::_; -using testing::AllOf; -using testing::Contains; -using testing::DoAll; -using testing::ElementsAre; -using testing::IsEmpty; -using testing::IsNull; -using testing::Mock; -using testing::NiceMock; -using testing::Pointee; -using testing::Return; -using testing::ReturnRef; -using testing::SaveArg; -using testing::SaveArgPointee; -using testing::UnorderedElementsAre; - namespace password_manager { namespace { +using ::autofill::AutofillUploadContents; +using ::autofill::FieldPropertiesFlags; +using ::autofill::FieldRendererId; +using ::autofill::FieldSignature; +using ::autofill::FormData; +using ::autofill::FormFieldData; +using ::autofill::FormRendererId; +using ::autofill::FormSignature; +using ::autofill::FormStructure; +using ::autofill::IsMostRecentSingleUsernameCandidate; +using ::autofill::NOT_USERNAME; +using ::autofill::PasswordFormFillData; +using ::autofill::PasswordFormGenerationData; +using ::autofill::ServerFieldType; +using ::autofill::ServerFieldTypeSet; +using ::autofill::SINGLE_USERNAME; +using ::autofill::SINGLE_USERNAME_FORGOT_PASSWORD; +using ::autofill::UNKNOWN_TYPE; +using ::autofill::password_generation::PasswordGenerationType; +using ::base::TestMockTimeTaskRunner; +using ::signin::GaiaIdHash; +using ::testing::_; +using ::testing::AllOf; +using ::testing::Contains; +using ::testing::DoAll; +using ::testing::ElementsAre; +using ::testing::IsEmpty; +using ::testing::IsNull; +using ::testing::Mock; +using ::testing::NiceMock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::ReturnRef; +using ::testing::SaveArg; +using ::testing::SaveArgPointee; +using ::testing::UnorderedElementsAre; + // Indices of username and password fields in the observed form. constexpr int kUsernameFieldIndex = 1; constexpr int kPasswordFieldIndex = 2; @@ -151,33 +151,11 @@ MOCK_METHOD(bool, IsInPrimaryMainFrame, (), (const, override)); }; -class MockAutofillDownloadManager : public autofill::AutofillDownloadManager { - public: - MockAutofillDownloadManager() - : AutofillDownloadManager(nullptr, - version_info::Channel::UNKNOWN, - nullptr) {} - MockAutofillDownloadManager(const MockAutofillDownloadManager&) = delete; - MockAutofillDownloadManager& operator=(const MockAutofillDownloadManager&) = - delete; - - MOCK_METHOD(bool, - StartUploadRequest, - (const FormStructure&, - bool, - const ServerFieldTypeSet&, - const std::string&, - bool, - PrefService*, - base::WeakPtr<Observer>), - (override)); -}; - class MockPasswordManagerClient : public StubPasswordManagerClient { public: MOCK_METHOD(bool, IsOffTheRecord, (), (const, override)); - MOCK_METHOD(autofill::AutofillDownloadManager*, - GetAutofillDownloadManager, + MOCK_METHOD(autofill::AutofillCrowdsourcingManager*, + GetAutofillCrowdsourcingManager, (), (override)); MOCK_METHOD(void, UpdateFormManagers, (), (override)); @@ -448,14 +426,14 @@ parsed_submitted_form_.password_value = submitted_form_.fields[kPasswordFieldIndex].value; - EXPECT_CALL(client_, GetAutofillDownloadManager()) - .WillRepeatedly(Return(&mock_autofill_download_manager_)); + EXPECT_CALL(client_, GetAutofillCrowdsourcingManager()) + .WillRepeatedly(Return(&mock_autofill_crowdsourcing_manager_)); ON_CALL(client_, GetPrefs()).WillByDefault(Return(&pref_service_)); ON_CALL(client_, IsCommittedMainFrameSecure()).WillByDefault(Return(true)); ON_CALL(*client_.GetPasswordFeatureManager(), ShouldShowAccountStorageBubbleUi) .WillByDefault(Return(true)); - ON_CALL(mock_autofill_download_manager_, StartUploadRequest) + ON_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) .WillByDefault(Return(true)); ON_CALL(*client_.GetPasswordFeatureManager(), GetDefaultPasswordStore) .WillByDefault(Return(PasswordForm::Store::kProfileStore)); @@ -488,7 +466,8 @@ protected: autofill::test::AutofillUnitTestEnvironment autofill_test_environment_; - MockAutofillDownloadManager mock_autofill_download_manager_; + NiceMock<autofill::MockAutofillCrowdsourcingManager> + mock_autofill_crowdsourcing_manager_{/*client=*/nullptr}; FormData observed_form_; FormData submitted_form_; FormData observed_form_only_password_fields_; @@ -577,7 +556,7 @@ is_most_recent_single_username_candidate = autofill::IsMostRecentSingleUsernameCandidate:: kNotPartOfUsernameFirstFlow) { - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(form_signature), UploadedSingleUsernameVoteTypeIs(vote_type), @@ -1224,12 +1203,12 @@ testing::InSequence in_sequence; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(UploadedAutofillTypesAre(expected_types), false, _, _, true, nullptr, /*observer=*/IsNull())); if (expected_vote == autofill::NEW_PASSWORD) { // An unrelated |FIRST_USE| vote. - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(_, _, _, _, _, _, /*observer=*/IsNull())); } @@ -1239,7 +1218,7 @@ form_manager_->OnNoInteraction(true /* is_update */); else form_manager_->OnNopeUpdateClicked(); - Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + Mock::VerifyAndClearExpectations(&mock_autofill_crowdsourcing_manager_); } } @@ -1297,7 +1276,7 @@ testing::InSequence in_sequence; // Unrelated regular PASSWORD vote. - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(_, _, _, _, _, _, _)); std::map<std::u16string, autofill::ServerFieldType> expected_types; expected_types[saved_match_.all_alternative_usernames[0].name] = @@ -1315,7 +1294,7 @@ AutofillUploadContents::Field::USERNAME_OVERWRITTEN}}; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(saved_match_.form_data)), UploadedAutofillTypesAre(expected_types), @@ -1365,7 +1344,7 @@ // Credentials saved on the signup form were reused on a login form. The vote // applies to the first (signup) form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(saved_match_.form_data)), VoteTypesAre( @@ -1380,7 +1359,7 @@ // Saved credentials from the signup form were used for the first time on a // submitted form. The vote applies to the new form being submitted. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(submitted_form_)), VoteTypesAre({{submitted_form_.fields[kPasswordFieldIndex] @@ -1433,7 +1412,7 @@ VoteTypeMap expected_vote_types = { {submitted_form_.fields[0].unique_renderer_id, AutofillUploadContents::Field::USERNAME_EDITED}}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(AllOf(UploadedAutofillTypesAre(expected_types), HasGenerationVote(false), VoteTypesAre(expected_vote_types)), @@ -1476,7 +1455,7 @@ // TODO(https://crbug.com/928690): implement not sending incorrect votes and // check that StartUploadRequest is not called. - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(_, _, _, _, _, _, /*observer=*/IsNull())) .Times(1); form_manager_->Save(); @@ -1519,7 +1498,7 @@ // likely picked wrong. Make sure votes for password field and password // generation attributes are not uploaded. ServerFieldTypeSet expected_types = {autofill::USERNAME}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(HasPasswordAttributesVote(false), _, expected_types, _, _, _, _)); form_manager_->Save(); @@ -1556,7 +1535,7 @@ expected_types[expected.password_element] = autofill::PASSWORD; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(UploadedAutofillTypesAre(expected_types), false, _, _, true, nullptr, /*observer=*/IsNull())); @@ -2231,11 +2210,11 @@ form_manager_->OnPasswordsRevealed(); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(PasswordsWereRevealed(password_revealed), false, _, _, true, nullptr, /*observer=*/IsNull())); form_manager_->Save(); - Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + Mock::VerifyAndClearExpectations(&mock_autofill_crowdsourcing_manager_); } } @@ -2254,12 +2233,12 @@ EXPECT_TRUE( form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr)); - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr, /*observer=*/IsNull())) .Times(generation_popup_shown ? 1 : 0); form_manager_->OnNoInteraction(false /*is_update */); - Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + Mock::VerifyAndClearExpectations(&mock_autofill_crowdsourcing_manager_); } } @@ -2278,12 +2257,12 @@ EXPECT_TRUE( form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr)); - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr, /*observer=*/IsNull())) .Times(generation_popup_shown ? 1 : 0); form_manager_->OnNeverClicked(); - Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + Mock::VerifyAndClearExpectations(&mock_autofill_crowdsourcing_manager_); } } @@ -2661,7 +2640,7 @@ // Check that no SINGLE_USERNAME vote is sent (PASSWORD != SINGLE_USERNAME). auto expected_votes = ServerFieldTypeSet{autofill::PASSWORD}; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form)), _, expected_votes, _, _, _, _)); form_manager_->Save(); @@ -2716,7 +2695,7 @@ // Upload username first flow votes on the username form. #if !BUILDFLAG(IS_ANDROID) - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kSingleUsernameFormSignature), false, ServerFieldTypeSet{SINGLE_USERNAME}, _, true, nullptr, /*observer=*/IsNull())); @@ -2735,7 +2714,7 @@ : autofill::AutofillUploadContents::USERNAME_LIKE); expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::EDITED_POSITIVE); - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(submitted_form)), UploadedSingleUsernameDataIs( @@ -2745,7 +2724,7 @@ if (is_password_update) { // Expect another upload for first login votes. This upload is not related // to UFF, so it should not contain single username data. - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SingleUsernameDataNotUploaded(), _, _, _, _, _, /*observer=*/IsNull())); } @@ -2764,7 +2743,7 @@ histogram_tester.ExpectTotalCount( "PasswordManager.SingleUsername.PasswordFormHadUsernameField", 0); #endif - Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + Mock::VerifyAndClearExpectations(&mock_autofill_crowdsourcing_manager_); } } @@ -2799,7 +2778,7 @@ // Upload username first flow vote on the single username form. #if !BUILDFLAG(IS_ANDROID) - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kSingleUsernameFormSignature), false, ServerFieldTypeSet{SINGLE_USERNAME}, _, true, nullptr, /*observer=*/IsNull())); @@ -2817,7 +2796,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::NOT_EDITED_POSITIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(submitted_form_)), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -2837,7 +2816,7 @@ histogram_tester.ExpectTotalCount( "PasswordManager.SingleUsername.PasswordFormHadUsernameField", 0); #endif - Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + Mock::VerifyAndClearExpectations(&mock_autofill_crowdsourcing_manager_); } // Tests that when the save/update prompt suggests single username value and the @@ -2889,7 +2868,7 @@ // Expect upload for the password form. This upload is unrelated to UFF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form_)), _, _, _, _, _, _)); @@ -2949,7 +2928,7 @@ // Expect upload for the password form. This upload is unrelated to UFF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form_)), _, _, _, _, _, _)); @@ -2995,7 +2974,7 @@ form_manager_->SaveSuggestedUsernameValueToVotesUploader(); // Expect no upload on single text field. - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kSingleUsernameFormSignature), _, _, _, _, _, _)) .Times(0); @@ -3003,7 +2982,7 @@ // Expect upload for the password form. This upload is unrelated to UFF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form_)), _, _, _, _, _, _)); @@ -3061,7 +3040,7 @@ // Upload username first flow vote on the single username form. #if !BUILDFLAG(IS_ANDROID) - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kSingleUsernameFormSignature), false, ServerFieldTypeSet{SINGLE_USERNAME}, _, true, nullptr, /*observer=*/IsNull())); @@ -3079,7 +3058,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::NOT_EDITED_POSITIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(submitted_form_)), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -3099,7 +3078,7 @@ histogram_tester.ExpectTotalCount( "PasswordManager.SingleUsername.PasswordFormHadUsernameField", 0); #endif - Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + Mock::VerifyAndClearExpectations(&mock_autofill_crowdsourcing_manager_); } // Tests that when the user edits the username value in the save prompt @@ -3185,7 +3164,7 @@ // Expect upload for the password form. This upload is unrelated to UFF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form)), _, _, _, _, _, _)); @@ -3305,12 +3284,13 @@ // Upload for the username form. Ensure that we send `NOT_USERNAME` for the // username field. #if !BUILDFLAG(IS_ANDROID) - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kUsernameFormSignature), false, ServerFieldTypeSet{NOT_USERNAME}, _, true, nullptr, /*observer=*/IsNull())); #else - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); #endif // !BUILDFLAG(IS_ANDROID) // Upload for the password form. @@ -3325,7 +3305,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::EDITED_NEGATIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(submitted_form)), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -3376,7 +3356,7 @@ // Check vote uploads. testing::InSequence in_sequence; // No single username upload for the OTP field. - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kSingleUsernameFormSignature), _, _, _, _, _, /*observer=*/IsNull())) .Times(0); @@ -3387,7 +3367,7 @@ expected_single_username_data.set_value_type( autofill::AutofillUploadContents::NO_VALUE_TYPE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(CalculateFormSignature(submitted_form)), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -3811,7 +3791,7 @@ // Expect upload for the password form. This upload is unrelated to FPF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form)), _, _, _, _, _, _)); @@ -3866,7 +3846,7 @@ // Expect upload for the password form. This upload is unrelated to FPF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form)), _, _, _, _, _, _)); @@ -3913,14 +3893,14 @@ // Expect no vote on another single text field form, unrelated to FPF. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kOtherFormSignature), _, _, _, _, _, _)) .Times(0); // Expect upload for the password form. This upload is unrelated to FPF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form)), _, _, _, _, _, _)); @@ -3977,14 +3957,14 @@ // Expect no vote on another single text field form, unrelated to FPF. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kOtherFormSignature), _, _, _, _, _, _)) .Times(0); // Expect upload for the password form. This upload is unrelated to FPF: it // is a result of saving a new password on the password form. EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(CalculateFormSignature(submitted_form)), _, _, _, _, _, _));
diff --git a/components/password_manager/core/browser/password_manager_client.cc b/components/password_manager/core/browser/password_manager_client.cc index e7244d2..a80bb45 100644 --- a/components/password_manager/core/browser/password_manager_client.cc +++ b/components/password_manager/core/browser/password_manager_client.cc
@@ -126,8 +126,8 @@ return nullptr; } -autofill::AutofillDownloadManager* -PasswordManagerClient::GetAutofillDownloadManager() { +autofill::AutofillCrowdsourcingManager* +PasswordManagerClient::GetAutofillCrowdsourcingManager() { return nullptr; }
diff --git a/components/password_manager/core/browser/password_manager_client.h b/components/password_manager/core/browser/password_manager_client.h index 170651c7..aa365c6 100644 --- a/components/password_manager/core/browser/password_manager_client.h +++ b/components/password_manager/core/browser/password_manager_client.h
@@ -31,7 +31,7 @@ class PrefService; namespace autofill { -class AutofillDownloadManager; +class AutofillCrowdsourcingManager; class LogManager; } // namespace autofill @@ -372,8 +372,9 @@ // Returns the HttpAuthManager associated with this client. virtual HttpAuthManager* GetHttpAuthManager(); - // Returns the AutofillDownloadManager for votes uploading. - virtual autofill::AutofillDownloadManager* GetAutofillDownloadManager(); + // Returns the AutofillCrowdsourcingManager for votes uploading. + virtual autofill::AutofillCrowdsourcingManager* + GetAutofillCrowdsourcingManager(); // Returns true if the main frame URL has a secure origin. // The WebContents only has a primary main frame, so MainFrame here refers to
diff --git a/components/password_manager/core/browser/password_manager_util_unittest.cc b/components/password_manager/core/browser/password_manager_util_unittest.cc index 2668846..0d630ad 100644 --- a/components/password_manager/core/browser/password_manager_util_unittest.cc +++ b/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -14,12 +14,14 @@ #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/payments/local_card_migration_manager.h" +#include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/ui/payments/card_unmask_prompt_options.h" #include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/browser/ui/popup_types.h" @@ -45,16 +47,16 @@ #include "base/android/build_info.h" #endif -using autofill::password_generation::PasswordGenerationType; -using device_reauth::MockDeviceAuthenticator; -using password_manager::Facet; -using password_manager::FacetURI; -using password_manager::GroupedFacets; -using password_manager::PasswordForm; - namespace password_manager_util { namespace { +using ::autofill::password_generation::PasswordGenerationType; +using ::device_reauth::MockDeviceAuthenticator; +using ::password_manager::Facet; +using ::password_manager::FacetURI; +using ::password_manager::GroupedFacets; +using ::password_manager::PasswordForm; + constexpr char kTestAndroidRealm[] = "android://hash@com.example.beta.android"; constexpr char kTestFederationURL[] = "https://google.com/"; constexpr char kTestProxyOrigin[] = "http://proxy.com/"; @@ -84,150 +86,6 @@ (override)); }; -class MockAutofillClient : public autofill::AutofillClient { - public: - MockAutofillClient() = default; - MockAutofillClient(const MockAutofillClient&) = delete; - MockAutofillClient& operator=(const MockAutofillClient&) = delete; - ~MockAutofillClient() override = default; - - MOCK_METHOD(version_info::Channel, GetChannel, (), (const, override)); - MOCK_METHOD(bool, IsOffTheRecord, (), (override)); - MOCK_METHOD(scoped_refptr<network::SharedURLLoaderFactory>, - GetURLLoaderFactory, - (), - (override)); - MOCK_METHOD(autofill::PersonalDataManager*, - GetPersonalDataManager, - (), - (override)); - MOCK_METHOD(autofill::AutocompleteHistoryManager*, - GetAutocompleteHistoryManager, - (), - (override)); - MOCK_METHOD(PrefService*, GetPrefs, (), (override)); - MOCK_METHOD(const PrefService*, GetPrefs, (), (const, override)); - MOCK_METHOD(syncer::SyncService*, GetSyncService, (), (override)); - MOCK_METHOD(signin::IdentityManager*, GetIdentityManager, (), (override)); - MOCK_METHOD(autofill::FormDataImporter*, GetFormDataImporter, (), (override)); - MOCK_METHOD(autofill::payments::PaymentsNetworkInterface*, - GetPaymentsNetworkInterface, - (), - (override)); - MOCK_METHOD(autofill::StrikeDatabase*, GetStrikeDatabase, (), (override)); - MOCK_METHOD(ukm::UkmRecorder*, GetUkmRecorder, (), (override)); - MOCK_METHOD(ukm::SourceId, GetUkmSourceId, (), (override)); - MOCK_METHOD(autofill::AddressNormalizer*, - GetAddressNormalizer, - (), - (override)); - MOCK_METHOD(const GURL&, - GetLastCommittedPrimaryMainFrameURL, - (), - (const, override)); - MOCK_METHOD(url::Origin, - GetLastCommittedPrimaryMainFrameOrigin, - (), - (const, override)); - MOCK_METHOD(security_state::SecurityLevel, - GetSecurityLevelForUmaHistograms, - (), - (override)); - MOCK_METHOD(const translate::LanguageState*, - GetLanguageState, - (), - (override)); - MOCK_METHOD(translate::TranslateDriver*, GetTranslateDriver, (), (override)); - MOCK_METHOD(void, ShowAutofillSettings, (autofill::PopupType), (override)); - MOCK_METHOD(void, - ConfirmCreditCardFillAssist, - (const autofill::CreditCard&, base::OnceClosure), - (override)); - MOCK_METHOD(void, - ConfirmSaveAddressProfile, - (const autofill::AutofillProfile&, - const autofill::AutofillProfile*, - SaveAddressProfilePromptOptions, - AddressProfileSavePromptCallback), - (override)); - MOCK_METHOD(void, - ShowEditAddressProfileDialog, - (const autofill::AutofillProfile&, - AutofillClient::AddressProfileSavePromptCallback), - (override)); - MOCK_METHOD(void, - ShowDeleteAddressProfileDialog, - (const autofill::AutofillProfile&, - AutofillClient::AddressProfileDeleteDialogCallback), - (override)); - MOCK_METHOD(bool, HasCreditCardScanFeature, (), (override)); - MOCK_METHOD(void, ScanCreditCard, (CreditCardScanCallback), (override)); - MOCK_METHOD(bool, IsTouchToFillCreditCardSupported, (), (override)); - MOCK_METHOD(bool, - ShowTouchToFillCreditCard, - (base::WeakPtr<autofill::TouchToFillDelegate>, - base::span<const autofill::CreditCard>), - (override)); - MOCK_METHOD(void, HideTouchToFillCreditCard, (), (override)); - MOCK_METHOD(void, - ShowAutofillPopup, - (const PopupOpenArgs&, - base::WeakPtr<autofill::AutofillPopupDelegate>), - (override)); - MOCK_METHOD(void, - UpdateAutofillPopupDataListValues, - (base::span<const autofill::SelectOption>), - (override)); - MOCK_METHOD(void, PinPopupView, (), (override)); - MOCK_METHOD(PopupOpenArgs, - GetReopenPopupArgs, - (autofill::AutofillSuggestionTriggerSource), - (const, override)); - MOCK_METHOD(std::vector<autofill::Suggestion>, - GetPopupSuggestions, - (), - (const, override)); - MOCK_METHOD(void, - UpdatePopup, - (const std::vector<autofill::Suggestion>&, - autofill::PopupType, - autofill::AutofillSuggestionTriggerSource), - (override)); - MOCK_METHOD(void, - HideAutofillPopup, - (autofill::PopupHidingReason), - (override)); - MOCK_METHOD(bool, IsAutocompleteEnabled, (), (const, override)); - MOCK_METHOD(bool, IsPasswordManagerEnabled, (), (override)); - MOCK_METHOD(void, - DidFillOrPreviewForm, - (autofill::mojom::ActionPersistence action_persistence, - autofill::AutofillTriggerSource trigger_source, - bool is_refill), - (override)); - MOCK_METHOD(void, - DidFillOrPreviewField, - (const std::u16string&, const std::u16string&), - (override)); - MOCK_METHOD(bool, IsContextSecure, (), (const, override)); - MOCK_METHOD(autofill::LogManager*, GetLogManager, (), (const, override)); - MOCK_METHOD(const autofill::AutofillAblationStudy&, - GetAblationStudy, - (), - (const, override)); -#if BUILDFLAG(IS_IOS) - MOCK_METHOD(bool, IsLastQueriedField, (autofill::FieldGlobalId), (override)); -#endif - MOCK_METHOD(void, - LoadRiskData, - (base::OnceCallback<void(const std::string&)>), - (override)); - MOCK_METHOD(autofill::FormInteractionsFlowId, - GetCurrentFormInteractionsFlowId, - (), - (override)); -}; - PasswordForm GetTestAndroidCredential() { PasswordForm form; form.scheme = PasswordForm::Scheme::kHtml; @@ -792,15 +650,17 @@ } TEST(PasswordManagerUtil, AvoidOverlappingAutofillMenuAndManualGeneration) { + base::test::TaskEnvironment task_environment; password_manager::StubPasswordManagerClient stub_password_client; - MockAutofillClient mock_autofill_client; + autofill::TestAutofillClient test_autofill_client; - EXPECT_CALL(mock_autofill_client, - HideAutofillPopup(autofill::PopupHidingReason:: - kOverlappingWithPasswordGenerationPopup)); - + test_autofill_client.ShowAutofillPopup( + autofill::AutofillClient::PopupOpenArgs(), /*delegate=*/nullptr); UserTriggeredManualGenerationFromContextMenu(&stub_password_client, - &mock_autofill_client); + &test_autofill_client); + EXPECT_EQ( + test_autofill_client.popup_hiding_reason(), + autofill::PopupHidingReason::kOverlappingWithPasswordGenerationPopup); } TEST(PasswordManagerUtil, StripAuthAndParams) {
diff --git a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc index 2459a6c..64b24f4d 100644 --- a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc +++ b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
@@ -9,7 +9,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/test_mock_time_task_runner.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_download_manager.h" +#include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/test_utils/vote_uploads_test_matchers.h" #include "components/autofill/core/common/unique_ids.h" @@ -25,33 +25,33 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using autofill::AutofillUploadContents; -using autofill::FormData; -using autofill::FormFieldData; -using autofill::FormStructure; -using autofill::PasswordFormFillData; -using autofill::mojom::SubmissionIndicatorEvent; -using base::TestMockTimeTaskRunner; -using testing::_; -using testing::AllOf; -using testing::Contains; -using testing::DoAll; -using testing::ElementsAre; -using testing::IsEmpty; -using testing::Mock; -using testing::NiceMock; -using testing::Pointee; -using testing::Return; -using testing::SaveArg; -using testing::UnorderedElementsAre; - namespace password_manager { namespace { +using ::autofill::AutofillUploadContents; +using ::autofill::FormData; +using ::autofill::FormFieldData; +using ::autofill::FormStructure; +using ::autofill::PasswordFormFillData; +using ::autofill::mojom::SubmissionIndicatorEvent; +using ::base::TestMockTimeTaskRunner; +using ::testing::_; +using ::testing::AllOf; +using ::testing::Contains; +using ::testing::DoAll; +using ::testing::ElementsAre; +using ::testing::IsEmpty; +using ::testing::Mock; +using ::testing::NiceMock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::UnorderedElementsAre; + // Indices of username and password fields in the observed form. -const int kUsernameFieldIndex = 1; -const int kPasswordFieldIndex = 2; +constexpr int kUsernameFieldIndex = 1; +constexpr int kPasswordFieldIndex = 2; MATCHER_P(FormHasUniqueKey, key, "") { return ArePasswordFormUniqueKeysEqual(arg, key); @@ -159,8 +159,8 @@ class MockPasswordManagerClient : public StubPasswordManagerClient { public: MOCK_METHOD(bool, IsOffTheRecord, (), (const, override)); - MOCK_METHOD(autofill::AutofillDownloadManager*, - GetAutofillDownloadManager, + MOCK_METHOD(autofill::AutofillCrowdsourcingManager*, + GetAutofillCrowdsourcingManager, (), (override)); MOCK_METHOD(void, UpdateFormManagers, (), (override)); @@ -171,28 +171,6 @@ MOCK_METHOD(bool, IsCommittedMainFrameSecure, (), (const, override)); }; -class MockAutofillDownloadManager : public autofill::AutofillDownloadManager { - public: - MockAutofillDownloadManager() - : AutofillDownloadManager(nullptr, - version_info::Channel::UNKNOWN, - nullptr) {} - MockAutofillDownloadManager(const MockAutofillDownloadManager&) = delete; - MockAutofillDownloadManager& operator=(const MockAutofillDownloadManager&) = - delete; - - MOCK_METHOD(bool, - StartUploadRequest, - (const FormStructure&, - bool, - const autofill::ServerFieldTypeSet&, - const std::string&, - bool, - PrefService*, - base::WeakPtr<Observer>), - (override)); -}; - } // namespace class PasswordSaveManagerImplTestBase : public testing::Test { @@ -301,9 +279,9 @@ password_save_manager_impl_->Init(&client_, fetcher_.get(), metrics_recorder_, &votes_uploader_); - ON_CALL(client_, GetAutofillDownloadManager()) - .WillByDefault(Return(&mock_autofill_download_manager_)); - ON_CALL(mock_autofill_download_manager_, StartUploadRequest) + ON_CALL(client_, GetAutofillCrowdsourcingManager()) + .WillByDefault(Return(&mock_autofill_crowdsourcing_manager_)); + ON_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) .WillByDefault(Return(true)); ON_CALL(*client_.GetPasswordFeatureManager(), GetDefaultPasswordStore) .WillByDefault(Return(PasswordForm::Store::kProfileStore)); @@ -340,8 +318,9 @@ return metrics_recorder_.get(); } - MockAutofillDownloadManager* mock_autofill_download_manager() { - return &mock_autofill_download_manager_; + autofill::MockAutofillCrowdsourcingManager* + mock_autofill_crowdsourcing_manager() { + return &mock_autofill_crowdsourcing_manager_; } TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); } @@ -409,7 +388,8 @@ std::unique_ptr<PasswordSaveManagerImpl> password_save_manager_impl_; raw_ptr<NiceMock<MockFormSaver>> mock_account_form_saver_ = nullptr; raw_ptr<NiceMock<MockFormSaver>> mock_profile_form_saver_ = nullptr; - NiceMock<MockAutofillDownloadManager> mock_autofill_download_manager_; + NiceMock<autofill::MockAutofillCrowdsourcingManager> + mock_autofill_crowdsourcing_manager_{/*client=*/nullptr}; }; // The boolean test parameter maps to the `enable_account_store` constructor @@ -911,7 +891,8 @@ // TODO(https://crbug.com/928690): implement not sending incorrect votes and // check that StartUploadRequest is not called. - EXPECT_CALL(*mock_autofill_download_manager(), StartUploadRequest).Times(1); + EXPECT_CALL(*mock_autofill_crowdsourcing_manager(), StartUploadRequest) + .Times(1); password_save_manager_impl()->Save(&observed_form_, parsed_submitted_form); } @@ -994,7 +975,7 @@ std::map<std::u16string, autofill::ServerFieldType> expected_types; expected_types[expected.password_element] = autofill::PASSWORD; - EXPECT_CALL(*mock_autofill_download_manager(), + EXPECT_CALL(*mock_autofill_crowdsourcing_manager(), StartUploadRequest(UploadedAutofillTypesAre(expected_types), false, _, _, true, nullptr, _)); @@ -1341,7 +1322,7 @@ expected_types[submitted_form_.fields[kPasswordFieldIndex].name] = autofill::PASSWORD; - EXPECT_CALL(*mock_autofill_download_manager(), + EXPECT_CALL(*mock_autofill_crowdsourcing_manager(), StartUploadRequest(UploadedAutofillTypesAre(expected_types), false, _, _, true, nullptr, _)); @@ -1352,7 +1333,7 @@ autofill::USERNAME; correction_upload_expected_types[u"password"] = autofill::ACCOUNT_CREATION_PASSWORD; - EXPECT_CALL(*mock_autofill_download_manager(), + EXPECT_CALL(*mock_autofill_crowdsourcing_manager(), StartUploadRequest( UploadedAutofillTypesAre(correction_upload_expected_types), false, _, _, true, nullptr, _));
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index 690c266..90da716 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -17,8 +17,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/proto/server.pb.h" #include "components/autofill/core/browser/randomized_encoder.h" @@ -33,7 +33,7 @@ #include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/common/password_manager_constants.h" -using autofill::AutofillDownloadManager; +using autofill::AutofillCrowdsourcingManager; using autofill::AutofillField; using autofill::AutofillUploadContents; using autofill::FieldRendererId; @@ -441,8 +441,8 @@ return false; } - AutofillDownloadManager* download_manager = - client_->GetAutofillDownloadManager(); + AutofillCrowdsourcingManager* download_manager = + client_->GetAutofillCrowdsourcingManager(); if (!download_manager) return false; @@ -566,8 +566,8 @@ const std::vector<const PasswordForm*>& best_matches, const PasswordForm& pending_credentials, const PasswordForm& form_to_upload) { - AutofillDownloadManager* download_manager = - client_->GetAutofillDownloadManager(); + AutofillCrowdsourcingManager* download_manager = + client_->GetAutofillCrowdsourcingManager(); if (!download_manager) return; @@ -908,8 +908,8 @@ bool VotesUploader::StartUploadRequest( std::unique_ptr<autofill::FormStructure> form_to_upload, const ServerFieldTypeSet& available_field_types) { - AutofillDownloadManager* download_manager = - client_->GetAutofillDownloadManager(); + AutofillCrowdsourcingManager* download_manager = + client_->GetAutofillCrowdsourcingManager(); if (!download_manager) return false;
diff --git a/components/password_manager/core/browser/votes_uploader_unittest.cc b/components/password_manager/core/browser/votes_uploader_unittest.cc index 409a9ce..bdc52661 100644 --- a/components/password_manager/core/browser/votes_uploader_unittest.cc +++ b/components/password_manager/core/browser/votes_uploader_unittest.cc
@@ -17,7 +17,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "build/build_config.h" -#include "components/autofill/core/browser/autofill_download_manager.h" +#include "components/autofill/core/browser/crowdsourcing/mock_autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/test_utils/vote_uploads_test_matchers.h" #include "components/autofill/core/common/form_data.h" @@ -32,36 +32,37 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using autofill::AutofillDownloadManager; -using autofill::CONFIRMATION_PASSWORD; -using autofill::FieldRendererId; -using autofill::FieldSignature; -using autofill::FormData; -using autofill::FormFieldData; -using autofill::FormSignature; -using autofill::FormStructure; -using autofill::NEW_PASSWORD; -using autofill::NOT_USERNAME; -using autofill::PASSWORD; -using autofill::PasswordAttribute; -using autofill::ServerFieldType; -using autofill::ServerFieldTypeSet; -using autofill::SignatureIsSameAs; -using autofill::SINGLE_USERNAME; -using autofill::SubmissionEventIsSameAs; -using autofill::UNKNOWN_TYPE; -using autofill::mojom::SubmissionIndicatorEvent; -using base::ASCIIToUTF16; -using testing::_; -using testing::AllOf; -using testing::AnyNumber; -using testing::IsNull; -using testing::Return; -using testing::SaveArg; - namespace password_manager { namespace { +using ::autofill::AutofillCrowdsourcingManager; +using ::autofill::CONFIRMATION_PASSWORD; +using ::autofill::FieldRendererId; +using ::autofill::FieldSignature; +using ::autofill::FormData; +using ::autofill::FormFieldData; +using ::autofill::FormSignature; +using ::autofill::FormStructure; +using ::autofill::NEW_PASSWORD; +using ::autofill::NOT_USERNAME; +using ::autofill::PASSWORD; +using ::autofill::PasswordAttribute; +using ::autofill::ServerFieldType; +using ::autofill::ServerFieldTypeSet; +using ::autofill::SignatureIsSameAs; +using ::autofill::SINGLE_USERNAME; +using ::autofill::SubmissionEventIsSameAs; +using ::autofill::UNKNOWN_TYPE; +using ::autofill::mojom::SubmissionIndicatorEvent; +using ::base::ASCIIToUTF16; +using ::testing::_; +using ::testing::AllOf; +using ::testing::AnyNumber; +using ::testing::IsNull; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::SaveArg; + constexpr int kNumberOfPasswordAttributes = static_cast<int>(PasswordAttribute::kPasswordAttributesCount); @@ -90,32 +91,10 @@ return single_username_data; } -class MockAutofillDownloadManager : public AutofillDownloadManager { - public: - MockAutofillDownloadManager() - : AutofillDownloadManager(nullptr, - version_info::Channel::UNKNOWN, - nullptr) {} - - MockAutofillDownloadManager(const MockAutofillDownloadManager&) = delete; - MockAutofillDownloadManager& operator=(const MockAutofillDownloadManager&) = - delete; - - MOCK_METHOD(bool, - StartUploadRequest, - (const FormStructure&, - bool, - const ServerFieldTypeSet&, - const std::string&, - bool, - PrefService*, - base::WeakPtr<Observer>), - (override)); -}; - class MockPasswordManagerClient : public StubPasswordManagerClient { public: - MOCK_METHOD0(GetAutofillDownloadManager, AutofillDownloadManager*()); + MOCK_METHOD0(GetAutofillCrowdsourcingManager, + AutofillCrowdsourcingManager*()); }; } // namespace @@ -123,10 +102,10 @@ class VotesUploaderTest : public testing::Test { public: VotesUploaderTest() { - EXPECT_CALL(client_, GetAutofillDownloadManager()) - .WillRepeatedly(Return(&mock_autofill_download_manager_)); + EXPECT_CALL(client_, GetAutofillCrowdsourcingManager()) + .WillRepeatedly(Return(&mock_autofill_crowdsourcing_manager_)); - ON_CALL(mock_autofill_download_manager_, StartUploadRequest) + ON_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) .WillByDefault(Return(true)); // Create |fields| in |form_to_upload_| and |submitted_form_|. Only |name| @@ -151,8 +130,8 @@ } base::test::TaskEnvironment task_environment_; - MockAutofillDownloadManager mock_autofill_download_manager_; - + NiceMock<autofill::MockAutofillCrowdsourcingManager> + mock_autofill_crowdsourcing_manager_{/*client=*/nullptr}; MockPasswordManagerClient client_; PasswordForm form_to_upload_; @@ -183,7 +162,7 @@ SubmissionIndicatorEvent expected_submission_event = SubmissionIndicatorEvent::HTML_FORM_SUBMISSION; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(form_to_upload_), UploadedAutofillTypesAre(expected_types), @@ -209,7 +188,7 @@ SubmissionIndicatorEvent expected_submission_event = SubmissionIndicatorEvent::HTML_FORM_SUBMISSION; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( SubmissionEventIsSameAs(expected_submission_event), false, expected_field_types, login_form_signature_, true, @@ -236,7 +215,7 @@ autofill::ACCOUNT_CREATION_PASSWORD, autofill::USERNAME}; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(UploadedAutofillTypesAre(expected_types), UsernameVoteTypeIsSameAs(autofill::AutofillUploadContents:: @@ -280,10 +259,10 @@ // SendVotesOnSave should call UploadPasswordVote and StartUploadRequest // twice. The first call is not the one that should be tested. testing::Expectation first_call = - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( UsernameVoteTypeIsSameAs( autofill::AutofillUploadContents::Field::USERNAME_OVERWRITTEN), @@ -311,7 +290,7 @@ autofill::ACCOUNT_CREATION_PASSWORD, autofill::USERNAME}; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf( UploadedAutofillTypesAre(expected_types), @@ -345,7 +324,7 @@ ServerFieldTypeSet expected_field_types = {autofill::USERNAME}; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( UsernameVoteTypeIsSameAs( autofill::AutofillUploadContents::Field::CREDENTIALS_REUSED), @@ -375,7 +354,7 @@ VotesUploader::UsernameChangeState::kChangedToKnownValue); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(UploadedAutofillTypesAre(expected_types), UsernameVoteTypeIsSameAs( @@ -409,7 +388,7 @@ votes_uploader.set_username_change_state( VotesUploader::UsernameChangeState::kChangedToKnownValue); - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( UsernameVoteTypeIsSameAs( autofill::AutofillUploadContents::Field::USERNAME_EDITED), @@ -484,7 +463,7 @@ bool expect_password_attributes = autofill_type == autofill::PASSWORD || autofill_type == autofill::NEW_PASSWORD; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( HasPasswordAttributesVote(expect_password_attributes), false, _, login_form_signature_, true, @@ -495,7 +474,8 @@ form_to_upload_, submitted_form_, autofill_type, login_form_signature_)); - testing::Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_); + testing::Mock::VerifyAndClearExpectations( + &mock_autofill_crowdsourcing_manager_); } } @@ -656,7 +636,8 @@ TEST_F(VotesUploaderTest, NoSingleUsernameDataNoUpload) { VotesUploader votes_uploader(&client_, false); - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); base::HistogramTester histogram_tester; votes_uploader.set_should_send_username_first_flow_votes(true); votes_uploader.MaybeSendSingleUsernameVotes(); @@ -699,7 +680,7 @@ #if !BUILDFLAG(IS_ANDROID) // Upload on the username form. ServerFieldTypeSet expected_types = {SINGLE_USERNAME}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(kSingleUsernameFormSignature), UploadedSingleUsernameVoteTypeIs( @@ -707,7 +688,8 @@ false, expected_types, std::string(), true, /* pref_service= */ nullptr, /*observer=*/IsNull())); #else - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); #endif // !BUILDFLAG(IS_ANDROID) base::HistogramTester histogram_tester; @@ -740,7 +722,7 @@ #if !BUILDFLAG(IS_ANDROID) // Upload on the username form. ServerFieldTypeSet expected_types = {NOT_USERNAME}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(kSingleUsernameFormSignature), UploadedSingleUsernameVoteTypeIs( @@ -748,7 +730,8 @@ false, expected_types, std::string(), true, /* pref_service= */ nullptr, /*observer=*/IsNull())); #else - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); #endif // !BUILDFLAG(IS_ANDROID) votes_uploader.MaybeSendSingleUsernameVotes(); @@ -761,7 +744,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::EDITED_NEGATIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(submitted_form_), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -793,7 +776,7 @@ #if !BUILDFLAG(IS_ANDROID) // Upload on the username form. ServerFieldTypeSet expected_types = {SINGLE_USERNAME}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(kSingleUsernameFormSignature), UploadedSingleUsernameVoteTypeIs( @@ -804,7 +787,8 @@ /*pref_service=*/nullptr, /*observer=*/IsNull())); #else - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); #endif // !BUILDFLAG(IS_ANDROID) votes_uploader.MaybeSendSingleUsernameVotes(); @@ -815,7 +799,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::NOT_EDITED_POSITIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(submitted_form_), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -848,7 +832,7 @@ #if !BUILDFLAG(IS_ANDROID) // Upload on the username form. ServerFieldTypeSet expected_types = {NOT_USERNAME}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(kSingleUsernameFormSignature), UploadedSingleUsernameVoteTypeIs( @@ -859,7 +843,8 @@ /*pref_service=*/nullptr, /*observer=*/IsNull())); #else - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); #endif // !BUILDFLAG(IS_ANDROID) votes_uploader.MaybeSendSingleUsernameVotes(); @@ -870,7 +855,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::NOT_EDITED_NEGATIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(submitted_form_), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -902,7 +887,7 @@ #if !BUILDFLAG(IS_ANDROID) ServerFieldTypeSet expected_types = {SINGLE_USERNAME}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(kSingleUsernameFormSignature), UploadedSingleUsernameVoteTypeIs( @@ -913,7 +898,8 @@ /*pref_service=*/nullptr, /*observer=*/IsNull())); #else - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); #endif // !BUILDFLAG(IS_ANDROID) votes_uploader.MaybeSendSingleUsernameVotes(); @@ -924,7 +910,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::EDITED_POSITIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(submitted_form_), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -955,7 +941,7 @@ #if !BUILDFLAG(IS_ANDROID) // Upload on the username form. ServerFieldTypeSet expected_types = {NOT_USERNAME}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIs(kSingleUsernameFormSignature), UploadedSingleUsernameVoteTypeIs( @@ -966,7 +952,8 @@ /*pref_service=*/nullptr, /*observer=*/IsNull())); #else - EXPECT_CALL(mock_autofill_download_manager_, StartUploadRequest).Times(0); + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest) + .Times(0); #endif // !BUILDFLAG(IS_ANDROID) votes_uploader.MaybeSendSingleUsernameVotes(); @@ -977,7 +964,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::EDITED_NEGATIVE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(submitted_form_), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -1007,7 +994,7 @@ votes_uploader.set_should_send_username_first_flow_votes(true); // Expect no upload on username form, as th signal is not informative to us. - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(SignatureIs(kSingleUsernameFormSignature), _, _, _, _, _, /*observer=*/IsNull())) .Times(0); @@ -1019,7 +1006,7 @@ expected_single_username_data.set_prompt_edit( autofill::AutofillUploadContents::EDIT_UNSPECIFIED); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(submitted_form_), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -1053,7 +1040,7 @@ autofill::AutofillUploadContents::NO_VALUE_TYPE); EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest( AllOf(SignatureIsSameAs(submitted_form_), UploadedSingleUsernameDataIs({expected_single_username_data})), @@ -1079,7 +1066,7 @@ FieldRendererId(11); ServerFieldTypeSet expected_field_types = {PASSWORD, CONFIRMATION_PASSWORD}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(_, false, expected_field_types, login_form_signature_, true, /* pref_service= */ nullptr, @@ -1105,7 +1092,7 @@ FieldRendererId(12); ServerFieldTypeSet expected_field_types = {PASSWORD, CONFIRMATION_PASSWORD}; - EXPECT_CALL(mock_autofill_download_manager_, + EXPECT_CALL(mock_autofill_crowdsourcing_manager_, StartUploadRequest(_, false, expected_field_types, login_form_signature_, true, /* pref_service= */ nullptr, @@ -1135,7 +1122,7 @@ ServerFieldTypeSet expected_types = { autofill::SINGLE_USERNAME_FORGOT_PASSWORD}; EXPECT_CALL( - mock_autofill_download_manager_, + mock_autofill_crowdsourcing_manager_, StartUploadRequest(AllOf(SignatureIs(kSingleUsernameFormSignature), UploadedSingleUsernameVoteTypeIs( autofill::AutofillUploadContents::Field::
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc index d3ead2b..4ec08c1 100644 --- a/components/pdf/renderer/pdf_accessibility_tree.cc +++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -1860,8 +1860,6 @@ !did_have_an_image_) { // In this case, PDF OCR doesn't run. Thus, set the status node to notify // users that the PDF content has been loaded into an accessibility tree. - // TODO(crbug.com/1473176): Consider merging the code below with - // `SetOcrCompleteStatus()`. SetStatusMessage(IDS_PDF_LOADED_TO_A11Y_TREE); UnserializeNodes();
diff --git a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc index e5b1e08..24c41eed 100644 --- a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc +++ b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
@@ -2896,9 +2896,6 @@ status_node->GetStringAttribute(ax::mojom::StringAttribute::kName)); } -// TODO(crbug.com/1473176): Update it to provide fine-grained test coverage, -// considering that the status node can be updated with an OCR complete message -// before or after `UnserializeNodes()`. TEST_P(PdfOcrServiceTest, OCRCompleteNotification) { CreatePdfAccessibilityTree();
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn index cb66c46..4591bdf6 100644 --- a/components/performance_manager/BUILD.gn +++ b/components/performance_manager/BUILD.gn
@@ -167,6 +167,7 @@ "public/resource_attribution/attribution_helpers.h", "public/resource_attribution/cpu_measurement_delegate.h", "public/resource_attribution/frame_context.h", + "public/resource_attribution/memory_measurement_delegate.h", "public/resource_attribution/page_context.h", "public/resource_attribution/process_context.h", "public/resource_attribution/queries.h", @@ -194,6 +195,9 @@ "resource_attribution/cpu_measurement_monitor.h", "resource_attribution/frame_context.cc", "resource_attribution/graph_change.h", + "resource_attribution/memory_measurement_delegate.cc", + "resource_attribution/memory_measurement_provider.cc", + "resource_attribution/memory_measurement_provider.h", "resource_attribution/page_context.cc", "resource_attribution/process_context.cc", "resource_attribution/queries.cc", @@ -202,6 +206,8 @@ "resource_attribution/query_scheduler.cc", "resource_attribution/query_scheduler.h", "resource_attribution/scoped_cpu_query.cc", + "resource_attribution/worker_client_pages.cc", + "resource_attribution/worker_client_pages.h", "resource_attribution/worker_context.cc", "service_worker_client.cc", "service_worker_client.h", @@ -438,6 +444,7 @@ "performance_manager_browsertest.cc", "prerendering_browsertest.cc", "render_process_host_proxy_browsertest.cc", + "resource_attribution/memory_measurement_provider_browsertest.cc", "v8_memory/v8_context_tracker_browsertest.cc", ]
diff --git a/components/performance_manager/public/resource_attribution/memory_measurement_delegate.h b/components/performance_manager/public/resource_attribution/memory_measurement_delegate.h new file mode 100644 index 0000000..fb170dd --- /dev/null +++ b/components/performance_manager/public/resource_attribution/memory_measurement_delegate.h
@@ -0,0 +1,79 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_RESOURCE_ATTRIBUTION_MEMORY_MEASUREMENT_DELEGATE_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_RESOURCE_ATTRIBUTION_MEMORY_MEASUREMENT_DELEGATE_H_ + +#include <compare> +#include <map> +#include <memory> + +#include "base/functional/callback_forward.h" + +namespace performance_manager { +class Graph; +} + +namespace performance_manager::resource_attribution { + +class ProcessContext; + +// A shim that Resource Attribution queries use to request memory measurements. +// Public so that users of the API can inject a test override by passing a +// factory object to SetDelegateFactoryForTesting(). +class MemoryMeasurementDelegate { + public: + class Factory; + + // The minimal results returned for a process memory measurement. + // MemoryMeasurementProvider will wrap this in a full MemorySummaryResult. + struct MemorySummaryMeasurement { + uint64_t resident_set_size_kb = 0; + uint64_t private_footprint_kb = 0; + + // Division operator required by SplitResourceAmongFramesAndWorkers(). + constexpr MemorySummaryMeasurement operator/(size_t divisor) { + return MemorySummaryMeasurement{ + .resident_set_size_kb = resident_set_size_kb / divisor, + .private_footprint_kb = private_footprint_kb / divisor}; + } + + friend constexpr auto operator<=>(const MemorySummaryMeasurement&, + const MemorySummaryMeasurement&) = + default; + friend constexpr bool operator==(const MemorySummaryMeasurement&, + const MemorySummaryMeasurement&) = default; + }; + + using MemorySummaryMap = std::map<ProcessContext, MemorySummaryMeasurement>; + + // The given `factory` will be used to create a MemoryMeasurementDelegate to + // measure ProcessNodes in `graph`. The factory object must outlive the graph. + // Usually it's owned by the test harness. nullptr will cause the factory + // returned by GetDefaultFactory() to be used. + static void SetDelegateFactoryForTesting(Graph* graph, Factory* factory); + + // Returns the default factory to use in production. + static Factory* GetDefaultFactory(); + + virtual ~MemoryMeasurementDelegate() = default; + + // Requests a memory summary for all processes. `callback` will be invoked + // with the results, or an empty map on error. + virtual void RequestMemorySummary( + base::OnceCallback<void(MemorySummaryMap)>) = 0; +}; + +class MemoryMeasurementDelegate::Factory { + public: + virtual ~Factory() = default; + + // Creates a MemoryMeasurementDelegate for all ProcessNodes in `graph`. + virtual std::unique_ptr<MemoryMeasurementDelegate> CreateDelegate( + Graph* graph) = 0; +}; + +} // namespace performance_manager::resource_attribution + +#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_RESOURCE_ATTRIBUTION_MEMORY_MEASUREMENT_DELEGATE_H_
diff --git a/components/performance_manager/public/resource_attribution/query_results.h b/components/performance_manager/public/resource_attribution/query_results.h index 81d9949..de760710 100644 --- a/components/performance_manager/public/resource_attribution/query_results.h +++ b/components/performance_manager/public/resource_attribution/query_results.h
@@ -45,7 +45,16 @@ base::TimeDelta cumulative_cpu; }; -using QueryResult = absl::variant<CPUTimeResult>; +// Results of a kMemorySummary query. +// TODO(crbug.com/1471683): Add kMemorySummary to the ResourceType enum, +// implement queries for it. +struct MemorySummaryResult { + ResultMetadata metadata; + uint64_t resident_set_size_kb = 0; + uint64_t private_footprint_kb = 0; +}; + +using QueryResult = absl::variant<CPUTimeResult, MemorySummaryResult>; using QueryResults = std::vector<QueryResult>; using QueryResultMap = std::map<ResourceContext, QueryResults>; @@ -108,6 +117,24 @@ return !(a == b); } +inline bool operator==(const MemorySummaryResult& a, + const MemorySummaryResult& b) { + static_assert( + sizeof(MemorySummaryResult) == + sizeof(decltype(MemorySummaryResult::metadata)) + + sizeof(decltype(MemorySummaryResult::resident_set_size_kb)) + + sizeof(decltype(MemorySummaryResult::private_footprint_kb)), + "update operator== when changing MemorySummaryResult"); + return a.metadata == b.metadata && + a.resident_set_size_kb == b.resident_set_size_kb && + a.private_footprint_kb == b.private_footprint_kb; +} + +inline bool operator!=(const MemorySummaryResult& a, + const MemorySummaryResult& b) { + return !(a == b); +} + } // namespace performance_manager::resource_attribution #endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_RESOURCE_ATTRIBUTION_QUERY_RESULTS_H_
diff --git a/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc b/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc index 87e7e58..6413dba 100644 --- a/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc +++ b/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc
@@ -28,6 +28,7 @@ #include "components/performance_manager/public/resource_attribution/frame_context.h" #include "components/performance_manager/public/resource_attribution/worker_context.h" #include "components/performance_manager/resource_attribution/graph_change.h" +#include "components/performance_manager/resource_attribution/worker_client_pages.h" #include "content/public/common/process_type.h" #include "third_party/abseil-cpp/absl/types/variant.h" @@ -105,69 +106,6 @@ ValidateCPUTimeResult(result); } -// Recursively visits all client workers of `worker_node`, and all client -// frames of each worker, and adds each frame's PageNode to `client_pages`. -// `visited_workers` is used to check for loops in the graph of client -// workers. `graph_change` is a change to the graph topology in progress that -// may affect the client page set, or NoGraphChange. -void RecursivelyFindClientPages(const WorkerNode* worker_node, - GraphChange graph_change, - std::set<const PageNode*>& client_pages, - std::set<const WorkerNode*>& visited_workers) { - const auto [_, inserted] = visited_workers.insert(worker_node); - if (!inserted) { - // Already visited, halt recursion. - return; - } - worker_node->VisitClientFrames( - [&client_pages, &graph_change, worker_node](const FrameNode* f) { - const auto* add_client_frame_change = - absl::get_if<GraphChangeAddClientFrameToWorker>(&graph_change); - if (add_client_frame_change && - add_client_frame_change->worker_node == worker_node && - add_client_frame_change->client_frame_node == f) { - // Skip this client node. The measurement being distributed includes - // CPU usage from before it was added. - return true; - } - client_pages.insert(f->GetPageNode()); - return true; - }); - worker_node->VisitClientWorkers([&client_pages, &visited_workers, - &graph_change, - worker_node](const WorkerNode* w) { - const auto* add_client_worker_change = - absl::get_if<GraphChangeAddClientWorkerToWorker>(&graph_change); - if (add_client_worker_change && - add_client_worker_change->worker_node == worker_node && - add_client_worker_change->client_worker_node == w) { - // Skip this client node. The measurement being distributed includes CPU - // usage from before it was added. - return true; - } - - RecursivelyFindClientPages(w, graph_change, client_pages, visited_workers); - return true; - }); - // Unlike FrameNode, WorkerNode does not update any graph links in - // WorkerNodeImpl::OnBeforeLeavingGraph(). So no need to check for - // GraphChangeRemoveClient*FromWorker. - // TODO(https://crbug.com/1481676): If that changes. handle - // `graph_change.client_*_node` as if it was visited by the above visitors. -} - -// Returns the complete set of pages that are clients of `worker_node`. -// `graph_change` is a change to the graph topology in progress that may affect -// the client page set, or NoGraphChange. -std::set<const PageNode*> GetClientPages(const WorkerNode* worker_node, - GraphChange graph_change) { - std::set<const PageNode*> client_pages; - std::set<const WorkerNode*> visited_workers; - RecursivelyFindClientPages(worker_node, graph_change, client_pages, - visited_workers); - return client_pages; -} - } // namespace CPUMeasurementMonitor::CPUMeasurementMonitor() @@ -454,7 +392,7 @@ AsContext<WorkerContext>(context).GetWorkerNode(); CHECK(worker_node); for (const PageNode* page_node : - GetClientPages(worker_node, graph_change)) { + GetWorkerClientPages(worker_node, graph_change)) { ApplyOverlappingDelta( measurement_results_[page_node->GetResourceContext()], delta); }
diff --git a/components/performance_manager/resource_attribution/cpu_measurement_monitor_unittest.cc b/components/performance_manager/resource_attribution/cpu_measurement_monitor_unittest.cc index 7a954c8..7024e2e 100644 --- a/components/performance_manager/resource_attribution/cpu_measurement_monitor_unittest.cc +++ b/components/performance_manager/resource_attribution/cpu_measurement_monitor_unittest.cc
@@ -6,7 +6,6 @@ #include <map> #include <memory> -#include <ostream> #include <utility> #include <vector> @@ -36,6 +35,7 @@ #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "components/performance_manager/test_support/performance_manager_test_harness.h" +#include "components/performance_manager/test_support/resource_attribution/gtest_util.h" #include "components/performance_manager/test_support/resource_attribution/simulated_cpu_measurement_delegate.h" #include "components/performance_manager/test_support/run_in_graph.h" #include "content/public/browser/web_contents.h" @@ -44,31 +44,10 @@ #include "content/public/test/navigation_simulator.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/abseil-cpp/absl/types/variant.h" #include "url/gurl.h" namespace performance_manager::resource_attribution { -// Test result printers. These need to go in the same namespace as the type -// being printed. - -std::ostream& operator<<(std::ostream& os, const ResultMetadata& metadata) { - return os << "measurement_time:" << metadata.measurement_time; -} - -std::ostream& operator<<(std::ostream& os, const CPUTimeResult& result) { - return os << "cpu:" << result.cumulative_cpu - << ",start_time:" << result.start_time - << ",metadata:" << result.metadata << " (" - << (result.metadata.measurement_time - result.start_time) << ")"; -} - -std::ostream& operator<<(std::ostream& os, const ResourceContext& context) { - absl::visit([&os](const auto& token) { os << token.ToString(); }, context); - return os; -} - namespace { using ::testing::AllOf; @@ -76,7 +55,6 @@ using ::testing::Field; using ::testing::IsEmpty; using ::testing::Not; -using ::testing::Optional; constexpr base::TimeDelta kTimeBetweenMeasurements = base::Minutes(5);
diff --git a/components/performance_manager/resource_attribution/memory_measurement_delegate.cc b/components/performance_manager/resource_attribution/memory_measurement_delegate.cc new file mode 100644 index 0000000..6dcaaa9 --- /dev/null +++ b/components/performance_manager/resource_attribution/memory_measurement_delegate.cc
@@ -0,0 +1,133 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/public/resource_attribution/memory_measurement_delegate.h" + +#include <utility> + +#include "base/check.h" +#include "base/functional/bind.h" +#include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/no_destructor.h" +#include "base/notreached.h" +#include "base/process/process_handle.h" +#include "components/performance_manager/graph/graph_impl.h" +#include "components/performance_manager/graph/process_node_impl.h" +#include "components/performance_manager/public/resource_attribution/process_context.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" + +namespace performance_manager::resource_attribution { + +namespace { + +using GlobalMemoryDump = memory_instrumentation::GlobalMemoryDump; + +// A production MemoryMeasurementDelegate that measures processes with +// memory_instrumentation::MemoryInstrumentation. +class MemoryMeasurementDelegateImpl final : public MemoryMeasurementDelegate { + public: + explicit MemoryMeasurementDelegateImpl(Graph* graph) + : graph_impl_(GraphImpl::FromGraph(graph)) {} + + ~MemoryMeasurementDelegateImpl() final = default; + + MemoryMeasurementDelegateImpl(const MemoryMeasurementDelegateImpl&) = delete; + MemoryMeasurementDelegateImpl& operator=( + const MemoryMeasurementDelegateImpl&) = delete; + + void RequestMemorySummary( + base::OnceCallback<void(MemorySummaryMap)> callback) final; + + private: + void OnMemorySummary(base::OnceCallback<void(MemorySummaryMap)> callback, + bool success, + std::unique_ptr<GlobalMemoryDump> memory_dump); + + raw_ptr<GraphImpl> graph_impl_; + base::WeakPtrFactory<MemoryMeasurementDelegateImpl> weak_factory_{this}; +}; + +void MemoryMeasurementDelegateImpl::RequestMemorySummary( + base::OnceCallback<void(MemorySummaryMap)> callback) { + auto* mem_instrumentation = + memory_instrumentation::MemoryInstrumentation::GetInstance(); + // The memory instrumentation service is not available in unit tests unless + // explicitly created. + if (!mem_instrumentation) { + std::move(callback).Run({}); + return; + } + // TODO(crbug.com/1471683): Pass a set of processes to measure instead of all? + mem_instrumentation->RequestPrivateMemoryFootprint( + base::kNullProcessId, + base::BindOnce(&MemoryMeasurementDelegateImpl::OnMemorySummary, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void MemoryMeasurementDelegateImpl::OnMemorySummary( + base::OnceCallback<void(MemorySummaryMap)> callback, + bool success, + std::unique_ptr<GlobalMemoryDump> memory_dump) { + if (!success) { + std::move(callback).Run({}); + return; + } + MemorySummaryMap results; + CHECK(memory_dump); + for (const auto& process_dump : memory_dump->process_dumps()) { + ProcessNodeImpl* process_node = + graph_impl_->GetProcessNodeByPid(process_dump.pid()); + if (!process_node) { + // TODO(crbug.com/1471683): Save ProcessContext by PID when the request + // starts, so that ProcessNode's deleted before the result task runs can + // be measured? + continue; + } + results.emplace( + ProcessContext::FromProcessNode(process_node), + MemorySummaryMeasurement{ + .resident_set_size_kb = process_dump.os_dump().resident_set_kb, + .private_footprint_kb = process_dump.os_dump().private_footprint_kb, + }); + } + std::move(callback).Run(std::move(results)); +} + +// The default production factory for MemoryMeasurementDelegateImpl objects. +class MemoryMeasurementDelegateFactoryImpl final + : public MemoryMeasurementDelegate::Factory { + public: + MemoryMeasurementDelegateFactoryImpl() = default; + ~MemoryMeasurementDelegateFactoryImpl() final = default; + + std::unique_ptr<MemoryMeasurementDelegate> CreateDelegate( + Graph* graph) final { + return std::make_unique<MemoryMeasurementDelegateImpl>(graph); + } +}; + +} // namespace + +// static +void MemoryMeasurementDelegate::SetDelegateFactoryForTesting( + Graph* graph, + MemoryMeasurementDelegate::Factory* factory) { + // TODO(crbug.com/1471683): When a MemoryProvider is added to + // QueryScheduler, implement this the same way as + // CPUMeasurementDelegate::SetDelegateFactoryForTesting(). + NOTIMPLEMENTED(); +} + +// static +MemoryMeasurementDelegate::Factory* +MemoryMeasurementDelegate::GetDefaultFactory() { + static base::NoDestructor<MemoryMeasurementDelegateFactoryImpl> + default_factory; + return default_factory.get(); +} + +} // namespace performance_manager::resource_attribution
diff --git a/components/performance_manager/resource_attribution/memory_measurement_provider.cc b/components/performance_manager/resource_attribution/memory_measurement_provider.cc new file mode 100644 index 0000000..2b1bcae --- /dev/null +++ b/components/performance_manager/resource_attribution/memory_measurement_provider.cc
@@ -0,0 +1,87 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/resource_attribution/memory_measurement_provider.h" + +#include <utility> + +#include "base/check.h" +#include "base/containers/contains.h" +#include "base/functional/bind.h" +#include "base/functional/callback.h" +#include "base/time/time.h" +#include "components/performance_manager/public/graph/frame_node.h" +#include "components/performance_manager/public/graph/graph.h" +#include "components/performance_manager/public/graph/page_node.h" +#include "components/performance_manager/public/graph/process_node.h" +#include "components/performance_manager/public/graph/worker_node.h" +#include "components/performance_manager/public/resource_attribution/attribution_helpers.h" +#include "components/performance_manager/resource_attribution/worker_client_pages.h" + +namespace performance_manager::resource_attribution { + +MemoryMeasurementProvider::MemoryMeasurementProvider(Graph* graph) + : graph_(graph) { + measurement_delegate_ = + MemoryMeasurementDelegate::GetDefaultFactory()->CreateDelegate( + graph_.get()); +} + +MemoryMeasurementProvider::~MemoryMeasurementProvider() = default; + +void MemoryMeasurementProvider::RequestMemorySummary(ResultCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + measurement_delegate_->RequestMemorySummary(base::BindOnce( + &MemoryMeasurementProvider::OnMemorySummary, std::move(callback))); +} + +void MemoryMeasurementProvider::OnMemorySummary( + ResultCallback callback, + MemoryMeasurementDelegate::MemorySummaryMap process_summaries) { + using MemorySummaryMeasurement = + MemoryMeasurementDelegate::MemorySummaryMeasurement; + std::map<ResourceContext, MemorySummaryResult> results; + + // Adds the memory from `summary` to a MemorySummaryResult for `context`. + // Returns true if a new result was created, false if one already existed. + auto accumulate_summary = [&results, now = base::TimeTicks::Now()]( + const ResourceContext& context, + MemorySummaryMeasurement summary) -> bool { + // Create a result with metadata if the key isn't in the map yet. + const auto [it, inserted] = results.try_emplace( + context, MemorySummaryResult{.metadata = {.measurement_time = now}}); + it->second.resident_set_size_kb += summary.resident_set_size_kb; + it->second.private_footprint_kb += summary.private_footprint_kb; + return inserted; + }; + + // Iterate and record all process results. + for (const auto& [process_context, process_summary] : process_summaries) { + bool inserted = accumulate_summary(process_context, process_summary); + CHECK(inserted); + + // Split results between all frames and workers in the process. + const ProcessNode* process_node = process_context.GetProcessNode(); + if (!process_node) { + continue; + } + resource_attribution::SplitResourceAmongFramesAndWorkers( + process_summary, process_node, + [&](const FrameNode* f, MemorySummaryMeasurement summary) { + bool inserted = accumulate_summary(f->GetResourceContext(), summary); + CHECK(inserted); + accumulate_summary(f->GetPageNode()->GetResourceContext(), summary); + }, + [&](const WorkerNode* w, MemorySummaryMeasurement summary) { + bool inserted = accumulate_summary(w->GetResourceContext(), summary); + CHECK(inserted); + for (const PageNode* page_node : GetWorkerClientPages(w)) { + accumulate_summary(page_node->GetResourceContext(), summary); + } + }); + } + std::move(callback).Run(results); +} + +} // namespace performance_manager::resource_attribution
diff --git a/components/performance_manager/resource_attribution/memory_measurement_provider.h b/components/performance_manager/resource_attribution/memory_measurement_provider.h new file mode 100644 index 0000000..d058da5 --- /dev/null +++ b/components/performance_manager/resource_attribution/memory_measurement_provider.h
@@ -0,0 +1,56 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_MEMORY_MEASUREMENT_PROVIDER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_MEMORY_MEASUREMENT_PROVIDER_H_ + +#include <map> +#include <memory> + +#include "base/functional/callback_forward.h" +#include "base/memory/raw_ptr.h" +#include "base/sequence_checker.h" +#include "components/performance_manager/public/resource_attribution/memory_measurement_delegate.h" +#include "components/performance_manager/public/resource_attribution/query_results.h" +#include "components/performance_manager/public/resource_attribution/resource_contexts.h" + +namespace performance_manager { +class Graph; +} + +namespace performance_manager::resource_attribution { + +class MemoryMeasurementProvider { + public: + explicit MemoryMeasurementProvider(Graph* graph); + ~MemoryMeasurementProvider(); + + MemoryMeasurementProvider(const MemoryMeasurementProvider& other) = delete; + MemoryMeasurementProvider& operator=(const MemoryMeasurementProvider&) = + delete; + + using ResultCallback = + base::OnceCallback<void(std::map<ResourceContext, MemorySummaryResult>)>; + + // Requests memory summaries for all processes. `callback` will be invoked + // with the results. + void RequestMemorySummary(ResultCallback callback); + + private: + static void OnMemorySummary( + ResultCallback callback, + MemoryMeasurementDelegate::MemorySummaryMap process_summaries); + + SEQUENCE_CHECKER(sequence_checker_); + + // Delegate that measures memory usage of ProcessNodes. + std::unique_ptr<MemoryMeasurementDelegate> measurement_delegate_ + GUARDED_BY_CONTEXT(sequence_checker_); + + raw_ptr<Graph> graph_ GUARDED_BY_CONTEXT(sequence_checker_) = nullptr; +}; + +} // namespace performance_manager::resource_attribution + +#endif // COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_MEMORY_MEASUREMENT_PROVIDER_H_
diff --git a/components/performance_manager/resource_attribution/memory_measurement_provider_browsertest.cc b/components/performance_manager/resource_attribution/memory_measurement_provider_browsertest.cc new file mode 100644 index 0000000..c841c13 --- /dev/null +++ b/components/performance_manager/resource_attribution/memory_measurement_provider_browsertest.cc
@@ -0,0 +1,198 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/resource_attribution/memory_measurement_provider.h" + +#include <map> +#include <memory> +#include <utility> + +#include "base/command_line.h" +#include "base/functional/bind.h" +#include "base/functional/callback.h" +#include "base/test/bind.h" +#include "components/performance_manager/public/graph/graph.h" +#include "components/performance_manager/public/resource_attribution/query_results.h" +#include "components/performance_manager/public/resource_attribution/resource_contexts.h" +#include "components/performance_manager/test_support/performance_manager_browsertest_harness.h" +#include "components/performance_manager/test_support/resource_attribution/gtest_util.h" +#include "components/performance_manager/test_support/run_in_graph.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "content/shell/browser/shell.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace performance_manager::resource_attribution { + +namespace { + +using ::testing::_; +using ::testing::AllOf; +using ::testing::Field; +using ::testing::Gt; +using ::testing::IsEmpty; +using ::testing::IsSupersetOf; +using ::testing::Lt; +using ::testing::Pair; +using ResultMap = std::map<ResourceContext, MemorySummaryResult>; + +class ResourceAttrMemoryMeasurementProviderBrowserTest + : public PerformanceManagerBrowserTestHarness { + protected: + using Super = PerformanceManagerBrowserTestHarness; + + void OnGraphCreated(Graph* graph) override { + memory_provider_ = std::make_unique<MemoryMeasurementProvider>(graph); + Super::OnGraphCreated(graph); + } + + void TearDownOnMainThread() override { + // Delete MemoryMeasurementProvider before tearing down the graph to avoid + // dangling pointers. + RunInGraph([&] { memory_provider_.reset(); }); + Super::TearDownOnMainThread(); + } + + // Calls MemoryMeasurementProvider::RequestMemorySummary, waits for its result + // callback to fire, and returns the result map passed to the callback. + ResultMap WaitForMemorySummary() { + ResultMap return_results; + RunInGraph([&](base::OnceClosure quit_closure) { + memory_provider_->RequestMemorySummary( + base::BindOnce(base::BindLambdaForTesting([&](ResultMap results) { + return_results = std::move(results); + })).Then(std::move(quit_closure))); + }); + return return_results; + } + + private: + std::unique_ptr<MemoryMeasurementProvider> memory_provider_; +}; + +// GMock matcher expecting that a given MemorySummaryResult has the metadata +// filled in and all memory measurements >0. +auto MemorySummaryResultIsPositive() { + return AllOf( + Field("metadata", &MemorySummaryResult::metadata, + Field("measurement_time", &ResultMetadata::measurement_time, + AllOf(Gt(base::TimeTicks()), Lt(base::TimeTicks::Now())))), + Field("resident_set_size_kb", &MemorySummaryResult::resident_set_size_kb, + Gt(0u)), + Field("private_footprint_kb", &MemorySummaryResult::private_footprint_kb, + Gt(0u))); +} + +IN_PROC_BROWSER_TEST_F(ResourceAttrMemoryMeasurementProviderBrowserTest, + TwoFramesOneProcess) { + // Navigate to an initial URL that will load 2 frames in the same process. + ASSERT_TRUE(NavigateAndWaitForConsoleMessage( + shell()->web_contents(), + embedded_test_server()->GetURL("a.com", "/a_embeds_a.html"), + "a.html loaded")); + + content::RenderFrameHost* main_rfh = + shell()->web_contents()->GetPrimaryMainFrame(); + ASSERT_TRUE(main_rfh); + content::RenderFrameHost* child_rfh = ChildFrameAt(main_rfh, 0); + ASSERT_TRUE(child_rfh); + ASSERT_TRUE(main_rfh->GetProcess()); + ASSERT_EQ(main_rfh->GetProcess(), child_rfh->GetProcess()); + + const ResourceContext main_frame_context = + FrameContext::FromRenderFrameHost(main_rfh).value(); + const ResourceContext child_frame_context = + FrameContext::FromRenderFrameHost(child_rfh).value(); + const ResourceContext process_context = + ProcessContext::FromRenderProcessHost(main_rfh->GetProcess()).value(); + + // Measure the memory of all processes. Results will include the browser and + // utility processes. + ResultMap results = WaitForMemorySummary(); + EXPECT_THAT( + results, + IsSupersetOf( + {Pair(process_context, MemorySummaryResultIsPositive()), + Pair(main_frame_context, MemorySummaryResultIsPositive()), + Pair(child_frame_context, MemorySummaryResultIsPositive())})); + + // The process memory should be split between frames in the + // process. + const auto main_frame_result = results.at(main_frame_context); + const auto child_frame_result = results.at(child_frame_context); + const auto process_result = results.at(process_context); + EXPECT_LE(main_frame_result.resident_set_size_kb, + process_result.resident_set_size_kb); + EXPECT_LE(main_frame_result.private_footprint_kb, + process_result.private_footprint_kb); + EXPECT_LE(child_frame_result.resident_set_size_kb, + process_result.resident_set_size_kb); + EXPECT_LE(child_frame_result.private_footprint_kb, + process_result.private_footprint_kb); +} + +IN_PROC_BROWSER_TEST_F(ResourceAttrMemoryMeasurementProviderBrowserTest, + TwoFramesSeparateProcesses) { + // Navigate to an initial URL that will load 2 frames in separate processes. + content::IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess()); + ASSERT_TRUE(NavigateAndWaitForConsoleMessage( + shell()->web_contents(), + embedded_test_server()->GetURL("a.com", "/a_embeds_b.html"), + "b.html loaded")); + + content::RenderFrameHost* main_rfh = + shell()->web_contents()->GetPrimaryMainFrame(); + ASSERT_TRUE(main_rfh); + content::RenderFrameHost* child_rfh = ChildFrameAt(main_rfh, 0); + ASSERT_TRUE(child_rfh); + ASSERT_TRUE(main_rfh->GetProcess()); + ASSERT_NE(main_rfh->GetProcess(), child_rfh->GetProcess()); + + const ResourceContext main_frame_context = + FrameContext::FromRenderFrameHost(main_rfh).value(); + const ResourceContext child_frame_context = + FrameContext::FromRenderFrameHost(child_rfh).value(); + const ResourceContext process_a_context = + ProcessContext::FromRenderProcessHost(main_rfh->GetProcess()).value(); + const ResourceContext process_b_context = + ProcessContext::FromRenderProcessHost(child_rfh->GetProcess()).value(); + + // Measure the memory of all processes. Results will include the browser and + // utility processes. + ResultMap results = WaitForMemorySummary(); + EXPECT_THAT( + results, + IsSupersetOf( + {Pair(process_a_context, MemorySummaryResultIsPositive()), + Pair(process_b_context, MemorySummaryResultIsPositive()), + Pair(main_frame_context, MemorySummaryResultIsPositive()), + Pair(child_frame_context, MemorySummaryResultIsPositive())})); + + // Each process memory should be assigned entirely to the frame in the + // process. + const auto main_frame_result = results.at(main_frame_context); + const auto child_frame_result = results.at(child_frame_context); + const auto process_a_result = results.at(process_a_context); + const auto process_b_result = results.at(process_b_context); + EXPECT_EQ(main_frame_result.resident_set_size_kb, + process_a_result.resident_set_size_kb); + EXPECT_EQ(main_frame_result.private_footprint_kb, + process_a_result.private_footprint_kb); + EXPECT_EQ(child_frame_result.resident_set_size_kb, + process_b_result.resident_set_size_kb); + EXPECT_EQ(child_frame_result.private_footprint_kb, + process_b_result.private_footprint_kb); +} + +} // namespace + +} // namespace performance_manager::resource_attribution
diff --git a/components/performance_manager/resource_attribution/queries_unittest.cc b/components/performance_manager/resource_attribution/queries_unittest.cc index 56b4de5e..0e4b608 100644 --- a/components/performance_manager/resource_attribution/queries_unittest.cc +++ b/components/performance_manager/resource_attribution/queries_unittest.cc
@@ -34,7 +34,7 @@ #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "components/performance_manager/test_support/performance_manager_test_harness.h" -#include "components/performance_manager/test_support/resource_attribution/gmock_matchers.h" +#include "components/performance_manager/test_support/resource_attribution/gtest_util.h" #include "components/performance_manager/test_support/resource_attribution/simulated_cpu_measurement_delegate.h" #include "components/performance_manager/test_support/run_in_graph.h" #include "content/public/browser/render_frame_host.h"
diff --git a/components/performance_manager/resource_attribution/query_scheduler_unittest.cc b/components/performance_manager/resource_attribution/query_scheduler_unittest.cc index d819ca7f..2b6cb80 100644 --- a/components/performance_manager/resource_attribution/query_scheduler_unittest.cc +++ b/components/performance_manager/resource_attribution/query_scheduler_unittest.cc
@@ -33,7 +33,7 @@ #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "components/performance_manager/test_support/performance_manager_test_harness.h" -#include "components/performance_manager/test_support/resource_attribution/gmock_matchers.h" +#include "components/performance_manager/test_support/resource_attribution/gtest_util.h" #include "components/performance_manager/test_support/resource_attribution/simulated_cpu_measurement_delegate.h" #include "components/performance_manager/test_support/run_in_graph.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/components/performance_manager/resource_attribution/worker_client_pages.cc b/components/performance_manager/resource_attribution/worker_client_pages.cc new file mode 100644 index 0000000..02fb97b3a --- /dev/null +++ b/components/performance_manager/resource_attribution/worker_client_pages.cc
@@ -0,0 +1,78 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/resource_attribution/worker_client_pages.h" + +#include "components/performance_manager/public/graph/frame_node.h" +#include "components/performance_manager/public/graph/page_node.h" +#include "components/performance_manager/public/graph/worker_node.h" +#include "third_party/abseil-cpp/absl/types/variant.h" + +namespace performance_manager::resource_attribution { + +namespace { + +// Recursively visits all client workers of `worker_node`, and all client +// frames of each worker, and adds each frame's PageNode to `client_pages`. +// `visited_workers` is used to check for loops in the graph of client +// workers. `graph_change` is a change to the graph topology in progress that +// may affect the client page set, or NoGraphChange. +void RecursivelyFindClientPages(const WorkerNode* worker_node, + GraphChange graph_change, + std::set<const PageNode*>& client_pages, + std::set<const WorkerNode*>& visited_workers) { + const auto [_, inserted] = visited_workers.insert(worker_node); + if (!inserted) { + // Already visited, halt recursion. + return; + } + worker_node->VisitClientFrames( + [&client_pages, &graph_change, worker_node](const FrameNode* f) { + const auto* add_client_frame_change = + absl::get_if<GraphChangeAddClientFrameToWorker>(&graph_change); + if (add_client_frame_change && + add_client_frame_change->worker_node == worker_node && + add_client_frame_change->client_frame_node == f) { + // Skip this client node. The measurement being distributed includes + // results from before it was added. + return true; + } + client_pages.insert(f->GetPageNode()); + return true; + }); + worker_node->VisitClientWorkers([&client_pages, &visited_workers, + &graph_change, + worker_node](const WorkerNode* w) { + const auto* add_client_worker_change = + absl::get_if<GraphChangeAddClientWorkerToWorker>(&graph_change); + if (add_client_worker_change && + add_client_worker_change->worker_node == worker_node && + add_client_worker_change->client_worker_node == w) { + // Skip this client node. The measurement being distributed includes + // results from before it was added. + return true; + } + + RecursivelyFindClientPages(w, graph_change, client_pages, visited_workers); + return true; + }); + // Unlike FrameNode, WorkerNode does not update any graph links in + // WorkerNodeImpl::OnBeforeLeavingGraph(). So no need to check for + // GraphChangeRemoveClient*FromWorker. + // TODO(https://crbug.com/1481676): If that changes. handle + // `graph_change.client_*_node` as if it was visited by the above visitors. +} + +} // namespace + +std::set<const PageNode*> GetWorkerClientPages(const WorkerNode* worker_node, + GraphChange graph_change) { + std::set<const PageNode*> client_pages; + std::set<const WorkerNode*> visited_workers; + RecursivelyFindClientPages(worker_node, graph_change, client_pages, + visited_workers); + return client_pages; +} + +} // namespace performance_manager::resource_attribution
diff --git a/components/performance_manager/resource_attribution/worker_client_pages.h b/components/performance_manager/resource_attribution/worker_client_pages.h new file mode 100644 index 0000000..37a9fcd1 --- /dev/null +++ b/components/performance_manager/resource_attribution/worker_client_pages.h
@@ -0,0 +1,28 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_WORKER_CLIENT_PAGES_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_WORKER_CLIENT_PAGES_H_ + +#include <set> + +#include "components/performance_manager/resource_attribution/graph_change.h" + +namespace performance_manager { +class PageNode; +class WorkerNode; +} // namespace performance_manager + +namespace performance_manager::resource_attribution { + +// Returns the complete set of pages that are clients of `worker_node`. +// `graph_change` is a change to the graph topology in progress that may affect +// the client page set, or NoGraphChange. +std::set<const PageNode*> GetWorkerClientPages( + const WorkerNode* worker_node, + GraphChange graph_change = NoGraphChange{}); + +} // namespace performance_manager::resource_attribution + +#endif // COMPONENTS_PERFORMANCE_MANAGER_RESOURCE_ATTRIBUTION_WORKER_CLIENT_PAGES_H_
diff --git a/components/performance_manager/test_support/BUILD.gn b/components/performance_manager/test_support/BUILD.gn index d3c3912..a68c6847 100644 --- a/components/performance_manager/test_support/BUILD.gn +++ b/components/performance_manager/test_support/BUILD.gn
@@ -11,6 +11,7 @@ sources = [ "decorators_utils.h", "graph_impl.h", + "resource_attribution/gtest_util.h", "run_in_graph.cc", "run_in_graph.h", "test_browser_child_process.cc", @@ -48,7 +49,6 @@ "mock_graphs.h", "performance_manager_test_harness.cc", "performance_manager_test_harness.h", - "resource_attribution/gmock_matchers.h", "resource_attribution/simulated_cpu_measurement_delegate.cc", "resource_attribution/simulated_cpu_measurement_delegate.h", "test_worker_node_factory.cc",
diff --git a/components/performance_manager/test_support/resource_attribution/gmock_matchers.h b/components/performance_manager/test_support/resource_attribution/gmock_matchers.h deleted file mode 100644 index cb958aa7..0000000 --- a/components/performance_manager/test_support/resource_attribution/gmock_matchers.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_GMOCK_MATCHERS_H_ -#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_GMOCK_MATCHERS_H_ - -#include "components/performance_manager/public/resource_attribution/query_results.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace performance_manager::resource_attribution { - -// GMock matcher expecting that a given QueryResultMap entry has a key of -// `resource_context` whose value contains a result of type ResultType. -// -// Usage: -// -// // Tests that the map contains `context1` and possibly other elements. -// EXPECT_THAT(result_map, ::testing::Contains( -// QueryResultMapEntryMatches<CPUTimeResult>(context1)); -// -// // Tests that the map contains exactly `context1` and `context2`. -// EXPECT_THAT(result_map, ::testing::UnorderedElementsAre( -// QueryResultMapEntryMatches<CPUTimeResult>(context1), -// QueryResultMapEntryMatches<CPUTimeResult>(context2)); -template <typename ResultType> -auto QueryResultMapEntryMatches(const ResourceContext& resource_context) { - return ::testing::Pair( - resource_context, - ::testing::ResultOf("contains correct QueryResult type", - ContainsResult<ResultType>, ::testing::IsTrue())); -} - -} // namespace performance_manager::resource_attribution - -#endif // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_GMOCK_MATCHERS_H_
diff --git a/components/performance_manager/test_support/resource_attribution/gtest_util.h b/components/performance_manager/test_support/resource_attribution/gtest_util.h new file mode 100644 index 0000000..692be0d7 --- /dev/null +++ b/components/performance_manager/test_support/resource_attribution/gtest_util.h
@@ -0,0 +1,78 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_GTEST_UTIL_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_GTEST_UTIL_H_ + +#include <ostream> + +#include "components/performance_manager/public/resource_attribution/query_results.h" +#include "components/performance_manager/public/resource_attribution/resource_contexts.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace performance_manager::resource_attribution { + +// GMock matcher expecting that a given QueryResultMap entry has a key of +// `resource_context` whose value contains a result of type ResultType. +// +// Usage: +// +// // Tests that the map contains `context1` and possibly other elements. +// EXPECT_THAT(result_map, ::testing::Contains( +// QueryResultMapEntryMatches<CPUTimeResult>(context1)); +// +// // Tests that the map contains exactly `context1` and `context2`. +// EXPECT_THAT(result_map, ::testing::UnorderedElementsAre( +// QueryResultMapEntryMatches<CPUTimeResult>(context1), +// QueryResultMapEntryMatches<CPUTimeResult>(context2)); +template <typename ResultType> +auto QueryResultMapEntryMatches(const ResourceContext& resource_context) { + return ::testing::Pair( + resource_context, + ::testing::ResultOf("contains correct QueryResult type", + ContainsResult<ResultType>, ::testing::IsTrue())); +} + +// Test result printers. These need to go in the same namespace as the type +// being printed. + +inline void PrintTo(const ResultMetadata& metadata, std::ostream* os) { + *os << "measurement_time:" << metadata.measurement_time; +} + +inline void PrintTo(const CPUTimeResult& result, std::ostream* os) { + *os << "cpu:" << result.cumulative_cpu << ",start_time:" << result.start_time + << ",metadata:" << ::testing::PrintToString(result.metadata) << " (" + << (result.metadata.measurement_time - result.start_time) << ")"; +} + +inline void PrintTo(const MemorySummaryResult& result, std::ostream* os) { + *os << "rss:" << result.resident_set_size_kb + << ",pmf:" << result.private_footprint_kb + << ",metadata:" << ::testing::PrintToString(result.metadata); +} + +// PrintTo() matches the generic absl::variant overload before ResourceContext, +// so each context type needs a separate printer. + +inline void PrintTo(const FrameContext& context, std::ostream* os) { + *os << context.ToString(); +} + +inline void PrintTo(const PageContext& context, std::ostream* os) { + *os << context.ToString(); +} + +inline void PrintTo(const ProcessContext& context, std::ostream* os) { + *os << context.ToString(); +} + +inline void PrintTo(const WorkerContext& context, std::ostream* os) { + *os << context.ToString(); +} + +} // namespace performance_manager::resource_attribution + +#endif // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_GTEST_UTIL_H_
diff --git a/components/performance_manager/worker_watcher.cc b/components/performance_manager/worker_watcher.cc index 6806e92..7c6868e 100644 --- a/components/performance_manager/worker_watcher.cc +++ b/components/performance_manager/worker_watcher.cc
@@ -10,6 +10,7 @@ #include "base/check_op.h" #include "base/containers/contains.h" #include "base/containers/cxx20_erase_map.h" +#include "base/functional/overloaded.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "components/performance_manager/frame_node_source.h" @@ -225,7 +226,7 @@ void WorkerWatcher::OnWorkerCreated( const blink::DedicatedWorkerToken& dedicated_worker_token, int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) { + content::DedicatedWorkerCreator creator) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TODO(https://crbug.com/993029): Plumb through the URL. @@ -237,13 +238,23 @@ dedicated_worker_token, std::move(worker_node)); DCHECK(insertion_result.second); - AddFrameClientConnection(insertion_result.first->second.get(), - ancestor_render_frame_host_id); + absl::visit( + base::Overloaded( + [&, + this](const content::GlobalRenderFrameHostId& render_frame_host_id) { + AddFrameClientConnection(insertion_result.first->second.get(), + render_frame_host_id); + }, + [&, this](blink::DedicatedWorkerToken dedicated_worker_token) { + ConnectDedicatedWorkerClient(insertion_result.first->second.get(), + dedicated_worker_token); + }), + creator); } void WorkerWatcher::OnBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& dedicated_worker_token, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) { + content::DedicatedWorkerCreator creator) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto it = dedicated_worker_nodes_.find(dedicated_worker_token); @@ -251,8 +262,20 @@ auto worker_node = std::move(it->second); - // First disconnect the ancestor's frame node from this worker node. - RemoveFrameClientConnection(worker_node.get(), ancestor_render_frame_host_id); + // First disconnect the creator's node from this worker node. + + absl::visit( + base::Overloaded( + [&, + this](const content::GlobalRenderFrameHostId& render_frame_host_id) { + RemoveFrameClientConnection(worker_node.get(), + render_frame_host_id); + }, + [&, this](blink::DedicatedWorkerToken dedicated_worker_token) { + DisconnectDedicatedWorkerClient(worker_node.get(), + dedicated_worker_token); + }), + creator); // Disconnect all child workers before destroying the node. auto child_it = dedicated_worker_child_workers_.find(dedicated_worker_token); @@ -660,11 +683,13 @@ GetDedicatedWorkerNode(client_dedicated_worker_token); if (!client_dedicated_worker_node) { #if DCHECK_IS_ON() - bool inserted = - missing_service_worker_clients_[worker_node] - .insert(ServiceWorkerClient(client_dedicated_worker_token)) - .second; - DCHECK(inserted); + if (IsServiceWorkerNode(worker_node)) { + bool inserted = + missing_service_worker_clients_[worker_node] + .insert(ServiceWorkerClient(client_dedicated_worker_token)) + .second; + DCHECK(inserted); + } #endif return; } @@ -687,12 +712,15 @@ GetDedicatedWorkerNode(client_dedicated_worker_token); if (!client_dedicated_worker) { #if DCHECK_IS_ON() - auto it = missing_service_worker_clients_.find(worker_node); - DCHECK(it != missing_service_worker_clients_.end()); - DCHECK_EQ(1u, it->second.erase( - ServiceWorkerClient(client_dedicated_worker_token))); - if (it->second.empty()) - missing_service_worker_clients_.erase(it); + if (IsServiceWorkerNode(worker_node)) { + auto it = missing_service_worker_clients_.find(worker_node); + DCHECK(it != missing_service_worker_clients_.end()); + DCHECK_EQ(1u, it->second.erase( + ServiceWorkerClient(client_dedicated_worker_token))); + if (it->second.empty()) { + missing_service_worker_clients_.erase(it); + } + } #endif return; } @@ -721,6 +749,7 @@ GetSharedWorkerNode(client_shared_worker_token); if (!client_shared_worker_node) { #if DCHECK_IS_ON() + DCHECK(IsServiceWorkerNode(worker_node)); bool inserted = missing_service_worker_clients_[worker_node] .insert(ServiceWorkerClient(client_shared_worker_token)) .second; @@ -752,6 +781,7 @@ shared_worker_child_workers_.end()); #if DCHECK_IS_ON() + DCHECK(IsServiceWorkerNode(worker_node)); auto it = missing_service_worker_clients_.find(worker_node); DCHECK(it != missing_service_worker_clients_.end()); DCHECK_EQ(
diff --git a/components/performance_manager/worker_watcher.h b/components/performance_manager/worker_watcher.h index b5e1f5a..4aebde1 100644 --- a/components/performance_manager/worker_watcher.h +++ b/components/performance_manager/worker_watcher.h
@@ -78,10 +78,10 @@ void OnWorkerCreated( const blink::DedicatedWorkerToken& dedicated_worker_token, int worker_process_id, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override; + content::DedicatedWorkerCreator creator) override; void OnBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& dedicated_worker_token, - content::GlobalRenderFrameHostId ancestor_render_frame_host_id) override; + content::DedicatedWorkerCreator creator) override; void OnFinalResponseURLDetermined( const blink::DedicatedWorkerToken& dedicated_worker_token, const GURL& url) override;
diff --git a/components/performance_manager/worker_watcher_unittest.cc b/components/performance_manager/worker_watcher_unittest.cc index a86d637..6b473d5 100644 --- a/components/performance_manager/worker_watcher_unittest.cc +++ b/components/performance_manager/worker_watcher_unittest.cc
@@ -24,6 +24,7 @@ #include "components/performance_manager/performance_manager_impl.h" #include "components/performance_manager/process_node_source.h" #include "components/performance_manager/public/features.h" +#include "content/public/browser/dedicated_worker_creator.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/shared_worker_service.h" #include "content/public/test/browser_task_environment.h" @@ -86,7 +87,7 @@ // Creates a new dedicated worker and returns its ID. const blink::DedicatedWorkerToken& CreateDedicatedWorker( int worker_process_id, - content::GlobalRenderFrameHostId client_render_frame_host_id); + content::DedicatedWorkerCreator creator); // Destroys an existing dedicated worker. void DestroyDedicatedWorker(const blink::DedicatedWorkerToken& token); @@ -94,9 +95,9 @@ private: base::ObserverList<Observer> observer_list_; - // Maps each running worker to its client RenderFrameHost ID. - base::flat_map<blink::DedicatedWorkerToken, content::GlobalRenderFrameHostId> - dedicated_worker_client_frame_; + // Maps each running worker to its creator. + base::flat_map<blink::DedicatedWorkerToken, content::DedicatedWorkerCreator> + dedicated_worker_creators_; }; TestDedicatedWorkerService::TestDedicatedWorkerService() = default; @@ -119,19 +120,17 @@ const blink::DedicatedWorkerToken& TestDedicatedWorkerService::CreateDedicatedWorker( int worker_process_id, - content::GlobalRenderFrameHostId client_render_frame_host_id) { + content::DedicatedWorkerCreator creator) { // Create a new token for the worker and add it to the map, along with its // client ID. const blink::DedicatedWorkerToken token; - auto result = dedicated_worker_client_frame_.emplace( - token, client_render_frame_host_id); + auto result = dedicated_worker_creators_.emplace(token, creator); DCHECK(result.second); // Check inserted. // Notify observers. for (auto& observer : observer_list_) { - observer.OnWorkerCreated(token, worker_process_id, - client_render_frame_host_id); + observer.OnWorkerCreated(token, worker_process_id, creator); } return result.first->first; @@ -139,15 +138,15 @@ void TestDedicatedWorkerService::DestroyDedicatedWorker( const blink::DedicatedWorkerToken& token) { - auto it = dedicated_worker_client_frame_.find(token); - DCHECK(it != dedicated_worker_client_frame_.end()); + auto it = dedicated_worker_creators_.find(token); + DCHECK(it != dedicated_worker_creators_.end()); // Notify observers that the worker is being destroyed. for (auto& observer : observer_list_) observer.OnBeforeWorkerDestroyed(token, it->second); // Remove the worker ID from the map. - dedicated_worker_client_frame_.erase(it); + dedicated_worker_creators_.erase(it); } // TestSharedWorkerService ----------------------------------------------------- @@ -806,7 +805,7 @@ return worker_watcher_->GetServiceWorkerNode(version_id); } -// This test creates one dedicated worker. +// This test creates one dedicated worker with a frame client. TEST_F(WorkerWatcherTest, SimpleDedicatedWorker) { int render_process_id = process_node_source()->CreateProcessNode(); @@ -843,6 +842,46 @@ EXPECT_EQ(worker_watcher()->FindWorkerNodeForToken(token), nullptr); } +TEST_F(WorkerWatcherTest, NestedDedicatedWorker) { + int render_process_id = process_node_source()->CreateProcessNode(); + + // Create the ancestor frame node. + content::GlobalRenderFrameHostId render_frame_host_id = + frame_node_source()->CreateFrameNode( + render_process_id, + process_node_source()->GetProcessNode(render_process_id)); + + // Create the parent worker. + const blink::DedicatedWorkerToken parent_worker_token = + dedicated_worker_service()->CreateDedicatedWorker(render_process_id, + render_frame_host_id); + + // Create the nested worker. + const blink::DedicatedWorkerToken nested_worker_token = + dedicated_worker_service()->CreateDedicatedWorker(render_process_id, + parent_worker_token); + + // Check expectations on the graph. + CallOnGraphAndWait(base::BindLambdaForTesting( + [process_node = process_node_source()->GetProcessNode(render_process_id), + parent_worker_node = GetDedicatedWorkerNode(parent_worker_token), + nested_worker_node = GetDedicatedWorkerNode(nested_worker_token), + ancestor_frame_node = frame_node_source()->GetFrameNode( + render_frame_host_id)](GraphImpl* graph) { + EXPECT_TRUE(graph->NodeInGraph(nested_worker_node)); + EXPECT_EQ(nested_worker_node->GetWorkerType(), + WorkerNode::WorkerType::kDedicated); + EXPECT_EQ(nested_worker_node->process_node(), process_node); + // The ancestor frame is not directly a client of the nested worker. + EXPECT_FALSE(IsWorkerClient(nested_worker_node, ancestor_frame_node)); + EXPECT_TRUE(IsWorkerClient(nested_worker_node, parent_worker_node)); + })); + + // Disconnect and clean up the dedicated workers. + dedicated_worker_service()->DestroyDedicatedWorker(nested_worker_token); + dedicated_worker_service()->DestroyDedicatedWorker(parent_worker_token); +} + // This test creates one shared worker with one client frame. TEST_F(WorkerWatcherTest, SimpleSharedWorker) { int render_process_id = process_node_source()->CreateProcessNode();
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowChromeDataInBackups.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowChromeDataInBackups.yaml index 94d56b7..01b06411 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowChromeDataInBackups.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/AllowChromeDataInBackups.yaml
@@ -7,8 +7,8 @@ features: dynamic_refresh: true per_profile: false -future_on: -- ios +supported_on: +- ios:121- items: - caption: Allow <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> data to be included in backups
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index 51fd552..c380c4d 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -596,9 +596,10 @@ return true; } -// Given the |device| and |canvas| to draw on, prints the appropriate headers -// and footers using strings from |header_footer_info| on to the canvas. +// Given the `canvas` to draw on, prints the appropriate headers and footers on +// the canvas using `frame`, with data from the remaining parameters. void PrintHeaderAndFooter(cc::PaintCanvas* canvas, + blink::WebLocalFrame& frame, uint32_t page_index, uint32_t total_pages, const blink::WebLocalFrame& source_frame, @@ -608,77 +609,17 @@ DCHECK_LE(total_pages, kMaxPageCount); DCHECK_LT(page_index, kMaxPageCount); - // Scaling has already been applied to the canvas, but headers and footers - // should not be affected by that, so cancel it out. - cc::PaintCanvasAutoRestore auto_restore(canvas, true); - canvas->scale(1 / scale_factor, 1 / scale_factor); - - gfx::SizeF page_size(page_layout.margin_left + page_layout.margin_right + - page_layout.content_width, - page_layout.margin_top + page_layout.margin_bottom + - page_layout.content_height); - - blink::WebView* web_view = blink::WebView::Create( - /*client=*/nullptr, - /*is_hidden=*/false, /*is_prerendering=*/false, - /*is_inside_portal=*/false, - /*fenced_frame_mode=*/absl::nullopt, - /*compositing_enabled=*/false, /*widgets_never_composited=*/false, - /*opener=*/nullptr, mojo::NullAssociatedReceiver(), - *source_frame.GetAgentGroupScheduler(), - /*session_storage_namespace_id=*/base::EmptyString(), - /*page_base_background_color=*/absl::nullopt, - blink::BrowsingContextGroupInfo::CreateUnique()); - web_view->GetSettings()->SetJavaScriptEnabled(true); - - class HeaderAndFooterClient final : public blink::WebLocalFrameClient { - public: - // WebLocalFrameClient: - void BindToFrame(blink::WebNavigationControl* frame) override { - frame_ = frame; - } - void FrameDetached() override { - frame_->Close(); - frame_ = nullptr; - } - - private: - raw_ptr<blink::WebNavigationControl, ExperimentalRenderer> frame_ = nullptr; - }; - - HeaderAndFooterClient frame_client; - blink::WebLocalFrame* frame = blink::WebLocalFrame::CreateMainFrame( - web_view, &frame_client, nullptr, blink::LocalFrameToken(), - blink::DocumentToken(), nullptr); - - mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; - mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> - frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiver(); - - mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; - std::ignore = frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); - - mojo::AssociatedRemote<blink::mojom::Widget> widget_remote; - mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget_receiver = - widget_remote.BindNewEndpointAndPassDedicatedReceiver(); - - mojo::AssociatedRemote<blink::mojom::WidgetHost> widget_host_remote; - std::ignore = widget_host_remote.BindNewEndpointAndPassDedicatedReceiver(); - - blink::WebNonCompositedWidgetClient client; - blink::WebFrameWidget* web_frame_widget = frame->InitializeFrameWidget( - frame_widget_host.Unbind(), std::move(frame_widget_receiver), - widget_host_remote.Unbind(), std::move(widget_receiver), - viz::FrameSinkId()); - web_frame_widget->InitializeNonCompositing(&client); - web_view->DidAttachLocalMainFrame(); - base::Value html( ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( IDR_PRINT_HEADER_FOOTER_TEMPLATE_PAGE)); // Load page with script to avoid async operations. - ExecuteScript(frame, kPageLoadScriptFormat, html); + ExecuteScript(&frame, kPageLoadScriptFormat, html); + + const gfx::SizeF page_size( + page_layout.margin_left + page_layout.margin_right + + page_layout.content_width, + page_layout.margin_top + page_layout.margin_bottom + + page_layout.content_height); base::Value::Dict options; options.Set(kSettingHeaderFooterDate, @@ -699,16 +640,20 @@ options.Set("footerTemplate", params.footer_template); options.Set("isRtl", base::i18n::IsRTL()); - ExecuteScript(frame, kPageSetupScriptFormat, base::Value(std::move(options))); + ExecuteScript(&frame, kPageSetupScriptFormat, + base::Value(std::move(options))); blink::WebPrintParams webkit_params(page_size); webkit_params.printer_dpi = GetDPI(params); - frame->PrintBegin(webkit_params, blink::WebNode()); - frame->PrintPage(0, canvas); - frame->PrintEnd(); + // Scaling has already been applied to the canvas, but headers and footers + // should not be affected by that, so cancel it out. + cc::PaintCanvasAutoRestore auto_restore(canvas, true); + canvas->scale(1 / scale_factor, 1 / scale_factor); - web_view->Close(); + frame.PrintBegin(webkit_params, blink::WebNode()); + frame.PrintPage(0, canvas); + frame.PrintEnd(); } // Renders page contents from `frame` to `content_area` of `canvas`. @@ -729,6 +674,87 @@ frame->PrintPage(page_index, canvas); } +class HeaderAndFooterContext { + public: + class HeaderAndFooterClient final : public blink::WebLocalFrameClient { + public: + // WebLocalFrameClient: + void BindToFrame(blink::WebNavigationControl* frame) override { + frame_ = frame; + } + void FrameDetached() override { + frame_->Close(); + frame_ = nullptr; + } + + private: + raw_ptr<blink::WebNavigationControl, ExperimentalRenderer> frame_ = nullptr; + }; + + explicit HeaderAndFooterContext(const blink::WebLocalFrame& source_frame) + : web_view_(CreateWebView(source_frame)), frame_(CreateFrame()) { + CHECK(web_view_); + CHECK(frame_); + InitWebView(); + } + ~HeaderAndFooterContext() { web_view_->Close(); } + + blink::WebLocalFrame& frame() { return *frame_; } + + private: + static blink::WebView* CreateWebView( + const blink::WebLocalFrame& source_frame) { + auto* view = blink::WebView::Create( + /*client=*/nullptr, + /*is_hidden=*/false, /*is_prerendering=*/false, + /*is_inside_portal=*/false, + /*fenced_frame_mode=*/absl::nullopt, + /*compositing_enabled=*/false, /*widgets_never_composited=*/false, + /*opener=*/nullptr, mojo::NullAssociatedReceiver(), + *source_frame.GetAgentGroupScheduler(), + /*session_storage_namespace_id=*/base::EmptyString(), + /*page_base_background_color=*/absl::nullopt, + blink::BrowsingContextGroupInfo::CreateUnique()); + view->GetSettings()->SetJavaScriptEnabled(true); + return view; + } + + blink::WebLocalFrame* CreateFrame() { + return blink::WebLocalFrame::CreateMainFrame( + web_view_, &frame_client_, nullptr, blink::LocalFrameToken(), + blink::DocumentToken(), nullptr); + } + + void InitWebView() { + mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; + mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> + frame_widget_receiver = + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); + + mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; + std::ignore = frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); + + mojo::AssociatedRemote<blink::mojom::Widget> widget_remote; + mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget_receiver = + widget_remote.BindNewEndpointAndPassDedicatedReceiver(); + + mojo::AssociatedRemote<blink::mojom::WidgetHost> widget_host_remote; + std::ignore = widget_host_remote.BindNewEndpointAndPassDedicatedReceiver(); + + blink::WebFrameWidget* web_frame_widget = frame_->InitializeFrameWidget( + frame_widget_host.Unbind(), std::move(frame_widget_receiver), + widget_host_remote.Unbind(), std::move(widget_receiver), + viz::FrameSinkId()); + web_frame_widget->InitializeNonCompositing(&widget_client_); + web_view_->DidAttachLocalMainFrame(); + } + + HeaderAndFooterClient frame_client_; + blink::WebNonCompositedWidgetClient widget_client_; + blink::WebView* const web_view_; + blink::WebLocalFrame* const frame_; +}; + } // namespace FrameReference::FrameReference(blink::WebLocalFrame* frame) { @@ -2545,8 +2571,9 @@ canvas->SetPrintingMetafile(metafile); if (params.display_header_footer) { - PrintHeaderAndFooter(canvas, page_index, page_count, *frame, - layout.fit_to_page_scale_factor, + HeaderAndFooterContext context(*frame); + PrintHeaderAndFooter(canvas, context.frame(), page_index, page_count, + *frame, layout.fit_to_page_scale_factor, *page_layout_in_css_pixels, params); }
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc index 5df837b3..8b46704 100644 --- a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc +++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
@@ -136,16 +136,16 @@ url_real_time_lookup_enabled_ ? url_lookup_service->GetMetricSuffix() : kNoRealTimeURLLookupService; - sb_checker_ = std::make_unique<UrlCheckerOnSB>( + sync_sb_checker_ = std::make_unique<UrlCheckerOnSB>( std::move(delegate_getter), frame_tree_node_id, web_contents_getter, /*complete_callback=*/ - base::BindRepeating(&BrowserURLLoaderThrottle::OnCompleteCheck, + base::BindRepeating(&BrowserURLLoaderThrottle::OnCompleteSyncCheck, weak_factory_.GetWeakPtr()), /*skip_checks_callback=*/ base::BindRepeating(&BrowserURLLoaderThrottle::SkipChecks, weak_factory_.GetWeakPtr()), /*slow_check_callback=*/ - base::BindRepeating(&BrowserURLLoaderThrottle::NotifySlowCheck, + base::BindRepeating(&BrowserURLLoaderThrottle::NotifySyncSlowCheck, weak_factory_.GetWeakPtr()), url_real_time_lookup_enabled_, can_urt_check_subresource_url, can_check_db, can_check_high_confidence_allowlist, @@ -161,14 +161,14 @@ TRACE_ID_LOCAL(this)); } - DeleteCheckerOnSB(); + DeleteUrlCheckerOnSB(); } void BrowserURLLoaderThrottle::WillStartRequest( network::ResourceRequest* request, bool* defer) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(0u, pending_checks_); + DCHECK_EQ(0u, pending_sync_checks_); DCHECK(!blocked_); base::UmaHistogramEnumeration( "SafeBrowsing.BrowserThrottle.RequestDestination", request->destination); @@ -194,18 +194,18 @@ "SafeBrowsing.BrowserThrottle.RequestDestination.Checked", request->destination); - pending_checks_++; + pending_sync_checks_++; start_request_time_ = base::TimeTicks::Now(); is_start_request_called_ = true; if (base::FeatureList::IsEnabled(kSafeBrowsingOnUIThread)) { - sb_checker_->Start(request->headers, request->load_flags, - request->destination, request->has_user_gesture, - request->originated_from_service_worker, request->url, - request->method); + sync_sb_checker_->Start(request->headers, request->load_flags, + request->destination, request->has_user_gesture, + request->originated_from_service_worker, + request->url, request->method); } else { content::GetIOThreadTaskRunner({})->PostTask( FROM_HERE, - base::BindOnce(&UrlCheckerOnSB::Start, sb_checker_->AsWeakPtr(), + base::BindOnce(&UrlCheckerOnSB::Start, sync_sb_checker_->AsWeakPtr(), request->headers, request->load_flags, request->destination, request->has_user_gesture, request->originated_from_service_worker, request->url, @@ -234,13 +234,14 @@ return; } - pending_checks_++; + pending_sync_checks_++; if (base::FeatureList::IsEnabled(kSafeBrowsingOnUIThread)) { - sb_checker_->CheckUrl(redirect_info->new_url, redirect_info->new_method); + sync_sb_checker_->CheckUrl(redirect_info->new_url, + redirect_info->new_method); } else { content::GetIOThreadTaskRunner({})->PostTask( FROM_HERE, - base::BindOnce(&UrlCheckerOnSB::CheckUrl, sb_checker_->AsWeakPtr(), + base::BindOnce(&UrlCheckerOnSB::CheckUrl, sync_sb_checker_->AsWeakPtr(), redirect_info->new_url, redirect_info->new_method)); } } @@ -255,14 +256,14 @@ "SafeBrowsing.BrowserThrottle.WillProcessResponseCount", will_process_response_count_); - if (sb_checker_) { + if (sync_sb_checker_) { if (base::FeatureList::IsEnabled(kSafeBrowsingOnUIThread)) { - sb_checker_->LogWillProcessResponseTime(base::TimeTicks::Now()); + sync_sb_checker_->LogWillProcessResponseTime(base::TimeTicks::Now()); } else { content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&UrlCheckerOnSB::LogWillProcessResponseTime, - sb_checker_->AsWeakPtr(), base::TimeTicks::Now())); + FROM_HERE, base::BindOnce(&UrlCheckerOnSB::LogWillProcessResponseTime, + sync_sb_checker_->AsWeakPtr(), + base::TimeTicks::Now())); } } @@ -274,10 +275,10 @@ return; } - bool check_completed = (pending_checks_ == 0); + bool sync_check_completed = (pending_sync_checks_ == 0); base::UmaHistogramBoolean( "SafeBrowsing.BrowserThrottle.IsCheckCompletedOnProcessResponse", - check_completed); + sync_check_completed); is_response_from_cache_ = response_head->was_fetched_via_cache && !response_head->network_accessed; if (is_start_request_called_) { @@ -291,14 +292,14 @@ is_response_from_cache_ ? kFromCacheUmaSuffix : kFromNetworkUmaSuffix}), interval); - if (check_completed) { + if (sync_check_completed) { LogTotalDelay2MetricsWithResponseType(is_response_from_cache_, base::TimeDelta()); } is_start_request_called_ = false; } - if (check_completed) { + if (sync_check_completed) { return; } @@ -314,11 +315,11 @@ return "SafeBrowsingBrowserThrottle"; } -UrlCheckerOnSB* BrowserURLLoaderThrottle::GetSBCheckerForTesting() { - return sb_checker_.get(); +UrlCheckerOnSB* BrowserURLLoaderThrottle::GetSyncSBCheckerForTesting() { + return sync_sb_checker_.get(); } -void BrowserURLLoaderThrottle::OnCompleteCheck( +void BrowserURLLoaderThrottle::OnCompleteSyncCheck( bool slow_check, bool proceed, bool showed_interstitial, @@ -330,17 +331,17 @@ performed_check != SafeBrowsingUrlCheckerImpl::PerformedCheck::kUrlRealTimeCheck); - DCHECK_LT(0u, pending_checks_); - pending_checks_--; + DCHECK_LT(0u, pending_sync_checks_); + pending_sync_checks_--; if (slow_check) { - DCHECK_LT(0u, pending_slow_checks_); - pending_slow_checks_--; + DCHECK_LT(0u, pending_sync_slow_checks_); + pending_sync_slow_checks_--; } // If the resource load is going to finish (either being cancelled or // resumed), record the total delay. - if (!proceed || pending_checks_ == 0) { + if (!proceed || pending_sync_checks_ == 0) { // If the resource load is currently deferred, there is a delay. if (deferred_) { total_delay_ = base::TimeTicks::Now() - defer_start_time_; @@ -352,11 +353,11 @@ } if (proceed) { - if (pending_slow_checks_ == 0 && slow_check) { + if (pending_sync_slow_checks_ == 0 && slow_check) { delegate_->ResumeReadingBodyFromNet(); } - if (pending_checks_ == 0 && deferred_) { + if (pending_sync_checks_ == 0 && deferred_) { deferred_ = false; TRACE_EVENT_NESTABLE_ASYNC_END0("safe_browsing", "Deferred", TRACE_ID_LOCAL(this)); @@ -367,9 +368,9 @@ } else { blocked_ = true; - DeleteCheckerOnSB(); - pending_checks_ = 0; - pending_slow_checks_ = 0; + DeleteUrlCheckerOnSB(); + pending_sync_checks_ = 0; + pending_sync_slow_checks_ = 0; // If we didn't show an interstitial, we cancel with ERR_ABORTED to not show // an error page either. delegate_->CancelWithError( @@ -400,15 +401,15 @@ // Future checks for redirects will be skipped. skip_checks_ = true; - pending_checks_--; - if (pending_checks_ == 0 && deferred_) { + pending_sync_checks_--; + if (pending_sync_checks_ == 0 && deferred_) { delegate_->Resume(); } } -void BrowserURLLoaderThrottle::NotifySlowCheck() { +void BrowserURLLoaderThrottle::NotifySyncSlowCheck() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - pending_slow_checks_++; + pending_sync_slow_checks_++; // Pending slow checks indicate that the resource may be unsafe. In that case, // pause reading response body from network to minimize the chance of @@ -418,17 +419,17 @@ // For real time Safe Browsing checks, we continue reading the response body // but, similar to hash-based checks, do not process it until we know it is // SAFE. - if (pending_slow_checks_ == 1) { + if (pending_sync_slow_checks_ == 1) { delegate_->PauseReadingBodyFromNet(); } } -void BrowserURLLoaderThrottle::DeleteCheckerOnSB() { +void BrowserURLLoaderThrottle::DeleteUrlCheckerOnSB() { if (base::FeatureList::IsEnabled(kSafeBrowsingOnUIThread)) { - sb_checker_.reset(); + sync_sb_checker_.reset(); } else { content::GetIOThreadTaskRunner({})->DeleteSoon(FROM_HERE, - std::move(sb_checker_)); + std::move(sync_sb_checker_)); } }
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.h b/components/safe_browsing/content/browser/browser_url_loader_throttle.h index ee36dea..3894002 100644 --- a/components/safe_browsing/content/browser/browser_url_loader_throttle.h +++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.h
@@ -76,7 +76,7 @@ bool* defer) override; const char* NameForLoggingWillProcessResponse() override; - UrlCheckerOnSB* GetSBCheckerForTesting(); + UrlCheckerOnSB* GetSyncSBCheckerForTesting(); private: // |web_contents_getter| is used for displaying SafeBrowsing UI when @@ -93,34 +93,39 @@ base::WeakPtr<AsyncCheckTracker> async_check_tracker); // |slow_check| indicates whether it reports the result of a slow check. - // (Please see comments of CheckerOnSB::OnCheckUrlResult() for what slow check - // means). - void OnCompleteCheck( + // (Please see comments of UrlCheckerOnSB::OnCheckUrlResult() for what slow + // check means). + void OnCompleteSyncCheck( bool slow_check, bool proceed, bool showed_interstitial, SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check, bool did_check_url_real_time_allowlist); - // Returns the suffixed to be used for the TotalDelay2 metrics that specifies - // which type of check was performed. - std::string GetUrlCheckTypeForLogging( - SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check); - // Called to skip future safe browsing checks and resume the request if // necessary. void SkipChecks(); // Called when a slow safe browsing check is ongoing. - void NotifySlowCheck(); + void NotifySyncSlowCheck(); - // Destroys |sb_checker_| on the IO thread, or UI thread if + // Returns the suffixed to be used for the TotalDelay2 metrics that specifies + // which type of check was performed. + std::string GetUrlCheckTypeForLogging( + SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check); + + // Destroys all checkers on the IO thread, or UI thread if // kSafeBrowsingOnUIThread is enabled. - void DeleteCheckerOnSB(); + void DeleteUrlCheckerOnSB(); - size_t pending_checks_ = 0; + size_t pending_sync_checks_ = 0; + // How many slow checks that haven't received results. - size_t pending_slow_checks_ = 0; + size_t pending_sync_slow_checks_ = 0; + + // Whether future safe browsing checks should be skipped. + bool skip_checks_ = false; + bool blocked_ = false; // The time when |WillStartRequest| is called. @@ -136,10 +141,7 @@ // The total delay caused by SafeBrowsing deferring the resource load. base::TimeDelta total_delay_; - // Whether future safe browsing checks should be skipped. - bool skip_checks_ = false; - - std::unique_ptr<UrlCheckerOnSB> sb_checker_; + std::unique_ptr<UrlCheckerOnSB> sync_sb_checker_; // Metric suffix for the URL lookup service. std::string url_lookup_service_metric_suffix_;
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc index 35f45a8..6f8707c 100644 --- a/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc +++ b/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc
@@ -269,9 +269,14 @@ callback_infos_.push_back(std::move(callback_info)); } + base::WeakPtr<MockSafeBrowsingUrlChecker> GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + private: size_t check_url_called_cnt_ = 0; std::vector<CallbackInfo> callback_infos_; + base::WeakPtrFactory<MockSafeBrowsingUrlChecker> weak_factory_{this}; }; } // namespace @@ -309,7 +314,7 @@ url_checker_delegate_ = base::MakeRefCounted<MockUrlCheckerDelegate>(); throttle_delegate_ = std::make_unique<MockThrottleDelegate>(); - std::unique_ptr<MockSafeBrowsingUrlChecker> url_checker = + std::unique_ptr<MockSafeBrowsingUrlChecker> sync_url_checker = std::make_unique<MockSafeBrowsingUrlChecker>( net::HttpRequestHeaders(), /*load_flags=*/0, network::mojom::RequestDestination::kDocument, @@ -329,10 +334,10 @@ /*is_mechanism_experiment_allowed=*/false, /*hash_realtime_selection=*/ hash_realtime_utils::HashRealTimeSelection::kNone); - url_checker_ = url_checker.get(); + sync_url_checker_ = sync_url_checker->GetWeakPtr(); - throttle_->GetSBCheckerForTesting()->SetUrlCheckerForTesting( - std::move(url_checker)); + throttle_->GetSyncSBCheckerForTesting()->SetUrlCheckerForTesting( + std::move(sync_url_checker)); throttle_->set_delegate(throttle_delegate_.get()); url_ = GURL("https://example.com/"); @@ -394,15 +399,15 @@ std::string expected_histogram) { SetUpTest(url_real_time_lookup_enabled); base::HistogramTester histograms; - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true, - performed_check); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true, + performed_check); CallWillStartRequest(); CallWillProcessResponse(); task_environment_.FastForwardBy(base::Milliseconds(200)); - url_checker_->RestartDelayedCallback(/*index=*/0); + sync_url_checker_->RestartDelayedCallback(/*index=*/0); task_environment_.RunUntilIdle(); histograms.ExpectUniqueTimeSample(expected_histogram, @@ -417,8 +422,7 @@ std::unique_ptr<BrowserURLLoaderThrottle> throttle_; // Owned by |throttle_|. May be deleted before the test completes. Prefer // setting it up at the start of the test. - raw_ptr<MockSafeBrowsingUrlChecker, AcrossTasksDanglingUntriaged> - url_checker_; + base::WeakPtr<MockSafeBrowsingUrlChecker> sync_url_checker_; std::unique_ptr<MockRealTimeUrlLookupService> url_lookup_service_ = std::make_unique<MockRealTimeUrlLookupService>(); scoped_refptr<MockUrlCheckerDelegate> url_checker_delegate_; @@ -428,9 +432,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DoesNotDeferOnSafeDocumentUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); bool defer = CallWillStartRequest(); EXPECT_FALSE(defer); @@ -442,9 +446,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DeferOnUnsafeDocumentUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/false); bool defer = CallWillStartRequest(); // Safe Browsing and URL loader are performed in parallel. Safe Browsing @@ -460,9 +464,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DoesNotDeferOnUnsafeIframeUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/false); bool defer = CallWillStartRequestWithDestination( network::mojom::RequestDestination::kIframe); @@ -475,12 +479,12 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DeferIfRedirectUrlIsUnsafe) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/false); CallWillStartRequest(); CallWillRedirectRequest(); @@ -492,9 +496,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DoesNotDeferOnSkippedUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/false); url_checker_delegate_->EnableSkipRequestCheck(); CallWillStartRequestWithDestination( @@ -507,12 +511,12 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DoesNotDeferOnKnownSafeUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true); bool defer = false; network::ResourceRequest request; @@ -529,9 +533,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DeferOnSlowCheck) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true); CallWillStartRequest(); @@ -540,19 +544,19 @@ EXPECT_TRUE(defer); EXPECT_FALSE(throttle_delegate_->IsResumed()); - url_checker_->RestartDelayedCallback(/*index=*/0); + sync_url_checker_->RestartDelayedCallback(/*index=*/0); task_environment_.RunUntilIdle(); EXPECT_TRUE(throttle_delegate_->IsResumed()); } TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DeferOnSlowRedirectCheck) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true); CallWillStartRequest(); CallWillRedirectRequest(); @@ -562,7 +566,7 @@ EXPECT_TRUE(defer); EXPECT_FALSE(throttle_delegate_->IsResumed()); - url_checker_->RestartDelayedCallback(/*index=*/1); + sync_url_checker_->RestartDelayedCallback(/*index=*/1); task_environment_.RunUntilIdle(); EXPECT_TRUE(throttle_delegate_->IsResumed()); } @@ -570,9 +574,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DoesNotResumeOnSlowCheckNotProceed) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/true); CallWillStartRequest(); @@ -580,7 +584,7 @@ EXPECT_TRUE(defer); EXPECT_FALSE(throttle_delegate_->IsResumed()); - url_checker_->RestartDelayedCallback(/*index=*/0); + sync_url_checker_->RestartDelayedCallback(/*index=*/0); task_environment_.RunUntilIdle(); // Resume should not be called because the slow check returns don't proceed. EXPECT_FALSE(throttle_delegate_->IsResumed()); @@ -590,12 +594,12 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DoesNotDeferRedirectOnSlowCheck) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); CallWillStartRequest(); @@ -608,9 +612,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyDefer_DeferRedirectWhenFirstUrlAlreadyBlocked) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/false); CallWillStartRequest(); EXPECT_EQ(throttle_delegate_->GetErrorCode(), net::ERR_BLOCKED_BY_CLIENT); @@ -622,9 +626,9 @@ TEST_F(SBBrowserUrlLoaderThrottleTest, VerifyErrorCodeWhenInterstitialNotShown) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); CallWillStartRequest(); EXPECT_EQ(throttle_delegate_->GetErrorCode(), net::ERR_ABORTED); @@ -634,9 +638,9 @@ VerifyTotalDelayHistograms_FastCheckFromNetwork) { SetUpTest(); base::HistogramTester histograms; - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); CallWillStartRequest(); task_environment_.FastForwardBy(base::Milliseconds(200)); @@ -656,9 +660,9 @@ VerifyTotalDelayHistograms_FastCheckFromCache) { SetUpTest(); base::HistogramTester histograms; - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); CallWillStartRequest(); task_environment_.FastForwardBy(base::Milliseconds(200)); @@ -678,14 +682,14 @@ VerifyTotalDelayHistograms_SlowCheckFromNetwork) { SetUpTest(); base::HistogramTester histograms; - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true); CallWillStartRequest(); CallWillProcessResponse(); task_environment_.FastForwardBy(base::Milliseconds(200)); - url_checker_->RestartDelayedCallback(/*index=*/0); + sync_url_checker_->RestartDelayedCallback(/*index=*/0); task_environment_.RunUntilIdle(); histograms.ExpectUniqueTimeSample( @@ -702,14 +706,14 @@ VerifyTotalDelayHistograms_SlowCheckFromCache) { SetUpTest(); base::HistogramTester histograms; - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/true); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/true); CallWillStartRequest(); CallWillProcessResponseFromCache(); task_environment_.FastForwardBy(base::Milliseconds(200)); - url_checker_->RestartDelayedCallback(/*index=*/0); + sync_url_checker_->RestartDelayedCallback(/*index=*/0); task_environment_.RunUntilIdle(); histograms.ExpectUniqueTimeSample( @@ -768,9 +772,9 @@ TEST_F(SBBrowserUrlLoaderThrottleDisableSkipSubresourcesTest, VerifyDefer_DoesNotDeferOnSafeDocumentUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/true, - /*should_show_interstitial=*/false, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/true, + /*should_show_interstitial=*/false, + /*should_delay_callback=*/false); bool defer = CallWillStartRequest(); EXPECT_FALSE(defer); @@ -783,9 +787,9 @@ TEST_F(SBBrowserUrlLoaderThrottleDisableSkipSubresourcesTest, VerifyDefer_DefersOnUnsafeDocumentUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/false); bool defer = CallWillStartRequest(); // Safe Browsing and URL loader are performed in parallel. Safe Browsing @@ -801,9 +805,9 @@ TEST_F(SBBrowserUrlLoaderThrottleDisableSkipSubresourcesTest, VerifyDefer_DefersOnUnsafeIframeUrl) { SetUpTest(); - url_checker_->AddCallbackInfo(/*should_proceed=*/false, - /*should_show_interstitial=*/true, - /*should_delay_callback=*/false); + sync_url_checker_->AddCallbackInfo(/*should_proceed=*/false, + /*should_show_interstitial=*/true, + /*should_delay_callback=*/false); bool defer = CallWillStartRequestWithDestination( network::mojom::RequestDestination::kIframe);
diff --git a/components/search_engine_descriptions_strings.grd b/components/search_engine_descriptions_strings.grd new file mode 100644 index 0000000..460ac2e --- /dev/null +++ b/components/search_engine_descriptions_strings.grd
@@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- This file contains definition of resources that will be translated for each +locale. The strings in the file are not translated by the Chrome translation +process but are generated using a script that pulls them from outside the repo.--> + +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/search_engine_descriptions_strings.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="search_engine_descriptions_strings_af.pak" type="data_package" lang="af" /> + <output filename="search_engine_descriptions_strings_am.pak" type="data_package" lang="am" /> + <output filename="search_engine_descriptions_strings_ar.pak" type="data_package" lang="ar" /> + <output filename="search_engine_descriptions_strings_as.pak" type="data_package" lang="as" /> + <output filename="search_engine_descriptions_strings_az.pak" type="data_package" lang="az" /> + <output filename="search_engine_descriptions_strings_be.pak" type="data_package" lang="be" /> + <output filename="search_engine_descriptions_strings_bg.pak" type="data_package" lang="bg" /> + <output filename="search_engine_descriptions_strings_bn.pak" type="data_package" lang="bn" /> + <output filename="search_engine_descriptions_strings_bs.pak" type="data_package" lang="bs" /> + <output filename="search_engine_descriptions_strings_ca.pak" type="data_package" lang="ca" /> + <output filename="search_engine_descriptions_strings_cs.pak" type="data_package" lang="cs" /> + <output filename="search_engine_descriptions_strings_cy.pak" type="data_package" lang="cy" /> + <output filename="search_engine_descriptions_strings_da.pak" type="data_package" lang="da" /> + <output filename="search_engine_descriptions_strings_de.pak" type="data_package" lang="de" /> + <output filename="search_engine_descriptions_strings_el.pak" type="data_package" lang="el" /> + <output filename="search_engine_descriptions_strings_en-GB.pak" type="data_package" lang="en-GB" /> + <output filename="search_engine_descriptions_strings_en-US.pak" type="data_package" lang="en" /> + <output filename="search_engine_descriptions_strings_es.pak" type="data_package" lang="es" /> + <if expr="is_ios"> + <then> + <!-- iOS uses es-MX for es-419 --> + <output filename="search_engine_descriptions_strings_es-MX.pak" type="data_package" lang="es-419" /> + </then> + <else> + <output filename="search_engine_descriptions_strings_es-419.pak" type="data_package" lang="es-419" /> + </else> + </if> + <output filename="search_engine_descriptions_strings_et.pak" type="data_package" lang="et" /> + <output filename="search_engine_descriptions_strings_eu.pak" type="data_package" lang="eu" /> + <output filename="search_engine_descriptions_strings_fa.pak" type="data_package" lang="fa" /> + <output filename="search_engine_descriptions_strings_fi.pak" type="data_package" lang="fi" /> + <output filename="search_engine_descriptions_strings_fil.pak" type="data_package" lang="fil" /> + <output filename="search_engine_descriptions_strings_fr-CA.pak" type="data_package" lang="fr-CA" /> + <output filename="search_engine_descriptions_strings_fr.pak" type="data_package" lang="fr" /> + <output filename="search_engine_descriptions_strings_gl.pak" type="data_package" lang="gl" /> + <output filename="search_engine_descriptions_strings_gu.pak" type="data_package" lang="gu" /> + <output filename="search_engine_descriptions_strings_he.pak" type="data_package" lang="he" /> + <output filename="search_engine_descriptions_strings_hi.pak" type="data_package" lang="hi" /> + <output filename="search_engine_descriptions_strings_hr.pak" type="data_package" lang="hr" /> + <output filename="search_engine_descriptions_strings_hu.pak" type="data_package" lang="hu" /> + <output filename="search_engine_descriptions_strings_hy.pak" type="data_package" lang="hy" /> + <output filename="search_engine_descriptions_strings_id.pak" type="data_package" lang="id" /> + <output filename="search_engine_descriptions_strings_is.pak" type="data_package" lang="is" /> + <output filename="search_engine_descriptions_strings_it.pak" type="data_package" lang="it" /> + <output filename="search_engine_descriptions_strings_ja.pak" type="data_package" lang="ja" /> + <output filename="search_engine_descriptions_strings_ka.pak" type="data_package" lang="ka" /> + <output filename="search_engine_descriptions_strings_kk.pak" type="data_package" lang="kk" /> + <output filename="search_engine_descriptions_strings_km.pak" type="data_package" lang="km" /> + <output filename="search_engine_descriptions_strings_kn.pak" type="data_package" lang="kn" /> + <output filename="search_engine_descriptions_strings_ko.pak" type="data_package" lang="ko" /> + <output filename="search_engine_descriptions_strings_ky.pak" type="data_package" lang="ky" /> + <output filename="search_engine_descriptions_strings_lo.pak" type="data_package" lang="lo" /> + <output filename="search_engine_descriptions_strings_lt.pak" type="data_package" lang="lt" /> + <output filename="search_engine_descriptions_strings_lv.pak" type="data_package" lang="lv" /> + <output filename="search_engine_descriptions_strings_mk.pak" type="data_package" lang="mk" /> + <output filename="search_engine_descriptions_strings_ml.pak" type="data_package" lang="ml" /> + <output filename="search_engine_descriptions_strings_mn.pak" type="data_package" lang="mn" /> + <output filename="search_engine_descriptions_strings_mr.pak" type="data_package" lang="mr" /> + <output filename="search_engine_descriptions_strings_ms.pak" type="data_package" lang="ms" /> + <output filename="search_engine_descriptions_strings_my.pak" type="data_package" lang="my" /> + <output filename="search_engine_descriptions_strings_ne.pak" type="data_package" lang="ne" /> + <output filename="search_engine_descriptions_strings_nl.pak" type="data_package" lang="nl" /> + <!-- The translation console uses 'no' for Norwegian Bokmål. It should + be 'nb'. --> + <output filename="search_engine_descriptions_strings_nb.pak" type="data_package" lang="no" /> + <output filename="search_engine_descriptions_strings_pa.pak" type="data_package" lang="pa" /> + <output filename="search_engine_descriptions_strings_pl.pak" type="data_package" lang="pl" /> + <if expr="is_ios"> + <then> + <!-- iOS uses pt for pt-BR --> + <output filename="search_engine_descriptions_strings_pt.pak" type="data_package" lang="pt-BR" /> + </then> + <else> + <output filename="search_engine_descriptions_strings_pt-BR.pak" type="data_package" lang="pt-BR" /> + </else> + </if> + <output filename="search_engine_descriptions_strings_pt-PT.pak" type="data_package" lang="pt-PT" /> + <output filename="search_engine_descriptions_strings_or.pak" type="data_package" lang="or" /> + <output filename="search_engine_descriptions_strings_ro.pak" type="data_package" lang="ro" /> + <output filename="search_engine_descriptions_strings_ru.pak" type="data_package" lang="ru" /> + <output filename="search_engine_descriptions_strings_si.pak" type="data_package" lang="si" /> + <output filename="search_engine_descriptions_strings_sk.pak" type="data_package" lang="sk" /> + <output filename="search_engine_descriptions_strings_sl.pak" type="data_package" lang="sl" /> + <output filename="search_engine_descriptions_strings_sq.pak" type="data_package" lang="sq" /> + <output filename="search_engine_descriptions_strings_sr-Latn.pak" type="data_package" lang="sr-Latn" /> + <output filename="search_engine_descriptions_strings_sr.pak" type="data_package" lang="sr" /> + <output filename="search_engine_descriptions_strings_sv.pak" type="data_package" lang="sv" /> + <output filename="search_engine_descriptions_strings_sw.pak" type="data_package" lang="sw" /> + <output filename="search_engine_descriptions_strings_ta.pak" type="data_package" lang="ta" /> + <output filename="search_engine_descriptions_strings_te.pak" type="data_package" lang="te" /> + <output filename="search_engine_descriptions_strings_th.pak" type="data_package" lang="th" /> + <output filename="search_engine_descriptions_strings_tr.pak" type="data_package" lang="tr" /> + <output filename="search_engine_descriptions_strings_uk.pak" type="data_package" lang="uk" /> + <output filename="search_engine_descriptions_strings_ur.pak" type="data_package" lang="ur" /> + <output filename="search_engine_descriptions_strings_uz.pak" type="data_package" lang="uz" /> + <output filename="search_engine_descriptions_strings_vi.pak" type="data_package" lang="vi" /> + <output filename="search_engine_descriptions_strings_zh-CN.pak" type="data_package" lang="zh-CN" /> + <output filename="search_engine_descriptions_strings_zh-HK.pak" type="data_package" lang="zh-HK" /> + <output filename="search_engine_descriptions_strings_zh-TW.pak" type="data_package" lang="zh-TW" /> + <output filename="search_engine_descriptions_strings_zu.pak" type="data_package" lang="zu" /> + <!-- Pseudolocales --> + <output filename="search_engine_descriptions_strings_ar-XB.pak" type="data_package" lang="ar-XB" /> + <output filename="search_engine_descriptions_strings_en-XA.pak" type="data_package" lang="en-XA" /> + </outputs> + <translations> + <!-- The below files are generated using a script. Do not modify them manually. --> + <file path="strings/search_engine_descriptions_strings_en-GB.xtb" lang="en-GB" /> + </translations> + <release seq="1"> + <messages fallback_to_english="true"> + <!-- The below strings are generated using a script. Do not modify them manually. --> + <message name="IDS_GOOGLE_SEARCH_DESCRIPTION" use_name_for_id="true"> + Google US + </message> + </messages> + </release> +</grit>
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn index 2bc4861..8e20103 100644 --- a/components/search_engines/BUILD.gn +++ b/components/search_engines/BUILD.gn
@@ -109,6 +109,10 @@ deps += [ "//components/search_engines/android:jni_headers" ] } + if (!is_android) { + sources += [ "generated_marketing_snippets.cc" ] + } + if (is_linux || is_win || is_mac || is_chromeos_ash) { sources += [ "site_search_policy_handler.cc",
diff --git a/components/search_engines/DEPS b/components/search_engines/DEPS index af7fe69e..7a56871 100644 --- a/components/search_engines/DEPS +++ b/components/search_engines/DEPS
@@ -12,6 +12,7 @@ "+components/pref_registry", "+components/prefs", "+components/strings/grit/components_strings.h", + "+components/strings/grit/search_engine_descriptions_strings.h", "+components/signin", "+components/sync", "+components/sync_preferences/testing_pref_service_syncable.h",
diff --git a/components/search_engines/OWNERS b/components/search_engines/OWNERS index 4c57f36..a153aac7 100644 --- a/components/search_engines/OWNERS +++ b/components/search_engines/OWNERS
@@ -1,3 +1,4 @@ file://components/omnibox/OWNERS per-file search_engine_choice*=file://chrome/browser/search_engine_choice/OWNERS +per-file generated_marketing_snippets*=file://chrome/browser/search_engine_choice/OWNERS
diff --git a/components/search_engines/generated_marketing_snippets.cc b/components/search_engines/generated_marketing_snippets.cc new file mode 100644 index 0000000..9e98fad --- /dev/null +++ b/components/search_engines/generated_marketing_snippets.cc
@@ -0,0 +1,20 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/search_engines/search_engine_choice_utils.h" + +#include "base/strings/utf_string_conversions.h" +#include "components/search_engines/prepopulated_engines.h" +#include "components/strings/grit/search_engine_descriptions_strings.h" + +namespace search_engines { +// This file will be generated. Don't modify it manually. +int GetMarketingSnippetResourceId(const std::u16string& engine_keyword) { + if (engine_keyword == + base::WideToUTF16(TemplateURLPrepopulateData::google.keyword)) { + return IDS_GOOGLE_SEARCH_DESCRIPTION; + } + return -1; +} +} // namespace search_engines
diff --git a/components/search_engines/search_engine_choice_utils.cc b/components/search_engines/search_engine_choice_utils.cc index 766a5a0..42b5090 100644 --- a/components/search_engines/search_engine_choice_utils.cc +++ b/components/search_engines/search_engine_choice_utils.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "components/search_engines/search_engine_choice_utils.h" +#include <string> #include "base/check_deref.h" #include "base/command_line.h" @@ -17,7 +18,9 @@ #include "components/search_engines/search_engines_switches.h" #include "components/search_engines/template_url_service.h" #include "components/signin/public/base/signin_switches.h" +#include "components/strings/grit/components_strings.h" #include "components/version_info/version_info.h" +#include "ui/base/l10n/l10n_util.h" namespace search_engines { namespace { @@ -349,4 +352,15 @@ } } +#if !BUILDFLAG(IS_ANDROID) +std::u16string GetMarketingSnippetString( + const TemplateURLData& template_url_data) { + int snippet_resource_id = + GetMarketingSnippetResourceId(template_url_data.keyword()); + return l10n_util::GetStringUTF16( + snippet_resource_id == -1 ? IDS_SEARCH_ENGINE_FALLBACK_MARKETING_SNIPPET + : snippet_resource_id); +} +#endif + } // namespace search_engines
diff --git a/components/search_engines/search_engine_choice_utils.h b/components/search_engines/search_engine_choice_utils.h index 65e50983..4b2c825 100644 --- a/components/search_engines/search_engine_choice_utils.h +++ b/components/search_engines/search_engine_choice_utils.h
@@ -13,6 +13,7 @@ } class PrefService; +struct TemplateURLData; class TemplateURLService; namespace search_engines { @@ -185,6 +186,19 @@ // version, to ensure the choice screen is shown again. void WipeSearchEngineChoicePrefs(PrefService& profile_prefs); +#if !BUILDFLAG(IS_ANDROID) +// Returns the engine marketing snippet string resource id or -1 if the snippet +// was not found. +// The function definition is generated in `generated_marketing_snippets.cc`. +// `engine_keyword` is the search engine keyword. +int GetMarketingSnippetResourceId(const std::u16string& engine_keyword); + +// Returns the marketing snippet string or the fallback string if the search +// engine didn't provide its own. +std::u16string GetMarketingSnippetString( + const TemplateURLData& template_url_data); +#endif + } // namespace search_engines #endif // COMPONENTS_SEARCH_ENGINES_SEARCH_ENGINE_CHOICE_UTILS_H_
diff --git a/components/search_engines/search_engines_pref_names.cc b/components/search_engines/search_engines_pref_names.cc index 1b3669e3..3035118 100644 --- a/components/search_engines/search_engines_pref_names.cc +++ b/components/search_engines/search_engines_pref_names.cc
@@ -86,4 +86,12 @@ // local state, not the profile prefs. const char kSearchEnginesChoiceProfile[] = "search_engines.choice_profile"; +// String that refers to the study group in which this install was enrolled. +// Used to implement the first run experiment tracking. +// NOTE: Unlike most of the other preferences here, this one is stored in the +// local state, not the profile prefs. +// TODO(b/313067383): Clean up experiment setup. +const char kSearchEnginesStudyGroup[] = + "search_engines.client_side_study_group"; + } // namespace prefs
diff --git a/components/search_engines/search_engines_pref_names.h b/components/search_engines/search_engines_pref_names.h index 3ffda08..eacb5144 100644 --- a/components/search_engines/search_engines_pref_names.h +++ b/components/search_engines/search_engines_pref_names.h
@@ -20,6 +20,7 @@ extern const char kSearchProviderOverrides[]; extern const char kSearchProviderOverridesVersion[]; extern const char kSearchEnginesChoiceProfile[]; +extern const char kSearchEnginesStudyGroup[]; } // namespace prefs
diff --git a/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc b/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc index 8f281be..3358c8b3 100644 --- a/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc +++ b/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc
@@ -158,8 +158,6 @@ return role_name; } -// TODO(https://crbug.com/1443341): Consider merging the following functions -// into a template, e.g. using std::is_same. void AddAttribute(const std::string& name, int value, screenai::UiElement& ui_element) { @@ -169,17 +167,9 @@ ui_element.add_attributes()->Swap(&attrib); } +template <class T> void AddAttribute(const std::string& name, - const char* value, - screenai::UiElement& ui_element) { - screenai::UiElementAttribute attrib; - attrib.set_name(name); - attrib.set_string_value(value); - ui_element.add_attributes()->Swap(&attrib); -} - -void AddAttribute(const std::string& name, - const std::string& value, + const T& value, screenai::UiElement& ui_element) { screenai::UiElementAttribute attrib; attrib.set_name(name);
diff --git a/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc b/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc index cc18fc51..e22d029 100644 --- a/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc +++ b/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc
@@ -264,7 +264,7 @@ if (!word_box.language().empty() && inline_text_box.GetStringAttribute( ax ::mojom::StringAttribute::kLanguage) != word_box.language()) { - // TODO(crbug.com/1423809): Need to test it more with a more diverse set of + // TODO(crbug.com/1506085): Need to test it more with a more diverse set of // PDF examples that contain from different languages. Design heuristics // of verifying language recognition output from OCR. VLOG(2) << "A `WordBox` has a different language than its enclosing "
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc index f0014608..e7b6d3f7 100644 --- a/components/signin/public/base/signin_switches.cc +++ b/components/signin/public/base/signin_switches.cc
@@ -92,6 +92,9 @@ const base::FeatureParam<bool> kWithSearchEngineMarketingSnippets{ &kSearchEngineChoice, "with-marketing-snippets", /*default_value=*/false}; +const base::FeatureParam<bool> kWithForcedScrollEnabled{ + &kSearchEngineChoice, "with-forced-scroll", /*default_value=*/false}; + // Enables the search engine choice feature in the FRE. BASE_FEATURE(kSearchEngineChoiceFre, "SearchEngineChoiceFre",
diff --git a/components/signin/public/base/signin_switches.h b/components/signin/public/base/signin_switches.h index 1d72971..0aad1ed 100644 --- a/components/signin/public/base/signin_switches.h +++ b/components/signin/public/base/signin_switches.h
@@ -79,6 +79,9 @@ extern const base::FeatureParam<bool> kWithSearchEngineMarketingSnippets; COMPONENT_EXPORT(SIGNIN_SWITCHES) +extern const base::FeatureParam<bool> kWithForcedScrollEnabled; + +COMPONENT_EXPORT(SIGNIN_SWITCHES) BASE_DECLARE_FEATURE(kSearchEngineChoice); COMPONENT_EXPORT(SIGNIN_SWITCHES)
diff --git a/components/strings/BUILD.gn b/components/strings/BUILD.gn index 62efcab..04cc00d 100644 --- a/components/strings/BUILD.gn +++ b/components/strings/BUILD.gn
@@ -27,6 +27,7 @@ ":components_branded_strings", ":components_locale_settings", ":components_strings", + ":search_engine_descriptions_strings", ] } @@ -91,6 +92,14 @@ } } +grit("search_engine_descriptions_strings") { + source = "../search_engine_descriptions_strings.grd" + outputs = [ "grit/search_engine_descriptions_strings.h" ] + foreach(locale, all_chrome_locales) { + outputs += [ "search_engine_descriptions_strings_$locale.pak" ] + } +} + if (is_android) { java_strings_grd_prebuilt("components_locale_settings_grd") { grit_output_dir = "$root_gen_dir/components/strings/java/res"
diff --git a/components/strings/search_engine_descriptions_strings_en-GB.xtb b/components/strings/search_engine_descriptions_strings_en-GB.xtb new file mode 100644 index 0000000..9fd3229 --- /dev/null +++ b/components/strings/search_engine_descriptions_strings_en-GB.xtb
@@ -0,0 +1,5 @@ +<?xml version="1.0" ?> +<!DOCTYPE translationbundle> +<translationbundle lang="en-GB"> +<translation id="IDS_GOOGLE_SEARCH_DESCRIPTION">Google GB</translation> +</translationbundle>
diff --git a/components/test/data/autofill/heuristics-json/internal b/components/test/data/autofill/heuristics-json/internal index 2a35e0b..2b834f1 160000 --- a/components/test/data/autofill/heuristics-json/internal +++ b/components/test/data/autofill/heuristics-json/internal
@@ -1 +1 @@ -Subproject commit 2a35e0b28ccdd4298cc12ba2ef477f9e1320c711 +Subproject commit 2b834f173d97ca859a49701c51dadb6f7cc7387f
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc index 132ae2d..972c369 100644 --- a/components/user_manager/known_user.cc +++ b/components/user_manager/known_user.cc
@@ -572,7 +572,7 @@ SetStringPref(account_id, kDeviceId, device_id); } -std::string KnownUser::GetDeviceId(const AccountId& account_id) { +std::string KnownUser::GetDeviceId(const AccountId& account_id) const { const std::string* device_id = FindStringPath(account_id, kDeviceId); if (device_id) return *device_id;
diff --git a/components/user_manager/known_user.h b/components/user_manager/known_user.h index aca8745..49fac09 100644 --- a/components/user_manager/known_user.h +++ b/components/user_manager/known_user.h
@@ -141,7 +141,7 @@ // Setter and getter for DeviceId known user string preference. void SetDeviceId(const AccountId& account_id, const std::string& device_id); - std::string GetDeviceId(const AccountId& account_id); + std::string GetDeviceId(const AccountId& account_id) const; // Setter and getter for GAPSCookie known user string preference. void SetGAPSCookie(const AccountId& account_id,
diff --git a/components/vector_icons/README.md b/components/vector_icons/README.md index 558e7113..e491b16 100644 --- a/components/vector_icons/README.md +++ b/components/vector_icons/README.md
@@ -56,6 +56,8 @@ Use [this extension](https://github.com/sadrulhc/vector-icons) to preview icons in [codesearch](http://cs.chromium.org/). +You can also use the [Vector Icon Viewer](https://marketplace.visualstudio.com/items?itemName=adolfdaniel.vscode-chromium-vector-icons) extension for VS Code to preview icons in Visual Studio. This is especially helpful when adding new icons. + You can also build and run the `views_examples_exe` (or `views_examples_with_content_exe`) target and select "Vector Icons" from the dropdown menu. This loads a simple interface which allows you view a provided vector icon file at a specified size and color. Contributions to improve this interface are welcome ([bug](https://bugs.chromium.org/p/chromium/issues/detail?id=630295)). ### Can my vector icon have more than one color?
diff --git a/components/viz/service/display/display_resource_provider.cc b/components/viz/service/display/display_resource_provider.cc index b5a70fdf..e68a468 100644 --- a/components/viz/service/display/display_resource_provider.cc +++ b/components/viz/service/display/display_resource_provider.cc
@@ -237,7 +237,9 @@ ResourceId local_id = resource_id_generator_.GenerateNextId(); DCHECK(!transferable_resource.is_software || - transferable_resource.format.IsBitmapFormatSupported()); + transferable_resource.mailbox_holder.mailbox.IsSharedImage() || + (!transferable_resource.mailbox_holder.mailbox.IsSharedImage() && + transferable_resource.format.IsBitmapFormatSupported())); resources_.emplace(local_id, ChildResource(child_id, transferable_resource)); child_info.child_to_parent_map[transferable_resource.id] = local_id;
diff --git a/components/webapps/browser/android/add_to_homescreen_data_fetcher.cc b/components/webapps/browser/android/add_to_homescreen_data_fetcher.cc index 93c9509..72c8b92 100644 --- a/components/webapps/browser/android/add_to_homescreen_data_fetcher.cc +++ b/components/webapps/browser/android/add_to_homescreen_data_fetcher.cc
@@ -21,7 +21,7 @@ #include "base/threading/thread_restrictions.h" #include "components/dom_distiller/core/url_utils.h" #include "components/favicon/content/large_favicon_provider_getter.h" -#include "components/favicon/core/large_favicon_provider.h" +#include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/favicon_types.h" #include "components/webapps/browser/android/webapps_icon_utils.h" #include "components/webapps/browser/android/webapps_utils.h"
diff --git a/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc b/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc index 82f73fec..daeb6ac 100644 --- a/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc +++ b/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc
@@ -20,7 +20,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "components/favicon/content/large_favicon_provider_getter.h" -#include "components/favicon/core/large_favicon_provider.h" +#include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/favicon_types.h" #include "components/webapps/browser/features.h" #include "components/webapps/browser/installable/installable_data.h" @@ -244,9 +244,9 @@ web_contents()->GetUserData(TestInstallableManager::UserDataKey())); favicon::SetLargeFaviconProviderGetter(base::BindRepeating( - [](favicon::LargeFaviconProvider* provider, - content::BrowserContext* context) { return provider; }, - &null_large_favicon_provider_)); + [](favicon::LargeIconService* service, + content::BrowserContext* context) { return service; }, + &null_large_icon_service_)); NavigateAndCommit(GURL(kDefaultStartUrl)); } @@ -319,10 +319,10 @@ base::test::ScopedFeatureList scoped_feature_list_; private: - class NullLargeFaviconProvider : public favicon::LargeFaviconProvider { + class NullLargeIconService : public favicon::LargeIconService { public: - NullLargeFaviconProvider() = default; - virtual ~NullLargeFaviconProvider() = default; + NullLargeIconService() = default; + ~NullLargeIconService() override = default; MOCK_METHOD5(GetLargeIconRawBitmapOrFallbackStyleForPageUrl, base::CancelableTaskTracker::TaskId( @@ -338,6 +338,27 @@ int desired_size_in_pixel, favicon_base::LargeIconImageCallback callback, base::CancelableTaskTracker* tracker)); + MOCK_METHOD5(GetLargeIconRawBitmapOrFallbackStyleForIconUrl, + base::CancelableTaskTracker::TaskId( + const GURL& icon_url, + int min_source_size_in_pixel, + int desired_size_in_pixel, + favicon_base::LargeIconCallback callback, + base::CancelableTaskTracker* tracker)); + MOCK_METHOD4(GetIconRawBitmapOrFallbackStyleForPageUrl, + base::CancelableTaskTracker::TaskId( + const GURL& page_url, + int desired_size_in_pixel, + favicon_base::LargeIconCallback callback, + base::CancelableTaskTracker* tracker)); + MOCK_METHOD5( + GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache, + void(const GURL& page_url, + bool may_page_url_be_private, + bool should_trim_page_url_path, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + favicon_base::GoogleFaviconServerCallback callback)); + MOCK_METHOD1(TouchIconFromGoogleServer, void(const GURL& icon_url)); base::CancelableTaskTracker::TaskId GetLargeIconRawBitmapForPageUrl( const GURL& page_url, int min_source_size_in_pixel, @@ -351,7 +372,7 @@ }; raw_ptr<TestInstallableManager> installable_manager_; - NullLargeFaviconProvider null_large_favicon_provider_; + NullLargeIconService null_large_icon_service_; }; TEST_F(AddToHomescreenDataFetcherTest, EmptyManifest) {
diff --git a/components/webapps/browser/installable/installable_icon_fetcher.cc b/components/webapps/browser/installable/installable_icon_fetcher.cc index 0c7d520..a506097 100644 --- a/components/webapps/browser/installable/installable_icon_fetcher.cc +++ b/components/webapps/browser/installable/installable_icon_fetcher.cc
@@ -11,7 +11,7 @@ #include "base/task/thread_pool.h" #include "base/threading/thread_restrictions.h" #include "components/favicon/content/large_favicon_provider_getter.h" -#include "components/favicon/core/large_favicon_provider.h" +#include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/favicon_types.h" #include "components/webapps/browser/features.h" #include "components/webapps/browser/installable/installable_evaluator.h" @@ -191,14 +191,14 @@ } void InstallableIconFetcher::FetchFavicon() { - favicon::LargeFaviconProvider* favicon_provider = + favicon::LargeIconService* favicon_service = favicon::GetLargeFaviconProvider(web_contents_->GetBrowserContext()); - if (!favicon_provider) { + if (!favicon_service) { EndWithError(NO_ACCEPTABLE_ICON); return; } - favicon_provider->GetLargeIconRawBitmapForPageUrl( + favicon_service->GetLargeIconRawBitmapForPageUrl( web_contents_->GetLastCommittedURL(), GetIdealPrimaryIconSizeInPx(IconPurpose::ANY), base::BindOnce(&InstallableIconFetcher::OnFaviconFetched,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index a455867e..6959df731 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1726,39 +1726,10 @@ "renderer_host/input/render_widget_host_latency_tracker.h", "renderer_host/input/stylus_text_selector.cc", "renderer_host/input/stylus_text_selector.h", - "renderer_host/input/synthetic_gesture.cc", - "renderer_host/input/synthetic_gesture.h", - "renderer_host/input/synthetic_gesture_controller.cc", - "renderer_host/input/synthetic_gesture_controller.h", - "renderer_host/input/synthetic_gesture_target.h", "renderer_host/input/synthetic_gesture_target_aura.cc", "renderer_host/input/synthetic_gesture_target_aura.h", "renderer_host/input/synthetic_gesture_target_base.cc", "renderer_host/input/synthetic_gesture_target_base.h", - "renderer_host/input/synthetic_mouse_driver.cc", - "renderer_host/input/synthetic_mouse_driver.h", - "renderer_host/input/synthetic_pen_driver.cc", - "renderer_host/input/synthetic_pen_driver.h", - "renderer_host/input/synthetic_pinch_gesture.cc", - "renderer_host/input/synthetic_pinch_gesture.h", - "renderer_host/input/synthetic_pointer_action.cc", - "renderer_host/input/synthetic_pointer_action.h", - "renderer_host/input/synthetic_pointer_driver.cc", - "renderer_host/input/synthetic_pointer_driver.h", - "renderer_host/input/synthetic_smooth_drag_gesture.cc", - "renderer_host/input/synthetic_smooth_drag_gesture.h", - "renderer_host/input/synthetic_smooth_move_gesture.cc", - "renderer_host/input/synthetic_smooth_move_gesture.h", - "renderer_host/input/synthetic_smooth_scroll_gesture.cc", - "renderer_host/input/synthetic_smooth_scroll_gesture.h", - "renderer_host/input/synthetic_tap_gesture.cc", - "renderer_host/input/synthetic_tap_gesture.h", - "renderer_host/input/synthetic_touch_driver.cc", - "renderer_host/input/synthetic_touch_driver.h", - "renderer_host/input/synthetic_touchpad_pinch_gesture.cc", - "renderer_host/input/synthetic_touchpad_pinch_gesture.h", - "renderer_host/input/synthetic_touchscreen_pinch_gesture.cc", - "renderer_host/input/synthetic_touchscreen_pinch_gesture.h", "renderer_host/input/timeout_monitor.cc", "renderer_host/input/timeout_monitor.h", "renderer_host/input/touch_action_filter.cc",
diff --git a/content/browser/aggregation_service/aggregatable_report.cc b/content/browser/aggregation_service/aggregatable_report.cc index 14e5b08..9c0dff89e 100644 --- a/content/browser/aggregation_service/aggregatable_report.cc +++ b/content/browser/aggregation_service/aggregatable_report.cc
@@ -18,7 +18,6 @@ #include "base/base64.h" #include "base/check.h" #include "base/check_op.h" -#include "base/containers/contains.h" #include "base/containers/flat_map.h" #include "base/containers/span.h" #include "base/debug/dump_without_crashing.h"
diff --git a/content/browser/aggregation_service/aggregatable_report.h b/content/browser/aggregation_service/aggregatable_report.h index d1c5667..ef05e18 100644 --- a/content/browser/aggregation_service/aggregatable_report.h +++ b/content/browser/aggregation_service/aggregatable_report.h
@@ -9,7 +9,6 @@ #include <stdint.h> #include <optional> -#include <ostream> #include <string> #include <vector> @@ -21,7 +20,6 @@ #include "base/values.h" #include "content/browser/aggregation_service/public_key.h" #include "content/common/content_export.h" -#include "third_party/abseil-cpp/absl/numeric/int128.h" #include "third_party/blink/public/mojom/private_aggregation/aggregatable_report.mojom.h" #include "url/gurl.h" #include "url/origin.h"
diff --git a/content/browser/aggregation_service/aggregatable_report_assembler.h b/content/browser/aggregation_service/aggregatable_report_assembler.h index 65533b7..b80d294 100644 --- a/content/browser/aggregation_service/aggregatable_report_assembler.h +++ b/content/browser/aggregation_service/aggregatable_report_assembler.h
@@ -8,7 +8,6 @@ #include <stddef.h> #include <stdint.h> -#include <array> #include <memory> #include <optional> #include <vector>
diff --git a/content/browser/aggregation_service/aggregatable_report_assembler_unittest.cc b/content/browser/aggregation_service/aggregatable_report_assembler_unittest.cc index 6e6ffe8..23ec4c5 100644 --- a/content/browser/aggregation_service/aggregatable_report_assembler_unittest.cc +++ b/content/browser/aggregation_service/aggregatable_report_assembler_unittest.cc
@@ -12,12 +12,10 @@ #include <vector> #include "base/memory/raw_ptr.h" -#include "base/test/bind.h" #include "base/test/gmock_callback_support.h" #include "base/test/gmock_move_support.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" -#include "base/time/time.h" #include "content/browser/aggregation_service/aggregatable_report.h" #include "content/browser/aggregation_service/aggregation_service_key_fetcher.h" #include "content/browser/aggregation_service/aggregation_service_test_utils.h"
diff --git a/content/browser/aggregation_service/aggregatable_report_request_storage_id.h b/content/browser/aggregation_service/aggregatable_report_request_storage_id.h index ce429a0d..b985715 100644 --- a/content/browser/aggregation_service/aggregatable_report_request_storage_id.h +++ b/content/browser/aggregation_service/aggregatable_report_request_storage_id.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_REQUEST_STORAGE_ID_H_ #define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_REQUEST_STORAGE_ID_H_ +#include <stdint.h> + #include "base/types/strong_alias.h" namespace content {
diff --git a/content/browser/aggregation_service/aggregatable_report_scheduler.cc b/content/browser/aggregation_service/aggregatable_report_scheduler.cc index 79f8357..e9846681 100644 --- a/content/browser/aggregation_service/aggregatable_report_scheduler.cc +++ b/content/browser/aggregation_service/aggregatable_report_scheduler.cc
@@ -4,7 +4,6 @@ #include "content/browser/aggregation_service/aggregatable_report_scheduler.h" -#include <algorithm> #include <memory> #include <optional> #include <utility> @@ -16,7 +15,6 @@ #include "base/containers/cxx20_erase.h" #include "base/functional/bind.h" #include "base/functional/callback.h" -#include "base/location.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/threading/sequence_bound.h"
diff --git a/content/browser/aggregation_service/aggregatable_report_sender.cc b/content/browser/aggregation_service/aggregatable_report_sender.cc index f616ae3..cfd9151 100644 --- a/content/browser/aggregation_service/aggregatable_report_sender.cc +++ b/content/browser/aggregation_service/aggregatable_report_sender.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/check.h" +#include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/json/json_writer.h" #include "base/logging.h"
diff --git a/content/browser/aggregation_service/aggregatable_report_sender.h b/content/browser/aggregation_service/aggregatable_report_sender.h index 3cc46ab..775369f 100644 --- a/content/browser/aggregation_service/aggregatable_report_sender.h +++ b/content/browser/aggregation_service/aggregatable_report_sender.h
@@ -96,4 +96,4 @@ } // namespace content -#endif // CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_SENDER_H_ \ No newline at end of file +#endif // CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_SENDER_H_
diff --git a/content/browser/aggregation_service/aggregatable_report_unittest.cc b/content/browser/aggregation_service/aggregatable_report_unittest.cc index da513ce..1792bb6 100644 --- a/content/browser/aggregation_service/aggregatable_report_unittest.cc +++ b/content/browser/aggregation_service/aggregatable_report_unittest.cc
@@ -30,7 +30,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/numeric/int128.h" #include "third_party/blink/public/mojom/private_aggregation/aggregatable_report.mojom.h" -#include "third_party/boringssl/src/include/openssl/hpke.h" #include "url/gurl.h" #include "url/origin.h"
diff --git a/content/browser/aggregation_service/aggregation_service_impl.cc b/content/browser/aggregation_service/aggregation_service_impl.cc index 32c71fc..53b3be1 100644 --- a/content/browser/aggregation_service/aggregation_service_impl.cc +++ b/content/browser/aggregation_service/aggregation_service_impl.cc
@@ -22,7 +22,6 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" -#include "base/strings/strcat.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/task/updateable_sequenced_task_runner.h"
diff --git a/content/browser/aggregation_service/aggregation_service_impl.h b/content/browser/aggregation_service/aggregation_service_impl.h index 8a488d18..e43dc32 100644 --- a/content/browser/aggregation_service/aggregation_service_impl.h +++ b/content/browser/aggregation_service/aggregation_service_impl.h
@@ -5,14 +5,11 @@ #ifndef CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_IMPL_H_ #define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_IMPL_H_ -#include <stdint.h> - #include <memory> #include <optional> #include <set> #include <vector> -#include "base/containers/flat_map.h" #include "base/functional/callback_forward.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h"
diff --git a/content/browser/aggregation_service/aggregation_service_key_fetcher_unittest.cc b/content/browser/aggregation_service/aggregation_service_key_fetcher_unittest.cc index 556a643..79713bc 100644 --- a/content/browser/aggregation_service/aggregation_service_key_fetcher_unittest.cc +++ b/content/browser/aggregation_service/aggregation_service_key_fetcher_unittest.cc
@@ -6,7 +6,6 @@ #include <memory> #include <optional> -#include <tuple> #include <utility> #include <vector>
diff --git a/content/browser/aggregation_service/aggregation_service_storage.h b/content/browser/aggregation_service/aggregation_service_storage.h index 4a1e7478..2d2b0010 100644 --- a/content/browser/aggregation_service/aggregation_service_storage.h +++ b/content/browser/aggregation_service/aggregation_service_storage.h
@@ -5,8 +5,6 @@ #ifndef CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_H_ #define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATION_SERVICE_STORAGE_H_ -#include <stdint.h> - #include <optional> #include <set> #include <vector>
diff --git a/content/browser/aggregation_service/aggregation_service_storage_sql.cc b/content/browser/aggregation_service/aggregation_service_storage_sql.cc index 7ee2f64..4f7d472 100644 --- a/content/browser/aggregation_service/aggregation_service_storage_sql.cc +++ b/content/browser/aggregation_service/aggregation_service_storage_sql.cc
@@ -37,7 +37,6 @@ #include "sql/statement.h" #include "sql/statement_id.h" #include "sql/transaction.h" -#include "third_party/abseil-cpp/absl/numeric/int128.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/gurl.h" #include "url/origin.h"
diff --git a/content/browser/aggregation_service/report_scheduler_timer_unittest.cc b/content/browser/aggregation_service/report_scheduler_timer_unittest.cc index 32bdf01..d5ff08e 100644 --- a/content/browser/aggregation_service/report_scheduler_timer_unittest.cc +++ b/content/browser/aggregation_service/report_scheduler_timer_unittest.cc
@@ -13,7 +13,6 @@ #include "base/test/gmock_move_support.h" #include "base/test/task_environment.h" #include "base/time/time.h" -#include "content/public/browser/network_service_instance.h" #include "services/network/public/mojom/network_change_manager.mojom.h" #include "services/network/test/test_network_connection_tracker.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/content/browser/android/selection/selection_popup_controller.cc b/content/browser/android/selection/selection_popup_controller.cc index bfbc3c14..0dedba7a 100644 --- a/content/browser/android/selection/selection_popup_controller.cc +++ b/content/browser/android/selection/selection_popup_controller.cc
@@ -96,9 +96,6 @@ WebContents* web_contents) : RenderWidgetHostConnector(web_contents) { java_obj_ = JavaObjectWeakGlobalRef(env, obj); - auto* wcva = static_cast<WebContentsViewAndroid*>( - static_cast<WebContentsImpl*>(web_contents)->GetView()); - wcva->set_selection_popup_controller(this); } SelectionPopupController::~SelectionPopupController() {
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc index 422b41f..ce0f6f4e 100644 --- a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
@@ -1458,7 +1458,7 @@ // Wait for parsing to finish. task_environment_.FastForwardBy(base::TimeDelta()); - histograms.ExpectUniqueSample("Conversions.SourceRegistrationError8", + histograms.ExpectUniqueSample("Conversions.SourceRegistrationError9", SourceRegistrationError::kInvalidJson, 1); }
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc b/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc index 80153a67..44dc075 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc +++ b/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
@@ -107,7 +107,8 @@ EXPECT_EQ(kExampleDeveloperId2, worker->last_registration()->developer_id); } -TEST_F(BackgroundFetchEventDispatcherTest, DispatchClickEvent) { +// TODO(crbug.com/1506090): Disabled due to flakiness. +TEST_F(BackgroundFetchEventDispatcherTest, DISABLED_DispatchClickEvent) { auto* worker = embedded_worker_test_helper() ->AddNewPendingServiceWorker<BackgroundFetchTestServiceWorker>( @@ -208,7 +209,8 @@ EXPECT_EQ(kExampleDeveloperId2, worker->last_registration()->developer_id); } -TEST_F(BackgroundFetchEventDispatcherTest, DispatchFetchSuccessEvent) { +// TODO(crbug.com/1506090): Disabled due to flakiness. +TEST_F(BackgroundFetchEventDispatcherTest, DISABLED_DispatchFetchSuccessEvent) { auto* worker = embedded_worker_test_helper() ->AddNewPendingServiceWorker<BackgroundFetchTestServiceWorker>(
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index ad00480..a1f93b0 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc
@@ -286,14 +286,6 @@ return child_id_ != ChildProcessHost::kInvalidUniqueID; } -bool ChildProcessSecurityPolicyImpl::Handle::CanCommitURL(const GURL& url) { - if (child_id_ == ChildProcessHost::kInvalidUniqueID) - return false; - - auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); - return policy->CanCommitURL(child_id_, url); -} - bool ChildProcessSecurityPolicyImpl::Handle::CanReadFile( const base::FilePath& file) { if (child_id_ == ChildProcessHost::kInvalidUniqueID)
diff --git a/content/browser/child_process_security_policy_impl.h b/content/browser/child_process_security_policy_impl.h index 7c382fc..c637acc2 100644 --- a/content/browser/child_process_security_policy_impl.h +++ b/content/browser/child_process_security_policy_impl.h
@@ -90,9 +90,6 @@ // created this object after the process has already been destructed. bool is_valid() const; - // Whether the process is allowed to commit a document from the given URL. - bool CanCommitURL(const GURL& url); - // Before servicing a child process's request to upload a file to the web, // the browser should call this method to determine whether the process has // the capability to upload the requested file.
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc index a9f539a..d83f1f8 100644 --- a/content/browser/child_process_security_policy_unittest.cc +++ b/content/browser/child_process_security_policy_unittest.cc
@@ -407,10 +407,8 @@ // A non-locked process cannot access URL (because with // site-per-process all the URLs need to be isolated). EXPECT_FALSE(p->CanCommitURL(kRendererID, commit_url)) << commit_url; - EXPECT_FALSE(handle.CanCommitURL(commit_url)) << commit_url; } else { EXPECT_TRUE(p->CanCommitURL(kRendererID, commit_url)) << commit_url; - EXPECT_TRUE(handle.CanCommitURL(commit_url)) << commit_url; } } @@ -431,7 +429,6 @@ for (const auto& url_string : kFailedCommitURLs) { const GURL commit_url(url_string); EXPECT_FALSE(p->CanCommitURL(kRendererID, commit_url)) << commit_url; - EXPECT_FALSE(handle.CanCommitURL(commit_url)) << commit_url; } p->Remove(kRendererID);
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc index 94193ab..2866ecb 100644 --- a/content/browser/devtools/protocol/input_handler.cc +++ b/content/browser/devtools/protocol/input_handler.cc
@@ -24,19 +24,19 @@ #include "content/browser/devtools/protocol/native_input_event_builder.h" #include "content/browser/devtools/protocol/protocol.h" #include "content/browser/renderer_host/data_transfer_util.h" -#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" #include "content/browser/renderer_host/input/touch_emulator.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_pinch_gesture.h" #include "content/common/input/synthetic_pinch_gesture_params.h" +#include "content/common/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_pointer_driver.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" +#include "content/common/input/synthetic_tap_gesture.h" #include "content/common/input/synthetic_tap_gesture_params.h" #include "content/public/common/content_features.h" #include "third_party/blink/public/common/input/web_input_event.h"
diff --git a/content/browser/devtools/protocol/input_handler.h b/content/browser/devtools/protocol/input_handler.h index 05b285ee..8bc1ca4 100644 --- a/content/browser/devtools/protocol/input_handler.h +++ b/content/browser/devtools/protocol/input_handler.h
@@ -16,8 +16,8 @@ #include "base/memory/weak_ptr.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h" #include "content/browser/devtools/protocol/input.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/common/input/synthetic_gesture.h" #include "content/common/input/synthetic_pointer_action_list_params.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" #include "content/public/browser/render_widget_host.h"
diff --git a/content/browser/media/active_media_session_controller.cc b/content/browser/media/active_media_session_controller.cc index ceab687..00da8ded 100644 --- a/content/browser/media/active_media_session_controller.cc +++ b/content/browser/media/active_media_session_controller.cc
@@ -9,6 +9,7 @@ #include "base/containers/contains.h" #include "base/metrics/histogram_macros.h" +#include "base/unguessable_token.h" #include "content/browser/browser_main_loop.h" #include "content/browser/media/media_keys_listener_manager_impl.h" #include "content/public/browser/media_keys_listener_manager.h" @@ -21,15 +22,26 @@ using media_session::mojom::MediaSessionAction; -ActiveMediaSessionController::ActiveMediaSessionController() { +ActiveMediaSessionController::ActiveMediaSessionController( + base::UnguessableToken request_id) + : request_id_(request_id) { // Connect to the MediaControllerManager and create a MediaController that - // controls the active session. - mojo::Remote<media_session::mojom::MediaControllerManager> - controller_manager_remote; + // controls the session given by `request_id`. GetMediaSessionService().BindMediaControllerManager( - controller_manager_remote.BindNewPipeAndPassReceiver()); - controller_manager_remote->CreateActiveMediaController( - media_controller_remote_.BindNewPipeAndPassReceiver()); + controller_manager_remote_.BindNewPipeAndPassReceiver()); + + if (request_id == base::UnguessableToken::Null()) { + // ID is null for all scenarios where kWebAppSystemMediaControlsWin is not + // supported. ie. Mac, Linux, Windows with the feature flag off. + // Create a media controller that follows the active session for this case. + controller_manager_remote_->CreateActiveMediaController( + media_controller_remote_.BindNewPipeAndPassReceiver()); + } else { + // Create a media controller tied to |request_id| when + // kWebAppSystemMediaControlsWin is enabled (on Windows OS). + controller_manager_remote_->CreateMediaControllerForSession( + media_controller_remote_.BindNewPipeAndPassReceiver(), request_id); + } // Observe the active media controller for changes to playback state and // supported actions. @@ -39,6 +51,22 @@ ActiveMediaSessionController::~ActiveMediaSessionController() = default; +void ActiveMediaSessionController::RebindMojoForNewID( + base::UnguessableToken request_id) { + media_controller_remote_.reset(); + media_controller_observer_receiver_.reset(); + + // Don't think this is necessary for browser as we pass it to + // Start/StopWatchingMediaKey which only uses it for PWAs, but probably good + // to keep it up to date. + request_id_ = request_id; + + controller_manager_remote_->CreateMediaControllerForSession( + media_controller_remote_.BindNewPipeAndPassReceiver(), request_id); + media_controller_remote_->AddObserver( + media_controller_observer_receiver_.BindNewPipeAndPassRemote()); +} + void ActiveMediaSessionController::MediaSessionInfoChanged( media_session::mojom::MediaSessionInfoPtr session_info) { MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = @@ -59,13 +87,16 @@ // Stop listening to any keys that are currently being watched, but aren't in // |actions|. + // This loop is what tells SMTC to stop watching next/previous when a new tab + // is active because next/previous are in actions_ but NOT in actions for (const MediaSessionAction& action : actions_) { absl::optional<ui::KeyboardCode> action_key_code = MediaSessionActionToKeyCode(action); if (!action_key_code.has_value()) continue; if (!base::Contains(actions, action)) - media_keys_listener_manager->StopWatchingMediaKey(*action_key_code, this); + media_keys_listener_manager->StopWatchingMediaKey(*action_key_code, this, + request_id_); } // Populate |actions_| with the new MediaSessionActions and start listening @@ -77,8 +108,8 @@ if (action_key_code.has_value()) { // It's okay to call this even on keys we're already listening to, since // it's a no-op in that case. - if (media_keys_listener_manager->StartWatchingMediaKey(*action_key_code, - this)) { + if (media_keys_listener_manager->StartWatchingMediaKey( + *action_key_code, this, request_id_)) { actions_.insert(action); } } else {
diff --git a/content/browser/media/active_media_session_controller.h b/content/browser/media/active_media_session_controller.h index 0956062..1db9c52 100644 --- a/content/browser/media/active_media_session_controller.h +++ b/content/browser/media/active_media_session_controller.h
@@ -17,20 +17,37 @@ #include "ui/base/accelerators/media_keys_listener.h" #include "ui/events/keycodes/keyboard_codes.h" +namespace base { +class UnguessableToken; +} namespace content { // Intakes media events (such as media key presses) and controls the active // media session. +// TODO(crbug.com/1502989) Consider renaming this class in the world of +// instanced system media controls. class CONTENT_EXPORT ActiveMediaSessionController : public media_session::mojom::MediaControllerObserver, public ui::MediaKeysListener::Delegate { public: - ActiveMediaSessionController(); + explicit ActiveMediaSessionController(base::UnguessableToken request_id); ActiveMediaSessionController(const ActiveMediaSessionController&) = delete; ActiveMediaSessionController& operator=(const ActiveMediaSessionController&) = delete; ~ActiveMediaSessionController() override; + // This mechanism allows this AMSC to be rebound to track a different + // request_id. This is used by the browser singleton active media session + // controller which is created to track a specific request_id but conceptually + // needs to follow around whatever the most recent active playing media is. + // This has the added benefit that things like |actions_| will persist across + // multiple tabs. If we simply recreate for each browser-associated media, + // |actions_| may not get switched off causing a previously available button + // to stay available when it is not available in the current media context. + // Currently used only by browser system media controls when + // kWebAppSystemMediaControlsWin is enabled. + void RebindMojoForNewID(base::UnguessableToken request_id); + // media_session::mojom::MediaControllerObserver: void MediaSessionInfoChanged( media_session::mojom::MediaSessionInfoPtr session_info) override; @@ -77,6 +94,9 @@ bool SupportsAction(media_session::mojom::MediaSessionAction action) const; void PerformAction(media_session::mojom::MediaSessionAction action); + mojo::Remote<media_session::mojom::MediaControllerManager> + controller_manager_remote_; + // Used to control the active session. mojo::Remote<media_session::mojom::MediaController> media_controller_remote_; @@ -93,6 +113,12 @@ // Stores the current playback position. absl::optional<media_session::MediaPosition> position_; + + // Stores the media session (if any specific one) this active media session + // controller is associated with. If this is null, this AMSC follows + // around the active media session automatically and will receive events for + // it. + base::UnguessableToken request_id_; }; } // namespace content
diff --git a/content/browser/media/android/browser_gpu_video_accelerator_factories.cc b/content/browser/media/android/browser_gpu_video_accelerator_factories.cc index 412dafc..ac7ffc2 100644 --- a/content/browser/media/android/browser_gpu_video_accelerator_factories.cc +++ b/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
@@ -4,6 +4,7 @@ #include "content/browser/media/android/browser_gpu_video_accelerator_factories.h" +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/task/sequenced_task_runner.h" #include "content/browser/browser_main_loop.h" @@ -20,13 +21,24 @@ namespace { +// Controls if browser compositor context can be backed by raster decoder. +// TODO(crbug.com/1505425): Remove kill switch once rolled out to stable. +BASE_FEATURE(kUseRasterDecoderForAndroidBrowserMediaContext, + "UseRasterDecoderForAndroidBrowserMediaContext", + base::FEATURE_ENABLED_BY_DEFAULT); + void OnGpuChannelEstablished( GpuVideoAcceleratorFactoriesCallback callback, scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) { + const bool use_raster_decoder = base::FeatureList::IsEnabled( + kUseRasterDecoderForAndroidBrowserMediaContext); + gpu::ContextCreationAttribs attributes; attributes.bind_generates_resource = false; attributes.enable_raster_interface = true; - attributes.enable_grcontext = true; + attributes.enable_oop_rasterization = use_raster_decoder; + attributes.enable_gles2_interface = !use_raster_decoder; + attributes.enable_grcontext = !use_raster_decoder; int32_t stream_id = kGpuStreamIdDefault; gpu::SchedulingPriority stream_priority = kGpuStreamPriorityUI;
diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc index 65fa0fd..9057dbf 100644 --- a/content/browser/media/media_keys_listener_manager_impl.cc +++ b/content/browser/media/media_keys_listener_manager_impl.cc
@@ -14,10 +14,16 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/media/active_media_session_controller.h" #include "content/browser/media/system_media_controls_notifier.h" +#include "content/browser/media/web_app_system_media_controls.h" +#include "content/public/common/content_features.h" #include "media/audio/audio_manager.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/idle/idle.h" +#if BUILDFLAG(IS_WIN) +#include "content/browser/media/web_app_system_media_controls_manager.h" +#endif + namespace content { MediaKeysListenerManagerImpl::ListeningData::ListeningData() = default; @@ -32,28 +38,52 @@ return BrowserMainLoop::GetInstance()->media_keys_listener_manager(); } -MediaKeysListenerManagerImpl::MediaKeysListenerManagerImpl() - : active_media_session_controller_( - std::make_unique<ActiveMediaSessionController>()) { +MediaKeysListenerManagerImpl::MediaKeysListenerManagerImpl() { DCHECK(!MediaKeysListenerManager::GetInstance()); + +#if BUILDFLAG(IS_WIN) + // If instanced system media controls are enabled, the ...controls_manager_ + // will handle creation of browser related classes such as the + // browser_active_media_session_controller_. + if (ShouldUseWebAppSystemMediaControls()) { + web_app_system_media_controls_manager_ = + std::make_unique<WebAppSystemMediaControlsManager>(); + web_app_system_media_controls_manager_->Init(); + return; + } +#endif + // If instanced web app system media controls aren't supported, create the + // single ActiveMediaSessionController that follows the active session. + // It can be unsupported due to feature flag being off or platform + // constraints. + browser_active_media_session_controller_ = + std::make_unique<ActiveMediaSessionController>( + base::UnguessableToken::Null()); } MediaKeysListenerManagerImpl::~MediaKeysListenerManagerImpl() = default; bool MediaKeysListenerManagerImpl::StartWatchingMediaKey( ui::KeyboardCode key_code, - ui::MediaKeysListener::Delegate* delegate) { + ui::MediaKeysListener::Delegate* delegate, + base::UnguessableToken web_app_request_id) { DCHECK(ui::MediaKeysListener::IsMediaKeycode(key_code)); DCHECK(delegate); StartListeningForMediaKeysIfNecessary(); - // We don't want to start watching the key for the - // ActiveMediaSessionController if the ActiveMediaSessionController won't + // We don't want to start watching the key for an + // ActiveMediaSessionController if an ActiveMediaSessionController won't // receive events. - bool is_active_media_session_controller = - delegate == active_media_session_controller_.get(); - bool should_start_watching = !is_active_media_session_controller || - CanActiveMediaSessionControllerReceiveEvents(); + bool is_delegate_for_browser = + delegate == browser_active_media_session_controller_.get(); + bool is_delegate_for_pwa = ShouldUseWebAppSystemMediaControls() && + IsDelegateForWebAppSession(delegate); + + bool is_delegate_an_active_media_session_controller = + is_delegate_for_browser || is_delegate_for_pwa; + bool should_start_watching = + !is_delegate_an_active_media_session_controller || + CanActiveMediaSessionControllerReceiveEvents(); // Tell the underlying MediaKeysListener to listen for the key. if (should_start_watching && media_keys_listener_ && @@ -64,9 +94,24 @@ ListeningData* listening_data = GetOrCreateListeningData(key_code); // If this is the ActiveMediaSessionController, just update the flag. - if (is_active_media_session_controller) { - listening_data->active_media_session_controller_listening = true; + if (is_delegate_an_active_media_session_controller) { + // |delegate| should never be for both the browser and a PWA + DCHECK(is_delegate_for_browser != is_delegate_for_pwa); + + if (is_delegate_for_browser) { + listening_data->browser_active_media_session_controller_listening = true; + } else if (is_delegate_for_pwa) { + // If token is specified, it's a PWA that's starting to watch for a media + // key. As a result, add it to the PWA list. + DCHECK(web_app_request_id != base::UnguessableToken::Null()); + listening_data->listening_web_apps.insert(web_app_request_id); + } UpdateWhichKeysAreListenedFor(); + + // Notify test observers if they exist. + if (test_observer_) { + test_observer_->OnStartWatchingMediaKey(is_delegate_for_pwa); + } return true; } @@ -78,12 +123,18 @@ // longer be needed. UpdateWhichKeysAreListenedFor(); + // Notify test observers if they exist. + if (test_observer_) { + test_observer_->OnStartWatchingMediaKey(is_delegate_for_pwa); + } + return true; } void MediaKeysListenerManagerImpl::StopWatchingMediaKey( ui::KeyboardCode key_code, - ui::MediaKeysListener::Delegate* delegate) { + ui::MediaKeysListener::Delegate* delegate, + base::UnguessableToken web_app_request_id) { DCHECK(ui::MediaKeysListener::IsMediaKeycode(key_code)); DCHECK(delegate); StartListeningForMediaKeysIfNecessary(); @@ -91,11 +142,16 @@ // Find or create the list of listening delegates for this key code. ListeningData* listening_data = GetOrCreateListeningData(key_code); - // Update the listening data to remove this delegate. - if (delegate == active_media_session_controller_.get()) - listening_data->active_media_session_controller_listening = false; - else + if (delegate == browser_active_media_session_controller_.get()) { + // Update the browser's listening data to remove this delegate. + listening_data->browser_active_media_session_controller_listening = false; + } else if (ShouldUseWebAppSystemMediaControls() && + IsDelegateForWebAppSession(delegate)) { + // Remove this pwa_request_id from the listening data. + listening_data->listening_web_apps.erase(web_app_request_id); + } else { listening_data->listeners.RemoveObserver(delegate); + } UpdateWhichKeysAreListenedFor(); } @@ -130,9 +186,10 @@ // If the ActiveMediaSessionController is listening and is allowed to listen, // notify it of the media key press. - if (listening_data->active_media_session_controller_listening && + if (listening_data->browser_active_media_session_controller_listening && CanActiveMediaSessionControllerReceiveEvents()) { - active_media_session_controller_->OnMediaKeysAccelerator(accelerator); + browser_active_media_session_controller_->OnMediaKeysAccelerator( + accelerator); return; } @@ -148,8 +205,7 @@ void MediaKeysListenerManagerImpl::OnNext( system_media_controls::SystemMediaControls* sender) { if (ShouldActiveMediaSessionControllerReceiveKey(ui::VKEY_MEDIA_NEXT_TRACK)) { - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnNext(); + GetControllerForSystemMediaControls(sender)->OnNext(); return; } MaybeSendKeyCode(ui::VKEY_MEDIA_NEXT_TRACK); @@ -158,8 +214,7 @@ void MediaKeysListenerManagerImpl::OnPrevious( system_media_controls::SystemMediaControls* sender) { if (ShouldActiveMediaSessionControllerReceiveKey(ui::VKEY_MEDIA_PREV_TRACK)) { - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnPrevious(); + GetControllerForSystemMediaControls(sender)->OnPrevious(); return; } MaybeSendKeyCode(ui::VKEY_MEDIA_PREV_TRACK); @@ -168,8 +223,7 @@ void MediaKeysListenerManagerImpl::OnPlay( system_media_controls::SystemMediaControls* sender) { if (ShouldActiveMediaSessionControllerReceiveKey(ui::VKEY_MEDIA_PLAY_PAUSE)) { - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnPlay(); + GetControllerForSystemMediaControls(sender)->OnPlay(); return; } if (!is_media_playing_) @@ -179,8 +233,7 @@ void MediaKeysListenerManagerImpl::OnPause( system_media_controls::SystemMediaControls* sender) { if (ShouldActiveMediaSessionControllerReceiveKey(ui::VKEY_MEDIA_PLAY_PAUSE)) { - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnPause(); + GetControllerForSystemMediaControls(sender)->OnPause(); return; } if (is_media_playing_) @@ -190,8 +243,7 @@ void MediaKeysListenerManagerImpl::OnPlayPause( system_media_controls::SystemMediaControls* sender) { if (ShouldActiveMediaSessionControllerReceiveKey(ui::VKEY_MEDIA_PLAY_PAUSE)) { - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnPlayPause(); + GetControllerForSystemMediaControls(sender)->OnPlayPause(); return; } MaybeSendKeyCode(ui::VKEY_MEDIA_PLAY_PAUSE); @@ -200,8 +252,7 @@ void MediaKeysListenerManagerImpl::OnStop( system_media_controls::SystemMediaControls* sender) { if (ShouldActiveMediaSessionControllerReceiveKey(ui::VKEY_MEDIA_STOP)) { - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnStop(); + GetControllerForSystemMediaControls(sender)->OnStop(); return; } MaybeSendKeyCode(ui::VKEY_MEDIA_STOP); @@ -212,8 +263,7 @@ const base::TimeDelta& time) { if (!CanActiveMediaSessionControllerReceiveEvents()) return; - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnSeek(time); + GetControllerForSystemMediaControls(sender)->OnSeek(time); } void MediaKeysListenerManagerImpl::OnSeekTo( @@ -221,8 +271,7 @@ const base::TimeDelta& time) { if (!CanActiveMediaSessionControllerReceiveEvents()) return; - // TODO(liahiscock): Use |sender|'s media controller. - active_media_session_controller_->OnSeekTo(time); + GetControllerForSystemMediaControls(sender)->OnSeekTo(time); } void MediaKeysListenerManagerImpl::MaybeSendKeyCode(ui::KeyboardCode key_code) { @@ -246,33 +295,58 @@ } void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() { - if (system_media_controls_ || media_keys_listener_) + if (browser_system_media_controls_ || media_keys_listener_) { return; + } -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \ BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) - system_media_controls_ = system_media_controls::SystemMediaControls::Create( - media::AudioManager::GetGlobalAppName()); + // Create SystemMediaControls with the SingletonHwnd. + browser_system_media_controls_ = + system_media_controls::SystemMediaControls::Create( + media::AudioManager::GetGlobalAppName()); #endif - if (system_media_controls_) { - system_media_controls_->AddObserver(this); - system_media_controls_notifier_ = + if (browser_system_media_controls_) { + browser_system_media_controls_->AddObserver(this); + // Pass Null request ID so this notifier will track the active session, not + // a specific session. + browser_system_media_controls_notifier_ = std::make_unique<SystemMediaControlsNotifier>( - system_media_controls_.get()); + browser_system_media_controls_.get(), + base::UnguessableToken::Null()); } else { - // If we can't access system media controls, then directly listen for media - // key keypresses instead. media_keys_listener_ = ui::MediaKeysListener::Create( this, ui::MediaKeysListener::Scope::kGlobal); DCHECK(media_keys_listener_); } - EnsureAuxiliaryServices(); } +void MediaKeysListenerManagerImpl::SetBrowserActiveMediaRequestId( + base::UnguessableToken request_id) { + if (!browser_system_media_controls_) { + browser_system_media_controls_ = + system_media_controls::SystemMediaControls::Create( + media::AudioManager::GetGlobalAppName()); + + CHECK(browser_system_media_controls_); + browser_system_media_controls_->AddObserver(this); + } + + // Recreate the notifier and controller so their mojo remotes get rebound + // appropriately. + browser_system_media_controls_notifier_ = + std::make_unique<SystemMediaControlsNotifier>( + browser_system_media_controls_.get(), request_id); + if (!browser_active_media_session_controller_) { + browser_active_media_session_controller_ = + std::make_unique<ActiveMediaSessionController>(request_id); + } else { + browser_active_media_session_controller_->RebindMojoForNewID(request_id); + } +} + MediaKeysListenerManagerImpl::ListeningData* MediaKeysListenerManagerImpl::GetOrCreateListeningData( ui::KeyboardCode key_code) { @@ -289,37 +363,86 @@ void MediaKeysListenerManagerImpl::UpdateWhichKeysAreListenedFor() { StartListeningForMediaKeysIfNecessary(); - if (system_media_controls_) + if (browser_system_media_controls_) { UpdateSystemMediaControlsEnabledControls(); - else + } else { UpdateMediaKeysListener(); + } } void MediaKeysListenerManagerImpl::UpdateSystemMediaControlsEnabledControls() { - DCHECK(system_media_controls_); + // This should be safe to call even if nothing is playing - which should + // result in a no-op. - for (const auto& key_code_listening_data : delegate_map_) { - const ui::KeyboardCode& key_code = key_code_listening_data.first; - const ListeningData* listening_data = key_code_listening_data.second.get(); + if (browser_system_media_controls_) { + // Update the browser box. + for (const auto& key_code_listening_data : delegate_map_) { + const ui::KeyboardCode& key_code = key_code_listening_data.first; + const ListeningData* listening_data = + key_code_listening_data.second.get(); - bool should_enable = ShouldListenToKey(*listening_data); - switch (key_code) { - case ui::VKEY_MEDIA_PLAY_PAUSE: - system_media_controls_->SetIsPlayPauseEnabled(should_enable); - break; - case ui::VKEY_MEDIA_NEXT_TRACK: - system_media_controls_->SetIsNextEnabled(should_enable); - break; - case ui::VKEY_MEDIA_PREV_TRACK: - system_media_controls_->SetIsPreviousEnabled(should_enable); - break; - case ui::VKEY_MEDIA_STOP: - system_media_controls_->SetIsStopEnabled(should_enable); - break; - default: - NOTREACHED(); + bool should_enable = ShouldListenToKey(*listening_data); + switch (key_code) { + case ui::VKEY_MEDIA_PLAY_PAUSE: + browser_system_media_controls_->SetIsPlayPauseEnabled(should_enable); + break; + case ui::VKEY_MEDIA_NEXT_TRACK: + browser_system_media_controls_->SetIsNextEnabled(should_enable); + break; + case ui::VKEY_MEDIA_PREV_TRACK: + browser_system_media_controls_->SetIsPreviousEnabled(should_enable); + break; + case ui::VKEY_MEDIA_STOP: + browser_system_media_controls_->SetIsStopEnabled(should_enable); + break; + default: + NOTREACHED(); + } } } + +#if BUILDFLAG(IS_WIN) + // This loops over active web app instanced system media controls and updates + // what controls are available on each set of controls. + if (!ShouldUseWebAppSystemMediaControls()) { + return; + } + + for (auto* controls : + web_app_system_media_controls_manager_->GetAllControls()) { + system_media_controls::SystemMediaControls* smc = + controls->GetSystemMediaControls(); + base::UnguessableToken request_id = controls->GetRequestID(); + + for (const auto& key_code_listening_data : delegate_map_) { + const ui::KeyboardCode& key_code = key_code_listening_data.first; + const ListeningData* listening_data = + key_code_listening_data.second.get(); + + // If we don't see this token in the listening_pwas, we should not + // enable it. If we do find the token in the listening_pwas, we will + // enable it. + bool should_enable = + listening_data->listening_web_apps.contains(request_id); + switch (key_code) { + case ui::VKEY_MEDIA_PLAY_PAUSE: + smc->SetIsPlayPauseEnabled(should_enable); + break; + case ui::VKEY_MEDIA_NEXT_TRACK: + smc->SetIsNextEnabled(should_enable); + break; + case ui::VKEY_MEDIA_PREV_TRACK: + smc->SetIsPreviousEnabled(should_enable); + break; + case ui::VKEY_MEDIA_STOP: + smc->SetIsStopEnabled(should_enable); + break; + default: + NOTREACHED(); + } + } + } +#endif } void MediaKeysListenerManagerImpl::UpdateMediaKeysListener() { @@ -338,8 +461,9 @@ bool MediaKeysListenerManagerImpl::ShouldListenToKey( const ListeningData& listening_data) const { + // TODO(crbug.com/1502991) verify if this needs a PWA check. return !listening_data.listeners.empty() || - (listening_data.active_media_session_controller_listening && + (listening_data.browser_active_media_session_controller_listening && CanActiveMediaSessionControllerReceiveEvents()); } @@ -370,7 +494,59 @@ DCHECK_NE(nullptr, listening_data); - return listening_data->active_media_session_controller_listening; + return listening_data->browser_active_media_session_controller_listening || + (ShouldUseWebAppSystemMediaControls() && + !listening_data->listening_web_apps.empty()); +} + +bool MediaKeysListenerManagerImpl::ShouldUseWebAppSystemMediaControls() const { +#if BUILDFLAG(IS_WIN) + return base::FeatureList::IsEnabled(features::kWebAppSystemMediaControlsWin); +#else + return false; +#endif +} + +bool MediaKeysListenerManagerImpl::IsDelegateForWebAppSession( + ui::MediaKeysListener::Delegate* delegate) { +#if BUILDFLAG(IS_WIN) + std::vector<WebAppSystemMediaControls*> pwa_controls = + web_app_system_media_controls_manager_->GetAllControls(); + + for (auto* curr_controls : pwa_controls) { + if (curr_controls->GetController() == delegate) { + return true; + } + } +#endif + return false; +} + +ActiveMediaSessionController* +MediaKeysListenerManagerImpl::GetControllerForSystemMediaControls( + system_media_controls::SystemMediaControls* system_media_controls) { + // Check if system_media_controls is browser box. + // If kWebAppSystemMediaControlsWin is not supported, we should always use the + // browser controller. + if (!ShouldUseWebAppSystemMediaControls() || + system_media_controls == browser_system_media_controls_.get()) { + return browser_active_media_session_controller_.get(); + } + +#if BUILDFLAG(IS_WIN) + // Ask the manager for the appropriate ActiveMediaSessionController. + WebAppSystemMediaControls* controls = + web_app_system_media_controls_manager_ + ->GetWebAppSystemMediaControlsForSystemMediaControls( + system_media_controls); + if (controls) { + return controls->GetController(); + } +#endif + + // It's unexpected that any code asks for the controller for a + // system_media_controls object we don't know about. + NOTREACHED_NORETURN(); } } // namespace content
diff --git a/content/browser/media/media_keys_listener_manager_impl.h b/content/browser/media/media_keys_listener_manager_impl.h index f9a803d7..a678fcc 100644 --- a/content/browser/media/media_keys_listener_manager_impl.h +++ b/content/browser/media/media_keys_listener_manager_impl.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_MEDIA_MEDIA_KEYS_LISTENER_MANAGER_IMPL_H_ #include <memory> +#include <set> #include <utility> #include "base/containers/flat_map.h" @@ -24,11 +25,22 @@ class ActiveMediaSessionController; class SystemMediaControlsNotifier; +class WebAppSystemMediaControlsManager; + +class MediaKeysListenerManagerImplTestObserver { + public: + virtual void OnStartWatchingMediaKey(bool is_pwa) {} +}; // Listens for media keys and decides which listeners receive which events. In // particular, it owns one of its delegates (ActiveMediaSessionController), and // only propagates to the ActiveMediaSessionController if no other delegates are // listening to a particular media key. + +// It also owns the WebAppSystemMediaControlsManager which it retrieves +// information from and propagates to if no other delegates are listening to a +// particular media key. See WebAppSystemMediaControlsManager for more +// information on that class' responsibilities. class MediaKeysListenerManagerImpl : public MediaKeysListenerManager, public ui::MediaKeysListener::Delegate, @@ -41,11 +53,14 @@ ~MediaKeysListenerManagerImpl() override; // MediaKeysListenerManager implementation. - bool StartWatchingMediaKey( - ui::KeyboardCode key_code, - ui::MediaKeysListener::Delegate* delegate) override; + bool StartWatchingMediaKey(ui::KeyboardCode key_code, + ui::MediaKeysListener::Delegate* delegate, + base::UnguessableToken web_app_request_id = + base::UnguessableToken::Null()) override; void StopWatchingMediaKey(ui::KeyboardCode key_code, - ui::MediaKeysListener::Delegate* delegate) override; + ui::MediaKeysListener::Delegate* delegate, + base::UnguessableToken web_app_request_id = + base::UnguessableToken::Null()) override; void DisableInternalMediaKeyHandling() override; void EnableInternalMediaKeyHandling() override; @@ -69,13 +84,22 @@ void SetIsMediaPlaying(bool is_playing); ActiveMediaSessionController* active_media_session_controller_for_testing() { - return active_media_session_controller_.get(); + return browser_active_media_session_controller_.get(); } void SetMediaKeysListenerForTesting( std::unique_ptr<ui::MediaKeysListener> media_keys_listener) { media_keys_listener_ = std::move(media_keys_listener); } + // Creates everything for the browser's connection to the system media + // controls. If already created, this method will rebind existing bookkeeping + // to point at the new active media session. This pattern is not ideal, as + // WebAppSystemMediaControlsManager is the class that is receiving + // onFocusGained and realizing it is not related to web apps, and calling us + // back here to create the browser stuff. crbug.com/1502981 covers reworking + // this. + void SetBrowserActiveMediaRequestId(base::UnguessableToken request_id); + private: // ListeningData tracks which delegates are listening to a particular key. We // track the ActiveMediaSessionController separately from the other listeners @@ -89,10 +113,13 @@ ~ListeningData(); // True if the ActiveMediaSessionController is listening for this key. - bool active_media_session_controller_listening = false; + bool browser_active_media_session_controller_listening = false; // Contains non-ActiveMediaSessionController listeners. base::ObserverList<ui::MediaKeysListener::Delegate> listeners; + + // These request IDs represent dPWAs that are listening for this key. + std::set<base::UnguessableToken> listening_web_apps; }; void MaybeSendKeyCode(ui::KeyboardCode key_code); @@ -130,14 +157,36 @@ bool ShouldActiveMediaSessionControllerReceiveKey( ui::KeyboardCode key_code) const; + // Performs a platform and feature flag check and returns true if we should + // use instanced system media controls for dPWAs. + bool ShouldUseWebAppSystemMediaControls() const; + + // Returns true if |delegate| is an ActiveMediaSessionController for a dPWA. + bool IsDelegateForWebAppSession(ui::MediaKeysListener::Delegate* delegate); + + // Gets the ActiveMediaSessionController associated with |smc_sender| + ActiveMediaSessionController* GetControllerForSystemMediaControls( + system_media_controls::SystemMediaControls* system_media_controls); + base::flat_map<ui::KeyboardCode, std::unique_ptr<ListeningData>> delegate_map_; - std::unique_ptr<system_media_controls::SystemMediaControls> - system_media_controls_; std::unique_ptr<ui::MediaKeysListener> media_keys_listener_; + + // TODO(crbug.com/1502981) consider moving these somewhere else. + // Browser's connection to the system media controls. + std::unique_ptr<system_media_controls::SystemMediaControls> + browser_system_media_controls_; std::unique_ptr<ActiveMediaSessionController> - active_media_session_controller_; - std::unique_ptr<SystemMediaControlsNotifier> system_media_controls_notifier_; + browser_active_media_session_controller_; + std::unique_ptr<SystemMediaControlsNotifier> + browser_system_media_controls_notifier_; + +#if BUILDFLAG(IS_WIN) + // Owning reference to web apps' connections to the system media controls. + // See WebAppSystemMediaControlsManager for this classes' responsibilities. + std::unique_ptr<WebAppSystemMediaControlsManager> + web_app_system_media_controls_manager_; +#endif // False if media key handling has been explicitly disabled by a call to // |DisableInternalMediaKeyHandling()|. @@ -148,6 +197,13 @@ bool is_media_playing_ = false; + // Tests that friend this class will use this mechanism to be notified of + // certain events that are otherwise difficult to wait for. + raw_ptr<MediaKeysListenerManagerImplTestObserver> test_observer_ = nullptr; + void SetTestObserver(MediaKeysListenerManagerImplTestObserver* observer) { + test_observer_ = observer; + } + friend class WebAppSystemMediaControlsBrowserTest; };
diff --git a/content/browser/media/system_media_controls_notifier.cc b/content/browser/media/system_media_controls_notifier.cc index 8a73ba42..5e0bc8f 100644 --- a/content/browser/media/system_media_controls_notifier.cc +++ b/content/browser/media/system_media_controls_notifier.cc
@@ -9,6 +9,7 @@ #include "base/functional/bind.h" #include "base/time/time.h" +#include "base/unguessable_token.h" #include "build/build_config.h" #include "components/system_media_controls/system_media_controls.h" #include "content/public/browser/content_browser_client.h" @@ -40,7 +41,8 @@ constexpr base::TimeDelta kDebounceDelay = base::Milliseconds(10); SystemMediaControlsNotifier::SystemMediaControlsNotifier( - system_media_controls::SystemMediaControls* system_media_controls) + system_media_controls::SystemMediaControls* system_media_controls, + base::UnguessableToken request_id) : system_media_controls_(system_media_controls) { DCHECK(system_media_controls_); @@ -51,21 +53,31 @@ base::Unretained(this))); #endif // BUILDFLAG(IS_WIN) - // Connect to the MediaControllerManager and create a MediaController that - // controls the active session so we can observe it. - mojo::Remote<media_session::mojom::MediaControllerManager> controller_manager; + mojo::Remote<media_session::mojom::MediaControllerManager> + controller_manager_remote; GetMediaSessionService().BindMediaControllerManager( - controller_manager.BindNewPipeAndPassReceiver()); - controller_manager->CreateActiveMediaController( - media_controller_.BindNewPipeAndPassReceiver()); + controller_manager_remote.BindNewPipeAndPassReceiver()); + + if (request_id == base::UnguessableToken::Null()) { + // Null ID for all scenarios where kWebAppSystemMediaControlsWin is not + // supported. ie. Mac, Linux, Windows with the feature flag off. + // Create a media controller that follows the active session for this case. + controller_manager_remote->CreateActiveMediaController( + media_controller_remote_.BindNewPipeAndPassReceiver()); + } else { + // Create a media controller tied to |request_id| when + // kWebAppSystemMediaControlsWin is enabled (on Windows OS). + controller_manager_remote->CreateMediaControllerForSession( + media_controller_remote_.BindNewPipeAndPassReceiver(), request_id); + } // Observe the active media controller for changes to playback state and // supported actions. - media_controller_->AddObserver( + media_controller_remote_->AddObserver( media_controller_observer_receiver_.BindNewPipeAndPassRemote()); // Observe the active media controller for changes to provided artwork. - media_controller_->ObserveImages( + media_controller_remote_->ObserveImages( media_session::mojom::MediaSessionImageType::kArtwork, kMinImageSize, kDesiredImageSize, media_controller_image_observer_receiver_.BindNewPipeAndPassRemote());
diff --git a/content/browser/media/system_media_controls_notifier.h b/content/browser/media/system_media_controls_notifier.h index 92d33f2..a09f6bf 100644 --- a/content/browser/media/system_media_controls_notifier.h +++ b/content/browser/media/system_media_controls_notifier.h
@@ -18,6 +18,9 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/media_session/public/mojom/media_controller.mojom.h" +namespace base { +class UnguessableToken; +} namespace content { // The SystemMediaControlsNotifier connects to the SystemMediaControls API and @@ -28,8 +31,9 @@ : public media_session::mojom::MediaControllerObserver, public media_session::mojom::MediaControllerImageObserver { public: - explicit SystemMediaControlsNotifier( - system_media_controls::SystemMediaControls* system_media_controls); + SystemMediaControlsNotifier( + system_media_controls::SystemMediaControls* system_media_controls, + base::UnguessableToken request_id); SystemMediaControlsNotifier(const SystemMediaControlsNotifier&) = delete; SystemMediaControlsNotifier& operator=(const SystemMediaControlsNotifier&) = @@ -100,8 +104,8 @@ base::OneShotTimer hide_smtc_timer_; #endif // BUILDFLAG(IS_WIN) - // Our connection to the System Media Controls. We don't own it since it's a - // global instance. + // Our connection to the System Media Controls instance we should notify. + // Owned by WebAppSystemMediaControls. const raw_ptr<system_media_controls::SystemMediaControls> system_media_controls_; @@ -123,7 +127,7 @@ absl::optional<bool> delayed_is_seek_to_enabled_; // Tracks current media session state/metadata. - mojo::Remote<media_session::mojom::MediaController> media_controller_; + mojo::Remote<media_session::mojom::MediaController> media_controller_remote_; media_session::mojom::MediaSessionInfoPtr session_info_ptr_; // Used to receive updates to the active media controller.
diff --git a/content/browser/media/system_media_controls_notifier_unittest.cc b/content/browser/media/system_media_controls_notifier_unittest.cc index eee6c49b..6643d4a0 100644 --- a/content/browser/media/system_media_controls_notifier_unittest.cc +++ b/content/browser/media/system_media_controls_notifier_unittest.cc
@@ -51,7 +51,7 @@ void SetUp() override { notifier_ = std::make_unique<SystemMediaControlsNotifier>( - &mock_system_media_controls_); + &mock_system_media_controls_, base::UnguessableToken::Null()); SetupMediaSessionClient(); }
diff --git a/content/browser/media/web_app_system_media_controls_browsertest.cc b/content/browser/media/web_app_system_media_controls_browsertest.cc index 98026b5..16bf97f8 100644 --- a/content/browser/media/web_app_system_media_controls_browsertest.cc +++ b/content/browser/media/web_app_system_media_controls_browsertest.cc
@@ -29,7 +29,8 @@ // Currently, this test suite only runs on windows. class WebAppSystemMediaControlsBrowserTest : public ContentBrowserTest, - public system_media_controls::SystemMediaControlsObserver { + public WebAppSystemMediaControlsManagerObserver, + public MediaKeysListenerManagerImplTestObserver { public: WebAppSystemMediaControlsBrowserTest() = default; @@ -46,28 +47,20 @@ net::EmbeddedTestServer::TYPE_HTTPS); https_server_->ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(https_server_->Start()); + + // Also start listening to events from a few different classes. + MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = + BrowserMainLoop::GetInstance()->media_keys_listener_manager(); + media_keys_listener_manager_impl->SetTestObserver(this); + + WebAppSystemMediaControlsManager* web_app_system_media_controls_manager = + media_keys_listener_manager_impl->web_app_system_media_controls_manager_ + .get(); + web_app_system_media_controls_manager->SetObserverForTesting(this); } net::EmbeddedTestServer* https_server() { return https_server_.get(); } - // SystemMediaControlsObserver - void OnServiceReady() override { - if (waiting_for_service_ready_) { - ASSERT_NE(service_ready_run_loop_, nullptr); - waiting_for_service_ready_ = false; - service_ready_run_loop_->Quit(); - } - } - - // After media plays, there can be an arbitrary delay before system media - // controls is ready to receive control requests. This function allows a - // mechanism to wait until the system media controls fires OnServiceReady - // before attempting to continue with the test. - void PrepareWaitForOnServiceReady(base::RunLoop* run_loop) { - waiting_for_service_ready_ = true; - service_ready_run_loop_ = run_loop; - } - void StartPlaybackAndWait(Shell* shell, const std::string& id) { shell->web_contents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests( base::ASCIIToUTF16( @@ -94,10 +87,112 @@ .ExtractBool(); } + WebAppSystemMediaControlsManager* GetWebAppSystemMediaControlsManager() { + MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = + BrowserMainLoop::GetInstance()->media_keys_listener_manager(); + + return media_keys_listener_manager_impl + ->web_app_system_media_controls_manager_.get(); + } + system_media_controls::SystemMediaControls* GetBrowserSystemMediaControls() { MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = BrowserMainLoop::GetInstance()->media_keys_listener_manager(); - return media_keys_listener_manager_impl->system_media_controls_.get(); + return media_keys_listener_manager_impl->browser_system_media_controls_ + .get(); + } + + system_media_controls::SystemMediaControls* GetSystemMediaControlsForWebApp( + base::UnguessableToken request_id) { + WebAppSystemMediaControls* web_app_system_media_controls = + GetWebAppSystemMediaControlsManager()->GetControlsForRequestId( + request_id); + EXPECT_NE(web_app_system_media_controls, nullptr); + + system_media_controls::SystemMediaControls* system_media_controls = + web_app_system_media_controls->GetSystemMediaControls(); + EXPECT_NE(system_media_controls, nullptr); + + return system_media_controls; + } + + // This method asks the WebAppSystemMediaControlsManager to just assume + // requests that come in come from a web app. + void SetAlwaysAssumeWebAppForTesting() { + GetWebAppSystemMediaControlsManager()->always_assume_web_app_for_testing_ = + true; + } + + // This mechanism allows us to wait for the browser to be added to + // WebAppSystemMediaControls bookkeeping. + void OnBrowserAdded() override { + if (waiting_for_browser_added_) { + waiting_for_browser_added_ = false; + CHECK(browser_added_run_loop_); + browser_added_run_loop_->Quit(); + } + } + + void PrepareToWaitForBrowserAdded(base::RunLoop* run_loop) { + browser_added_run_loop_ = run_loop; + waiting_for_browser_added_ = true; + } + + void WaitForBrowserAdded() { + CHECK(browser_added_run_loop_); + browser_added_run_loop_->Run(); + } + + // This mechanism allows us to wait for a web app to be added to the + // WebAppSystemMediaControls bookkeeping. + void OnWebAppAdded(base::UnguessableToken request_id) override { + if (waiting_for_web_app_added_) { + waiting_for_web_app_added_ = false; + CHECK(web_app_added_run_loop_); + web_app_request_id_ = request_id; + web_app_added_run_loop_->Quit(); + } + } + + void PrepareToWaitForWebAppAdded(base::RunLoop* run_loop) { + web_app_added_run_loop_ = run_loop; + waiting_for_web_app_added_ = true; + } + + base::UnguessableToken WaitForWebAppAdded() { + CHECK(web_app_added_run_loop_); + web_app_added_run_loop_->Run(); + CHECK(web_app_request_id_ != base::UnguessableToken::Null()); + base::UnguessableToken cached_token = web_app_request_id_; + web_app_request_id_ = base::UnguessableToken::Null(); + return cached_token; + } + + // This mechanism allows us to wait for MediaKeysListenerImpl to be ready + // to listen to keys. + void OnStartWatchingMediaKey(bool is_pwa) override { + if (!waiting_for_start_watching_media_key_) { + return; + } + waiting_for_start_watching_media_key_ = false; + CHECK(start_watching_media_key_run_loop_); + start_watching_media_key_run_loop_->Quit(); + last_watch_was_for_pwa_ = is_pwa; + } + + void PrepareToWaitForStartWatchingMediaKey(base::RunLoop* run_loop) { + start_watching_media_key_run_loop_ = run_loop; + waiting_for_start_watching_media_key_ = true; + last_watch_was_for_pwa_ = absl::nullopt; + } + + bool WaitForStartWatchingMediaKey() { + CHECK(start_watching_media_key_run_loop_); + start_watching_media_key_run_loop_->Run(); + EXPECT_TRUE( + last_watch_was_for_pwa_); // Check the value got set, optional resolves + // to true if the value got set. + return last_watch_was_for_pwa_.value(); } protected: @@ -111,8 +206,17 @@ } private: - bool waiting_for_service_ready_ = false; - raw_ptr<base::RunLoop> service_ready_run_loop_ = nullptr; + bool waiting_for_web_app_added_ = false; + raw_ptr<base::RunLoop> web_app_added_run_loop_ = nullptr; + base::UnguessableToken web_app_request_id_ = base::UnguessableToken::Null(); + + bool waiting_for_browser_added_ = false; + raw_ptr<base::RunLoop> browser_added_run_loop_ = nullptr; + + bool waiting_for_start_watching_media_key_ = false; + raw_ptr<base::RunLoop> start_watching_media_key_run_loop_ = nullptr; + absl::optional<bool> last_watch_was_for_pwa_; + std::unique_ptr<net::EmbeddedTestServer> https_server_; base::test::ScopedFeatureList feature_list_; }; @@ -123,34 +227,32 @@ EXPECT_TRUE(NavigateToURL(shell(), http_url)); base::RunLoop run_loop; - PrepareWaitForOnServiceReady(&run_loop); + PrepareToWaitForBrowserAdded(&run_loop); + base::RunLoop watcher_run_loop; + PrepareToWaitForStartWatchingMediaKey(&watcher_run_loop); // Run javascript to play the video, and wait for it to begin playing. StartPlaybackAndWait(shell(), "long-video-loop"); // Check video is playing. EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); - // Occasionally, the browser system media controls can not be ready. - // If that happens, just retry a few more times. - int max_retries = 3; - for (int retry = 0; retry < max_retries; retry++) { - if (GetBrowserSystemMediaControls() != nullptr) { - break; - } - - // Check the video continues to play. - EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); - } - - EXPECT_NE(GetBrowserSystemMediaControls(), nullptr); - - GetBrowserSystemMediaControls()->AddObserver(this); - // Wait till the System Media Controls are ready to be used. - run_loop.Run(); + // Wait till the WebAppSystemMediaControlsManager adds the browser. + WaitForBrowserAdded(); // Hit pause via simulating SMTC pause. MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = BrowserMainLoop::GetInstance()->media_keys_listener_manager(); + + // Unfortunately, even though we wait for the browser to be added + // the MediaKeysListenerManager can still not have the browser + // registered properly. We have to wait for MKLM to also add it to it's + // bookkeeping. + bool is_for_pwa = WaitForStartWatchingMediaKey(); + EXPECT_FALSE(is_for_pwa); + + // Check video is still playing. + EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); + media_keys_listener_manager_impl->OnPause(GetBrowserSystemMediaControls()); // Check video is paused. @@ -167,6 +269,11 @@ EXPECT_TRUE(NavigateToURL(browser2, http_url)); EXPECT_TRUE(NavigateToURL(browser3, http_url)); + base::RunLoop run_loop; + PrepareToWaitForBrowserAdded(&run_loop); + base::RunLoop watcher_run_loop; + PrepareToWaitForStartWatchingMediaKey(&watcher_run_loop); + // Press play and wait for each one to start. StartPlaybackAndWait(shell(), "long-video-loop"); StartPlaybackAndWait(browser2, "long-video-loop"); @@ -179,6 +286,13 @@ // Now we have 3 things playing at the same time. // Browser 3 should have control and be shown in SMTC. + // Wait till the WebAppSystemMediaControlsManager adds the browser. + WaitForBrowserAdded(); + + // Also wait until MediaKeysListenerManagerImpl starts listening for keys. + bool is_for_pwa = WaitForStartWatchingMediaKey(); + EXPECT_FALSE(is_for_pwa); + // Hit pause via simulating SMTC pause. MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = BrowserMainLoop::GetInstance()->media_keys_listener_manager(); @@ -192,4 +306,169 @@ EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); } +IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest, + BrowserAndWebAppTest) { + // navigate two shells to the page. + GURL http_url(https_server()->GetURL("/media/session/media-session.html")); + EXPECT_TRUE(NavigateToURL(shell(), http_url)); + + Shell* web_app = CreateBrowser(); + EXPECT_TRUE(NavigateToURL(web_app, http_url)); + + EXPECT_TRUE(NavigateToURL(shell(), http_url)); + EXPECT_TRUE(NavigateToURL(web_app, http_url)); + + // Start two playbacks, but set the testing flag so that the second window + // will register as a web app to WebAppSystemMediaControlsManager. + { + base::RunLoop watcher_run_loop; + PrepareToWaitForStartWatchingMediaKey(&watcher_run_loop); + + StartPlaybackAndWait(shell(), "long-video-loop"); + EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); + + // We need to be careful here that this first play is completely done + // before we set the flag to pretend subsequent plays are from apps. + bool is_for_pwa = WaitForStartWatchingMediaKey(); + EXPECT_FALSE(is_for_pwa); + + EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); + } + + SetAlwaysAssumeWebAppForTesting(); + + base::RunLoop run_loop; + PrepareToWaitForWebAppAdded(&run_loop); + base::RunLoop watcher_run_loop; + PrepareToWaitForStartWatchingMediaKey(&watcher_run_loop); + + StartPlaybackAndWait(web_app, "long-video-loop"); + base::UnguessableToken request_id = WaitForWebAppAdded(); + + EXPECT_TRUE(IsPlaying(web_app, "long-video-loop")); + + EXPECT_NE(request_id, base::UnguessableToken::Null()); + + // Now retrieve the SMC and make a call to pause the + // video. + system_media_controls::SystemMediaControls* system_media_controls = + GetSystemMediaControlsForWebApp(request_id); + + MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = + BrowserMainLoop::GetInstance()->media_keys_listener_manager(); + + // Also wait for MediaKeysListenerManagerImpl to also start watching. + bool is_for_pwa = WaitForStartWatchingMediaKey(); + EXPECT_TRUE(is_for_pwa); + + media_keys_listener_manager_impl->OnPause(system_media_controls); + + // the "web app" should be paused. + WaitForStop(web_app); + + // the browser is still playing. + EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); + + // now start the webapp again. + media_keys_listener_manager_impl->OnPlay(system_media_controls); + WaitForStart(web_app); + + // the browser is still playing. + EXPECT_TRUE(IsPlaying(shell(), "long-video-loop")); +} + +IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest, ThreeWebAppTest) { + // navigate two shells to the page. + GURL http_url(https_server()->GetURL("/media/session/media-session.html")); + // We're mostly going to ignore this shell() based browser. + + Shell* web_app1 = CreateBrowser(); + Shell* web_app2 = CreateBrowser(); + Shell* web_app3 = CreateBrowser(); + EXPECT_TRUE(NavigateToURL(web_app1, http_url)); + EXPECT_TRUE(NavigateToURL(web_app2, http_url)); + EXPECT_TRUE(NavigateToURL(web_app3, http_url)); + + // start all the playbacks. + SetAlwaysAssumeWebAppForTesting(); + + base::UnguessableToken web_app1_request_id; + base::UnguessableToken web_app2_request_id; + base::UnguessableToken web_app3_request_id; + + { + base::RunLoop watcher_run_loop; + PrepareToWaitForStartWatchingMediaKey(&watcher_run_loop); + + base::RunLoop run_loop; + PrepareToWaitForWebAppAdded(&run_loop); + StartPlaybackAndWait(web_app1, "long-video-loop"); + web_app1_request_id = WaitForWebAppAdded(); + + // Also wait until MediaKeysListenerManagerImpl starts listening for keys. + bool is_for_pwa = WaitForStartWatchingMediaKey(); + EXPECT_TRUE(is_for_pwa); + } + + { + base::RunLoop watcher_run_loop; + PrepareToWaitForStartWatchingMediaKey(&watcher_run_loop); + + base::RunLoop run_loop; + PrepareToWaitForWebAppAdded(&run_loop); + StartPlaybackAndWait(web_app2, "long-video-loop"); + web_app2_request_id = WaitForWebAppAdded(); + + // Also wait until MediaKeysListenerManagerImpl starts listening for keys. + bool is_for_pwa = WaitForStartWatchingMediaKey(); + EXPECT_TRUE(is_for_pwa); + } + + { + base::RunLoop watcher_run_loop; + PrepareToWaitForStartWatchingMediaKey(&watcher_run_loop); + + base::RunLoop run_loop; + PrepareToWaitForWebAppAdded(&run_loop); + StartPlaybackAndWait(web_app3, "long-video-loop"); + web_app3_request_id = WaitForWebAppAdded(); + + // Also wait until MediaKeysListenerManagerImpl starts listening for keys. + bool is_for_pwa = WaitForStartWatchingMediaKey(); + EXPECT_TRUE(is_for_pwa); + } + + // all request ids should be valid + EXPECT_NE(web_app1_request_id, base::UnguessableToken::Null()); + EXPECT_NE(web_app2_request_id, base::UnguessableToken::Null()); + EXPECT_NE(web_app3_request_id, base::UnguessableToken::Null()); + + system_media_controls::SystemMediaControls* web_app1_system_media_controls = + GetSystemMediaControlsForWebApp(web_app1_request_id); + system_media_controls::SystemMediaControls* web_app2_system_media_controls = + GetSystemMediaControlsForWebApp(web_app2_request_id); + system_media_controls::SystemMediaControls* web_app3_system_media_controls = + GetSystemMediaControlsForWebApp(web_app3_request_id); + + MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = + BrowserMainLoop::GetInstance()->media_keys_listener_manager(); + + media_keys_listener_manager_impl->OnPause(web_app2_system_media_controls); + WaitForStop(web_app2); + + // The other stuff should be continuing to loop. + EXPECT_TRUE(IsPlaying(web_app1, "long-video-loop")); + EXPECT_TRUE(IsPlaying(web_app3, "long-video-loop")); + + // pause 3, only 1 remains. + media_keys_listener_manager_impl->OnPause(web_app3_system_media_controls); + WaitForStop(web_app3); + + EXPECT_TRUE(IsPlaying(web_app1, "long-video-loop")); + + // pause 1, only 1 remains. + media_keys_listener_manager_impl->OnPause(web_app1_system_media_controls); + WaitForStop(web_app1); +} + } // namespace content
diff --git a/content/browser/media/web_app_system_media_controls_manager.cc b/content/browser/media/web_app_system_media_controls_manager.cc index c2ff23e..e6f5043 100644 --- a/content/browser/media/web_app_system_media_controls_manager.cc +++ b/content/browser/media/web_app_system_media_controls_manager.cc
@@ -108,10 +108,26 @@ return; } - // Check if the web contents found is in a PWA. - if (web_contents->GetDelegate()->ShouldUseInstancedSystemMediaControls()) { - // TODO(stahon): Not yet implemented, but we should consider handling - // initialization of browser system media controls here + // Check if the web contents found is in a dPWA. + bool is_web_contents_for_web_app = + web_contents->GetDelegate()->ShouldUseInstancedSystemMediaControls() || + always_assume_web_app_for_testing_; + if (!is_web_contents_for_web_app) { + // TODO(crbug.com/1502981) this is the only place we have the request_id for + // the browser's controls, but logically doesn't make a ton of sense to do + // browser handling in here. This bug tracks investigating moving it + // somewhere else. + + MediaKeysListenerManagerImpl* media_keys_listener_manager_impl = + BrowserMainLoop::GetInstance()->media_keys_listener_manager(); + DCHECK(media_keys_listener_manager_impl); + media_keys_listener_manager_impl->SetBrowserActiveMediaRequestId( + request_id); + + // notify test observers we added the browser. + if (test_observer_) { + test_observer_->OnBrowserAdded(); + } return; } @@ -126,14 +142,10 @@ if (!existing_controls) { window = GetHWNDFromWebContents(web_contents); - // TODO(stahon): Update SystemMediaControls::Create to take HWND window - // parameter. For now, just check for validity to get around unused - // warning. - CHECK(window != -1); std::unique_ptr<system_media_controls::SystemMediaControls> system_media_controls = system_media_controls::SystemMediaControls::Create( - media::AudioManager::GetGlobalAppName()); + media::AudioManager::GetGlobalAppName(), window); if (!system_media_controls) { DVLOG(1) << "WebAppSystemMediaControlsManager::OnFocusGained, " @@ -147,15 +159,16 @@ BrowserMainLoop::GetInstance()->media_keys_listener_manager()); controls_map_.emplace( - request_id, std::make_unique<WebAppSystemMediaControls>( - request_id, std::move(system_media_controls), - // TODO(stahon) Update SystemMediaControlsNotifier to - // require RequestID parameter - std::make_unique<SystemMediaControlsNotifier>( - system_media_controls.get()), - // TODO(stahon) Update ActiveMediaSessionController to - // require RequestId parameter - std::make_unique<ActiveMediaSessionController>())); + request_id, + std::make_unique<WebAppSystemMediaControls>( + request_id, std::move(system_media_controls), + std::make_unique<SystemMediaControlsNotifier>( + system_media_controls.get(), request_id), + std::make_unique<ActiveMediaSessionController>(request_id))); + + if (test_observer_) { + test_observer_->OnWebAppAdded(request_id); + } } else { // If the requestID already exists in the map, we still need to rebind // the notifier and controller as they have been invalidated. @@ -163,14 +176,10 @@ // which causes onFocusGained to fire but the notifier and controller // cannot be reused afterwards. existing_controls->SetNotifier( - // TODO(stahon) Update SystemMediaControlsNotifier to require - // RequestID parameter std::make_unique<SystemMediaControlsNotifier>( - existing_controls->GetSystemMediaControls())); - // TODO(stahon) Update ActiveMediaSessionController to require - // RequestId parameter + existing_controls->GetSystemMediaControls(), request_id)); existing_controls->SetController( - std::make_unique<ActiveMediaSessionController>()); + std::make_unique<ActiveMediaSessionController>(request_id)); } }
diff --git a/content/browser/media/web_app_system_media_controls_manager.h b/content/browser/media/web_app_system_media_controls_manager.h index fea7d196..abc25ffa 100644 --- a/content/browser/media/web_app_system_media_controls_manager.h +++ b/content/browser/media/web_app_system_media_controls_manager.h
@@ -5,13 +5,12 @@ #ifndef CONTENT_BROWSER_MEDIA_WEB_APP_SYSTEM_MEDIA_CONTROLS_MANAGER_H_ #define CONTENT_BROWSER_MEDIA_WEB_APP_SYSTEM_MEDIA_CONTROLS_MANAGER_H_ +#include "base/unguessable_token.h" #include "content/common/content_export.h" -#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/media_controller.mojom.h" -#include "third_party/blink/public/mojom/mediasession/media_session.mojom.h" namespace system_media_controls { class SystemMediaControls; @@ -21,6 +20,14 @@ class WebAppSystemMediaControls; +// A simple observer interface for tests to be notified when events are +// received by the WebAppSystemmediaControlsManager. +class WebAppSystemMediaControlsManagerObserver { + public: + virtual void OnBrowserAdded() {} + virtual void OnWebAppAdded(base::UnguessableToken request_id) {} +}; + // WebAppSystemMediaControlsManager is a class that handles system media // controls related metadata for use with instanced per dPWA system media // controls. Primarily, it is used by other systems to find associated objects @@ -89,6 +96,13 @@ void TryConnectToAudioFocusManager(); + // This method allows friended tests to register themselves as observers + // to be notified of events happening in this manager. + void SetObserverForTesting( + WebAppSystemMediaControlsManagerObserver* observer) { + test_observer_ = observer; + } + std::map<base::UnguessableToken, std::unique_ptr<WebAppSystemMediaControls>> controls_map_; @@ -101,8 +115,12 @@ bool initialized_ = false; bool skip_mojo_connection_for_testing_ = false; + bool always_assume_web_app_for_testing_ = false; + + raw_ptr<WebAppSystemMediaControlsManagerObserver> test_observer_; friend class WebAppSystemMediaControlsManagerTest; + friend class WebAppSystemMediaControlsBrowserTest; }; } // namespace content
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc index 3ce5219a..d6e699f6 100644 --- a/content/browser/preloading/prerender/prerender_browsertest.cc +++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -50,7 +50,6 @@ #include "content/browser/preloading/prerender/prerender_metrics.h" #include "content/browser/renderer_host/back_forward_cache_impl.h" #include "content/browser/renderer_host/frame_tree_node.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" #include "content/browser/renderer_host/navigation_request.h" #include "content/browser/renderer_host/navigation_type.h" #include "content/browser/renderer_host/render_frame_host_impl.h" @@ -60,6 +59,7 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/content_navigation_policy.h" #include "content/common/features.h" +#include "content/common/input/synthetic_tap_gesture.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/disallow_activation_reason.h"
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc index 4bcd4e5..4a6ef8b 100644 --- a/content/browser/renderer_host/frame_tree_node.cc +++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -825,11 +825,7 @@ break; case blink::mojom::UserActivationUpdateType:: kNotifyActivationPendingBrowserVerification: { - const bool user_activation_verified = VerifyUserActivation(); - // Add UMA metric for when browser user activation verification succeeds - base::UmaHistogramBoolean("Event.BrowserVerifiedUserActivation", - user_activation_verified); - if (user_activation_verified) { + if (VerifyUserActivation()) { update_result = NotifyUserActivation( blink::mojom::UserActivationNotificationType::kInteraction); update_type = blink::mojom::UserActivationUpdateType::kNotifyActivation;
diff --git a/content/browser/renderer_host/input/composited_scrolling_browsertest.cc b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc index 2aefd433..00c3bf11 100644 --- a/content/browser/renderer_host/input/composited_scrolling_browsertest.cc +++ b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
@@ -13,11 +13,11 @@ #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "cc/base/features.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_gesture.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" #include "content/public/browser/render_view_host.h" #include "content/public/common/content_switches.h"
diff --git a/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc b/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc index 65b9ddc..1aca25d 100644 --- a/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc +++ b/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
@@ -11,11 +11,11 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/common/content_switches.h"
diff --git a/content/browser/renderer_host/input/fling_browsertest.cc b/content/browser/renderer_host/input/fling_browsertest.cc index 48178268..1439d7c 100644 --- a/content/browser/renderer_host/input/fling_browsertest.cc +++ b/content/browser/renderer_host/input/fling_browsertest.cc
@@ -10,9 +10,9 @@ #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h"
diff --git a/content/browser/renderer_host/input/input_event_browsertest.cc b/content/browser/renderer_host/input/input_event_browsertest.cc index 3ecc4aff..a2e73e26 100644 --- a/content/browser/renderer_host/input/input_event_browsertest.cc +++ b/content/browser/renderer_host/input/input_event_browsertest.cc
@@ -9,12 +9,12 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_gesture_controller.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_pointer_driver.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/common/content_switches.h"
diff --git a/content/browser/renderer_host/input/input_injector_impl.cc b/content/browser/renderer_host/input/input_injector_impl.cc index 24cac1e..b55b5a7fd 100644 --- a/content/browser/renderer_host/input/input_injector_impl.cc +++ b/content/browser/renderer_host/input/input_injector_impl.cc
@@ -8,15 +8,15 @@ #include <utility> #include "base/functional/bind.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/input/input_injector.mojom.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_pinch_gesture.h" +#include "content/common/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_smooth_drag_gesture.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" +#include "content/common/input/synthetic_tap_gesture.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h"
diff --git a/content/browser/renderer_host/input/input_injector_impl.h b/content/browser/renderer_host/input/input_injector_impl.h index 831e6c27..1457d9c4 100644 --- a/content/browser/renderer_host/input/input_injector_impl.h +++ b/content/browser/renderer_host/input/input_injector_impl.h
@@ -7,8 +7,8 @@ #include <memory> -#include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/common/input/input_injector.mojom.h" +#include "content/common/input/synthetic_gesture.h" #include "mojo/public/cpp/bindings/pending_receiver.h" namespace content {
diff --git a/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc b/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc index ff0f7559..f16b5f8 100644 --- a/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc +++ b/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
@@ -12,11 +12,11 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/common/content_switches.h"
diff --git a/content/browser/renderer_host/input/mouse_latency_browsertest.cc b/content/browser/renderer_host/input/mouse_latency_browsertest.cc index bf9d432..fe7158a 100644 --- a/content/browser/renderer_host/input/mouse_latency_browsertest.cc +++ b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -12,18 +12,18 @@ #include "base/test/test_timeouts.h" #include "base/test/values_test_util.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_smooth_move_gesture.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" #include "content/browser/renderer_host/render_widget_host_factory.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/site_instance_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_controller.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_smooth_move_gesture.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" +#include "content/common/input/synthetic_tap_gesture.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/tracing_controller.h"
diff --git a/content/browser/renderer_host/input/scroll_behavior_browsertest.cc b/content/browser/renderer_host/input/scroll_behavior_browsertest.cc index 900d0af..5869c19f 100644 --- a/content/browser/renderer_host/input/scroll_behavior_browsertest.cc +++ b/content/browser/renderer_host/input/scroll_behavior_browsertest.cc
@@ -11,13 +11,13 @@ #include "build/build_config.h" #include "cc/base/switches.h" #include "cc/input/scroll_utils.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_controller.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" #include "content/public/browser/render_view_host.h" #include "content/public/common/content_switches.h"
diff --git a/content/browser/renderer_host/input/scroll_latency_browsertest.cc b/content/browser/renderer_host/input/scroll_latency_browsertest.cc index a61e8d0..d27f503 100644 --- a/content/browser/renderer_host/input/scroll_latency_browsertest.cc +++ b/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -12,13 +12,13 @@ #include "base/test/test_trace_processor.h" #include "build/build_config.h" #include "cc/base/switches.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_controller.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h"
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_base.h b/content/browser/renderer_host/input/synthetic_gesture_target_base.h index 95ce915..1a1a07d 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_base.h +++ b/content/browser/renderer_host/input/synthetic_gesture_target_base.h
@@ -8,7 +8,7 @@ #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_gesture_target.h" #include "ui/gfx/geometry/point_f.h" namespace ui {
diff --git a/content/browser/renderer_host/input/synthetic_input_browsertest.cc b/content/browser/renderer_host/input/synthetic_input_browsertest.cc index ca383f0..a3afba2 100644 --- a/content/browser/renderer_host/input/synthetic_input_browsertest.cc +++ b/content/browser/renderer_host/input/synthetic_input_browsertest.cc
@@ -14,11 +14,11 @@ #include "build/build_config.h" #include "cc/base/switches.h" #include "cc/input/scroll_utils.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_gesture.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h"
diff --git a/content/browser/renderer_host/input/touch_action_browsertest.cc b/content/browser/renderer_host/input/touch_action_browsertest.cc index 2ef8d4d1..06f9179 100644 --- a/content/browser/renderer_host/input/touch_action_browsertest.cc +++ b/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -19,17 +19,17 @@ #include "base/test/gmock_expected_support.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/input/actions_parser.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_controller.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_pointer_action.h" #include "content/common/input/synthetic_pointer_action_list_params.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h"
diff --git a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc index e4b2395e..40d0e00 100644 --- a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc +++ b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
@@ -6,10 +6,10 @@ #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/features.h" #include "content/common/input/synthetic_pinch_gesture_params.h" +#include "content/common/input/synthetic_touchpad_pinch_gesture.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h"
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 9b22d20..40a4ef40 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -11807,8 +11807,7 @@ mojo::MakeSelfOwnedReceiver( std::make_unique<DedicatedWorkerHostFactoryImpl>( worker_process_id, - /*creator_render_frame_host_id=*/GetGlobalId(), - /*creator_worker_token=*/absl::nullopt, + /*creator=*/GetGlobalId(), /*ancestor_render_frame_host_id=*/GetGlobalId(), GetStorageKey(), isolation_info_, BuildClientSecurityState(), /*creator_coep_reporter=*/coep_reporter,
diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc index 827871e..cb2ae90 100644 --- a/content/browser/renderer_host/render_widget_host_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -16,7 +16,6 @@ #include "build/build_config.h" #include "content/browser/permissions/permission_controller_impl.h" #include "content/browser/renderer_host/input/input_router_impl.h" -#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h" #include "content/browser/renderer_host/input/touch_action_filter.h" #include "content/browser/renderer_host/input/touch_emulator.h" #include "content/browser/renderer_host/render_widget_host_impl.h" @@ -24,6 +23,7 @@ #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/content_navigation_policy.h" +#include "content/common/input/synthetic_smooth_drag_gesture.h" #include "content/public/browser/render_widget_host_observer.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h"
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index cb56f1b..df4f6055 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -64,9 +64,6 @@ #include "content/browser/renderer_host/input/fling_scheduler.h" #include "content/browser/renderer_host/input/input_router_config_helper.h" #include "content/browser/renderer_host/input/input_router_impl.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/input/timeout_monitor.h" #include "content/browser/renderer_host/input/touch_emulator.h" #include "content/browser/renderer_host/render_process_host_impl.h" @@ -84,6 +81,9 @@ #include "content/browser/storage_partition_impl.h" #include "content/common/content_constants_internal.h" #include "content/common/frame.mojom.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_controller.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/device_service.h" @@ -1864,7 +1864,8 @@ if (!synthetic_gesture_controller_ && view_) { synthetic_gesture_controller_ = std::make_unique<SyntheticGestureController>( - this, view_->CreateSyntheticGestureTarget()); + this, view_->CreateSyntheticGestureTarget(), + content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput})); } }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 561bd92..28f8113 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -36,8 +36,6 @@ #include "content/browser/renderer_host/input/input_disposition_handler.h" #include "content/browser/renderer_host/input/input_router_impl.h" #include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" #include "content/browser/renderer_host/input/touch_emulator_client.h" #include "content/browser/renderer_host/render_frame_metadata_provider_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" @@ -46,6 +44,8 @@ #include "content/common/content_export.h" #include "content/common/frame.mojom-forward.h" #include "content/common/input/event_with_latency_info.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_controller.h" #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/render_process_host_priority_client.h" #include "content/public/browser/render_widget_host.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index f45a6ac..0d00264 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -297,6 +297,9 @@ void set_selection_popup_controller(SelectionPopupController* controller) { selection_popup_controller_ = controller; } + SelectionPopupController* selection_popup_controller() const { + return selection_popup_controller_.get(); + } void set_text_suggestion_host( TextSuggestionHostAndroid* text_suggestion_host) { text_suggestion_host_ = text_suggestion_host;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index f5f30d5..2b5c0cb 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -22,7 +22,6 @@ #include "content/browser/gpu/compositor_util.h" #include "content/browser/renderer_host/cross_process_frame_connector.h" #include "content/browser/renderer_host/cursor_manager.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" @@ -30,6 +29,7 @@ #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/renderer_host/render_widget_host_view_event_handler.h" #include "content/browser/renderer_host/text_input_manager.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/public/browser/render_process_host.h" #include "third_party/blink/public/common/frame/frame_visual_properties.h" #include "third_party/blink/public/common/input/web_touch_event.h"
diff --git a/content/browser/service_worker/service_worker_usb_delegate_observer.cc b/content/browser/service_worker/service_worker_usb_delegate_observer.cc index 1b318a3..d1506f5 100644 --- a/content/browser/service_worker/service_worker_usb_delegate_observer.cc +++ b/content/browser/service_worker/service_worker_usb_delegate_observer.cc
@@ -26,6 +26,7 @@ const blink::StorageKey& key, const device::mojom::UsbDeviceInfo& device_info) { return delegate && delegate->HasDevicePermission(browser_context, + /*frame=*/nullptr, key.origin(), device_info); }
diff --git a/content/browser/service_worker/service_worker_usb_delegate_observer.h b/content/browser/service_worker/service_worker_usb_delegate_observer.h index 53fdb43..d108c048 100644 --- a/content/browser/service_worker/service_worker_usb_delegate_observer.h +++ b/content/browser/service_worker/service_worker_usb_delegate_observer.h
@@ -24,7 +24,7 @@ // ServiceWorkerUsbDelegateObserver's UsbDelegate::Observer methods will be // invoked and deliver the device events to the service worker that has a device // event handler registered. -// For more information, please see go/usb-usb-extension-access. +// For more information, please see go/usb-hid-extension-access. class CONTENT_EXPORT ServiceWorkerUsbDelegateObserver : public ServiceWorkerDeviceDelegateObserver, public UsbDelegate::Observer {
diff --git a/content/browser/service_worker/service_worker_usb_delegate_observer_unittest.cc b/content/browser/service_worker/service_worker_usb_delegate_observer_unittest.cc index ea41ac4a..07078310 100644 --- a/content/browser/service_worker/service_worker_usb_delegate_observer_unittest.cc +++ b/content/browser/service_worker/service_worker_usb_delegate_observer_unittest.cc
@@ -486,7 +486,7 @@ EXPECT_CALL(usb_delegate(), GetDeviceInfo) .WillOnce(Return(device_info.get())); EXPECT_CALL(usb_delegate(), - HasDevicePermission(_, origin, Ref(*device_info))) + HasDevicePermission(_, nullptr, origin, Ref(*device_info))) .WillOnce(Return(false)); EXPECT_CALL(mock_device, Close) .WillOnce(RunClosure(run_loop.QuitClosure()));
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index bc92b60ee..a4e444a 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -59,11 +59,6 @@ #include "content/browser/renderer_host/frame_navigation_entry.h" #include "content/browser/renderer_host/frame_tree.h" #include "content/browser/renderer_host/input/input_router.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" -#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h" #include "content/browser/renderer_host/navigation_controller_impl.h" #include "content/browser/renderer_host/navigation_entry_impl.h" #include "content/browser/renderer_host/navigation_entry_restore_context_impl.h" @@ -82,7 +77,12 @@ #include "content/common/content_navigation_policy.h" #include "content/common/frame.mojom-test-utils.h" #include "content/common/input/actions_parser.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/common/input/synthetic_pinch_gesture_params.h" +#include "content/common/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_tap_gesture.h" +#include "content/common/input/synthetic_touchscreen_pinch_gesture.h" #include "content/common/renderer.mojom.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -10192,11 +10192,14 @@ // Finally, navigate the grandchild frame to a new origin, creating a new site // instance. Again, the new document should be sandboxed, as it should get its // flags from its (remote) parent in B. + RenderFrameDeletedObserver deleted_observer_grandchild( + root->child_at(0)->child_at(0)->current_frame_host()); EXPECT_TRUE(NavigateToURLFromRenderer( root->child_at(0)->child_at(0), embedded_test_server()->GetURL("baz.com", "/title1.html"))); if (sandboxed_iframes_are_isolated) { + deleted_observer_grandchild.WaitUntilDeleted(); switch (blink::features::kIsolateSandboxedIframesGroupingParam.Get()) { case blink::features::IsolateSandboxedIframesGrouping::kPerSite: case blink::features::IsolateSandboxedIframesGrouping::kPerOrigin:
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 4137707..617c5e35 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -23,14 +23,14 @@ #include "components/viz/test/host_frame_sink_manager_test_api.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/renderer_host/cursor_manager.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" -#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" #include "content/browser/renderer_host/input/touch_emulator.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" #include "content/browser/site_per_process_browsertest.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" +#include "content/common/input/synthetic_tap_gesture.h" +#include "content/common/input/synthetic_touchpad_pinch_gesture.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/context_menu_params.h"
diff --git a/content/browser/site_per_process_layout_browsertest.cc b/content/browser/site_per_process_layout_browsertest.cc index 9f5ccba..e60bc1e8 100644 --- a/content/browser/site_per_process_layout_browsertest.cc +++ b/content/browser/site_per_process_layout_browsertest.cc
@@ -11,11 +11,11 @@ #include "build/chromeos_buildflags.h" #include "cc/base/math_util.h" #include "content/browser/renderer_host/cross_process_frame_connector.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" #include "content/common/input/actions_parser.h" +#include "content/common/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_touchscreen_pinch_gesture.h" #include "content/public/browser/render_process_host_priority_client.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" @@ -33,7 +33,7 @@ #endif #if BUILDFLAG(IS_MAC) -#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" +#include "content/common/input/synthetic_touchpad_pinch_gesture.h" #include "ui/base/test/scoped_preferred_scroller_style_mac.h" #endif
diff --git a/content/browser/site_per_process_scroll_browsertest.cc b/content/browser/site_per_process_scroll_browsertest.cc index 584faab..ca7b129c 100644 --- a/content/browser/site_per_process_scroll_browsertest.cc +++ b/content/browser/site_per_process_scroll_browsertest.cc
@@ -10,8 +10,8 @@ #include "build/build_config.h" #include "content/browser/renderer_host/cross_process_frame_connector.h" #include "content/browser/renderer_host/frame_tree.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/render_frame_proxy_host.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h"
diff --git a/content/browser/usb/usb_test_utils.h b/content/browser/usb/usb_test_utils.h index d7d4f10..41cdb64 100644 --- a/content/browser/usb/usb_test_utils.h +++ b/content/browser/usb/usb_test_utils.h
@@ -108,8 +108,9 @@ MOCK_METHOD2(GetDeviceInfo, const device::mojom::UsbDeviceInfo*(BrowserContext*, const std::string& guid)); - MOCK_METHOD3(HasDevicePermission, + MOCK_METHOD4(HasDevicePermission, bool(BrowserContext*, + RenderFrameHost*, const url::Origin&, const device::mojom::UsbDeviceInfo&)); MOCK_METHOD2(GetDevices,
diff --git a/content/browser/usb/web_usb_service_impl.cc b/content/browser/usb/web_usb_service_impl.cc index a15447ba..7d11c1ea 100644 --- a/content/browser/usb/web_usb_service_impl.cc +++ b/content/browser/usb/web_usb_service_impl.cc
@@ -18,11 +18,13 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/document_service.h" +#include "content/public/browser/isolated_context_util.h" #include "content/public/common/content_client.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "services/device/public/mojom/usb_device.mojom.h" #include "services/device/public/mojom/usb_enumeration_options.mojom.h" #include "services/device/public/mojom/usb_manager_client.mojom.h" +#include "third_party/blink/public/common/features_generated.h" namespace content { @@ -251,6 +253,28 @@ render_frame_host_, classes); } + // Isolated contexts with permission to access the policy-controlled feature + // "usb-unrestricted" can claim USB interfaces with classes that are + // normally blocked. Currently the feature is gated by + // `kUnrestrictedUsb`. If the feature is disabled, Isolated Apps + // directly have unrestricted access to any USB interface class. + bool is_usb_unrestricted = false; + if (base::FeatureList::IsEnabled(blink::features::kUnrestrictedUsb)) { + is_usb_unrestricted = + render_frame_host_ && + render_frame_host_->IsFeatureEnabled( + blink::mojom::PermissionsPolicyFeature::kUsbUnrestricted) && + HasIsolatedContextCapability(render_frame_host_); + } else { + is_usb_unrestricted = + render_frame_host_ && + render_frame_host_->GetWebExposedIsolationLevel() >= + content::WebExposedIsolationLevel::kMaybeIsolatedApplication; + } + if (is_usb_unrestricted) { + classes.clear(); + } + return classes; } @@ -275,8 +299,8 @@ std::vector<device::mojom::UsbDeviceInfoPtr> device_infos; for (auto& device_info : device_info_list) { - if (delegate->HasDevicePermission(GetBrowserContext(), origin_, - *device_info)) { + if (delegate->HasDevicePermission(GetBrowserContext(), render_frame_host_, + origin_, *device_info)) { device_infos.push_back(device_info.Clone()); } } @@ -294,7 +318,8 @@ auto* browser_context = GetBrowserContext(); auto* device_info = delegate->GetDeviceInfo(browser_context, guid); if (!device_info || - !delegate->HasDevicePermission(browser_context, origin_, *device_info)) { + !delegate->HasDevicePermission(browser_context, render_frame_host_, + origin_, *device_info)) { return; } @@ -331,7 +356,8 @@ auto* browser_context = GetBrowserContext(); auto* device_info = delegate->GetDeviceInfo(browser_context, guid); if (device_info && - delegate->HasDevicePermission(browser_context, origin_, *device_info)) { + delegate->HasDevicePermission(browser_context, render_frame_host_, + origin_, *device_info)) { delegate->RevokeDevicePermissionWebInitiated(browser_context, origin_, *device_info); } @@ -380,15 +406,15 @@ if (!device_info) return true; - return !delegate->HasDevicePermission(browser_context, origin_, - *device_info); + return !delegate->HasDevicePermission(browser_context, render_frame_host_, + origin_, *device_info); }); } void WebUsbServiceImpl::OnDeviceAdded( const device::mojom::UsbDeviceInfo& device_info) { if (!GetContentClient()->browser()->GetUsbDelegate()->HasDevicePermission( - GetBrowserContext(), origin_, device_info)) { + GetBrowserContext(), render_frame_host_, origin_, device_info)) { return; } for (auto& client : clients_) @@ -402,7 +428,7 @@ }); if (!GetContentClient()->browser()->GetUsbDelegate()->HasDevicePermission( - GetBrowserContext(), origin_, device_info)) { + GetBrowserContext(), render_frame_host_, origin_, device_info)) { return; } for (auto& client : clients_)
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc index c51f59fd..b91e5d5 100644 --- a/content/browser/web_contents/web_contents_view_android.cc +++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -336,6 +336,15 @@ return select_popup_.get(); } +SelectionPopupController* +WebContentsViewAndroid::GetSelectionPopupController() { + SelectionPopupController* controller = nullptr; + if (auto* rwhva = GetRenderWidgetHostViewAndroid()) { + controller = rwhva->selection_popup_controller(); + } + return controller; +} + void WebContentsViewAndroid::ShowPopupMenu( RenderFrameHost* render_frame_host, mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client, @@ -398,8 +407,8 @@ return; } - if (selection_popup_controller_) { - selection_popup_controller_->HidePopupsAndPreserveSelection(); + if (auto* selection_popup_controller = GetSelectionPopupController()) { + selection_popup_controller->HidePopupsAndPreserveSelection(); // Hide the handles temporarily. auto* rwhva = GetRenderWidgetHostViewAndroid(); if (rwhva) @@ -527,8 +536,8 @@ web_contents_->GetRenderViewHost()->GetWidget()->DragSourceSystemDragEnded(); // Restore the selection popups and the text handles if necessary. - if (selection_popup_controller_) { - selection_popup_controller_->RestoreSelectionPopupsIfNecessary(); + if (auto* selection_popup_controller = GetSelectionPopupController()) { + selection_popup_controller->RestoreSelectionPopupsIfNecessary(); auto* rwhva = GetRenderWidgetHostViewAndroid(); if (rwhva) rwhva->SetTextHandlesTemporarilyHidden(false);
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h index e2d9cb4..9baeadc 100644 --- a/content/browser/web_contents/web_contents_view_android.h +++ b/content/browser/web_contents/web_contents_view_android.h
@@ -47,10 +47,6 @@ synchronous_compositor_client_ = client; } - void set_selection_popup_controller(SelectionPopupController* controller) { - selection_popup_controller_ = controller; - } - SynchronousCompositorClient* synchronous_compositor_client() const { return synchronous_compositor_client_; } @@ -159,6 +155,10 @@ SelectPopup* GetSelectPopup(); + // Returns the current `SelectionPopupController` from the current + // `RenderWidgetHostViewAndroid`. + SelectionPopupController* GetSelectionPopupController(); + // The WebContents whose contents we display. raw_ptr<WebContentsImpl> web_contents_; @@ -196,9 +196,6 @@ // Interface used to get notified of events from the synchronous compositor. raw_ptr<SynchronousCompositorClient> synchronous_compositor_client_; - raw_ptr<SelectionPopupController, AcrossTasksDanglingUntriaged> - selection_popup_controller_ = nullptr; - int device_orientation_ = 0; // Show/hide popup UI for <select> tag.
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index acc69ed4..08f1e69 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -10,6 +10,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/functional/overloaded.h" #include "build/build_config.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/broadcast_channel/broadcast_channel_provider.h" @@ -67,8 +68,7 @@ DedicatedWorkerServiceImpl* service, const blink::DedicatedWorkerToken& token, RenderProcessHost* worker_process_host, - absl::optional<GlobalRenderFrameHostId> creator_render_frame_host_id, - absl::optional<blink::DedicatedWorkerToken> creator_worker_token, + DedicatedWorkerCreator creator, GlobalRenderFrameHostId ancestor_render_frame_host_id, const blink::StorageKey& creator_storage_key, const net::IsolationInfo& isolation_info, @@ -79,8 +79,7 @@ : service_(service), token_(token), worker_process_host_(worker_process_host), - creator_render_frame_host_id_(creator_render_frame_host_id), - creator_worker_token_(creator_worker_token), + creator_(creator), ancestor_render_frame_host_id_(ancestor_render_frame_host_id), creator_origin_(creator_storage_key.origin()), // TODO(https://crbug.com/1058759): Calculate the worker origin based on @@ -99,8 +98,6 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(worker_process_host_); DCHECK(worker_process_host_->IsInitializedAndNotDead()); - DCHECK_NE(creator_render_frame_host_id_.has_value(), - creator_worker_token_.has_value()); DCHECK(creator_client_security_state_); // TODO(https://crbug.com/11990077): Once we add more stuff to @@ -152,7 +149,7 @@ ->GetNetworkContext() ->SendReportsAndRemoveSource(reporting_source_); - service_->NotifyBeforeWorkerDestroyed(token_, ancestor_render_frame_host_id_); + service_->NotifyBeforeWorkerDestroyed(token_, creator_); if (base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)) { WorkerDevToolsManager::GetInstance().WorkerDestroyed(this); @@ -253,26 +250,22 @@ RenderFrameHostImpl* creator_render_frame_host = nullptr; DedicatedWorkerHost* creator_worker = nullptr; - if (creator_render_frame_host_id_) { - // This is not a nested worker, it has a creator frame. - creator_render_frame_host = - RenderFrameHostImpl::FromID(*creator_render_frame_host_id_); - if (!creator_render_frame_host) { - ScriptLoadStartFailed( - script_url, network::URLLoaderCompletionStatus(net::ERR_ABORTED)); - return; - } - } else { - // The creator of this worker is a dedicated worker. - DCHECK(creator_worker_token_); - creator_worker = - service_->GetDedicatedWorkerHostFromToken(*creator_worker_token_); - if (!creator_worker) { - ScriptLoadStartFailed( - script_url, network::URLLoaderCompletionStatus(net::ERR_ABORTED)); - return; - } + absl::visit(base::Overloaded( + [&](const GlobalRenderFrameHostId& render_frame_host_id) { + creator_render_frame_host = + RenderFrameHostImpl::FromID(render_frame_host_id); + }, + [&](blink::DedicatedWorkerToken dedicated_worker_token) { + creator_worker = service_->GetDedicatedWorkerHostFromToken( + dedicated_worker_token); + }), + creator_); + + if (!creator_render_frame_host && !creator_worker) { + ScriptLoadStartFailed(script_url, + network::URLLoaderCompletionStatus(net::ERR_ABORTED)); + return; } // At this point there is either a creator frame or a creator worker. @@ -728,10 +721,8 @@ mojo::MakeSelfOwnedReceiver( std::make_unique<DedicatedWorkerHostFactoryImpl>( - worker_process_host_->GetID(), - /*creator_render_frame_host_id_=*/absl::nullopt, - /*creator_worker_token=*/token_, ancestor_render_frame_host_id_, - GetStorageKey(), isolation_info_, + worker_process_host_->GetID(), /*creator=*/token_, + ancestor_render_frame_host_id_, GetStorageKey(), isolation_info_, worker_client_security_state_->Clone(), creator_coep_reporter, ancestor_coep_reporter_), std::move(receiver)); @@ -869,10 +860,11 @@ // If this is a nested worker, there is no creator frame and // |creator_render_frame_host| will be null. + const content::GlobalRenderFrameHostId* const render_frame_host_id = + absl::get_if<content::GlobalRenderFrameHostId>(&creator_); RenderFrameHostImpl* creator_render_frame_host = - creator_render_frame_host_id_ - ? RenderFrameHostImpl::FromID(creator_render_frame_host_id_.value()) - : nullptr; + render_frame_host_id ? RenderFrameHostImpl::FromID(*render_frame_host_id) + : nullptr; // Recreate the default URLLoaderFactory. std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h index d87ab1f..895a771d 100644 --- a/content/browser/worker_host/dedicated_worker_host.h +++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -13,6 +13,7 @@ #include "content/browser/browser_interface_broker_impl.h" #include "content/browser/buckets/bucket_context.h" #include "content/browser/renderer_host/code_cache_host_impl.h" +#include "content/public/browser/dedicated_worker_creator.h" #include "content/public/browser/global_routing_id.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_observer.h" @@ -92,8 +93,7 @@ DedicatedWorkerServiceImpl* service, const blink::DedicatedWorkerToken& token, RenderProcessHost* worker_process_host, - absl::optional<GlobalRenderFrameHostId> creator_render_frame_host_id, - absl::optional<blink::DedicatedWorkerToken> creator_worker_token, + DedicatedWorkerCreator creator, GlobalRenderFrameHostId ancestor_render_frame_host_id, const blink::StorageKey& creator_storage_key, const net::IsolationInfo& isolation_info, @@ -116,6 +116,7 @@ const GlobalRenderFrameHostId& GetAncestorRenderFrameHostId() const { return ancestor_render_frame_host_id_; } + DedicatedWorkerCreator GetCreator() const { return creator_; } const absl::optional<GURL>& GetFinalResponseURL() const { return final_response_url_; } @@ -326,13 +327,10 @@ base::ScopedObservation<RenderProcessHost, RenderProcessHostObserver> scoped_process_host_observation_{this}; - // The ID of the frame that directly starts this worker. This is absl::nullopt - // when this worker is nested. - const absl::optional<GlobalRenderFrameHostId> creator_render_frame_host_id_; - - // The token of the dedicated worker that directly starts this worker. This is - // absl::nullopt when this worker is created from a frame. - const absl::optional<blink::DedicatedWorkerToken> creator_worker_token_; + // The creator of this worker. Holds a GlobalRenderFrameHostId if this worker + // was created by a frame, or holds a blink::DedicatedWorkerToken if this + // worker is nested. + const DedicatedWorkerCreator creator_; // The ID of the frame that owns this worker, either directly, or (in the case // of nested workers) indirectly via a tree of dedicated workers.
diff --git a/content/browser/worker_host/dedicated_worker_host_factory_impl.cc b/content/browser/worker_host/dedicated_worker_host_factory_impl.cc index 38ae46d..0e3928f1 100644 --- a/content/browser/worker_host/dedicated_worker_host_factory_impl.cc +++ b/content/browser/worker_host/dedicated_worker_host_factory_impl.cc
@@ -41,8 +41,7 @@ DedicatedWorkerHostFactoryImpl::DedicatedWorkerHostFactoryImpl( int worker_process_id, - absl::optional<GlobalRenderFrameHostId> creator_render_frame_host_id, - absl::optional<blink::DedicatedWorkerToken> creator_worker_token, + DedicatedWorkerCreator creator, GlobalRenderFrameHostId ancestor_render_frame_host_id, const blink::StorageKey& creator_storage_key, const net::IsolationInfo& isolation_info, @@ -50,8 +49,7 @@ base::WeakPtr<CrossOriginEmbedderPolicyReporter> creator_coep_reporter, base::WeakPtr<CrossOriginEmbedderPolicyReporter> ancestor_coep_reporter) : worker_process_id_(worker_process_id), - creator_render_frame_host_id_(creator_render_frame_host_id), - creator_worker_token_(creator_worker_token), + creator_(creator), ancestor_render_frame_host_id_(ancestor_render_frame_host_id), creator_storage_key_(creator_storage_key), isolation_info_(isolation_info), @@ -59,8 +57,6 @@ creator_coep_reporter_(std::move(creator_coep_reporter)), ancestor_coep_reporter_(std::move(ancestor_coep_reporter)) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK_NE(creator_render_frame_host_id_.has_value(), - creator_worker_token_.has_value()); DCHECK(creator_client_security_state_); } @@ -111,9 +107,8 @@ creator_client_security_state_->cross_origin_embedder_policy; auto* host = new DedicatedWorkerHost( - service, token, worker_process_host, creator_render_frame_host_id_, - creator_worker_token_, ancestor_render_frame_host_id_, - creator_storage_key_, isolation_info_, + service, token, worker_process_host, creator_, + ancestor_render_frame_host_id_, creator_storage_key_, isolation_info_, std::move(creator_client_security_state_), std::move(creator_coep_reporter_), std::move(ancestor_coep_reporter_), std::move(host_receiver)); @@ -158,9 +153,8 @@ mojo::PendingRemote<blink::mojom::DedicatedWorkerHost> pending_remote_host; auto* host = new DedicatedWorkerHost( - service, token, worker_process_host, creator_render_frame_host_id_, - creator_worker_token_, ancestor_render_frame_host_id_, - creator_storage_key_, isolation_info_, + service, token, worker_process_host, creator_, + ancestor_render_frame_host_id_, creator_storage_key_, isolation_info_, std::move(creator_client_security_state_), std::move(creator_coep_reporter_), std::move(ancestor_coep_reporter_), pending_remote_host.InitWithNewPipeAndPassReceiver());
diff --git a/content/browser/worker_host/dedicated_worker_host_factory_impl.h b/content/browser/worker_host/dedicated_worker_host_factory_impl.h index ff5ab666..ab482a4 100644 --- a/content/browser/worker_host/dedicated_worker_host_factory_impl.h +++ b/content/browser/worker_host/dedicated_worker_host_factory_impl.h
@@ -7,6 +7,7 @@ #include "content/browser/network/cross_origin_embedder_policy_reporter.h" #include "content/common/content_export.h" +#include "content/public/browser/dedicated_worker_creator.h" #include "content/public/browser/global_routing_id.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -31,14 +32,11 @@ const network::CrossOriginEmbedderPolicy&, mojo::PendingRemote<blink::mojom::BackForwardCacheControllerHost>)>; - // Exactly one of `creator_render_frame_host_id` and `creator_worker_token` - // must be specified. // `creator_client_security_state` specifies the client security state of // the creator frame or worker. Must not be nullptr. DedicatedWorkerHostFactoryImpl( int worker_process_id, - absl::optional<GlobalRenderFrameHostId> creator_render_frame_host_id, - absl::optional<blink::DedicatedWorkerToken> creator_worker_token, + DedicatedWorkerCreator creator, GlobalRenderFrameHostId ancestor_render_frame_host_id, const blink::StorageKey& creator_storage_key, const net::IsolationInfo& isolation_info, @@ -78,8 +76,7 @@ const int worker_process_id_; // See comments on the corresponding members of DedicatedWorkerHost. - const absl::optional<GlobalRenderFrameHostId> creator_render_frame_host_id_; - const absl::optional<blink::DedicatedWorkerToken> creator_worker_token_; + const DedicatedWorkerCreator creator_; const GlobalRenderFrameHostId ancestor_render_frame_host_id_; // Storage key is used for storage partitioning, and for retrieving the
diff --git a/content/browser/worker_host/dedicated_worker_service_impl.cc b/content/browser/worker_host/dedicated_worker_service_impl.cc index 80bf7cd6..c9ac2bc 100644 --- a/content/browser/worker_host/dedicated_worker_service_impl.cc +++ b/content/browser/worker_host/dedicated_worker_service_impl.cc
@@ -29,7 +29,7 @@ observer->OnWorkerCreated(dedicated_worker_token, host->GetProcessHost()->GetID(), - host->GetAncestorRenderFrameHostId()); + host->GetCreator()); auto& maybe_url = host->GetFinalResponseURL(); if (maybe_url) { observer->OnFinalResponseURLDetermined(dedicated_worker_token, @@ -46,19 +46,18 @@ for (Observer& observer : observers_) { observer.OnWorkerCreated(host->GetToken(), host->GetProcessHost()->GetID(), - host->GetAncestorRenderFrameHostId()); + host->GetCreator()); } } void DedicatedWorkerServiceImpl::NotifyBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& dedicated_worker_token, - GlobalRenderFrameHostId ancestor_render_frame_host_id) { + DedicatedWorkerCreator creator) { size_t removed = dedicated_worker_hosts_.erase(dedicated_worker_token); DCHECK_EQ(1u, removed); for (Observer& observer : observers_) { - observer.OnBeforeWorkerDestroyed(dedicated_worker_token, - ancestor_render_frame_host_id); + observer.OnBeforeWorkerDestroyed(dedicated_worker_token, creator); } }
diff --git a/content/browser/worker_host/dedicated_worker_service_impl.h b/content/browser/worker_host/dedicated_worker_service_impl.h index 84116c3..b38bb56d 100644 --- a/content/browser/worker_host/dedicated_worker_service_impl.h +++ b/content/browser/worker_host/dedicated_worker_service_impl.h
@@ -34,7 +34,7 @@ // Notifies all observers about a worker being destroyed. void NotifyBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& worker_token, - GlobalRenderFrameHostId ancestor_render_frame_host_id); + DedicatedWorkerCreator creator); // Notifies all observers that a worker's final response URL was determined. void NotifyWorkerFinalResponseURLDetermined(
diff --git a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc index 89d18c56..af262d1 100644 --- a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc +++ b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
@@ -51,9 +51,9 @@ mojo::MakeSelfOwnedReceiver( std::make_unique<DedicatedWorkerHostFactoryImpl>( - worker_process_id, render_frame_host_id, - /*creator_worker_token=*/absl::nullopt, render_frame_host_id, - blink::StorageKey(), net::IsolationInfo::CreateTransient(), + worker_process_id, /*creator=*/render_frame_host_id, + render_frame_host_id, blink::StorageKey(), + net::IsolationInfo::CreateTransient(), network::mojom::ClientSecurityState::New(), coep_reporter->GetWeakPtr(), coep_reporter->GetWeakPtr()), factory_.BindNewPipeAndPassReceiver()); @@ -161,12 +161,11 @@ public: struct DedicatedWorkerInfo { int worker_process_id; - GlobalRenderFrameHostId ancestor_render_frame_host_id; + DedicatedWorkerCreator creator; bool operator==(const DedicatedWorkerInfo& other) const { - return std::tie(worker_process_id, ancestor_render_frame_host_id) == - std::tie(other.worker_process_id, - other.ancestor_render_frame_host_id); + return std::tie(worker_process_id, creator) == + std::tie(other.worker_process_id, other.creator); } }; @@ -178,23 +177,20 @@ const TestDedicatedWorkerServiceObserver& other) = delete; // DedicatedWorkerService::Observer: - void OnWorkerCreated( - const blink::DedicatedWorkerToken& token, - int worker_process_id, - GlobalRenderFrameHostId ancestor_render_frame_host_id) override { + void OnWorkerCreated(const blink::DedicatedWorkerToken& token, + int worker_process_id, + DedicatedWorkerCreator creator) override { bool inserted = dedicated_worker_infos_ - .emplace(token, DedicatedWorkerInfo{worker_process_id, - ancestor_render_frame_host_id}) + .emplace(token, DedicatedWorkerInfo{worker_process_id, creator}) .second; DCHECK(inserted); if (on_worker_event_callback_) std::move(on_worker_event_callback_).Run(); } - void OnBeforeWorkerDestroyed( - const blink::DedicatedWorkerToken& token, - GlobalRenderFrameHostId ancestor_render_frame_host_id) override { + void OnBeforeWorkerDestroyed(const blink::DedicatedWorkerToken& token, + DedicatedWorkerCreator creator) override { size_t removed = dedicated_worker_infos_.erase(token); DCHECK_EQ(removed, 1u); @@ -241,11 +237,10 @@ EXPECT_TRUE(observer.dedicated_worker_infos().empty()); // Create the dedicated worker. - const GlobalRenderFrameHostId ancestor_render_frame_host_id = - render_frame_host->GetGlobalId(); + const DedicatedWorkerCreator creator(render_frame_host->GetGlobalId()); const int render_process_host_id = render_frame_host->GetProcess()->GetID(); auto mock_dedicated_worker = std::make_unique<MockDedicatedWorker>( - render_process_host_id, ancestor_render_frame_host_id); + render_process_host_id, render_frame_host->GetGlobalId()); observer.RunUntilWorkerEvent(); // The service sent a OnWorkerStarted() notification. @@ -254,8 +249,7 @@ const auto& dedicated_worker_info = observer.dedicated_worker_infos().begin()->second; EXPECT_EQ(dedicated_worker_info.worker_process_id, render_process_host_id); - EXPECT_EQ(dedicated_worker_info.ancestor_render_frame_host_id, - ancestor_render_frame_host_id); + EXPECT_EQ(dedicated_worker_info.creator, creator); } // Test EnumerateDedicatedWorkers(). @@ -270,8 +264,7 @@ const auto& dedicated_worker_info = enumeration_observer.dedicated_worker_infos().begin()->second; EXPECT_EQ(dedicated_worker_info.worker_process_id, render_process_host_id); - EXPECT_EQ(dedicated_worker_info.ancestor_render_frame_host_id, - ancestor_render_frame_host_id); + EXPECT_EQ(dedicated_worker_info.creator, creator); } // Delete the dedicated worker.
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index a4978b8b..bf4e98f5 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -123,20 +123,49 @@ "input/input_event_ack_state.cc", "input/input_event_stream_validator.cc", "input/input_event_stream_validator.h", + "input/synthetic_gesture.cc", + "input/synthetic_gesture.h", + "input/synthetic_gesture_controller.cc", + "input/synthetic_gesture_controller.h", "input/synthetic_gesture_params.cc", "input/synthetic_gesture_params.h", + "input/synthetic_gesture_target.h", + "input/synthetic_mouse_driver.cc", + "input/synthetic_mouse_driver.h", + "input/synthetic_pen_driver.cc", + "input/synthetic_pen_driver.h", + "input/synthetic_pinch_gesture.cc", + "input/synthetic_pinch_gesture.h", "input/synthetic_pinch_gesture_params.cc", "input/synthetic_pinch_gesture_params.h", + "input/synthetic_pointer_action.cc", + "input/synthetic_pointer_action.h", "input/synthetic_pointer_action_list_params.cc", "input/synthetic_pointer_action_list_params.h", "input/synthetic_pointer_action_params.cc", "input/synthetic_pointer_action_params.h", + "input/synthetic_pointer_driver.cc", + "input/synthetic_pointer_driver.h", + "input/synthetic_smooth_drag_gesture.cc", + "input/synthetic_smooth_drag_gesture.h", "input/synthetic_smooth_drag_gesture_params.cc", "input/synthetic_smooth_drag_gesture_params.h", + "input/synthetic_smooth_move_gesture.cc", + "input/synthetic_smooth_move_gesture.h", + "input/synthetic_smooth_scroll_gesture.cc", + "input/synthetic_smooth_scroll_gesture.h", "input/synthetic_smooth_scroll_gesture_params.cc", "input/synthetic_smooth_scroll_gesture_params.h", + "input/synthetic_tap_gesture.cc", + "input/synthetic_tap_gesture.h", "input/synthetic_tap_gesture_params.cc", "input/synthetic_tap_gesture_params.h", + "input/synthetic_touch_driver.cc", + "input/synthetic_touch_driver.h", + "input/synthetic_touchpad_pinch_gesture.cc", + "input/synthetic_touchpad_pinch_gesture.h", + "input/synthetic_touchscreen_pinch_gesture.cc", + "input/synthetic_touchscreen_pinch_gesture.h", "input/tap_suppression_controller.cc", "input/tap_suppression_controller.h", "input/touch_event_stream_validator.cc",
diff --git a/content/browser/renderer_host/input/synthetic_gesture.cc b/content/common/input/synthetic_gesture.cc similarity index 63% rename from content/browser/renderer_host/input/synthetic_gesture.cc rename to content/common/input/synthetic_gesture.cc index 8e8645e..e889b6c 100644 --- a/content/browser/renderer_host/input/synthetic_gesture.cc +++ b/content/common/input/synthetic_gesture.cc
@@ -2,15 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture.h" #include "base/notreached.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" namespace content {
diff --git a/content/browser/renderer_host/input/synthetic_gesture.h b/content/common/input/synthetic_gesture.h similarity index 94% rename from content/browser/renderer_host/input/synthetic_gesture.h rename to content/common/input/synthetic_gesture.h index 24e706b..e44585b 100644 --- a/content/browser/renderer_host/input/synthetic_gesture.h +++ b/content/common/input/synthetic_gesture.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_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_H_ #include <memory> @@ -106,4 +106,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller.cc b/content/common/input/synthetic_gesture_controller.cc similarity index 93% rename from content/browser/renderer_host/input/synthetic_gesture_controller.cc rename to content/common/input/synthetic_gesture_controller.cc index ce8fd9c..04cdefc 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_controller.cc +++ b/content/common/input/synthetic_gesture_controller.cc
@@ -2,26 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" +#include "content/common/input/synthetic_gesture_controller.h" #include <utility> #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/memory/scoped_refptr.h" +#include "base/task/sequenced_task_runner.h" #include "base/trace_event/trace_event.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/common/input/synthetic_smooth_scroll_gesture_params.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_widget_host.h" +#include "content/common/input/synthetic_gesture_target.h" namespace content { SyntheticGestureController::SyntheticGestureController( Delegate* delegate, - std::unique_ptr<SyntheticGestureTarget> gesture_target) + std::unique_ptr<SyntheticGestureTarget> gesture_target, + scoped_refptr<base::SequencedTaskRunner> task_runner) : delegate_(delegate), gesture_target_(std::move(gesture_target)) { DCHECK(delegate_); + dispatch_timer_.SetTaskRunner(task_runner); } SyntheticGestureController::~SyntheticGestureController() { @@ -204,9 +204,6 @@ return; } - dispatch_timer_.SetTaskRunner( - content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput})); - if (!dispatch_timer_.IsRunning()) { DCHECK(!pending_gesture_queue_.IsEmpty()); const SyntheticGesture& gesture = *pending_gesture_queue_.FrontGesture();
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller.h b/content/common/input/synthetic_gesture_controller.h similarity index 94% rename from content/browser/renderer_host/input/synthetic_gesture_controller.h rename to content/common/input/synthetic_gesture_controller.h index d0dfd80..c1ef21d 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_controller.h +++ b/content/common/input/synthetic_gesture_controller.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_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_ #include <memory> #include <utility> @@ -15,8 +15,8 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture.h" #include "content/common/input/synthetic_gesture_params.h" namespace content { @@ -40,7 +40,8 @@ }; SyntheticGestureController( Delegate* delegate, - std::unique_ptr<SyntheticGestureTarget> gesture_target); + std::unique_ptr<SyntheticGestureTarget> gesture_target, + scoped_refptr<base::SequencedTaskRunner> task_runner); SyntheticGestureController(const SyntheticGestureController&) = delete; SyntheticGestureController& operator=(const SyntheticGestureController&) = @@ -185,4 +186,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_CONTROLLER_H_
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/common/input/synthetic_gesture_controller_unittest.cc similarity index 98% rename from content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc rename to content/common/input/synthetic_gesture_controller_unittest.cc index fc81703..2da41f2 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc +++ b/content/common/input/synthetic_gesture_controller_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/renderer_host/input/synthetic_gesture_controller.h" +#include "content/common/input/synthetic_gesture_controller.h" #include <stddef.h> #include <stdint.h> @@ -15,25 +15,20 @@ #include "base/memory/raw_ptr.h" #include "base/test/task_environment.h" #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" -#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h" -#include "content/browser/renderer_host/input/synthetic_smooth_move_gesture.h" -#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" -#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" -#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" -#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h" -#include "content/browser/renderer_host/render_widget_host_delegate.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_pinch_gesture.h" #include "content/common/input/synthetic_pinch_gesture_params.h" +#include "content/common/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_smooth_drag_gesture.h" #include "content/common/input/synthetic_smooth_drag_gesture_params.h" +#include "content/common/input/synthetic_smooth_move_gesture.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" +#include "content/common/input/synthetic_tap_gesture.h" #include "content/common/input/synthetic_tap_gesture_params.h" -#include "content/public/test/browser_task_environment.h" -#include "content/public/test/mock_render_process_host.h" -#include "content/public/test/test_browser_context.h" -#include "content/test/test_render_view_host.h" +#include "content/common/input/synthetic_touchpad_pinch_gesture.h" +#include "content/common/input/synthetic_touchscreen_pinch_gesture.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "ui/gfx/geometry/point.h" @@ -817,11 +812,12 @@ ~SyntheticGestureControllerTestBase() {} protected: - template<typename MockGestureTarget> + template <typename MockGestureTarget> void CreateControllerAndTarget() { target_ = new MockGestureTarget(); controller_ = std::make_unique<SyntheticGestureController>( - &delegate_, std::unique_ptr<SyntheticGestureTarget>(target_)); + &delegate_, std::unique_ptr<SyntheticGestureTarget>(target_), + base::SingleThreadTaskRunner::GetCurrentDefault()); } void QueueSyntheticGesture(std::unique_ptr<SyntheticGesture> gesture) { @@ -857,7 +853,7 @@ base::TimeDelta GetTotalTime() const { return time_ - start_time_; } - content::BrowserTaskEnvironment env_; + base::test::TaskEnvironment env_; raw_ptr<MockSyntheticGestureTarget, DanglingUntriaged> target_; DummySyntheticGestureControllerDelegate delegate_; std::unique_ptr<SyntheticGestureController> controller_;
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target.h b/content/common/input/synthetic_gesture_target.h similarity index 91% rename from content/browser/renderer_host/input/synthetic_gesture_target.h rename to content/common/input/synthetic_gesture_target.h index 145c222e..036006a 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target.h +++ b/content/common/input/synthetic_gesture_target.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_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_TARGET_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_TARGET_H_ #include "base/functional/callback_forward.h" #include "base/time/time.h" @@ -63,4 +63,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_GESTURE_TARGET_H_
diff --git a/content/browser/renderer_host/input/synthetic_mouse_driver.cc b/content/common/input/synthetic_mouse_driver.cc similarity index 97% rename from content/browser/renderer_host/input/synthetic_mouse_driver.cc rename to content/common/input/synthetic_mouse_driver.cc index 5611f74..29d7314 100644 --- a/content/browser/renderer_host/input/synthetic_mouse_driver.cc +++ b/content/common/input/synthetic_mouse_driver.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/synthetic_mouse_driver.h" +#include "content/common/input/synthetic_mouse_driver.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_gesture_target.h" #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" namespace content {
diff --git a/content/browser/renderer_host/input/synthetic_mouse_driver.h b/content/common/input/synthetic_mouse_driver.h similarity index 90% rename from content/browser/renderer_host/input/synthetic_mouse_driver.h rename to content/common/input/synthetic_mouse_driver.h index 85a8530..3a6a918 100644 --- a/content/browser/renderer_host/input/synthetic_mouse_driver.h +++ b/content/common/input/synthetic_mouse_driver.h
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_MOUSE_DRIVER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_MOUSE_DRIVER_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_MOUSE_DRIVER_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_MOUSE_DRIVER_H_ #include "base/memory/weak_ptr.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" +#include "content/common/input/synthetic_pointer_driver.h" namespace content { @@ -95,4 +95,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_MOUSE_DRIVER_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_MOUSE_DRIVER_H_
diff --git a/content/browser/renderer_host/input/synthetic_pen_driver.cc b/content/common/input/synthetic_pen_driver.cc similarity index 93% rename from content/browser/renderer_host/input/synthetic_pen_driver.cc rename to content/common/input/synthetic_pen_driver.cc index 69152938..5f218175 100644 --- a/content/browser/renderer_host/input/synthetic_pen_driver.cc +++ b/content/common/input/synthetic_pen_driver.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/renderer_host/input/synthetic_pen_driver.h" +#include "content/common/input/synthetic_pen_driver.h" #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
diff --git a/content/browser/renderer_host/input/synthetic_pen_driver.h b/content/common/input/synthetic_pen_driver.h similarity index 69% rename from content/browser/renderer_host/input/synthetic_pen_driver.h rename to content/common/input/synthetic_pen_driver.h index b720d71..977de4b3 100644 --- a/content/browser/renderer_host/input/synthetic_pen_driver.h +++ b/content/common/input/synthetic_pen_driver.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PEN_DRIVER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PEN_DRIVER_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_PEN_DRIVER_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_PEN_DRIVER_H_ -#include "content/browser/renderer_host/input/synthetic_mouse_driver.h" +#include "content/common/input/synthetic_mouse_driver.h" namespace content { @@ -28,4 +28,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PEN_DRIVER_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_PEN_DRIVER_H_
diff --git a/content/browser/renderer_host/input/synthetic_pinch_gesture.cc b/content/common/input/synthetic_pinch_gesture.cc similarity index 87% rename from content/browser/renderer_host/input/synthetic_pinch_gesture.cc rename to content/common/input/synthetic_pinch_gesture.cc index daa7424..19187f9 100644 --- a/content/browser/renderer_host/input/synthetic_pinch_gesture.cc +++ b/content/common/input/synthetic_pinch_gesture.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" +#include "content/common/input/synthetic_pinch_gesture.h" #include <memory> -#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" -#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h" +#include "content/common/input/synthetic_touchpad_pinch_gesture.h" +#include "content/common/input/synthetic_touchscreen_pinch_gesture.h" namespace content {
diff --git a/content/browser/renderer_host/input/synthetic_pinch_gesture.h b/content/common/input/synthetic_pinch_gesture.h similarity index 78% rename from content/browser/renderer_host/input/synthetic_pinch_gesture.h rename to content/common/input/synthetic_pinch_gesture.h index 2390e0b..395ba7e 100644 --- a/content/browser/renderer_host/input/synthetic_pinch_gesture.h +++ b/content/common/input/synthetic_pinch_gesture.h
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PINCH_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PINCH_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_PINCH_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_PINCH_GESTURE_H_ #include <memory> #include "base/functional/callback_forward.h" #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/common/input/synthetic_pinch_gesture_params.h" namespace content { @@ -41,4 +41,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_PINCH_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_PINCH_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action.cc b/content/common/input/synthetic_pointer_action.cc similarity index 98% rename from content/browser/renderer_host/input/synthetic_pointer_action.cc rename to content/common/input/synthetic_pointer_action.cc index fd44d67..4888995a 100644 --- a/content/browser/renderer_host/input/synthetic_pointer_action.cc +++ b/content/common/input/synthetic_pointer_action.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/renderer_host/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_pointer_action.h" #include "base/check_op.h" #include "ui/latency/latency_info.h"
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action.h b/content/common/input/synthetic_pointer_action.h similarity index 87% rename from content/browser/renderer_host/input/synthetic_pointer_action.h rename to content/common/input/synthetic_pointer_action.h index 431b9259..fcbbb9a2 100644 --- a/content/browser/renderer_host/input/synthetic_pointer_action.h +++ b/content/common/input/synthetic_pointer_action.h
@@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_ACTION_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_ACTION_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_ACTION_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_ACTION_H_ #include <memory> #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/common/input/synthetic_pointer_action_list_params.h" #include "content/common/input/synthetic_pointer_action_params.h" +#include "content/common/input/synthetic_pointer_driver.h" namespace content { @@ -79,4 +79,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_ACTION_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_ACTION_H_
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/content/common/input/synthetic_pointer_action_unittest.cc similarity index 98% rename from content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc rename to content/common/input/synthetic_pointer_action_unittest.cc index d1daed0f..ef248de9 100644 --- a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc +++ b/content/common/input/synthetic_pointer_action_unittest.cc
@@ -2,14 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/synthetic_pointer_action.h" +#include "content/common/input/synthetic_pointer_action.h" #include "base/functional/bind.h" +#include "base/test/task_environment.h" #include "base/time/time.h" #include "build/build_config.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_controller.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_controller.h" +#include "content/common/input/synthetic_gesture_target.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "ui/gfx/geometry/point.h" @@ -434,7 +435,8 @@ synthetic_pointer_driver_ = SyntheticPointerDriver::Create( target_->GetDefaultSyntheticGestureSourceType()); controller_ = std::make_unique<SyntheticGestureController>( - &controller_delegate_, std::move(target)); + &controller_delegate_, std::move(target), + base::SingleThreadTaskRunner::GetCurrentDefault()); } std::unique_ptr<SyntheticPointerAction> CreatePointerAction( @@ -464,6 +466,7 @@ std::unique_ptr<SyntheticPointerAction> pointer_action_; std::unique_ptr<SyntheticPointerDriver> synthetic_pointer_driver_; SyntheticPointerActionListParams params_; + base::test::TaskEnvironment env_; }; TEST_F(SyntheticPointerActionTest, PointerTouchAction) {
diff --git a/content/browser/renderer_host/input/synthetic_pointer_driver.cc b/content/common/input/synthetic_pointer_driver.cc similarity index 80% rename from content/browser/renderer_host/input/synthetic_pointer_driver.cc rename to content/common/input/synthetic_pointer_driver.cc index ff05c33..0303a3a5 100644 --- a/content/browser/renderer_host/input/synthetic_pointer_driver.cc +++ b/content/common/input/synthetic_pointer_driver.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" +#include "content/common/input/synthetic_pointer_driver.h" -#include "content/browser/renderer_host/input/synthetic_mouse_driver.h" -#include "content/browser/renderer_host/input/synthetic_pen_driver.h" -#include "content/browser/renderer_host/input/synthetic_touch_driver.h" +#include "content/common/input/synthetic_mouse_driver.h" +#include "content/common/input/synthetic_pen_driver.h" +#include "content/common/input/synthetic_touch_driver.h" namespace content {
diff --git a/content/browser/renderer_host/input/synthetic_pointer_driver.h b/content/common/input/synthetic_pointer_driver.h similarity index 92% rename from content/browser/renderer_host/input/synthetic_pointer_driver.h rename to content/common/input/synthetic_pointer_driver.h index 8c6f847..3f20395 100644 --- a/content/browser/renderer_host/input/synthetic_pointer_driver.h +++ b/content/common/input/synthetic_pointer_driver.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_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_DRIVER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_DRIVER_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_DRIVER_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_DRIVER_H_ #include <memory> @@ -85,4 +85,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_DRIVER_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_DRIVER_H_
diff --git a/content/browser/renderer_host/input/synthetic_smooth_drag_gesture.cc b/content/common/input/synthetic_smooth_drag_gesture.cc similarity index 96% rename from content/browser/renderer_host/input/synthetic_smooth_drag_gesture.cc rename to content/common/input/synthetic_smooth_drag_gesture.cc index 21005391..9c4e78cc 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_drag_gesture.cc +++ b/content/common/input/synthetic_smooth_drag_gesture.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/renderer_host/input/synthetic_smooth_drag_gesture.h" +#include "content/common/input/synthetic_smooth_drag_gesture.h" #include <memory>
diff --git a/content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h b/content/common/input/synthetic_smooth_drag_gesture.h similarity index 79% rename from content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h rename to content/common/input/synthetic_smooth_drag_gesture.h index ec179d7..2eef489 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h +++ b/content/common/input/synthetic_smooth_drag_gesture.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_DRAG_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_DRAG_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_DRAG_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_DRAG_GESTURE_H_ #include <memory> -#include "content/browser/renderer_host/input/synthetic_smooth_move_gesture.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_smooth_move_gesture.h" #include "content/common/input/synthetic_smooth_drag_gesture_params.h" @@ -39,4 +39,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_DRAG_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_DRAG_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc b/content/common/input/synthetic_smooth_move_gesture.cc similarity index 99% rename from content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc rename to content/common/input/synthetic_smooth_move_gesture.cc index a4cdd64..074e2e94 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc +++ b/content/common/input/synthetic_smooth_move_gesture.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/renderer_host/input/synthetic_smooth_move_gesture.h" +#include "content/common/input/synthetic_smooth_move_gesture.h" #include <stdint.h>
diff --git a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h b/content/common/input/synthetic_smooth_move_gesture.h similarity index 90% rename from content/browser/renderer_host/input/synthetic_smooth_move_gesture.h rename to content/common/input/synthetic_smooth_move_gesture.h index c37cb6ed..aad20c13 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h +++ b/content/common/input/synthetic_smooth_move_gesture.h
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_MOVE_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_MOVE_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_MOVE_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_MOVE_GESTURE_H_ #include <memory> #include <vector> #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture.h" #include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_pointer_driver.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/common/input/web_mouse_wheel_event.h" #include "ui/events/types/scroll_types.h" @@ -128,4 +128,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_MOVE_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_MOVE_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc b/content/common/input/synthetic_smooth_scroll_gesture.cc similarity index 96% rename from content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc rename to content/common/input/synthetic_smooth_scroll_gesture.cc index 1d9ed72..74d8e63f 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc +++ b/content/common/input/synthetic_smooth_scroll_gesture.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/renderer_host/input/synthetic_smooth_scroll_gesture.h" +#include "content/common/input/synthetic_smooth_scroll_gesture.h" namespace content {
diff --git a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h b/content/common/input/synthetic_smooth_scroll_gesture.h similarity index 79% rename from content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h rename to content/common/input/synthetic_smooth_scroll_gesture.h index 468c840..992f60e 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h +++ b/content/common/input/synthetic_smooth_scroll_gesture.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_ #include <memory> -#include "content/browser/renderer_host/input/synthetic_smooth_move_gesture.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_smooth_move_gesture.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" @@ -39,4 +39,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_SMOOTH_SCROLL_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_tap_gesture.cc b/content/common/input/synthetic_tap_gesture.cc similarity index 98% rename from content/browser/renderer_host/input/synthetic_tap_gesture.cc rename to content/common/input/synthetic_tap_gesture.cc index 7aeca38..d445075b 100644 --- a/content/browser/renderer_host/input/synthetic_tap_gesture.cc +++ b/content/common/input/synthetic_tap_gesture.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/renderer_host/input/synthetic_tap_gesture.h" +#include "content/common/input/synthetic_tap_gesture.h" #include "base/check_op.h" #include "base/notreached.h"
diff --git a/content/browser/renderer_host/input/synthetic_tap_gesture.h b/content/common/input/synthetic_tap_gesture.h similarity index 77% rename from content/browser/renderer_host/input/synthetic_tap_gesture.h rename to content/common/input/synthetic_tap_gesture.h index 5a61e60..22d3b23 100644 --- a/content/browser/renderer_host/input/synthetic_tap_gesture.h +++ b/content/common/input/synthetic_tap_gesture.h
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_TAP_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_TAP_GESTURE_H_ #include <memory> #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_pointer_driver.h" #include "content/common/input/synthetic_tap_gesture_params.h" namespace content { @@ -54,4 +54,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_TAP_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_touch_driver.cc b/content/common/input/synthetic_touch_driver.cc similarity index 97% rename from content/browser/renderer_host/input/synthetic_touch_driver.cc rename to content/common/input/synthetic_touch_driver.cc index b18f747f..302892a 100644 --- a/content/browser/renderer_host/input/synthetic_touch_driver.cc +++ b/content/common/input/synthetic_touch_driver.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/synthetic_touch_driver.h" +#include "content/common/input/synthetic_touch_driver.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/common/input/synthetic_gesture_target.h" namespace content {
diff --git a/content/browser/renderer_host/input/synthetic_touch_driver.h b/content/common/input/synthetic_touch_driver.h similarity index 89% rename from content/browser/renderer_host/input/synthetic_touch_driver.h rename to content/common/input/synthetic_touch_driver.h index 71d49bf..b87061d 100644 --- a/content/browser/renderer_host/input/synthetic_touch_driver.h +++ b/content/common/input/synthetic_touch_driver.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCH_DRIVER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCH_DRIVER_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_TOUCH_DRIVER_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_TOUCH_DRIVER_H_ #include <map> #include "base/memory/weak_ptr.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" +#include "content/common/input/synthetic_pointer_driver.h" #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" namespace content { @@ -82,4 +82,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCH_DRIVER_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_TOUCH_DRIVER_H_
diff --git a/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc b/content/common/input/synthetic_touchpad_pinch_gesture.cc similarity index 98% rename from content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc rename to content/common/input/synthetic_touchpad_pinch_gesture.cc index b161ac6..e192ce0 100644 --- a/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc +++ b/content/common/input/synthetic_touchpad_pinch_gesture.cc
@@ -5,8 +5,8 @@ #include <stdint.h> #include "base/functional/callback.h" -#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" #include "content/common/input/input_injector.mojom.h" +#include "content/common/input/synthetic_touchpad_pinch_gesture.h" #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" namespace content {
diff --git a/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h b/content/common/input/synthetic_touchpad_pinch_gesture.h similarity index 82% rename from content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h rename to content/common/input/synthetic_touchpad_pinch_gesture.h index 1745be2..888b5d5 100644 --- a/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h +++ b/content/common/input/synthetic_touchpad_pinch_gesture.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_ #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/common/input/synthetic_pinch_gesture_params.h" #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/input/web_input_event.h" @@ -55,4 +55,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc b/content/common/input/synthetic_touchscreen_pinch_gesture.cc similarity index 98% rename from content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc rename to content/common/input/synthetic_touchscreen_pinch_gesture.cc index 727a0f3..18996aa 100644 --- a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc +++ b/content/common/input/synthetic_touchscreen_pinch_gesture.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/renderer_host/input/synthetic_touchscreen_pinch_gesture.h" +#include "content/common/input/synthetic_touchscreen_pinch_gesture.h" #include <stdint.h>
diff --git a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h b/content/common/input/synthetic_touchscreen_pinch_gesture.h similarity index 83% rename from content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h rename to content/common/input/synthetic_touchscreen_pinch_gesture.h index c72f5250..3fed03d 100644 --- a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h +++ b/content/common/input/synthetic_touchscreen_pinch_gesture.h
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_ +#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_ +#define CONTENT_COMMON_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_ #include <memory> #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_pointer_driver.h" #include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/common/input/synthetic_pinch_gesture_params.h" +#include "content/common/input/synthetic_pointer_driver.h" #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/input/web_input_event.h" @@ -68,4 +68,4 @@ } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_ +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 49b044dd..f0894db 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -129,6 +129,7 @@ "cookie_store_factory.h", "cors_origin_pattern_setter.cc", "cors_origin_pattern_setter.h", + "dedicated_worker_creator.h", "dedicated_worker_service.h", "desktop_capture.cc", "desktop_capture.h",
diff --git a/content/public/browser/dedicated_worker_creator.h b/content/public/browser/dedicated_worker_creator.h new file mode 100644 index 0000000..44090fb4 --- /dev/null +++ b/content/public/browser/dedicated_worker_creator.h
@@ -0,0 +1,21 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_CREATOR_H_ +#define CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_CREATOR_H_ + +#include "content/public/browser/global_routing_id.h" +#include "third_party/blink/public/common/tokens/tokens.h" + +namespace content { + +// Represents a creator of a dedicated worker. +// Holds a GlobalRenderFrameHostId if the creator is a RenderFrameHost, and +// holds a blink::DedicatedWorkerToken for a nested worker. +using DedicatedWorkerCreator = + absl::variant<GlobalRenderFrameHostId, blink::DedicatedWorkerToken>; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_CLIENT_INFO_H_
diff --git a/content/public/browser/dedicated_worker_service.h b/content/public/browser/dedicated_worker_service.h index f9fb093..274e30c 100644 --- a/content/public/browser/dedicated_worker_service.h +++ b/content/public/browser/dedicated_worker_service.h
@@ -7,6 +7,7 @@ #include "base/observer_list_types.h" #include "content/common/content_export.h" +#include "content/public/browser/dedicated_worker_creator.h" #include "content/public/browser/global_routing_id.h" #include "third_party/blink/public/common/tokens/tokens.h" @@ -26,10 +27,10 @@ virtual void OnWorkerCreated( const blink::DedicatedWorkerToken& worker_token, int worker_process_id, - GlobalRenderFrameHostId ancestor_render_frame_host_id) = 0; + DedicatedWorkerCreator creator) = 0; virtual void OnBeforeWorkerDestroyed( const blink::DedicatedWorkerToken& worker_token, - GlobalRenderFrameHostId ancestor_render_frame_host_id) = 0; + DedicatedWorkerCreator creator) = 0; // Called when the final response URL (the URL after redirects) was // determined when fetching the worker's script.
diff --git a/content/public/browser/media_keys_listener_manager.h b/content/public/browser/media_keys_listener_manager.h index 57b9886..5ae4926 100644 --- a/content/public/browser/media_keys_listener_manager.h +++ b/content/public/browser/media_keys_listener_manager.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_PUBLIC_BROWSER_MEDIA_KEYS_LISTENER_MANAGER_H_ #define CONTENT_PUBLIC_BROWSER_MEDIA_KEYS_LISTENER_MANAGER_H_ +#include "base/unguessable_token.h" #include "content/common/content_export.h" #include "ui/base/accelerators/media_keys_listener.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -32,17 +33,27 @@ // Note: Delegates *must* call |StopWatchingMediaKey()| for each key code // they're listening to before destruction in order to prevent the // MediaKeysListenerManager from holding invalid pointers. - virtual bool StartWatchingMediaKey( - ui::KeyboardCode key_code, - ui::MediaKeysListener::Delegate* delegate) = 0; + // For instanced web apps that are beginning to listen for media keys, + // the request_id of the media session that is associated with the web app + // needs to be provided via |web_app_request_id|. Otherwise, this param can + // be ignored. + virtual bool StartWatchingMediaKey(ui::KeyboardCode key_code, + ui::MediaKeysListener::Delegate* delegate, + base::UnguessableToken web_app_request_id = + base::UnguessableToken::Null()) = 0; // Stop listening for a given media key. This will free the key to be handled // by the HardwareKeyMediaController. Delegates must stop watching all keys // before they are destroyed in order to prevent the MediaKeysListenerManager // from holding invalid pointers. - virtual void StopWatchingMediaKey( - ui::KeyboardCode key_code, - ui::MediaKeysListener::Delegate* delegate) = 0; + // For instanced web apps that are beginning to listen for media keys, + // the request_id of the media session that is associated with the web app + // needs to be provided via |web_app_request_id|. Otherwise, this param can + // be ignored. + virtual void StopWatchingMediaKey(ui::KeyboardCode key_code, + ui::MediaKeysListener::Delegate* delegate, + base::UnguessableToken web_app_request_id = + base::UnguessableToken::Null()) = 0; // Prevent the browser from using media key presses to control the active // media session. This allows a caller to prevent the media key handling
diff --git a/content/public/browser/usb_delegate.h b/content/public/browser/usb_delegate.h index f3c74ef..fb8aec0 100644 --- a/content/public/browser/usb_delegate.h +++ b/content/public/browser/usb_delegate.h
@@ -85,11 +85,12 @@ const std::string& guid) = 0; // Returns whether `origin` in `browser_context` has permission to access - // the USB device described by `device`. + // the USB device described by `device_info`. virtual bool HasDevicePermission( BrowserContext* browser_context, + RenderFrameHost* frame, const url::Origin& origin, - const device::mojom::UsbDeviceInfo& device) = 0; + const device::mojom::UsbDeviceInfo& device_info) = 0; // These two methods are expected to proxy to the UsbDeviceManager interface // owned by the embedder.
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 2236d57b..15e6dd4 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -46,7 +46,6 @@ #include "content/browser/file_system_access/file_system_access_manager_impl.h" #include "content/browser/renderer_host/cross_process_frame_connector.h" #include "content/browser/renderer_host/frame_tree_node.h" -#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h" #include "content/browser/renderer_host/navigation_request.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_frame_metadata_provider_impl.h" @@ -60,6 +59,7 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_view.h" #include "content/common/frame.mojom.h" +#include "content/common/input/synthetic_touchscreen_pinch_gesture.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/content/public/test/file_system_chooser_test_helpers.cc b/content/public/test/file_system_chooser_test_helpers.cc index 6848c8a..db62316 100644 --- a/content/public/test/file_system_chooser_test_helpers.cc +++ b/content/public/test/file_system_chooser_test_helpers.cc
@@ -46,6 +46,10 @@ } else { out_params_->caller = absl::nullopt; } + + // Free the pointer since output parameters should only be written to + // once. + out_params_ = nullptr; } listener_->FileSelectionCanceled(params); } @@ -57,7 +61,11 @@ bool HasMultipleFileTypeChoicesImpl() override { return false; } private: - ~CancellingSelectFileDialog() override { out_params_ = nullptr; } + ~CancellingSelectFileDialog() override { + if (out_params_) { + out_params_ = nullptr; + } + } raw_ptr<SelectFileDialogParams> out_params_; }; @@ -97,6 +105,9 @@ } else { out_params_->caller = absl::nullopt; } + + // Clean up the output parameters; they should only be filled in once. + out_params_ = nullptr; } // The selected files are passed by reference to the listener. Ensure they // outlive the dialog if it is immediately deleted by the listener. @@ -116,9 +127,13 @@ bool HasMultipleFileTypeChoicesImpl() override { return false; } private: - ~FakeSelectFileDialog() override = default; + ~FakeSelectFileDialog() override { + if (out_params_) { + out_params_ = nullptr; + } + } std::vector<ui::SelectedFileInfo> result_; - raw_ptr<SelectFileDialogParams, LeakedDanglingUntriaged> out_params_; + raw_ptr<SelectFileDialogParams> out_params_; }; } // namespace @@ -153,7 +168,9 @@ SelectFileDialogParams* out_params) : result_(std::move(result)), out_params_(out_params) {} -FakeSelectFileDialogFactory::~FakeSelectFileDialogFactory() = default; +FakeSelectFileDialogFactory::~FakeSelectFileDialogFactory() { + out_params_ = nullptr; +} ui::SelectFileDialog* FakeSelectFileDialogFactory::Create( ui::SelectFileDialog::Listener* listener,
diff --git a/content/services/auction_worklet/bidder_worklet.cc b/content/services/auction_worklet/bidder_worklet.cc index 64b401e..99dbe6a4 100644 --- a/content/services/auction_worklet/bidder_worklet.cc +++ b/content/services/auction_worklet/bidder_worklet.cc
@@ -826,8 +826,9 @@ static_cast<double>(*browser_signal_modeling_signals))) || !browser_signals_dict.Set( "joinCount", static_cast<double>(browser_signal_join_count)) || - !browser_signals_dict.Set("recency", - static_cast<double>(browser_signal_recency)) || + (!is_for_additional_bid && + !browser_signals_dict.Set( + "recency", static_cast<double>(browser_signal_recency))) || !browser_signals_dict.Set("highestScoringOtherBid", browser_signal_highest_scoring_other_bid) || !browser_signals_dict.Set(
diff --git a/content/services/auction_worklet/bidder_worklet_unittest.cc b/content/services/auction_worklet/bidder_worklet_unittest.cc index f890224..a856931 100644 --- a/content/services/auction_worklet/bidder_worklet_unittest.cc +++ b/content/services/auction_worklet/bidder_worklet_unittest.cc
@@ -5669,6 +5669,23 @@ GURL("https://jumboshrimp.test")); } +TEST_F(BidderWorkletTest, ReportWinNoBrowserSignalRecencyForAdditionalBid) { + is_for_additional_bid_ = true; + browser_signal_recency_report_win_ = 19u; + const char kScript[] = R"( + function reportAdditionalBidWin( + auctionSignals, perBuyerSignals, sellerSignals, + browserSignals, directFromSellerSignals) { + if ('recency' in browserSignals) + throw 'Should not have recency in reportAdditionalBidWin'; + sendReportTo("https://report-additional-bid-win.test/"); + } + )"; + + RunReportWinWithJavascriptExpectingResult( + kScript, GURL("https://report-additional-bid-win.test/")); +} + TEST_F(BidderWorkletTest, ReportWinSignalKAnonStatusNotExposedByDefault) { RunReportWinWithFunctionBodyExpectingResult( R"(if (!("kAnonStatus" in browserSignals))
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 7dabad7..0de4fdc 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -2586,8 +2586,6 @@ "../browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc", "../browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc", "../browser/renderer_host/input/stylus_text_selector_unittest.cc", - "../browser/renderer_host/input/synthetic_gesture_controller_unittest.cc", - "../browser/renderer_host/input/synthetic_pointer_action_unittest.cc", "../browser/renderer_host/input/touch_action_filter_unittest.cc", "../browser/renderer_host/input/touch_emulator_unittest.cc", "../browser/renderer_host/input/touchpad_pinch_event_queue_unittest.cc", @@ -2782,6 +2780,8 @@ "../common/input/fling_controller_unittest.cc", "../common/input/gesture_event_queue_unittest.cc", "../common/input/gesture_event_stream_validator_unittest.cc", + "../common/input/synthetic_gesture_controller_unittest.cc", + "../common/input/synthetic_pointer_action_unittest.cc", "../common/input/tap_suppression_controller_unittest.cc", "../common/input/touch_event_stream_validator_unittest.cc", "../common/pseudonymization_salt_unittest.cc",
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index 191ed218..585f796 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -17,10 +17,10 @@ #include "content/browser/dom_storage/dom_storage_context_wrapper.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/browser/renderer_host/data_transfer_util.h" -#include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/render_frame_proxy_host.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/storage_partition_impl.h" +#include "content/common/input/synthetic_gesture_target.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h"
diff --git a/docs/ios/build_instructions.md b/docs/ios/build_instructions.md index 58aa90b..93ccccb9 100644 --- a/docs/ios/build_instructions.md +++ b/docs/ios/build_instructions.md
@@ -12,8 +12,13 @@ ## System requirements -* A 64-bit Mac running 11.3 or later. -* [Xcode](https://developer.apple.com/xcode) 13.1 or higher. +* A 64-bit Mac capable of running the required version of Xcode. +* [Xcode](https://developer.apple.com/xcode) 15.0 or higher. + +Note: after installing Xcode, you need to launch it and to let it install +the iOS simulator. This is required as part of the build, see [this discussion]( +https://groups.google.com/a/chromium.org/g/chromium-dev/c/98d6MyLoYHM/m/A_HyOGxPAgAJ) +on chromium-dev. ## Install `depot_tools`
diff --git a/extensions/browser/api/messaging/extension_message_port.cc b/extensions/browser/api/messaging/extension_message_port.cc index a7e727bd..3c8fba2 100644 --- a/extensions/browser/api/messaging/extension_message_port.cc +++ b/extensions/browser/api/messaging/extension_message_port.cc
@@ -435,7 +435,10 @@ info->guest_process_id = guest_process_id; info->guest_render_frame_routing_id = guest_render_frame_routing_id; - for (const auto& frame_token : pending_frames_) { + // `ShouldSkipFrameForBFCache` could mutate `pending_frames_` so we + // take it before iterating on it. + auto pending_frames = std::move(pending_frames_); + for (const auto& frame_token : pending_frames) { auto* frame = content::RenderFrameHost::FromFrameToken(frame_token); if (!frame || ShouldSkipFrameForBFCache(frame)) { continue; @@ -835,26 +838,27 @@ // We should have called OnConnect before SentToPort. CHECK(pending_frames_.empty()); CHECK(pending_service_workers_.empty()); - std::vector<mojom::MessagePort*> targets; + std::vector<content::GlobalRenderFrameHostToken> frame_targets; // Build the list of targets. for (const auto& item : frames_) { - auto* frame = content::RenderFrameHost::FromFrameToken(item.first); - if (!frame || ShouldSkipFrameForBFCache(frame)) { + frame_targets.push_back(item.first); + } + + for (const auto& target : frame_targets) { + auto item = frames_.find(target); + // `ShouldSkipFrameForBFCache` can mutate `frames_`, so verify the frame + // still exists. + if (item == frames_.end()) { continue; } - if (item.second.is_bound()) { - targets.push_back(item.second.get()); + auto* frame = content::RenderFrameHost::FromFrameToken(item->first); + if (frame && !ShouldSkipFrameForBFCache(frame)) { + send_callback.Run(item->second.get()); } } for (const auto& running_worker : service_workers_) { - if (running_worker.second.is_bound()) { - targets.push_back(running_worker.second.get()); - } - } - - for (auto* target : targets) { - send_callback.Run(target); + send_callback.Run(running_worker.second.get()); } } #endif
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 1cc0961..92e68ad 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -73,6 +73,7 @@ "mojom/automation_registry.mojom", "mojom/channel.mojom", "mojom/code_injection.mojom", + "mojom/context_type.mojom", "mojom/css_origin.mojom", "mojom/event_dispatcher.mojom", "mojom/event_router.mojom",
diff --git a/extensions/common/context_type_adapter.cc b/extensions/common/context_type_adapter.cc index 82226a3..bf3b5790 100644 --- a/extensions/common/context_type_adapter.cc +++ b/extensions/common/context_type_adapter.cc
@@ -6,7 +6,7 @@ #include "base/notreached.h" #include "extensions/common/features/feature.h" -#include "extensions/common/mojom/frame.mojom.h" +#include "extensions/common/mojom/context_type.mojom.h" namespace extensions {
diff --git a/extensions/common/context_type_adapter.h b/extensions/common/context_type_adapter.h index df82a0c..1cdee23 100644 --- a/extensions/common/context_type_adapter.h +++ b/extensions/common/context_type_adapter.h
@@ -6,7 +6,7 @@ #define EXTENSIONS_COMMON_CONTEXT_TYPE_ADAPTER_H_ #include "extensions/common/features/feature.h" -#include "extensions/common/mojom/frame.mojom-forward.h" +#include "extensions/common/mojom/context_type.mojom-forward.h" namespace extensions {
diff --git a/extensions/common/extension_features.cc b/extensions/common/extension_features.cc index 487998f..d4f11c3 100644 --- a/extensions/common/extension_features.cc +++ b/extensions/common/extension_features.cc
@@ -140,6 +140,7 @@ "NewWebstoreDomain", base::FEATURE_ENABLED_BY_DEFAULT); +// To investigate signal beacon loss in crrev.com/c/2262402. BASE_FEATURE(kReportKeepaliveUkm, "ReportKeepaliveUkm", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/extensions/common/mojom/context_type.mojom b/extensions/common/mojom/context_type.mojom new file mode 100644 index 0000000..432fe9b --- /dev/null +++ b/extensions/common/mojom/context_type.mojom
@@ -0,0 +1,20 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module extensions.mojom; + +// The context type associated with a running JS context. +// This should match the values in Feature::Context. +enum ContextType { + kPrivilegedExtension, + kUnprivilegedExtension, + kContentScript, + kWebPage, + kPrivilegedWebPage, + kWebUi, + kUntrustedWebUi, + kLockscreenExtension, + kOffscreenExtension, + kUserScript, +};
diff --git a/extensions/common/mojom/frame.mojom b/extensions/common/mojom/frame.mojom index 82c7b179..3e443e4 100644 --- a/extensions/common/mojom/frame.mojom +++ b/extensions/common/mojom/frame.mojom
@@ -6,6 +6,7 @@ import "mojo/public/mojom/base/uuid.mojom"; import "extensions/common/mojom/code_injection.mojom"; +import "extensions/common/mojom/context_type.mojom"; import "extensions/common/mojom/extra_response_data.mojom"; import "extensions/common/mojom/host_id.mojom"; import "extensions/common/mojom/injection_type.mojom"; @@ -19,21 +20,6 @@ import "url/mojom/url.mojom"; import "third_party/blink/public/mojom/devtools/console_message.mojom"; -// The context type associated with a running JS context. -// This should match the values in Feature::Context. -enum ContextType { - kPrivilegedExtension, - kUnprivilegedExtension, - kContentScript, - kWebPage, - kPrivilegedWebPage, - kWebUi, - kUntrustedWebUi, - kLockscreenExtension, - kOffscreenExtension, - kUserScript, -}; - // Allows an extension to execute code in a tab. struct ExecuteCodeParams { // The ID of the requesting injection host.
diff --git a/infra/config/generated/builders/ci/ios-asan/properties.json b/infra/config/generated/builders/ci/ios-asan/properties.json index fd6a871..1e16ef3a 100644 --- a/infra/config/generated/builders/ci/ios-asan/properties.json +++ b/infra/config/generated/builders/ci/ios-asan/properties.json
@@ -68,5 +68,5 @@ "sheriff_rotations": [ "ios" ], - "xcode_build_version": "14c18" + "xcode_build_version": "15a507" } \ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 45e12def..def9cb8 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -38883,8 +38883,8 @@ '}' execution_timeout_secs: 10800 caches { - name: "xcode_ios_14c18" - path: "xcode_ios_14c18.app" + name: "xcode_ios_15a507" + path: "xcode_ios_15a507.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl index df03249..1c94dfaf 100644 --- a/infra/config/generated/testing/test_suites.pyl +++ b/infra/config/generated/testing/test_suites.pyl
@@ -968,7 +968,7 @@ 'test': 'interactive_ui_tests', 'args': [ '--windows-virtual-display-driver', - '--gtest_filter=*MultiScreen*,*VirtualDisplayWinUtil*', + '--gtest_filter=*MultiScreen*:*VirtualDisplayWinUtil*', ], }, },
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index af4fbb9..bbf30ba 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -70,16 +70,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 121.0.6155.0', + 'description': 'Run with ash-chrome version 121.0.6156.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6155.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v121.0.6155.0', - 'revision': 'version:121.0.6155.0', + 'location': 'lacros_version_skew_tests_v121.0.6156.0', + 'revision': 'version:121.0.6156.0', }, ], },
diff --git a/infra/config/subprojects/chromium/ci/chromium.memory.star b/infra/config/subprojects/chromium/ci/chromium.memory.star index 74df509..cf6e9d8 100644 --- a/infra/config/subprojects/chromium/ci/chromium.memory.star +++ b/infra/config/subprojects/chromium/ci/chromium.memory.star
@@ -637,5 +637,5 @@ category = "iOS", short_name = "asn", ), - xcode = xcode.x14main, + xcode = xcode.x15main, )
diff --git a/infra/config/targets/basic_suites.star b/infra/config/targets/basic_suites.star index 03853dd0..ed1c9e3 100644 --- a/infra/config/targets/basic_suites.star +++ b/infra/config/targets/basic_suites.star
@@ -1201,7 +1201,7 @@ test = "interactive_ui_tests", args = [ "--windows-virtual-display-driver", - "--gtest_filter=*MultiScreen*,*VirtualDisplayWinUtil*", + "--gtest_filter=*MultiScreen*:*VirtualDisplayWinUtil*", ], ), },
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index c387a84..8557b5f6 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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.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_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ] }
diff --git a/internal b/internal index 244adce..6385567 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 244adce210fdea03ebaf44ba20db144ccd668ae2 +Subproject commit 63855671b456f868bcdbce8a29290156fca3dc6b
diff --git a/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm index d13852a..48f9eeb 100644 --- a/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm +++ b/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm
@@ -234,7 +234,9 @@ class TestAutofillClient : public ChromeAutofillClientIOS { public: using ChromeAutofillClientIOS::ChromeAutofillClientIOS; - AutofillDownloadManager* GetDownloadManager() override { return nullptr; } + AutofillCrowdsourcingManager* GetCrowdsourcingManager() override { + return nullptr; + } }; class TestAutofillManager : public BrowserAutofillManager {
diff --git a/ios/chrome/browser/autofill/model/form_structure_browsertest.mm b/ios/chrome/browser/autofill/model/form_structure_browsertest.mm index 89fd655..d4c1650 100644 --- a/ios/chrome/browser/autofill/model/form_structure_browsertest.mm +++ b/ios/chrome/browser/autofill/model/form_structure_browsertest.mm
@@ -130,7 +130,9 @@ class TestAutofillClient : public ChromeAutofillClientIOS { public: using ChromeAutofillClientIOS::ChromeAutofillClientIOS; - AutofillDownloadManager* GetDownloadManager() override { return nullptr; } + AutofillCrowdsourcingManager* GetCrowdsourcingManager() override { + return nullptr; + } }; class TestAutofillManager : public BrowserAutofillManager {
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index b5b1f5b9..09cb586 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -883,10 +883,6 @@ flag_descriptions::kForceStartupSigninPromoName, flag_descriptions::kForceStartupSigninPromoDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(switches::kForceStartupSigninPromo)}, - {"restore-session-from-cache", - flag_descriptions::kRestoreSessionFromCacheName, - flag_descriptions::kRestoreSessionFromCacheDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(web::kRestoreSessionFromCache)}, {"shared-highlighting-ios", flag_descriptions::kSharedHighlightingIOSName, flag_descriptions::kSharedHighlightingIOSDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kSharedHighlightingIOS)},
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index ef73597..ef93adea 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -868,12 +868,6 @@ const char kReplaceSyncPromosWithSignInPromosDescription[] = "When enabled, all sync-related promos will be replaced by sign-in ones."; -const char kRestoreSessionFromCacheName[] = - "Use native WKWebView sesion restoration (iOS15 only)."; -const char kRestoreSessionFromCacheDescription[] = - "Enable instant session restoration for faster web session restoration " - "(iOS15 only)."; - const char kSafeBrowsingAvailableName[] = "Make Safe Browsing available"; const char kSafeBrowsingAvailableDescription[] = "When enabled, navigation URLs are compared to Safe Browsing blocklists, "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 6cdb48b..74fe3010 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -759,10 +759,6 @@ extern const char kNotificationSettingsMenuItemName[]; extern const char kNotificationSettingsMenuItemDescription[]; -// Title and description for the flag to native restore web states. -extern const char kRestoreSessionFromCacheName[]; -extern const char kRestoreSessionFromCacheDescription[]; - // Title and description for the flag to remove excess NTP tabs that don't have // navigation history. extern const char kRemoveExcessNTPsExperimentName[];
diff --git a/ios/chrome/browser/infobars/BUILD.gn b/ios/chrome/browser/infobars/BUILD.gn index fcd08bcf..a25c739 100644 --- a/ios/chrome/browser/infobars/BUILD.gn +++ b/ios/chrome/browser/infobars/BUILD.gn
@@ -4,7 +4,6 @@ source_set("infobars") { sources = [ - "infobar_controller+protected.h", "infobar_ios.h", "infobar_ios.mm", "infobar_manager_impl.h",
diff --git a/ios/chrome/browser/infobars/infobar_controller+protected.h b/ios/chrome/browser/infobars/infobar_controller+protected.h deleted file mode 100644 index da54a05..0000000 --- a/ios/chrome/browser/infobars/infobar_controller+protected.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_INFOBARS_INFOBAR_CONTROLLER_PROTECTED_H_ -#define IOS_CHROME_BROWSER_INFOBARS_INFOBAR_CONTROLLER_PROTECTED_H_ - -#import "ios/chrome/browser/infobars/infobar_controller.h" - -@interface InfoBarController () - -// Returns a view with all the infobar elements in it. Will not add it as a -// subview yet. This method must be overriden in subclasses. -- (UIView*)infobarView; - -// Returns whether user interaction with the infobar should be ignored. -- (BOOL)shouldIgnoreUserInteraction; - -@end - -#endif // IOS_CHROME_BROWSER_INFOBARS_INFOBAR_CONTROLLER_PROTECTED_H_
diff --git a/ios/chrome/browser/promos_manager/constants.cc b/ios/chrome/browser/promos_manager/constants.cc index 9c7f252..7a20c63 100644 --- a/ios/chrome/browser/promos_manager/constants.cc +++ b/ios/chrome/browser/promos_manager/constants.cc
@@ -53,6 +53,10 @@ return promos_manager::Promo::DefaultBrowserRemindMeLater; } + if (promo == "promos_manager::Promo::OmniboxPosition") { + return promos_manager::Promo::OmniboxPosition; + } + return std::nullopt; } @@ -82,6 +86,8 @@ return "PostRestoreDefaultBrowserAlert"; case promos_manager::Promo::DefaultBrowserRemindMeLater: return "DefaultBrowserRemindMeLater"; + case promos_manager::Promo::OmniboxPosition: + return "OmniboxPosition"; } }
diff --git a/ios/chrome/browser/promos_manager/constants.h b/ios/chrome/browser/promos_manager/constants.h index 41d1fd92..37654c3 100644 --- a/ios/chrome/browser/promos_manager/constants.h +++ b/ios/chrome/browser/promos_manager/constants.h
@@ -39,9 +39,12 @@ PostRestoreDefaultBrowserAlert = 8, // Post Restore Default Browser (native iOS alert) DefaultBrowserRemindMeLater = 9, // Remind me later for default browser. - kMaxValue = DefaultBrowserRemindMeLater, + OmniboxPosition = 10, // Choose between top and bottom omnibox. + kMaxValue = OmniboxPosition, }; // LINT.ThenChange(/ios/chrome/browser/promos_manager/constants.cc) +// Also update IOSPromosManagerPromo in +// (/tools/metrics/histograms/metadata/ios/enums.xml). // Enum for IOS.PromosManager.Promo.ImpressionLimitEvaluation histogram. // Entries should not be renumbered and numeric values should never be reused.
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist index d49450f..db0e5a1 100644 --- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist +++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -142,6 +142,7 @@ <string>promos_manager::Promo::DefaultBrowser</string> <string>promos_manager::Promo::Choice</string> <string>promos_manager::Promo::PostRestoreDefaultBrowserAlert</string> + <string>promos_manager::Promo::OmniboxPosition</string> </array> <key>Titles</key> <array> @@ -150,6 +151,7 @@ <string>Default Browser</string> <string>Waffle</string> <string>Post Restore Default Browser Alert</string> + <string>Omnibox Position</string> </array> </dict> <dict> @@ -184,70 +186,70 @@ <key>DefaultValue</key> <false/> </dict> - <dict> - <key>Type</key> - <string>PSMultiValueSpecifier</string> - <key>Title</key> - <string>Update Chrome Safety Check State</string> - <key>Key</key> - <string>SafetyCheckUpdateChromeStateOverride</string> - <key>DefaultValue</key> - <string></string> - <key>Values</key> - <array> - <string></string> - <string>UpdateChromeSafetyCheckState::kOutOfDate</string> - </array> - <key>Titles</key> - <array> - <string>None</string> - <string>Out of date</string> - </array> - </dict> - <dict> - <key>Type</key> - <string>PSMultiValueSpecifier</string> - <key>Title</key> - <string>Password Safety Check State</string> - <key>Key</key> - <string>SafetyCheckPasswordStateOverride</string> - <key>DefaultValue</key> - <string></string> - <key>Values</key> - <array> - <string></string> - <string>PasswordSafetyCheckState::kUnmutedCompromisedPasswords</string> - <string>PasswordSafetyCheckState::kReusedPasswords</string> - <string>PasswordSafetyCheckState::kWeakPasswords</string> - </array> - <key>Titles</key> - <array> - <string>None</string> - <string>Compromised</string> - <string>Re-used</string> - <string>Weak</string> - </array> - </dict> - <dict> - <key>Type</key> - <string>PSMultiValueSpecifier</string> - <key>Title</key> - <string>Safe Browsing Safety Check State</string> - <key>Key</key> - <string>SafetyCheckSafeBrowsingStateOverride</string> - <key>DefaultValue</key> - <string></string> - <key>Values</key> - <array> - <string></string> - <string>SafeBrowsingSafetyCheckState::kUnsafe</string> - </array> - <key>Titles</key> - <array> - <string>None</string> - <string>Unsafe</string> - </array> - </dict> + <dict> + <key>Type</key> + <string>PSMultiValueSpecifier</string> + <key>Title</key> + <string>Update Chrome Safety Check State</string> + <key>Key</key> + <string>SafetyCheckUpdateChromeStateOverride</string> + <key>DefaultValue</key> + <string></string> + <key>Values</key> + <array> + <string></string> + <string>UpdateChromeSafetyCheckState::kOutOfDate</string> + </array> + <key>Titles</key> + <array> + <string>None</string> + <string>Out of date</string> + </array> + </dict> + <dict> + <key>Type</key> + <string>PSMultiValueSpecifier</string> + <key>Title</key> + <string>Password Safety Check State</string> + <key>Key</key> + <string>SafetyCheckPasswordStateOverride</string> + <key>DefaultValue</key> + <string></string> + <key>Values</key> + <array> + <string></string> + <string>PasswordSafetyCheckState::kUnmutedCompromisedPasswords</string> + <string>PasswordSafetyCheckState::kReusedPasswords</string> + <string>PasswordSafetyCheckState::kWeakPasswords</string> + </array> + <key>Titles</key> + <array> + <string>None</string> + <string>Compromised</string> + <string>Re-used</string> + <string>Weak</string> + </array> + </dict> + <dict> + <key>Type</key> + <string>PSMultiValueSpecifier</string> + <key>Title</key> + <string>Safe Browsing Safety Check State</string> + <key>Key</key> + <string>SafetyCheckSafeBrowsingStateOverride</string> + <key>DefaultValue</key> + <string></string> + <key>Values</key> + <array> + <string></string> + <string>SafeBrowsingSafetyCheckState::kUnsafe</string> + </array> + <key>Titles</key> + <array> + <string>None</string> + <string>Unsafe</string> + </array> + </dict> <dict> <key>Type</key> <string>PSMultiValueSpecifier</string> @@ -270,50 +272,50 @@ <string>2</string> </array> </dict> - <dict> - <key>Type</key> - <string>PSMultiValueSpecifier</string> - <key>Title</key> - <string>Reused Passwords Count (Safety Check)</string> - <key>Key</key> - <string>SafetyCheckReusedPasswordsCountOverride</string> - <key>DefaultValue</key> - <integer>0</integer> - <key>Values</key> - <array> - <integer>0</integer> - <integer>1</integer> - <integer>2</integer> - </array> - <key>Titles</key> - <array> - <string>Unset</string> - <string>1</string> - <string>2</string> - </array> - </dict> - <dict> - <key>Type</key> - <string>PSMultiValueSpecifier</string> - <key>Title</key> - <string>Compromised Passwords Count (Safety Check)</string> - <key>Key</key> - <string>SafetyCheckCompromisedPasswordsCountOverride</string> - <key>DefaultValue</key> - <integer>0</integer> - <key>Values</key> - <array> - <integer>0</integer> - <integer>1</integer> - <integer>2</integer> - </array> - <key>Titles</key> - <array> - <string>Unset</string> - <string>1</string> - <string>2</string> - </array> - </dict> + <dict> + <key>Type</key> + <string>PSMultiValueSpecifier</string> + <key>Title</key> + <string>Reused Passwords Count (Safety Check)</string> + <key>Key</key> + <string>SafetyCheckReusedPasswordsCountOverride</string> + <key>DefaultValue</key> + <integer>0</integer> + <key>Values</key> + <array> + <integer>0</integer> + <integer>1</integer> + <integer>2</integer> + </array> + <key>Titles</key> + <array> + <string>Unset</string> + <string>1</string> + <string>2</string> + </array> + </dict> + <dict> + <key>Type</key> + <string>PSMultiValueSpecifier</string> + <key>Title</key> + <string>Compromised Passwords Count (Safety Check)</string> + <key>Key</key> + <string>SafetyCheckCompromisedPasswordsCountOverride</string> + <key>DefaultValue</key> + <integer>0</integer> + <key>Values</key> + <array> + <integer>0</integer> + <integer>1</integer> + <integer>2</integer> + </array> + <key>Titles</key> + <array> + <string>Unset</string> + <string>1</string> + <string>2</string> + </array> + </dict> <dict> <key>Type</key> <string>PSToggleSwitchSpecifier</string>
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm b/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm index c8194b23..93a6d975 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm
@@ -643,7 +643,7 @@ // Do a session restoration and verify that all navigation history is // preserved. - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [ChromeEarlGrey waitForWebStateContainingText:l10n_util::GetStringUTF8(IDS_HEADING_NEW)]; @@ -883,7 +883,7 @@ waitForWebStateContainingText:l10n_util::GetStringUTF8(IDS_HEADING_NEW)]; // Perform session restoration, and verify that a warning is still shown. - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [ChromeEarlGrey waitForWebStateContainingText:l10n_util::GetStringUTF8(IDS_HEADING_NEW)]; }
diff --git a/ios/chrome/browser/sessions/BUILD.gn b/ios/chrome/browser/sessions/BUILD.gn index 2093cf9..df45895 100644 --- a/ios/chrome/browser/sessions/BUILD.gn +++ b/ios/chrome/browser/sessions/BUILD.gn
@@ -50,7 +50,6 @@ "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/browser_state", "//ios/chrome/browser/shared/model/web_state_list", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/browser/web/session_state", "//ios/web/public", "//ios/web/public:web_state_observer", @@ -217,6 +216,7 @@ ":session_service", "//base", "//ios/chrome/browser/shared/model/browser_state", + "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/web/session_state", "//ios/web/public", "//ios/web/public/session", @@ -239,7 +239,6 @@ "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/browser_state", "//ios/chrome/browser/tabs/model:features", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/browser/web/session_state", "//ios/web/common:features", ] @@ -379,7 +378,6 @@ "//ios/chrome/browser/signin/model", "//ios/chrome/browser/signin/model:test_support", "//ios/chrome/browser/tabs/model:features", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/browser/web:web_internal", "//ios/chrome/browser/web/session_state", "//ios/chrome/test:test_support",
diff --git a/ios/chrome/browser/sessions/legacy_session_restoration_service.h b/ios/chrome/browser/sessions/legacy_session_restoration_service.h index 92e427ce..3184ebf 100644 --- a/ios/chrome/browser/sessions/legacy_session_restoration_service.h +++ b/ios/chrome/browser/sessions/legacy_session_restoration_service.h
@@ -13,6 +13,7 @@ #include "base/sequence_checker.h" #include "ios/chrome/browser/sessions/session_restoration_observer.h" #include "ios/chrome/browser/sessions/session_restoration_service.h" +#include "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer.h" @class SessionServiceIOS; @class WebSessionStateCache; @@ -25,9 +26,9 @@ // feature is disabled. // // TODO(crbug.com/1383087): Remove when the feature is fully launched. -class LegacySessionRestorationService final - : public SessionRestorationService, - public SessionRestorationObserver { +class LegacySessionRestorationService final : public SessionRestorationService, + public SessionRestorationObserver, + public WebStateListObserver { public: LegacySessionRestorationService( bool is_pinned_tabs_enabled, @@ -64,6 +65,11 @@ Browser* browser, const std::vector<web::WebState*>& restored_web_states) final; + // WebStateListObserver implementation. + void WebStateListDidChange(WebStateList* web_state_list, + const WebStateListChange& change, + const WebStateListStatus& status) final; + private: SEQUENCE_CHECKER(sequence_checker_);
diff --git a/ios/chrome/browser/sessions/legacy_session_restoration_service.mm b/ios/chrome/browser/sessions/legacy_session_restoration_service.mm index 4858fcbd..7d83e4010 100644 --- a/ios/chrome/browser/sessions/legacy_session_restoration_service.mm +++ b/ios/chrome/browser/sessions/legacy_session_restoration_service.mm
@@ -8,12 +8,13 @@ #import "base/containers/contains.h" #import "base/functional/callback.h" #import "base/strings/sys_string_conversions.h" -#import "base/task/sequenced_task_runner.h" #import "ios/chrome/browser/sessions/session_migration.h" #import "ios/chrome/browser/sessions/session_restoration_browser_agent.h" #import "ios/chrome/browser/sessions/session_service_ios.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" #import "ios/chrome/browser/web/session_state/web_session_state_cache.h" +#import "ios/chrome/browser/web/session_state/web_session_state_tab_helper.h" #import "ios/web/public/session/crw_session_storage.h" #import "ios/web/public/session/proto/storage.pb.h" #import "ios/web/public/web_state.h" @@ -30,6 +31,7 @@ web_session_state_cache_(web_session_state_cache), tab_restore_service_(tab_restore_service) { DCHECK(session_service_ios_); + DCHECK(web_session_state_cache_); } LegacySessionRestorationService::~LegacySessionRestorationService() {} @@ -80,6 +82,8 @@ DCHECK(!base::Contains(browsers_, browser)); browsers_.insert(browser); + browser->GetWebStateList()->AddObserver(this); + // Migrate the storage to legacy format before trying to load. ios::sessions::MigrateNamedSessionToLegacy( browser->GetBrowserState()->GetStatePath(), identifier, @@ -115,6 +119,8 @@ // Destroy the SessionRestorationBrowserAgent for browser. SessionRestorationBrowserAgent::RemoveFromBrowser(browser); + + browser->GetWebStateList()->RemoveObserver(this); } std::unique_ptr<web::WebState> @@ -151,13 +157,8 @@ void LegacySessionRestorationService::PurgeUnassociatedData( base::OnceClosure closure) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (web_session_state_cache_) { - [web_session_state_cache_ - purgeUnassociatedDataWithCompletion:std::move(closure)]; - } else { - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, std::move(closure)); - } + [web_session_state_cache_ + purgeUnassociatedDataWithCompletion:std::move(closure)]; } void LegacySessionRestorationService::WillStartSessionRestoration( @@ -176,3 +177,28 @@ observer.SessionRestorationFinished(browser, restored_web_states); } } + +void LegacySessionRestorationService::WebStateListDidChange( + WebStateList* web_state_list, + const WebStateListChange& change, + const WebStateListStatus& status) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + switch (change.type()) { + case WebStateListChange::Type::kInsert: { + const auto& typed_change = change.As<WebStateListChangeInsert>(); + WebSessionStateTabHelper::CreateForWebState( + typed_change.inserted_web_state()); + break; + } + + case WebStateListChange::Type::kReplace: { + const auto& typed_change = change.As<WebStateListChangeReplace>(); + WebSessionStateTabHelper::CreateForWebState( + typed_change.inserted_web_state()); + break; + } + + default: + break; + } +}
diff --git a/ios/chrome/browser/sessions/legacy_session_restoration_service_unittest.mm b/ios/chrome/browser/sessions/legacy_session_restoration_service_unittest.mm index 36ece9e..06c889e0 100644 --- a/ios/chrome/browser/sessions/legacy_session_restoration_service_unittest.mm +++ b/ios/chrome/browser/sessions/legacy_session_restoration_service_unittest.mm
@@ -29,7 +29,6 @@ #import "ios/chrome/browser/shared/model/browser/browser_list_factory.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/web_state_list/test/fake_web_state_list_delegate.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_opener.h" #import "ios/chrome/browser/web/chrome_web_client.h" @@ -53,10 +52,6 @@ // TODO(crbug.com/1383087): remove once the feature is fully launched. #import "ios/web/common/features.h" -// To get access to web::UseNativeSessionRestorationCache(). -// TODO(crbug.com/1383087): remove once the feature is fully launched. -#import "ios/chrome/browser/web/features.h" - namespace { // Set of FilePath. @@ -185,18 +180,6 @@ bool is_native_session_available = false; }; -// A WebStateListDelegate that creates the WebSessionStateTabHelper for -// WebState inserted in the WebStateList (as this is required by the -// LegacySessionRestorationService). -class TestWebStateListDelegate final : public FakeWebStateListDelegate { - public: - void WillAddWebState(web::WebState* web_state) final { - if (web::UseNativeSessionRestorationCache()) { - WebSessionStateTabHelper::CreateForWebState(web_state); - } - } -}; - // Returns the storage file for `references` in `session_dir`. FilePathSet ExpectedStorageFilesForWebStates( const base::FilePath& storage_dir, @@ -210,14 +193,12 @@ .Append(kLegacySessionFilename)); } - if (web::UseNativeSessionRestorationCache()) { - const base::FilePath web_sessions_dir = - storage_dir.Append(kLegacyWebSessionsDirname); - for (const WebStateReference& reference : references) { - if (reference.is_native_session_available) { - result.insert(web_sessions_dir.Append(base::StringPrintf( - "%08u", reference.web_state->GetUniqueIdentifier().identifier()))); - } + const base::FilePath web_sessions_dir = + storage_dir.Append(kLegacyWebSessionsDirname); + for (const WebStateReference& reference : references) { + if (reference.is_native_session_available) { + result.insert(web_sessions_dir.Append(base::StringPrintf( + "%08u", reference.web_state->GetUniqueIdentifier().identifier()))); } } @@ -292,11 +273,8 @@ initWithSaveDelay:kSaveDelay taskRunner:base::SequencedTaskRunner::GetCurrentDefault()]; - WebSessionStateCache* web_session_state_cache = nil; - if (web::UseNativeSessionRestorationCache()) { - web_session_state_cache = - WebSessionStateCacheFactory::GetForBrowserState(browser_state_.get()); - } + WebSessionStateCache* web_session_state_cache = + WebSessionStateCacheFactory::GetForBrowserState(browser_state_.get()); // Create the service, force enabling the pinned tab support (since // the code using the `is_pinned_tabs_enabled` is tested by the @@ -408,8 +386,7 @@ observer.Observe(service()); // Check that calling SetSessionID() does not load the session. - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); EXPECT_FALSE(observer.restore_started()); @@ -431,8 +408,7 @@ // Check that when a Browser is modified, the changes are reflected to the // storage after a delay. { - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); EXPECT_FALSE(observer.restore_started()); @@ -467,8 +443,7 @@ // Check that the session can be reloaded and that it contains the same // state as when it was saved. { - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); EXPECT_FALSE(observer.restore_started()); @@ -511,8 +486,7 @@ // Check that the session can be loaded even if non-existent and that the // Browser is unmodified (but the observers notified). { - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); EXPECT_FALSE(observer.restore_started()); @@ -535,8 +509,7 @@ // Check that the session can be loaded even if non-existent and that the // Browser is unmodified (but the observers notified). { - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); EXPECT_FALSE(observer.restore_started()); @@ -555,10 +528,8 @@ TEST_F(LegacySessionRestorationServiceTest, SaveSessionOfModifiedBrowser) { // Register multiple Browser and modify one of them. Check that // only data for the modified Browser is written to disk. - TestBrowser browser0 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); - TestBrowser browser1 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser0 = TestBrowser(browser_state()); + TestBrowser browser1 = TestBrowser(browser_state()); service()->SetSessionID(&browser0, kIdentifier0); service()->SetSessionID(&browser1, kIdentifier1); @@ -579,8 +550,7 @@ TEST_F(LegacySessionRestorationServiceTest, SaveSessionChangesOnlyRequiredFiles) { // Create a Browser and add a few WebStates to it. - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); InsertTabsWithUrls(browser, base::make_span(kURLs)); @@ -616,8 +586,7 @@ // add some WebState, wait for the session to be serialized. The session // can then be loaed to get unrealized WebStates. { - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); // Insert a few WebState in the Browser's WebStateList. @@ -640,10 +609,8 @@ // Load the session created before, and then move the tabs from the first // browser to the second one. Check that the session files have been copied. - TestBrowser browser0 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); - TestBrowser browser1 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser0 = TestBrowser(browser_state()); + TestBrowser browser1 = TestBrowser(browser_state()); service()->SetSessionID(&browser0, kIdentifier0); service()->SetSessionID(&browser1, kIdentifier1); @@ -719,8 +686,7 @@ // Tests that the service save pending changes on disconnect. TEST_F(LegacySessionRestorationServiceTest, SavePendingChangesOnDisconnect) { // Create a Browser and add a few WebStates to it. - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); InsertTabsWithUrls(browser, base::make_span(kURLs)); @@ -767,8 +733,7 @@ { // Create a Browser and add a few WebStates to it and wait for all // pending scheduled tasks to complete. - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); InsertTabsWithUrls(browser, base::make_span(kURLs)); WaitForSessionSaveComplete(); @@ -790,8 +755,7 @@ } // Create a Browser. - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); // Load the session and check that the time spent loading was logged. @@ -812,8 +776,7 @@ // is correctly saved to the disk. TEST_F(LegacySessionRestorationServiceTest, CreateUnrealizedWebState) { // Create a Browser. - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); // Create an unrealized WebState. @@ -859,10 +822,8 @@ // Check that calling SaveSessions() when Browser are registered with no // changes updates the session on disk unconditionally. - TestBrowser browser0 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); - TestBrowser browser1 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser0 = TestBrowser(browser_state()); + TestBrowser browser1 = TestBrowser(browser_state()); service()->SetSessionID(&browser0, kIdentifier0); service()->SetSessionID(&browser1, kIdentifier1); @@ -936,10 +897,8 @@ // Check that calling ScheduleSaveSessions() when Browser are registered // with no changes is a no-op. - TestBrowser browser0 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); - TestBrowser browser1 = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser0 = TestBrowser(browser_state()); + TestBrowser browser1 = TestBrowser(browser_state()); service()->SetSessionID(&browser0, kIdentifier0); service()->SetSessionID(&browser1, kIdentifier1); @@ -1010,8 +969,7 @@ // Tests that calling DeleteDataForDiscardedSessions() deletes data for // discarded sessions and accept inexistant sessions identifiers. TEST_F(LegacySessionRestorationServiceTest, DeleteDataForDiscardedSessions) { - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); service()->SetSessionID(&browser, kIdentifier0); // Insert a few WebStage in one of the Browser and wait for the changes @@ -1046,14 +1004,7 @@ // delete any native WKWebView sessions that are not associated to a // Browser's WebState. TEST_F(LegacySessionRestorationServiceTest, PurgeUnassociatedData) { - // If the native session restoration cache is not used, this method - // does nothing. - if (!web::UseNativeSessionRestorationCache()) { - return; - } - - TestBrowser browser = TestBrowser( - browser_state(), std::make_unique<TestWebStateListDelegate>()); + TestBrowser browser = TestBrowser(browser_state()); // PurgeUnassociatedData requires the Browser to be registered with // the BrowserList (as it uses it to detect all the Browsers).
diff --git a/ios/chrome/browser/sessions/session_restoration_browser_agent.mm b/ios/chrome/browser/sessions/session_restoration_browser_agent.mm index 71a3e6b..067bbb8 100644 --- a/ios/chrome/browser/sessions/session_restoration_browser_agent.mm +++ b/ios/chrome/browser/sessions/session_restoration_browser_agent.mm
@@ -26,7 +26,6 @@ #import "ios/chrome/browser/shared/model/web_state_list/order_controller_source.h" #import "ios/chrome/browser/shared/model/web_state_list/removing_indexes.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" -#import "ios/chrome/browser/web/features.h" #import "ios/chrome/browser/web/session_state/web_session_state_tab_helper.h" #import "ios/web/public/navigation/navigation_item.h" #import "ios/web/public/navigation/navigation_manager.h" @@ -340,11 +339,11 @@ directory:browser_->GetBrowserState()->GetStatePath() immediately:immediately]; - if (web::UseNativeSessionRestorationCache()) { - for (int i = 0; i < web_state_list->count(); ++i) { - web::WebState* web_state = web_state_list->GetWebStateAt(i); - WebSessionStateTabHelper::FromWebState(web_state) - ->SaveSessionStateIfStale(); + for (int i = 0; i < web_state_list->count(); ++i) { + web::WebState* web_state = web_state_list->GetWebStateAt(i); + if (WebSessionStateTabHelper* tab_helper = + WebSessionStateTabHelper::FromWebState(web_state)) { + tab_helper->SaveSessionStateIfStale(); } } }
diff --git a/ios/chrome/browser/sessions/session_restoration_service_factory.mm b/ios/chrome/browser/sessions/session_restoration_service_factory.mm index 3bfa979..3ada37d 100644 --- a/ios/chrome/browser/sessions/session_restoration_service_factory.mm +++ b/ios/chrome/browser/sessions/session_restoration_service_factory.mm
@@ -20,10 +20,6 @@ // TODO(crbug.com/1383087): remove once the feature is fully launched. #import "ios/web/common/features.h" -// To get access to web::UseNativeSessionRestorationCache(). -// TODO(crbug.com/1383087): remove once the feature is fully launched. -#import "ios/chrome/browser/web/features.h" - namespace { // Value taken from Desktop Chrome. @@ -76,15 +72,9 @@ [[SessionServiceIOS alloc] initWithSaveDelay:kSaveDelay taskRunner:task_runner]; - WebSessionStateCache* web_session_state_cache = nil; - if (web::UseNativeSessionRestorationCache()) { - web_session_state_cache = - WebSessionStateCacheFactory::GetForBrowserState(browser_state); - } - return std::make_unique<LegacySessionRestorationService>( IsPinnedTabsEnabled(), storage_path, session_service_ios, - web_session_state_cache, + WebSessionStateCacheFactory::GetForBrowserState(browser_state), IOSChromeTabRestoreServiceFactory::GetForBrowserState(browser_state)); }
diff --git a/ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h b/ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h index 425ccbe..a8e01ce 100644 --- a/ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h +++ b/ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h
@@ -104,6 +104,12 @@ // Dismiss the plus address bottom sheet. - (void)dismissPlusAddressBottomSheet; +// Shows the omnibox position choice screen. +- (void)showOmniboxPositionChoice; + +// Dismisses the omnibox position choice screen. +- (void)dismissOmniboxPositionChoice; + @end #endif // IOS_CHROME_BROWSER_SHARED_PUBLIC_COMMANDS_BROWSER_COORDINATOR_COMMANDS_H_
diff --git a/ios/chrome/browser/shared/public/commands/promos_manager_commands.h b/ios/chrome/browser/shared/public/commands/promos_manager_commands.h index f33625c..3cf5115 100644 --- a/ios/chrome/browser/shared/public/commands/promos_manager_commands.h +++ b/ios/chrome/browser/shared/public/commands/promos_manager_commands.h
@@ -30,6 +30,9 @@ // Display the default browser promo after the user tapped Remind Me Later. - (void)displayDefaultBrowserPromoAfterRemindMeLater; +// Display the omnibox position choice screen as a promo. +- (void)showOmniboxPositionChoicePromo; + @end #endif // IOS_CHROME_BROWSER_SHARED_PUBLIC_COMMANDS_PROMOS_MANAGER_COMMANDS_H_
diff --git a/ios/chrome/browser/tab_insertion/model/BUILD.gn b/ios/chrome/browser/tab_insertion/model/BUILD.gn index a561a27d..cf40f8b 100644 --- a/ios/chrome/browser/tab_insertion/model/BUILD.gn +++ b/ios/chrome/browser/tab_insertion/model/BUILD.gn
@@ -37,8 +37,6 @@ "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/shared/model/web_state_list/test:test_support", "//ios/chrome/browser/url_loading/model:new_tab_animation_tab_helper", - "//ios/chrome/browser/web:feature_flags", - "//ios/chrome/browser/web/session_state", "//ios/web", "//ios/web/public/navigation", "//ios/web/public/test",
diff --git a/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent_unittest.mm b/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent_unittest.mm index c35739b..0270b38 100644 --- a/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent_unittest.mm +++ b/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent_unittest.mm
@@ -12,8 +12,6 @@ #import "ios/chrome/browser/shared/model/web_state_list/test/fake_web_state_list_delegate.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" #import "ios/chrome/browser/url_loading/model/new_tab_animation_tab_helper.h" -#import "ios/chrome/browser/web/features.h" -#import "ios/chrome/browser/web/session_state/web_session_state_tab_helper.h" #import "ios/web/public/navigation/navigation_manager.h" #import "ios/web/public/navigation/referrer.h" #import "ios/web/public/test/web_task_environment.h" @@ -23,21 +21,6 @@ const char kURL1[] = "https://www.some.url.com"; -// A WebStateListDelegate that creates the WebSessionStateTabHelper for -// WebState inserted in the WebStateList (as this is required by the -// LegacySessionRestorationService). -class TestWebStateListDelegate final : public FakeWebStateListDelegate { - public: - TestWebStateListDelegate() - : FakeWebStateListDelegate(/*force_realization_on_activation=*/true) {} - - void WillAddWebState(web::WebState* web_state) final { - if (web::UseNativeSessionRestorationCache()) { - WebSessionStateTabHelper::CreateForWebState(web_state); - } - } -}; - } // namespace class TabInsertionBrowserAgentTest : public PlatformTest { @@ -45,7 +28,8 @@ TabInsertionBrowserAgentTest() { browser_state_ = TestChromeBrowserState::Builder().Build(); browser_ = std::make_unique<TestBrowser>( - browser_state_.get(), std::make_unique<TestWebStateListDelegate>()); + browser_state_.get(), std::make_unique<FakeWebStateListDelegate>( + /*force_realization_on_activation=*/true)); TabInsertionBrowserAgent::CreateForBrowser(browser_.get()); agent_ = TabInsertionBrowserAgent::FromBrowser(browser_.get()); }
diff --git a/ios/chrome/browser/tabs/model/BUILD.gn b/ios/chrome/browser/tabs/model/BUILD.gn index f96a6c2d..007548da 100644 --- a/ios/chrome/browser/tabs/model/BUILD.gn +++ b/ios/chrome/browser/tabs/model/BUILD.gn
@@ -113,17 +113,13 @@ "//ios/chrome/browser/ui/download:features", "//ios/chrome/browser/voice/model", "//ios/chrome/browser/web", - "//ios/chrome/browser/web:delegate", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/browser/web:page_placeholder", "//ios/chrome/browser/web/annotations", "//ios/chrome/browser/web/font_size", "//ios/chrome/browser/web/image_fetch", "//ios/chrome/browser/web/print", - "//ios/chrome/browser/web/session_state", "//ios/chrome/browser/web/web_performance_metrics", "//ios/chrome/browser/web_selection/model", - "//ios/chrome/browser/web_state_list/model/web_usage_enabler", "//ios/chrome/browser/webui/model", "//ios/components/security_interstitials", "//ios/components/security_interstitials/https_only_mode", @@ -133,7 +129,6 @@ "//ios/public/provider/chrome/browser/text_zoom:text_zoom_api", "//ios/web/annotations", "//ios/web/common", - "//ios/web/common:features", "//ios/web/public/find_in_page", "//ios/web/public/security", "//ios/web/public/session",
diff --git a/ios/chrome/browser/tabs/model/tab_helper_util.mm b/ios/chrome/browser/tabs/model/tab_helper_util.mm index cc5580e2f..4eeca64 100644 --- a/ios/chrome/browser/tabs/model/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/model/tab_helper_util.mm
@@ -88,7 +88,6 @@ #import "ios/chrome/browser/voice/model/voice_search_navigations_tab_helper.h" #import "ios/chrome/browser/web/annotations/annotations_tab_helper.h" #import "ios/chrome/browser/web/blocked_popup_tab_helper.h" -#import "ios/chrome/browser/web/features.h" #import "ios/chrome/browser/web/font_size/font_size_tab_helper.h" #import "ios/chrome/browser/web/image_fetch/image_fetch_tab_helper.h" #import "ios/chrome/browser/web/invalid_url_tab_helper.h" @@ -97,7 +96,6 @@ #import "ios/chrome/browser/web/print/print_tab_helper.h" #import "ios/chrome/browser/web/repost_form_tab_helper.h" #import "ios/chrome/browser/web/sad_tab_tab_helper.h" -#import "ios/chrome/browser/web/session_state/web_session_state_tab_helper.h" #import "ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.h" #import "ios/chrome/browser/web_selection/model/web_selection_tab_helper.h" #import "ios/chrome/browser/webui/model/net_export_tab_helper.h" @@ -113,7 +111,6 @@ #import "ios/components/security_interstitials/safe_browsing/safe_browsing_unsafe_resource_container.h" #import "ios/public/provider/chrome/browser/text_zoom/text_zoom_api.h" #import "ios/web/common/annotations_utils.h" -#import "ios/web/common/features.h" #import "ios/web/public/find_in_page/java_script_find_in_page_manager.h" #import "ios/web/public/web_state.h" @@ -273,10 +270,6 @@ WebSelectionTabHelper::CreateForWebState(web_state); } - if (web::UseNativeSessionRestorationCache()) { - WebSessionStateTabHelper::CreateForWebState(web_state); - } - WebPerformanceMetricsTabHelper::CreateForWebState(web_state); OfflinePageTabHelper::CreateForWebState(
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h index 3cb61c94..2fa830971 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
@@ -13,8 +13,8 @@ #include "base/memory/weak_ptr.h" #include "components/autofill/core/browser/autocomplete_history_manager.h" #include "components/autofill/core/browser/autofill_client.h" -#include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/country_type.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/payments/card_unmask_delegate.h" #include "components/autofill/core/browser/payments/legal_message_line.h" #include "components/autofill/core/browser/payments/mandatory_reauth_manager.h" @@ -69,7 +69,7 @@ version_info::Channel GetChannel() const override; bool IsOffTheRecord() override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; - AutofillDownloadManager* GetDownloadManager() override; + AutofillCrowdsourcingManager* GetCrowdsourcingManager() override; PersonalDataManager* GetPersonalDataManager() override; AutocompleteHistoryManager* GetAutocompleteHistoryManager() override; CreditCardCvcAuthenticator* GetCvcAuthenticator() override; @@ -178,7 +178,7 @@ PrefService* pref_service_; syncer::SyncService* sync_service_; - std::unique_ptr<AutofillDownloadManager> download_manager_; + std::unique_ptr<AutofillCrowdsourcingManager> crowdsourcing_manager_; PersonalDataManager* personal_data_manager_; AutocompleteHistoryManager* autocomplete_history_manager_; ChromeBrowserState* browser_state_;
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm index 896f45a..4149982 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -142,13 +142,14 @@ web_state_->GetBrowserState()->GetURLLoaderFactory()); } -AutofillDownloadManager* ChromeAutofillClientIOS::GetDownloadManager() { - if (!download_manager_) { +AutofillCrowdsourcingManager* +ChromeAutofillClientIOS::GetCrowdsourcingManager() { + if (!crowdsourcing_manager_) { // Lazy initialization to avoid virtual function calls in the constructor. - download_manager_ = std::make_unique<AutofillDownloadManager>( + crowdsourcing_manager_ = std::make_unique<AutofillCrowdsourcingManager>( this, GetChannel(), GetLogManager()); } - return download_manager_.get(); + return crowdsourcing_manager_.get(); } PersonalDataManager* ChromeAutofillClientIOS::GetPersonalDataManager() {
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 3f66e66f..d926d84 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -147,6 +147,7 @@ "//ios/chrome/browser/ui/find_bar", "//ios/chrome/browser/ui/first_run", "//ios/chrome/browser/ui/first_run:utils", + "//ios/chrome/browser/ui/first_run/omnibox_position", "//ios/chrome/browser/ui/follow", "//ios/chrome/browser/ui/follow:first_follow", "//ios/chrome/browser/ui/follow:follow_iph",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index 626eab5..db419cb 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -153,6 +153,7 @@ #import "ios/chrome/browser/ui/download/vcard_coordinator.h" #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h" #import "ios/chrome/browser/ui/find_bar/find_bar_coordinator.h" +#import "ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.h" #import "ios/chrome/browser/ui/follow/first_follow_coordinator.h" #import "ios/chrome/browser/ui/follow/follow_iph_coordinator.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" @@ -526,6 +527,7 @@ WebNavigationBrowserAgent* _webNavigationBrowserAgent; UrlLoadingBrowserAgent* _urlLoadingBrowserAgent; AddContactsCoordinator* _addContactsCoordinator; + OmniboxPositionChoiceCoordinator* _omniboxPositionChoiceCoordinator; } #pragma mark - ChromeCoordinator @@ -1701,8 +1703,7 @@ } - (void)showSendTabToSelfUI:(const GURL&)url title:(NSString*)title { - // TODO(crbug.com/1488763): Convert to CHECK. - DUMP_WILL_BE_CHECK(!_sendTabToSelfCoordinator); + CHECK(!_sendTabToSelfCoordinator); _sendTabToSelfCoordinator = [[SendTabToSelfCoordinator alloc] initWithBaseViewController:self.viewController @@ -1805,6 +1806,27 @@ self.plusAddressBottomSheetCoordinator = nil; } +- (void)showOmniboxPositionChoice { + CHECK(IsBottomOmniboxPromoFlagEnabled(BottomOmniboxPromoType::kAppLaunch)); + + if (!_omniboxPositionChoiceCoordinator) { + _omniboxPositionChoiceCoordinator = + [[OmniboxPositionChoiceCoordinator alloc] + initWithBaseViewController:self.viewController + browser:self.browser]; + _omniboxPositionChoiceCoordinator.promosUIHandler = + self.promosManagerCoordinator; + } else { + [_omniboxPositionChoiceCoordinator stop]; + } + [_omniboxPositionChoiceCoordinator start]; +} + +- (void)dismissOmniboxPositionChoice { + [_omniboxPositionChoiceCoordinator stop]; + _omniboxPositionChoiceCoordinator = nil; +} + #pragma mark - DefaultBrowserPromoCommands - (void)hidePromo { @@ -2056,6 +2078,11 @@ [self.defaultBrowserPromoManager start]; } +- (void)showOmniboxPositionChoicePromo { + CHECK(IsBottomOmniboxPromoFlagEnabled(BottomOmniboxPromoType::kAppLaunch)); + [self showOmniboxPositionChoice]; +} + #pragma mark - PageInfoCommands - (void)showPageInfo {
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm index 8fe6c24..50ee6b43 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/browser_view/browser_coordinator.h" #import "base/files/file_util.h" +#import "base/test/scoped_feature_list.h" #import "components/bookmarks/test/bookmark_test_helpers.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/download/model/download_directory_util.h" @@ -59,6 +60,7 @@ #import "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" #import "third_party/ocmock/gtest_support.h" +#import "ui/base/device_form_factor.h" // Test fixture for BrowserCoordinator testing. class BrowserCoordinatorTest : public PlatformTest { @@ -404,3 +406,27 @@ [browser_coordinator stop]; } + +// Tests that the showOmniboxPositionChoice command does not +// crash. +TEST_F(BrowserCoordinatorTest, ShowOmniboxPositionChoice) { + // OmniboxPositionChoice is only available on phones. + if (ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_PHONE) { + return; + } + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(kBottomOmniboxPromoAppLaunch); + + // Start the BrowserCoordinator + BrowserCoordinator* browser_coordinator = GetBrowserCoordinator(); + [browser_coordinator start]; + + CommandDispatcher* dispatcher = browser_->GetCommandDispatcher(); + id<PromosManagerCommands> handler = + HandlerForProtocol(dispatcher, PromosManagerCommands); + + [handler showOmniboxPositionChoicePromo]; + + [browser_coordinator stop]; +}
diff --git a/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_remind_me_later_promo_display_handler_unittest.mm b/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_remind_me_later_promo_display_handler_unittest.mm index a3f6ffc..676a516 100644 --- a/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_remind_me_later_promo_display_handler_unittest.mm +++ b/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_remind_me_later_promo_display_handler_unittest.mm
@@ -43,6 +43,9 @@ self.displayDefaultBrowserPromoAfterRemindMeLaterCalled = YES; } +- (void)showOmniboxPositionChoicePromo { +} + @end class DefaultBrowserRemindMeLaterPromoDisplayHandlerTest : public PlatformTest {
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/BUILD.gn b/ios/chrome/browser/ui/first_run/omnibox_position/BUILD.gn index 775ffe04..aaef756 100644 --- a/ios/chrome/browser/ui/first_run/omnibox_position/BUILD.gn +++ b/ios/chrome/browser/ui/first_run/omnibox_position/BUILD.gn
@@ -16,9 +16,11 @@ "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/browser_state", "//ios/chrome/browser/shared/model/prefs:pref_names", + "//ios/chrome/browser/shared/public/commands", "//ios/chrome/browser/shared/public/features", "//ios/chrome/browser/ui/first_run:interruptible_chrome_coordinator", "//ios/chrome/browser/ui/first_run:screen_delegate", + "//ios/chrome/browser/ui/promos_manager:promos", ] }
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/DEPS b/ios/chrome/browser/ui/first_run/omnibox_position/DEPS index 04299b7..a13df4a8 100644 --- a/ios/chrome/browser/ui/first_run/omnibox_position/DEPS +++ b/ios/chrome/browser/ui/first_run/omnibox_position/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+ios/chrome/browser/ui/promos_manager", "+ios/chrome/browser/ui/settings/address_bar_preference/cells/address_bar_option_item_view.h", "+ios/chrome/browser/ui/toolbar/public/toolbar_type.h", ]
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.h b/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.h index 08e9621..a5a20a1b 100644 --- a/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.h +++ b/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.h
@@ -8,10 +8,17 @@ #import "ios/chrome/browser/ui/first_run/interruptible_chrome_coordinator.h" @protocol FirstRunScreenDelegate; +@protocol PromosManagerUIHandler; /// Coordinator for the omnibox position choice screen. @interface OmniboxPositionChoiceCoordinator : InterruptibleChromeCoordinator +/// Initiates a OmniboxPositionChoiceCoordinator. Used for app-launch promo with +/// the promos manager. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + NS_DESIGNATED_INITIALIZER; + /// Initiates a OmniboxPositionChoiceCoordinator with a first run delegate. - (instancetype)initWithBaseNavigationController: (UINavigationController*)navigationController @@ -19,6 +26,10 @@ delegate:(id<FirstRunScreenDelegate>) delegate; +/// The promos manager ui handler to alert for promo UI changes. Should only be +/// set if this coordinator was a promo presented by the PromosManager. +@property(nonatomic, weak) id<PromosManagerUIHandler> promosUIHandler; + @end #endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_OMNIBOX_POSITION_OMNIBOX_POSITION_CHOICE_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.mm b/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.mm index 357eb011..2ea3b381 100644 --- a/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.mm +++ b/ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_coordinator.mm
@@ -7,10 +7,13 @@ #import "ios/chrome/browser/first_run/model/first_run_metrics.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/public/commands/browser_coordinator_commands.h" +#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h" #import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/ui/first_run/first_run_screen_delegate.h" #import "ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_mediator.h" #import "ios/chrome/browser/ui/first_run/omnibox_position/omnibox_position_choice_view_controller.h" +#import "ios/chrome/browser/ui/promos_manager/promos_manager_ui_handler.h" @interface OmniboxPositionChoiceCoordinator () < PromoStyleViewControllerDelegate> @@ -86,6 +89,7 @@ [_viewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; + [self.promosUIHandler promoWasDismissed]; } _viewController = nil; _mediator = nil; @@ -113,7 +117,9 @@ if (_firstRun) { [_first_run_delegate screenWillFinishPresenting]; } else { - // TODO(crbug.com/1503638): Implement browser dismissal here. + id<BrowserCoordinatorCommands> handler = HandlerForProtocol( + self.browser->GetCommandDispatcher(), BrowserCoordinatorCommands); + [handler dismissOmniboxPositionChoice]; } }
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/promo/BUILD.gn b/ios/chrome/browser/ui/first_run/omnibox_position/promo/BUILD.gn new file mode 100644 index 0000000..76c7045 --- /dev/null +++ b/ios/chrome/browser/ui/first_run/omnibox_position/promo/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("promo") { + sources = [ + "omnibox_position_choice_display_handler.h", + "omnibox_position_choice_display_handler.mm", + ] + deps = [ + "//base", + "//components/feature_engagement/public", + "//ios/chrome/browser/policy", + "//ios/chrome/browser/promos_manager", + "//ios/chrome/browser/promos_manager:constants", + "//ios/chrome/browser/promos_manager:types", + "//ios/chrome/browser/shared/coordinator/scene:observing_scene_agent", + "//ios/chrome/browser/shared/model/browser_state", + "//ios/chrome/browser/ui/promos_manager:promos", + ] + frameworks = [ "UIKit.framework" ] +}
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/promo/DEPS b/ios/chrome/browser/ui/first_run/omnibox_position/promo/DEPS new file mode 100644 index 0000000..76fd7c8 --- /dev/null +++ b/ios/chrome/browser/ui/first_run/omnibox_position/promo/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ios/chrome/browser/ui/promos_manager", +]
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.h b/ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.h new file mode 100644 index 0000000..5f579a5 --- /dev/null +++ b/ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.h
@@ -0,0 +1,20 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FIRST_RUN_OMNIBOX_POSITION_PROMO_OMNIBOX_POSITION_CHOICE_DISPLAY_HANDLER_H_ +#define IOS_CHROME_BROWSER_UI_FIRST_RUN_OMNIBOX_POSITION_PROMO_OMNIBOX_POSITION_CHOICE_DISPLAY_HANDLER_H_ + +#import "ios/chrome/browser/ui/promos_manager/standard_promo_display_handler.h" + +/// Handler for displaying the OmniboxPositionChoice screen. Called by the +/// PromosManager. +@interface OmniboxPositionChoiceDisplayHandler + : NSObject <StandardPromoDisplayHandler> + +/// PromosManagerCommands handler. +@property(nonatomic, weak) id<PromosManagerCommands> handler; + +@end + +#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_OMNIBOX_POSITION_PROMO_OMNIBOX_POSITION_CHOICE_DISPLAY_HANDLER_H_
diff --git a/ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.mm b/ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.mm new file mode 100644 index 0000000..c645ea7 --- /dev/null +++ b/ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.mm
@@ -0,0 +1,27 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.h" + +#import "components/feature_engagement/public/feature_constants.h" +#import "ios/chrome/browser/promos_manager/constants.h" +#import "ios/chrome/browser/promos_manager/promo_config.h" + +@implementation OmniboxPositionChoiceDisplayHandler + +#pragma mark - StandardPromoDisplayHandler + +- (void)handleDisplay { + CHECK(self.handler); + [self.handler showOmniboxPositionChoicePromo]; +} + +#pragma mark - PromoProtocol + +- (PromoConfig)config { + return PromoConfig(promos_manager::Promo::OmniboxPosition, + &feature_engagement::kIPHiOSPromoOmniboxPositionFeature); +} + +@end
diff --git a/ios/chrome/browser/ui/menu/browser_action_factory.mm b/ios/chrome/browser/ui/menu/browser_action_factory.mm index 05145227..830da678 100644 --- a/ios/chrome/browser/ui/menu/browser_action_factory.mm +++ b/ios/chrome/browser/ui/menu/browser_action_factory.mm
@@ -324,7 +324,9 @@ OpenNewTabCommand* command = [OpenNewTabCommand commandWithIncognito:NO]; command.shouldFocusOmnibox = YES; - [handler openURLInNewTab:command]; + [UIView performWithoutAnimation:^{ + [handler openURLInNewTab:command]; + }]; }]; if (IsIncognitoModeForced(self.browser->GetBrowserState()->GetPrefs())) { @@ -347,7 +349,9 @@ OpenNewTabCommand* command = [OpenNewTabCommand commandWithIncognito:YES]; command.shouldFocusOmnibox = YES; - [handler openURLInNewTab:command]; + [UIView performWithoutAnimation:^{ + [handler openURLInNewTab:command]; + }]; }]; if (IsIncognitoModeDisabled(self.browser->GetBrowserState()->GetPrefs())) {
diff --git a/ios/chrome/browser/ui/ntp/feed_promos/BUILD.gn b/ios/chrome/browser/ui/ntp/feed_promos/BUILD.gn index 9d6e04e..1846b022 100644 --- a/ios/chrome/browser/ui/ntp/feed_promos/BUILD.gn +++ b/ios/chrome/browser/ui/ntp/feed_promos/BUILD.gn
@@ -15,6 +15,7 @@ "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/public/commands", + "//ios/chrome/browser/shared/public/features", "//ios/chrome/browser/ui/ntp/metrics", "//ios/chrome/common/ui/confirmation_alert", ]
diff --git a/ios/chrome/browser/ui/ntp/feed_top_section/BUILD.gn b/ios/chrome/browser/ui/ntp/feed_top_section/BUILD.gn index 2cb818a..57306a46c 100644 --- a/ios/chrome/browser/ui/ntp/feed_top_section/BUILD.gn +++ b/ios/chrome/browser/ui/ntp/feed_top_section/BUILD.gn
@@ -21,6 +21,8 @@ "feed_top_section_view_controller_delegate.h", ] deps = [ + ":constants", + ":feed_top_section_promos_ui", "//components/signin/public/identity_manager/objc", "//components/sync/base:features", "//ios/chrome/app/strings",
diff --git a/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_consumer.h b/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_consumer.h index cf7f266..7a5d68e 100644 --- a/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_consumer.h +++ b/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_consumer.h
@@ -7,16 +7,25 @@ @class SigninPromoViewConfigurator; +typedef NS_ENUM(NSInteger, PromoViewType) { + // Standard style used for the Content Notifications. + PromoViewTypeSignin = 0, + PromoViewTypeNotifications, +}; + // Protocol used to communicate with the Feed Top Section View. @protocol FeedTopSectionConsumer +// Property that stores the PromoViewType that is currently being displayed. +@property(nonatomic, assign) PromoViewType visiblePromoViewType; + // Allows the consumer to use the `configurator` to configure its view. - (void)updateSigninPromoWithConfigurator: (SigninPromoViewConfigurator*)configurator; -// Methods used to show or hide the Signin Promo. -- (void)showSigninPromo; -- (void)hideSigninPromo; +// Methods to show/hide the promo. +- (void)showPromo; +- (void)hidePromo; @end
diff --git a/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_mediator.mm b/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_mediator.mm index aea01ec..19fc0fc 100644 --- a/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_mediator.mm +++ b/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_mediator.mm
@@ -57,7 +57,7 @@ } - (void)setUp { - [self updateShouldShowSigninPromo]; + [self updateShouldShowPromo]; } - (void)dealloc { @@ -93,11 +93,11 @@ case signin::PrimaryAccountChangeEvent::Type::kSet: if (!self.signinPromoMediator.showSpinner) { // User has signed in, stop showing the promo. - [self updateShouldShowSigninPromo]; + [self updateShouldShowPromo]; } break; case signin::PrimaryAccountChangeEvent::Type::kCleared: - [self updateShouldShowSigninPromo]; + [self updateShouldShowPromo]; break; case signin::PrimaryAccountChangeEvent::Type::kNone: break; @@ -116,41 +116,48 @@ - (void)signinPromoViewMediatorCloseButtonWasTapped: (SigninPromoViewMediator*)mediator { [self.NTPDelegate handleFeedTopSectionClosed]; - [self.consumer hideSigninPromo]; + [self.consumer hidePromo]; } #pragma mark - Private -- (void)updateShouldShowSigninPromo { +- (void)updateShouldShowPromo { PrefService* localState = GetApplicationContext()->GetLocalState(); + // Don't show any promo if Set Up List is Enabled. + if (set_up_list_utils::IsSetUpListActive(localState)) { + return; + } // Don't show the promo for incognito or start surface. BOOL isStartSurfaceOrIncognito = self.isIncognito || [self.NTPDelegate isStartSurface] || !self.isSignInPromoEnabled; - // Don't show the promo if Set Up List is active. - BOOL isSetupListEnabled = set_up_list_utils::IsSetUpListActive(localState); - // Don't show the promo if the account is not elegible for a SigninPromo. - BOOL isAccountEligibleForPromo = NO; + BOOL isAccountEligibleForSignInPromo = NO; + auto consent = + base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) + ? signin::ConsentLevel::kSignin + : signin::ConsentLevel::kSync; if ([SigninPromoViewMediator shouldDisplaySigninPromoViewWithAccessPoint: signin_metrics::AccessPoint::ACCESS_POINT_NTP_FEED_TOP_PROMO authenticationService:self.authenticationService prefService:self.prefService]) { - auto consent = - base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) - ? signin::ConsentLevel::kSignin - : signin::ConsentLevel::kSync; - isAccountEligibleForPromo = + isAccountEligibleForSignInPromo = !self.identityManager->HasPrimaryAccount(consent); } + BOOL isAccountSignedIn = self.identityManager->HasPrimaryAccount(consent); - if (!isStartSurfaceOrIncognito && !isSetupListEnabled && - isAccountEligibleForPromo) { - [self.consumer showSigninPromo]; - } else { - [self.consumer hideSigninPromo]; + if (!isStartSurfaceOrIncognito && isAccountEligibleForSignInPromo) { + self.consumer.visiblePromoViewType = PromoViewTypeSignin; + [self.consumer showPromo]; + return; + } + + if (IsContentPushNotificationsPromoEnabled() && isAccountSignedIn) { + self.consumer.visiblePromoViewType = PromoViewTypeNotifications; + [self.consumer showPromo]; + return; } }
diff --git a/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_view_controller.mm b/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_view_controller.mm index 501cdb72..74c180e 100644 --- a/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/feed_top_section/feed_top_section_view_controller.mm
@@ -13,6 +13,8 @@ #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h" #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_constants.h" #import "ios/chrome/browser/ui/ntp/discover_feed_constants.h" +#import "ios/chrome/browser/ui/ntp/feed_top_section/notifications_promo_view.h" +#import "ios/chrome/browser/ui/ntp/feed_top_section/notifications_promo_view_constants.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_delegate.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -52,8 +54,15 @@ // A vertical StackView which contains all the elements of the top section. @property(nonatomic, strong) UIStackView* contentStack; +// The promo view UIView object. Could be `SigninPromoView` or +// `NotificationsPromoView`. +@property(nonatomic, strong) UIView* promoView; + // The signin promo view. -@property(nonatomic, strong) SigninPromoView* promoView; +@property(nonatomic, strong) SigninPromoView* signinPromoView; + +// The notifications promo view. +@property(nonatomic, strong) NotificationsPromoView* notificationsPromoView; // View to contain the signin promo. @property(nonatomic, strong) UIView* promoViewContainer; @@ -66,6 +75,8 @@ @implementation FeedTopSectionViewController +@synthesize visiblePromoViewType; + - (instancetype)init { self = [super init]; if (self) { @@ -89,7 +100,7 @@ #pragma mark - FeedTopSectionConsumer // Creates the `PromoViewContainer` and adds the SignInPromo. -- (void)createPromoViewContainer { +- (void)createPromoViewContainerForPromoType:(PromoViewType)type { DCHECK(!self.promoViewContainer); DCHECK(!self.promoView); self.promoViewContainer = [[UIView alloc] init]; @@ -103,8 +114,17 @@ [UIColor colorNamed:kBackgroundColor]; } self.promoViewContainer.layer.cornerRadius = kPromoViewContainerBorderRadius; - - self.promoView = [self createPromoView]; + self.visiblePromoViewType = type; + switch (type) { + case PromoViewTypeSignin: + self.signinPromoView = [self createSigninPromoView]; + self.promoView = self.signinPromoView; + break; + case PromoViewTypeNotifications: + self.notificationsPromoView = [self createNotificationsPromoView]; + self.promoView = self.notificationsPromoView; + break; + } // Add the subview to the promoViewContainer. [self.promoViewContainer addSubview:self.promoView]; [self.contentStack addArrangedSubview:self.promoViewContainer]; @@ -113,7 +133,7 @@ - (void)updateSigninPromoWithConfigurator: (SigninPromoViewConfigurator*)configurator { - [configurator configureSigninPromoView:self.promoView + [configurator configureSigninPromoView:self.signinPromoView withStyle:GetTopOfFeedPromoStyle()]; } @@ -121,7 +141,7 @@ - (void)setSigninPromoDelegate:(id<SigninPromoViewDelegate>)delegate { _signinPromoDelegate = delegate; - self.promoView.delegate = _signinPromoDelegate; + self.signinPromoView.delegate = _signinPromoDelegate; } #pragma mark - Private @@ -158,29 +178,41 @@ [NSLayoutConstraint activateConstraints:self.contentStackConstraints]; } -- (void)showSigninPromo { +- (void)showPromo { + // Hide any visible promo when `showPromo` is called to display a new one. + if (self.promoViewContainer) { + [self hidePromo]; + } // Check if the promoViewContainer does not exist. Might not exist if the // promo has been "hidden", which involves removing the container. - if (!self.promoViewContainer && !self.promoView) { - [self createPromoViewContainer]; + if (!self.promoViewContainer) { + [self createPromoViewContainerForPromoType:self.visiblePromoViewType]; } [self applyStackViewConstraintsForTopSectionVisible:YES]; [self.NTPDelegate updateFeedLayout]; } -- (void)hideSigninPromo { +- (void)hidePromo { [self.contentStack willRemoveSubview:self.promoViewContainer]; [self.promoViewContainer willRemoveSubview:self.promoView]; [self.promoView removeFromSuperview]; [self.promoViewContainer removeFromSuperview]; self.promoViewContainer = nil; self.promoView = nil; + self.signinPromoView = nil; + self.notificationsPromoView = nil; [self applyStackViewConstraintsForTopSectionVisible:NO]; - [self.NTPDelegate updateFeedLayout]; } -// Configures and creates a signin promo view. -- (SigninPromoView*)createPromoView { +// TODO(b/312248486): Assign configurator and delegate here. +- (NotificationsPromoView*)createNotificationsPromoView { + NotificationsPromoView* promoView = + [[NotificationsPromoView alloc] initWithFrame:CGRectZero]; + promoView.translatesAutoresizingMaskIntoConstraints = NO; + return promoView; +} + +- (SigninPromoView*)createSigninPromoView { SigninPromoView* promoView = [[SigninPromoView alloc] initWithFrame:CGRectZero]; promoView.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_header_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_header_view_controller.mm index 9a63546..78140de 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_header_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_header_view_controller.mm
@@ -289,6 +289,7 @@ andHeaderView:self.headerView]; [self.logoVendor fetchDoodle]; + self.headerView.tintAdjustmentMode = UIViewTintAdjustmentModeNormal; } }
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm index 82c91d4c..a512ed87 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
@@ -42,6 +42,8 @@ // Animation time for the shift up/down animations to focus/defocus omnibox. const CGFloat kShiftTilesDownAnimationDuration = 0.2; const CGFloat kShiftTilesUpAnimationDuration = 0.1; +// The minimum height of the feed container. +const CGFloat kFeedContainerMinimumHeight = 1000; } // namespace @interface NewTabPageViewController () <UICollectionViewDelegate, @@ -66,6 +68,7 @@ // view. @property(nonatomic, strong) NSArray<NSLayoutConstraint*>* fakeOmniboxConstraints; + // Constraint that pins the fake Omnibox to the top of the view. A subset of // `fakeOmniboxConstraints`. @property(nonatomic, strong) NSLayoutConstraint* headerTopAnchor; @@ -76,6 +79,9 @@ @property(nonatomic, strong) NSArray<NSLayoutConstraint*>* feedHeaderConstraints; +// Constraint for the height of the container view surrounding the feed. +@property(nonatomic, strong) NSLayoutConstraint* feedContainerHeightConstraint; + // `YES` if the NTP starting content offset should be set to a previous scroll // state (when navigating away and back), and `NO` if it should be the top of // the NTP. @@ -149,6 +155,9 @@ GradientView* _backgroundGradientView; // Container view surrounding the feed. UIView* _feedContainer; + // YES if the view is in the process of appearing, but viewDidAppear hasn't + // finished yet. + BOOL _appearing; } - (instancetype)init { @@ -165,6 +174,7 @@ _focusAccessibilityOmniboxWhenViewAppears = YES; _inhibitScrollPositionUpdates = NO; _shiftTileStartTime = -1; + _appearing = YES; } return self; } @@ -216,6 +226,7 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + _appearing = YES; if (IsIOSLargeFakeboxEnabled()) { self.headerViewController.view.alpha = 1; @@ -261,11 +272,6 @@ // back to the NTP. [self updateFakeOmniboxForScrollPosition]; - if (self.shouldFocusFakebox) { - [self shiftTilesUpToFocusOmnibox]; - self.shouldFocusFakebox = NO; - } - if (self.isFeedVisible) { [self updateFeedInsetsForMinimumHeight]; } else { @@ -287,7 +293,20 @@ // whenever an NTP reappears. [self handleStickyElementsForScrollPosition:[self scrollPosition] force:YES]; + if (self.shouldFocusFakebox) { + self.shouldFocusFakebox = NO; + __weak __typeof(self) weakSelf = self; + // Since a focus was requested before the view appeared, the shift up to + // focus should be performed without animation so that the NTP appears and + // is immediately ready to focus the omnibox. The actual focus animation + // will still happen. + [UIView performWithoutAnimation:^{ + [weakSelf shiftTilesUpToFocusOmnibox]; + }]; + } + self.viewDidAppear = YES; + _appearing = NO; } - (void)viewDidDisappear:(BOOL)animated { @@ -341,6 +360,7 @@ if (self.isFeedVisible) { [self updateFeedInsetsForMinimumHeight]; } + [self updateFeedContainerHeight]; }]; } @@ -407,7 +427,7 @@ // action) needs to wait until it is ready. viewDidAppear: currently serves as // this proxy as there is no specific signal given from the feed that its // contents have loaded. - if (self.isFeedVisible && !self.viewDidAppear) { + if (self.isFeedVisible && _appearing) { self.shouldFocusFakebox = YES; } else { [self shiftTilesUpToFocusOmnibox]; @@ -430,7 +450,6 @@ // Reduce the zPosition so that the container appears behind the feed // content. _feedContainer.layer.zPosition = -1; - _feedContainer.userInteractionEnabled = NO; // Add corner radius to the top border. _feedContainer.clipsToBounds = YES; @@ -657,6 +676,8 @@ if (self.hasSavedOffsetFromPreviousScrollState) { [self setContentOffset:self.savedScrollOffset]; } + + [self updateFeedContainerHeight]; } - (void)invalidate { @@ -1480,9 +1501,8 @@ constraintEqualToAnchor:self.collectionView.centerXAnchor], [_feedContainer.topAnchor constraintEqualToAnchor:self.feedHeaderViewController.view.topAnchor], - [_feedContainer.bottomAnchor - constraintEqualToAnchor:self.view.bottomAnchor], ]]; + [self updateFeedContainerHeight]; } [NSLayoutConstraint activateConstraints:@[ @@ -1601,6 +1621,25 @@ self.mutator.scrollPositionToSave = scrollPositionToSave; } +// Updates the feed container's height constraint. +- (void)updateFeedContainerHeight { + if (!_feedContainer) { + return; + } + CHECK(IsFeedContainmentEnabled()); + self.feedContainerHeightConstraint.active = NO; + // Container either takes the actual height of all feed components, or a + // minimum value of `kFeedContainerMinimumHeight` if the content hasn't + // loaded. + CGFloat containerHeight = + std::max((self.collectionView.contentSize.height + + [self feedHeaderHeight] + [self feedTopSectionHeight]), + kFeedContainerMinimumHeight); + self.feedContainerHeightConstraint = + [_feedContainer.heightAnchor constraintEqualToConstant:containerHeight]; + self.feedContainerHeightConstraint.active = YES; +} + #pragma mark - Helpers - (UIViewController*)contentSuggestionsViewController {
diff --git a/ios/chrome/browser/ui/passwords/OWNERS b/ios/chrome/browser/ui/passwords/OWNERS index 17faadd..a9edc3e1 100644 --- a/ios/chrome/browser/ui/passwords/OWNERS +++ b/ios/chrome/browser/ui/passwords/OWNERS
@@ -1,2 +1,2 @@ vsemeniuk@google.com -tmartino@google.com \ No newline at end of file +tmartino@chromium.org \ No newline at end of file
diff --git a/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm b/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm index 1662b15f..75afd507 100644 --- a/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm +++ b/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm
@@ -193,8 +193,8 @@ [ChromeEarlGrey waitForWebStateContainingText:kDesktopSiteLabel timeout:kWaitForUserAgentChangeTimeout]; - // Close all tabs and undo, trigerring a restoration. - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + // Restart the app to trigger a reload. + [self triggerRestoreByRestartingApplication]; // Verify that desktop user agent propagates. [ChromeEarlGreyUI openToolsMenu]; @@ -278,8 +278,8 @@ [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] assertWithMatcher:grey_sufficientlyVisible()]; - // Go back to NTP to restore the session from there. - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + // Restart the app to trigger a reload. + [self triggerRestoreByRestartingApplication]; // Make sure that the NTP is displayed. [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
diff --git a/ios/chrome/browser/ui/promos_manager/BUILD.gn b/ios/chrome/browser/ui/promos_manager/BUILD.gn index 7c4f931..f4b8d57b 100644 --- a/ios/chrome/browser/ui/promos_manager/BUILD.gn +++ b/ios/chrome/browser/ui/promos_manager/BUILD.gn
@@ -79,6 +79,7 @@ "//ios/chrome/browser/ui/default_promo/post_restore:features", "//ios/chrome/browser/ui/default_promo/post_restore:post_restore_default_browser", "//ios/chrome/browser/ui/default_promo/promo_handler", + "//ios/chrome/browser/ui/first_run/omnibox_position/promo", "//ios/chrome/browser/ui/post_restore_signin", "//ios/chrome/browser/ui/whats_new:util", "//ios/chrome/browser/ui/whats_new/promo",
diff --git a/ios/chrome/browser/ui/promos_manager/DEPS b/ios/chrome/browser/ui/promos_manager/DEPS index 9c611018..2f31cd9 100644 --- a/ios/chrome/browser/ui/promos_manager/DEPS +++ b/ios/chrome/browser/ui/promos_manager/DEPS
@@ -4,4 +4,5 @@ "+ios/chrome/browser/ui/whats_new", "+ios/chrome/browser/ui/credential_provider_promo", "+ios/chrome/browser/ui/default_promo", + "+ios/chrome/browser/ui/first_run/omnibox_position/promo", ]
diff --git a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm index 812ba52..5cb411e 100644 --- a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm +++ b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.mm
@@ -42,6 +42,7 @@ #import "ios/chrome/browser/ui/default_promo/post_restore/post_restore_default_browser_promo_provider.h" #import "ios/chrome/browser/ui/default_promo/promo_handler/default_browser_promo_display_handler.h" #import "ios/chrome/browser/ui/default_promo/promo_handler/default_browser_remind_me_later_promo_display_handler.h" +#import "ios/chrome/browser/ui/first_run/omnibox_position/promo/omnibox_position_choice_display_handler.h" #import "ios/chrome/browser/ui/post_restore_signin/post_restore_signin_provider.h" #import "ios/chrome/browser/ui/promos_manager/bannered_promo_view_provider.h" #import "ios/chrome/browser/ui/promos_manager/promos_manager_mediator.h" @@ -583,6 +584,12 @@ [[DefaultBrowserPromoDisplayHandler alloc] init]; _displayHandlerPromos[promos_manager::Promo::DefaultBrowserRemindMeLater] = [[DefaultBrowserRemindMeLaterPromoDisplayHandler alloc] init]; + + // Omnibox position choice promo handler. + if (IsBottomOmniboxPromoFlagEnabled(BottomOmniboxPromoType::kAppLaunch)) { + _displayHandlerPromos[promos_manager::Promo::OmniboxPosition] = + [[OmniboxPositionChoiceDisplayHandler alloc] init]; + } } - (PromoConfigsSet)promoImpressionLimits {
diff --git a/ios/chrome/browser/ui/promos_manager/standard_promo_display_handler.h b/ios/chrome/browser/ui/promos_manager/standard_promo_display_handler.h index 93d0d37a..f966bc9d 100644 --- a/ios/chrome/browser/ui/promos_manager/standard_promo_display_handler.h +++ b/ios/chrome/browser/ui/promos_manager/standard_promo_display_handler.h
@@ -16,6 +16,10 @@ // // When the Promos Manager determines it's time to display the promo // `identifier`, it will call `handleDisplay`. +// If this method is used to display promos, the promo must alert the Promos +// Manager when it is dismissed by calling the `PromosManagerCoordinator`'s +// `promoWasDismissed` method. the `PromosManagerUIHandler` protocol can be used +// for this purpose. @protocol StandardPromoDisplayHandler <PromoProtocol> @required
diff --git a/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_table/search_engine_choice_table_view_controller.mm b/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_table/search_engine_choice_table_view_controller.mm index 4fd22680..64c8559 100644 --- a/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_table/search_engine_choice_table_view_controller.mm +++ b/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_table/search_engine_choice_table_view_controller.mm
@@ -63,10 +63,17 @@ } - (void)scrollToBottom { - CGFloat scrollLimit = self.tableView.contentSize.height - - self.tableView.bounds.size.height + - self.tableView.contentInset.bottom; - [self.tableView setContentOffset:CGPointMake(0, scrollLimit) animated:YES]; + TableViewModel* model = self.tableViewModel; + NSInteger lastSectionIndex = [model numberOfSections] - 1; + NSInteger lastRowIndex = [model numberOfItemsInSection:lastSectionIndex] - 1; + NSIndexPath* lastRowIndexPath = + [NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex]; + [self.tableView scrollToRowAtIndexPath:lastRowIndexPath + atScrollPosition:UITableViewScrollPositionBottom + animated:YES]; + // Make sure the delegate receives the bottom reach event, so if the scroll + // as an offset of one pixel, the delegate will be called. + [self bottomReached]; } #pragma mark - UIViewController @@ -213,7 +220,7 @@ #pragma mark - Private -// Updates `-SearchEngineChoiceTableViewController.didReachBottom`. +// Checks if the the bottom has been reached. - (void)updateDidReachBottomFlag { if (self.didReachBottom) { // Don't update the value if the bottom was reached at least once. @@ -224,9 +231,15 @@ CGFloat scrollLimit = self.tableView.contentSize.height + self.tableView.contentInset.bottom; if (scrollPosition >= scrollLimit) { - [self.delegate didReachBottom]; - self.didReachBottom = YES; + [self bottomReached]; } } +// Updates `-SearchEngineChoiceTableViewController.didReachBottom`, and calls +// the delegate. +- (void)bottomReached { + self.didReachBottom = YES; + [self.delegate didReachBottom]; +} + @end
diff --git a/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_ui_util.mm b/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_ui_util.mm index ee648461..2b77fe8 100644 --- a/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_ui_util.mm +++ b/ios/chrome/browser/ui/search_engine_choice/search_engine_choice_ui_util.mm
@@ -12,6 +12,7 @@ #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/button_util.h" #import "ios/chrome/common/ui/util/device_util.h" +#import "ios/chrome/common/ui/util/sdk_forward_declares.h" #import "ui/base/l10n/l10n_util_mac.h" namespace {
diff --git a/ios/chrome/browser/ui/settings/autofill/BUILD.gn b/ios/chrome/browser/ui/settings/autofill/BUILD.gn index dfc0981..a8f9bfa7 100644 --- a/ios/chrome/browser/ui/settings/autofill/BUILD.gn +++ b/ios/chrome/browser/ui/settings/autofill/BUILD.gn
@@ -19,7 +19,6 @@ "autofill_credit_card_table_view_controller.mm", "autofill_credit_card_util.h", "autofill_credit_card_util.mm", - "autofill_edit_table_view_controller+protected.h", "autofill_edit_table_view_controller.h", "autofill_edit_table_view_controller.mm", "autofill_profile_edit_coordinator.h",
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm index 3d13f71..44cbff57 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_edit_table_view_controller.mm
@@ -28,7 +28,6 @@ #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" #import "ios/chrome/browser/ui/settings/autofill/autofill_constants.h" #import "ios/chrome/browser/ui/settings/autofill/autofill_credit_card_util.h" -#import "ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller+protected.h" #import "ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h" #import "ios/chrome/grit/ios_branded_strings.h" #import "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller+protected.h b/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller+protected.h deleted file mode 100644 index 0dc6c9b..0000000 --- a/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller+protected.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_AUTOFILL_EDIT_TABLE_VIEW_CONTROLLER_PROTECTED_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_AUTOFILL_EDIT_TABLE_VIEW_CONTROLLER_PROTECTED_H_ - -#import "ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.h" - -// The table view for an Autofill edit entry menu. -@interface AutofillEditTableViewController (Protected) - -// Returns the indexPath for the currently focused text field when in edit mode. -- (NSIndexPath*)indexPathForCurrentTextField; - -// Returns whether cell at indexPath is `TableViewTextEditCell`. Subclasses -// should implement. -- (BOOL)isItemAtIndexPathTextEditCell:(NSIndexPath*)cellPath; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_AUTOFILL_EDIT_TABLE_VIEW_CONTROLLER_PROTECTED_H_
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm index b61ef842..03d755d 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.mm
@@ -10,7 +10,6 @@ #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" #import "ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_chromium_text_data.h" -#import "ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller+protected.h" #import "ios/chrome/common/ui/elements/form_input_accessory_view.h" @interface AutofillEditTableViewController () <FormInputAccessoryViewDelegate> {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn index c33bd5e..5f4a034e 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn
@@ -235,7 +235,6 @@ "//ios/chrome/browser/tabs/model", "//ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/test:fakes", "//ios/chrome/browser/ui/tab_switcher/test:fakes", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/browser/web_state_list/model/web_usage_enabler", "//ios/chrome/test:test_support", "//ios/web/public",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_mediator_test.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_mediator_test.mm index fe5e68b..a67275e 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_mediator_test.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_mediator_test.mm
@@ -31,7 +31,6 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/test/fake_tab_grid_toolbars_mediator.h" #import "ios/chrome/browser/ui/tab_switcher/test/fake_tab_collection_consumer.h" -#import "ios/chrome/browser/web/features.h" #import "ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.h" #import "ios/web/public/test/fakes/fake_navigation_manager.h" #import "ios/web/public/test/fakes/fake_web_frames_manager.h"
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn index 5eae11b..e94a760 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn
@@ -10,6 +10,7 @@ "tab_groups_mediator.mm", ] deps = [ + ":tab_groups_ui", "//base", "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser", @@ -23,7 +24,10 @@ "tab_groups_view_controller.h", "tab_groups_view_controller.mm", ] - deps = [] + deps = [ + "//base", + "//ios/chrome/browser/shared/public/features", + ] } source_set("unit_tests") {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_coordinator.mm index 8d8cfb81..2ac5e74 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_coordinator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_coordinator.mm
@@ -8,10 +8,13 @@ #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_mediator.h" +#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.h" @implementation TabGroupsCoordinator { // Mediator for tab groups. TabGroupsMediator* _mediator; + // View controller for tab groups. + TabGroupsViewController* _viewController; } #pragma mark - ChromeCoordinator @@ -27,10 +30,12 @@ - (void)start { _mediator = [[TabGroupsMediator alloc] initWithWebStateList:self.browser->GetWebStateList()]; + _viewController = [[TabGroupsViewController alloc] init]; } - (void)stop { _mediator = nil; + _viewController = nil; } @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.h index 41f74d2..a14e744 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.h
@@ -5,4 +5,10 @@ #ifndef IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_TAB_GROUPS_TAB_GROUPS_VIEW_CONTROLLER_H_ #define IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_TAB_GROUPS_TAB_GROUPS_VIEW_CONTROLLER_H_ +#import <UIKit/UIKit.h> + +@interface TabGroupsViewController : UIViewController + +@end + #endif // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_TAB_GROUPS_TAB_GROUPS_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.mm index 3d2c45f..b63653c0 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.mm
@@ -3,3 +3,19 @@ // found in the LICENSE file. #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_view_controller.h" + +#import "base/check.h" +#import "ios/chrome/browser/shared/public/features/features.h" + +@implementation TabGroupsViewController + +#pragma mark - UIViewController + +- (instancetype)init { + CHECK(base::FeatureList::IsEnabled(kTabGroupsInGrid)) + << "You should not be able to create a tab group view controller outside " + "the Tab Groups experiment."; + return [super init]; +} + +@end
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn index 6a6f6f6..f4522f10 100644 --- a/ios/chrome/browser/web/BUILD.gn +++ b/ios/chrome/browser/web/BUILD.gn
@@ -164,6 +164,7 @@ ] deps = [ ":delegate", + ":feature_flags", ":page_placeholder", ":tab_helper_delegates", ":web", @@ -190,7 +191,6 @@ "//ios/chrome/browser/snapshots/model", "//ios/chrome/browser/tab_insertion/model", "//ios/chrome/browser/web", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/test:test_support", "//ios/net", "//ios/net:test_support", @@ -222,6 +222,7 @@ "ios_thread_profiler.h", ] deps = [ + ":feature_flags", ":web", "//base", "//base/allocator:buildflags", @@ -300,7 +301,6 @@ "//ios/chrome/browser/supervised_user/model", "//ios/chrome/browser/translate/model", "//ios/chrome/browser/ui/infobars/coordinators", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/browser/web/choose_file", "//ios/chrome/browser/web/font_size", "//ios/chrome/browser/web/image_fetch", @@ -511,8 +511,5 @@ "features.cc", "features.h", ] - deps = [ - "//base", - "//ios/web/common:features", - ] + deps = [ "//base" ] }
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm index e6481421..f973421 100644 --- a/ios/chrome/browser/web/chrome_web_client.mm +++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -494,12 +494,9 @@ } NSData* ChromeWebClient::FetchSessionFromCache(web::WebState* web_state) const { - if (!web::UseNativeSessionRestorationCache()) { - return nil; - } - - return WebSessionStateTabHelper::FromWebState(web_state) - ->FetchSessionFromCache(); + WebSessionStateTabHelper* tab_helper = + WebSessionStateTabHelper::FromWebState(web_state); + return tab_helper ? tab_helper->FetchSessionFromCache() : nil; } void ChromeWebClient::CleanupNativeRestoreURLs(web::WebState* web_state) const {
diff --git a/ios/chrome/browser/web/error_page_egtest.mm b/ios/chrome/browser/web/error_page_egtest.mm index 8d38ebc..0b39e699 100644 --- a/ios/chrome/browser/web/error_page_egtest.mm +++ b/ios/chrome/browser/web/error_page_egtest.mm
@@ -174,7 +174,7 @@ // Restore the session but with the page no longer loading. self.serverRespondsWithContent = NO; - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [ChromeEarlGrey waitForWebStateContainingText:GetErrorMessage()]; GREYAssertEqual(1, [ChromeEarlGrey navigationBackListItemsCount],
diff --git a/ios/chrome/browser/web/features.cc b/ios/chrome/browser/web/features.cc index 6ba646d..2dd76a7 100644 --- a/ios/chrome/browser/web/features.cc +++ b/ios/chrome/browser/web/features.cc
@@ -4,8 +4,6 @@ #include "ios/chrome/browser/web/features.h" -#include "ios/web/common/features.h" - namespace web { BASE_FEATURE(kWebPageDefaultZoomFromDynamicType, @@ -20,19 +18,4 @@ "WebPageTextZoomIPad", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kRestoreSessionFromCache, - "RestoreSessionFromCache", - base::FEATURE_ENABLED_BY_DEFAULT); - -bool UseNativeSessionRestorationCache() { - // The optimised session restoration code manage the session state save - // itself, so there is no need to use the native session restoration cache - // when the feature is enabled. - if (web::features::UseSessionSerializationOptimizations()) { - return false; - } - - return base::FeatureList::IsEnabled(web::kRestoreSessionFromCache); -} - } // namespace web
diff --git a/ios/chrome/browser/web/features.h b/ios/chrome/browser/web/features.h index ab1bd70..0473c53 100644 --- a/ios/chrome/browser/web/features.h +++ b/ios/chrome/browser/web/features.h
@@ -18,12 +18,6 @@ // Reneables text zoom on iPad. BASE_DECLARE_FEATURE(kWebPageTextZoomIPad); -// Feature flag for to use native session restoration. -BASE_DECLARE_FEATURE(kRestoreSessionFromCache); - -// Whether native session restoration cache is enabled. -bool UseNativeSessionRestorationCache(); - } // namespace web #endif // IOS_CHROME_BROWSER_WEB_FEATURES_H_
diff --git a/ios/chrome/browser/web/lookalike_url_egtest.mm b/ios/chrome/browser/web/lookalike_url_egtest.mm index 68e4ff2..0c94a1f0 100644 --- a/ios/chrome/browser/web/lookalike_url_egtest.mm +++ b/ios/chrome/browser/web/lookalike_url_egtest.mm
@@ -337,7 +337,7 @@ // after a load. [[EarlGrey selectElementWithMatcher:ForwardButton()] performAction:grey_tap()]; - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [LookalikeUrlAppInterface setUpLookalikeUrlDeciderForWebState]; [ChromeEarlGrey goBack]; [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
diff --git a/ios/chrome/browser/web/navigation_egtest.mm b/ios/chrome/browser/web/navigation_egtest.mm index afd6a5d..12b263c2 100644 --- a/ios/chrome/browser/web/navigation_egtest.mm +++ b/ios/chrome/browser/web/navigation_egtest.mm
@@ -566,7 +566,7 @@ [ChromeEarlGrey loadURL:destinationURL]; [ChromeEarlGrey goBack]; - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [ChromeEarlGrey waitForWebStateContainingText:"Revision"]; [[EarlGrey selectElementWithMatcher:OmniboxText("chrome://version")] @@ -585,7 +585,7 @@ [ChromeEarlGrey loadURL:destinationURL]; [ChromeEarlGrey goBack]; - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [ChromeEarlGrey goForward]; @@ -602,7 +602,7 @@ GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); const GURL destinationURL("chrome://crash"); [ChromeEarlGrey loadURL:destinationURL]; - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [[EarlGrey selectElementWithMatcher:OmniboxText("chrome://crash")] assertWithMatcher:grey_notNil()]; }
diff --git a/ios/chrome/browser/web/session_state/BUILD.gn b/ios/chrome/browser/web/session_state/BUILD.gn index d02cb0b..070458ff 100644 --- a/ios/chrome/browser/web/session_state/BUILD.gn +++ b/ios/chrome/browser/web/session_state/BUILD.gn
@@ -24,8 +24,6 @@ "//ios/chrome/browser/shared/model/browser_state", "//ios/chrome/browser/shared/model/url:constants", "//ios/chrome/browser/shared/model/web_state_list", - "//ios/chrome/browser/web:feature_flags", - "//ios/web/common:features", "//ios/web/navigation:wk_navigation_util", "//ios/web/public", "//ios/web/public/js_messaging", @@ -49,9 +47,7 @@ "//ios/chrome/browser/shared/model/browser_state:test_support", "//ios/chrome/browser/shared/model/url:constants", "//ios/chrome/browser/web", - "//ios/chrome/browser/web:feature_flags", "//ios/chrome/browser/web:web_internal", - "//ios/web/common:features", "//ios/web/navigation:wk_navigation_util", "//ios/web/public/session", "//ios/web/public/test",
diff --git a/ios/chrome/browser/web/session_state/web_session_state_cache_factory.mm b/ios/chrome/browser/web/session_state/web_session_state_cache_factory.mm index 3f4a2ac..ba4c414 100644 --- a/ios/chrome/browser/web/session_state/web_session_state_cache_factory.mm +++ b/ios/chrome/browser/web/session_state/web_session_state_cache_factory.mm
@@ -14,7 +14,6 @@ #import "ios/chrome/browser/shared/model/browser/browser_list_factory.h" #import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/web/features.h" #import "ios/chrome/browser/web/session_state/web_session_state_cache.h" #import "ios/chrome/browser/web/session_state/web_session_state_cache_web_state_list_observer.h" @@ -77,7 +76,6 @@ // static WebSessionStateCache* WebSessionStateCacheFactory::GetForBrowserState( ChromeBrowserState* browser_state) { - CHECK(web::UseNativeSessionRestorationCache()); WebSessionStateCacheWrapper* wrapper = static_cast<WebSessionStateCacheWrapper*>( GetInstance()->GetServiceForBrowserState(browser_state, true));
diff --git a/ios/chrome/browser/web/session_state/web_session_state_cache_web_state_list_observer.mm b/ios/chrome/browser/web/session_state/web_session_state_cache_web_state_list_observer.mm index c1e6e705..dedab84 100644 --- a/ios/chrome/browser/web/session_state/web_session_state_cache_web_state_list_observer.mm +++ b/ios/chrome/browser/web/session_state/web_session_state_cache_web_state_list_observer.mm
@@ -47,14 +47,14 @@ case WebStateListChange::Type::kMove: // Do nothing when a WebState is moved. break; - case WebStateListChange::Type::kReplace: { - const WebStateListChangeReplace& replace_change = - change.As<WebStateListChangeReplace>(); - WebSessionStateTabHelper::FromWebState( - replace_change.inserted_web_state()) - ->SaveSessionState(); + case WebStateListChange::Type::kReplace: + if (WebSessionStateTabHelper* tab_helper = + WebSessionStateTabHelper::FromWebState( + change.As<WebStateListChangeReplace>() + .inserted_web_state())) { + tab_helper->SaveSessionState(); + } break; - } case WebStateListChange::Type::kInsert: // Do nothing when a new WebState is inserted. break;
diff --git a/ios/chrome/browser/web/session_state/web_session_state_tab_helper.mm b/ios/chrome/browser/web/session_state/web_session_state_tab_helper.mm index 3b52878..4c5af0f5 100644 --- a/ios/chrome/browser/web/session_state/web_session_state_tab_helper.mm +++ b/ios/chrome/browser/web/session_state/web_session_state_tab_helper.mm
@@ -18,10 +18,8 @@ #import "components/strings/grit/components_strings.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/shared/model/url/chrome_url_constants.h" -#import "ios/chrome/browser/web/features.h" #import "ios/chrome/browser/web/session_state/web_session_state_cache.h" #import "ios/chrome/browser/web/session_state/web_session_state_cache_factory.h" -#import "ios/web/common/features.h" #import "ios/web/public/js_messaging/web_frame.h" #import "ios/web/public/navigation/navigation_context.h" #import "ios/web/public/navigation/navigation_manager.h" @@ -72,7 +70,6 @@ WebSessionStateTabHelper::WebSessionStateTabHelper(web::WebState* web_state) : web_state_(web_state) { - CHECK(web::UseNativeSessionRestorationCache()); web_state_->AddObserver(this); web_state_->GetPageWorldWebFramesManager()->AddObserver(this); if (web_state_->IsRealized()) {
diff --git a/ios/chrome/browser/web/session_state/web_session_state_tab_helper_unittest.mm b/ios/chrome/browser/web/session_state/web_session_state_tab_helper_unittest.mm index 87cd476..00703a0 100644 --- a/ios/chrome/browser/web/session_state/web_session_state_tab_helper_unittest.mm +++ b/ios/chrome/browser/web/session_state/web_session_state_tab_helper_unittest.mm
@@ -13,14 +13,11 @@ #import "base/strings/stringprintf.h" #import "base/task/thread_pool/thread_pool_instance.h" #import "base/test/ios/wait_util.h" -#import "base/test/scoped_feature_list.h" #import "ios/chrome/browser/sessions/session_constants.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/shared/model/url/chrome_url_constants.h" #import "ios/chrome/browser/web/chrome_web_client.h" -#import "ios/chrome/browser/web/features.h" #import "ios/chrome/browser/web/session_state/web_session_state_cache.h" -#import "ios/web/common/features.h" #import "ios/web/public/navigation/navigation_item.h" #import "ios/web/public/navigation/navigation_manager.h" #import "ios/web/public/session/serializable_user_data_manager.h" @@ -38,12 +35,7 @@ class WebSessionStateTabHelperTest : public PlatformTest { public: WebSessionStateTabHelperTest() - : web_client_(std::make_unique<ChromeWebClient>()) { - scoped_feature_list_.InitWithFeatures( - /*enabled_features=*/{web::kRestoreSessionFromCache}, - /*disabled_features=*/{ - web::features::kEnableSessionSerializationOptimizations}); - } + : web_client_(std::make_unique<ChromeWebClient>()) {} void SetUp() override { PlatformTest::SetUp(); @@ -75,7 +67,6 @@ protected: web::WebState* web_state() { return web_state_.get(); } - base::test::ScopedFeatureList scoped_feature_list_; web::ScopedTestingWebClient web_client_; web::WebTaskEnvironment task_environment_; std::unique_ptr<TestChromeBrowserState> browser_state_;
diff --git a/ios/chrome/browser/web/ssl_egtest.mm b/ios/chrome/browser/web/ssl_egtest.mm index 98290ce..df986b3 100644 --- a/ios/chrome/browser/web/ssl_egtest.mm +++ b/ios/chrome/browser/web/ssl_egtest.mm
@@ -82,7 +82,7 @@ // Test loading a page with a bad SSL certificate during session restore, to // avoid regressing https://crbug.com/1050808. - (void)testBadSSLInSessionRestore { - [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo]; + [self triggerRestoreByRestartingApplication]; [ChromeEarlGrey waitForWebStateContainingText:l10n_util::GetStringUTF8( IDS_SSL_V2_HEADING)]; }
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h index a2dd1de..2afca5d 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -616,10 +616,6 @@ // Cache-Control response header says otherwise. - (void)purgeCachedWebViewPages; -// Simulators background, killing, and restoring the app within the limitations -// of EG1, by simply doing a tab grid close all / undo / done. -- (void)triggerRestoreViaTabGridRemoveAllUndo; - // Returns YES if the current WebState's web view uses the content inset to // correctly align the top of the content with the bottom of the top bar. - (BOOL)webStateWebViewUsesContentInset;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index 3bc9a62..d4074ef3 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -769,21 +769,6 @@ [self waitForPageToFinishLoading]; } -- (void)triggerRestoreViaTabGridRemoveAllUndo { - [ChromeEarlGrey showTabSwitcher]; - GREYWaitForAppToIdle(@"App failed to idle"); - [ChromeEarlGrey - waitForAndTapButton:grey_allOf(chrome_test_util::TabGridEditButton(), - grey_sufficientlyVisible(), nil)]; - [ChromeEarlGrey - waitForAndTapButton:chrome_test_util::TabGridEditMenuCloseAllButton()]; - [ChromeEarlGrey - waitForAndTapButton:chrome_test_util::TabGridUndoCloseAllButton()]; - [ChromeEarlGrey waitForAndTapButton:chrome_test_util::TabGridDoneButton()]; - [self waitForRestoreSessionToFinish]; - [self waitForPageToFinishLoading]; -} - - (BOOL)webStateWebViewUsesContentInset { return [ChromeEarlGreyAppInterface webStateWebViewUsesContentInset]; }
diff --git a/ios/chrome/test/earl_grey/chrome_test_case.h b/ios/chrome/test/earl_grey/chrome_test_case.h index 8dbf0e17..1fad3e7 100644 --- a/ios/chrome/test/earl_grey/chrome_test_case.h +++ b/ios/chrome/test/earl_grey/chrome_test_case.h
@@ -54,6 +54,10 @@ // name of the currently running test method. - (BOOL)isRunningTest:(SEL)selector; +// Forces reloading the current session by restarting the app. This restarts +// the app with the same configuration as used by -setUp. +- (void)triggerRestoreByRestartingApplication; + // Configures the fixture for startup testing. + (void)testForStartup;
diff --git a/ios/chrome/test/earl_grey/chrome_test_case.mm b/ios/chrome/test/earl_grey/chrome_test_case.mm index 3b67b18..3abe8b5 100644 --- a/ios/chrome/test/earl_grey/chrome_test_case.mm +++ b/ios/chrome/test/earl_grey/chrome_test_case.mm
@@ -323,6 +323,12 @@ isEqualToString:NSStringFromSelector(selector)]; } +- (void)triggerRestoreByRestartingApplication { + AppLaunchConfiguration config = [self appConfigurationForTestCase]; + config.relaunch_policy = ForceRelaunchByCleanShutdown; + [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config]; +} + + (void)testForStartup { gStartupTest = YES; }
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h index 8988b7b..59635c9b 100644 --- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h +++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
@@ -12,7 +12,7 @@ #include "base/memory/weak_ptr.h" #include "components/autofill/core/browser/autocomplete_history_manager.h" #include "components/autofill/core/browser/autofill_client.h" -#include "components/autofill/core/browser/autofill_download_manager.h" +#include "components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.h" #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/browser/payments/card_unmask_delegate.h" #include "components/autofill/core/browser/payments/legal_message_line.h" @@ -58,7 +58,7 @@ // AutofillClient: bool IsOffTheRecord() override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; - AutofillDownloadManager* GetDownloadManager() override; + AutofillCrowdsourcingManager* GetCrowdsourcingManager() override; PersonalDataManager* GetPersonalDataManager() override; AutocompleteHistoryManager* GetAutocompleteHistoryManager() override; CreditCardCvcAuthenticator* GetCvcAuthenticator() override; @@ -145,7 +145,7 @@ private: PrefService* pref_service_; - std::unique_ptr<AutofillDownloadManager> download_manager_; + std::unique_ptr<AutofillCrowdsourcingManager> crowdsourcing_manager_; PersonalDataManager* personal_data_manager_; AutocompleteHistoryManager* autocomplete_history_manager_; web::WebState* web_state_;
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm index 72653bcc..dfacfce 100644 --- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm +++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -108,13 +108,14 @@ web_state_->GetBrowserState()->GetURLLoaderFactory()); } -AutofillDownloadManager* WebViewAutofillClientIOS::GetDownloadManager() { - if (!download_manager_) { +AutofillCrowdsourcingManager* +WebViewAutofillClientIOS::GetCrowdsourcingManager() { + if (!crowdsourcing_manager_) { // Lazy initialization to avoid virtual function calls in the constructor. - download_manager_ = std::make_unique<AutofillDownloadManager>( + crowdsourcing_manager_ = std::make_unique<AutofillCrowdsourcingManager>( this, GetChannel(), GetLogManager()); } - return download_manager_.get(); + return crowdsourcing_manager_.get(); } PersonalDataManager* WebViewAutofillClientIOS::GetPersonalDataManager() {
diff --git a/ios_internal b/ios_internal index 0715482..a71771e 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 0715482852883c643a16a68c3f6c01965c7e0ab2 +Subproject commit a71771e41c4c362860b19a619ce1ba6b018903b1
diff --git a/media/renderers/renderer_impl_unittest.cc b/media/renderers/renderer_impl_unittest.cc index 05a3a2a..f3c80d5 100644 --- a/media/renderers/renderer_impl_unittest.cc +++ b/media/renderers/renderer_impl_unittest.cc
@@ -42,10 +42,6 @@ const int64_t kStartPlayingTimeInMs = 100; -ACTION_P2(SetBool, var, value) { - *var = value; -} - ACTION_P3(SetBufferingState, renderer_client, buffering_state, reason) { (*renderer_client)->OnBufferingStateChange(buffering_state, reason); } @@ -54,15 +50,6 @@ (*renderer_client)->OnError(error); } -ACTION(PostCallback) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, arg0); -} - -ACTION(PostQuitWhenIdle) { - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); -} - class RendererImplTest : public ::testing::Test { public: class CallbackHelper : public MockRendererClient {
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index 6c6b6af..b3bbab8b 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -551,12 +551,11 @@ gfx::BufferUsage::SCANOUT, SinglePlaneSharedImageFormatToBufferFormat(format), caps); } - auto client_shared_image = sii->CreateSharedImage( + shared_image_ = sii->CreateSharedImage( format, size, color_space, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, shared_image_usage, "VideoResourceUpdater", gpu::kNullSurfaceHandle); - CHECK(client_shared_image); - mailbox_ = client_shared_image->mailbox(); + CHECK(shared_image_); InterfaceBase()->WaitSyncTokenCHROMIUM( sii->GenUnverifiedSyncToken().GetConstData()); } @@ -567,10 +566,11 @@ ~HardwarePlaneResource() override { gpu::SyncToken sync_token; InterfaceBase()->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); - SharedImageInterface()->DestroySharedImage(sync_token, mailbox_); + SharedImageInterface()->DestroySharedImage(sync_token, + std::move(shared_image_)); } - const gpu::Mailbox& mailbox() const { return mailbox_; } + const gpu::Mailbox& mailbox() const { return shared_image_->mailbox(); } GLenum texture_target() const { return texture_target_; } bool overlay_candidate() const { return overlay_candidate_; } @@ -601,7 +601,7 @@ } const raw_ptr<viz::RasterContextProvider> context_provider_; - gpu::Mailbox mailbox_; + scoped_refptr<gpu::ClientSharedImage> shared_image_; GLenum texture_target_ = GL_TEXTURE_2D; bool overlay_candidate_ = false; };
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc index a1bb4408..5ff4540 100644 --- a/net/disk_cache/backend_unittest.cc +++ b/net/disk_cache/backend_unittest.cc
@@ -5618,3 +5618,21 @@ // Should not have eaten any entries. EXPECT_EQ(kEntries, cache_->GetEntryCount()); } + +// Make sure that if we close an entry in callback from open/create we do not +// trigger dangling pointer warnings. +TEST_F(DiskCacheBackendTest, BlockFileImmediateCloseNoDangle) { + InitCache(); + base::RunLoop run_loop; + EntryResult result = + cache_->CreateEntry("some key", net::HIGHEST, + base::BindLambdaForTesting([&](EntryResult result) { + ASSERT_EQ(result.net_error(), net::OK); + result.ReleaseEntry()->Close(); + // Make sure the close actually happens now. + disk_cache::BackendImpl::FlushForTesting(); + run_loop.Quit(); + })); + EXPECT_EQ(result.net_error(), net::ERR_IO_PENDING); + run_loop.Run(); +}
diff --git a/net/disk_cache/blockfile/in_flight_backend_io.cc b/net/disk_cache/blockfile/in_flight_backend_io.cc index e272381..9401cb93 100644 --- a/net/disk_cache/blockfile/in_flight_backend_io.cc +++ b/net/disk_cache/blockfile/in_flight_backend_io.cc
@@ -125,9 +125,9 @@ if (result_ != net::OK) { entry_result = EntryResult::MakeError(static_cast<net::Error>(result())); } else if (out_entry_opened_) { - entry_result = EntryResult::MakeOpened(out_entry_); + entry_result = EntryResult::MakeOpened(out_entry_.ExtractAsDangling()); } else { - entry_result = EntryResult::MakeCreated(out_entry_); + entry_result = EntryResult::MakeCreated(out_entry_.ExtractAsDangling()); } std::move(entry_result_callback_).Run(std::move(entry_result)); }
diff --git a/net/disk_cache/blockfile/in_flight_backend_io.h b/net/disk_cache/blockfile/in_flight_backend_io.h index 1eecdad..fb013b3 100644 --- a/net/disk_cache/blockfile/in_flight_backend_io.h +++ b/net/disk_cache/blockfile/in_flight_backend_io.h
@@ -162,7 +162,7 @@ // Used for ops that open or create entries. EntryResultCallback entry_result_callback_; // if set, already has the user's ref added. - raw_ptr<EntryImpl, AcrossTasksDanglingUntriaged> out_entry_ = nullptr; + raw_ptr<EntryImpl> out_entry_ = nullptr; bool out_entry_opened_ = false; // For GetAvailableRange
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index daac947..95d6fd33 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2023-11-28 12:55 UTC +# Last updated: 2023-11-29 12:55 UTC PinsListTimestamp -1701176106 +1701262532 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json index 6da02346..14beac1 100644 --- a/net/http/transport_security_state_static_pins.json +++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@ // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets' // refer to, and the timestamp at which the pins list was last updated. // -// Last updated: 2023-11-28 12:55 UTC +// Last updated: 2023-11-29 12:55 UTC // { "pinsets": [
diff --git a/remoting/protocol/pseudotcp_adapter_unittest.cc b/remoting/protocol/pseudotcp_adapter_unittest.cc index 42ef315..d8d5772 100644 --- a/remoting/protocol/pseudotcp_adapter_unittest.cc +++ b/remoting/protocol/pseudotcp_adapter_unittest.cc
@@ -161,13 +161,15 @@ public: TCPChannelTester(scoped_refptr<base::SingleThreadTaskRunner> task_runner, P2PStreamSocket* client_socket, - P2PStreamSocket* host_socket) + P2PStreamSocket* host_socket, + raw_ptr<base::RunLoop> loop) : task_runner_(std::move(task_runner)), host_socket_(host_socket), client_socket_(client_socket), done_(false), write_errors_(0), - read_errors_(0) {} + read_errors_(0), + loop_(loop) {} void Start() { task_runner_->PostTask(FROM_HERE, @@ -192,8 +194,7 @@ void Done() { done_ = true; - task_runner_->PostTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); + loop_->QuitWhenIdle(); } void DoStart() { @@ -291,6 +292,8 @@ int write_errors_; int read_errors_; + + raw_ptr<base::RunLoop> loop_; }; class PseudoTcpAdapterTest : public testing::Test { @@ -321,6 +324,7 @@ TEST_F(PseudoTcpAdapterTest, DataTransfer) { net::TestCompletionCallback host_connect_cb; net::TestCompletionCallback client_connect_cb; + base::RunLoop loop; net::CompletionOnceCallback rv1 = host_pseudotcp_->Connect(host_connect_cb.callback()); @@ -332,12 +336,12 @@ EXPECT_EQ(net::OK, host_connect_cb.WaitForResult()); EXPECT_EQ(net::OK, client_connect_cb.WaitForResult()); - scoped_refptr<TCPChannelTester> tester = - new TCPChannelTester(base::SingleThreadTaskRunner::GetCurrentDefault(), - host_pseudotcp_.get(), client_pseudotcp_.get()); + scoped_refptr<TCPChannelTester> tester = new TCPChannelTester( + base::SingleThreadTaskRunner::GetCurrentDefault(), host_pseudotcp_.get(), + client_pseudotcp_.get(), &loop); tester->Start(); - base::RunLoop().Run(); + loop.Run(); tester->CheckResults(); } @@ -345,7 +349,7 @@ const int kLatencyMs = 20; const int kPacketsPerSecond = 400; const int kBurstPackets = 10; - + base::RunLoop loop; LeakyBucket host_limiter(kBurstPackets, kPacketsPerSecond); host_socket_->set_latency(kLatencyMs); host_socket_->set_rate_limiter(&host_limiter); @@ -367,12 +371,12 @@ EXPECT_EQ(net::OK, host_connect_cb.WaitForResult()); EXPECT_EQ(net::OK, client_connect_cb.WaitForResult()); - scoped_refptr<TCPChannelTester> tester = - new TCPChannelTester(base::SingleThreadTaskRunner::GetCurrentDefault(), - host_pseudotcp_.get(), client_pseudotcp_.get()); + scoped_refptr<TCPChannelTester> tester = new TCPChannelTester( + base::SingleThreadTaskRunner::GetCurrentDefault(), host_pseudotcp_.get(), + client_pseudotcp_.get(), &loop); tester->Start(); - base::RunLoop().Run(); + loop.Run(); tester->CheckResults(); // Drop unowned reference before local goes out of scope. @@ -382,29 +386,32 @@ class DeleteOnConnected { public: DeleteOnConnected(scoped_refptr<base::SingleThreadTaskRunner> task_runner, - std::unique_ptr<PseudoTcpAdapter>* adapter) - : task_runner_(std::move(task_runner)), adapter_(adapter) {} + std::unique_ptr<PseudoTcpAdapter>* adapter, + raw_ptr<base::RunLoop> loop) + : task_runner_(std::move(task_runner)), adapter_(adapter), loop_(loop) {} void OnConnected(int error) { adapter_->reset(); - task_runner_->PostTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); + loop_->QuitWhenIdle(); } scoped_refptr<base::SingleThreadTaskRunner> task_runner_; raw_ptr<std::unique_ptr<PseudoTcpAdapter>> adapter_; + raw_ptr<base::RunLoop> loop_; }; TEST_F(PseudoTcpAdapterTest, DeleteOnConnected) { // This test verifies that deleting the adapter mid-callback doesn't lead // to deleted structures being touched as the stack unrolls, so the failure // mode is a crash rather than a normal test failure. + base::RunLoop loop; net::TestCompletionCallback client_connect_cb; DeleteOnConnected host_delete( - base::SingleThreadTaskRunner::GetCurrentDefault(), &host_pseudotcp_); + base::SingleThreadTaskRunner::GetCurrentDefault(), &host_pseudotcp_, + &loop); host_pseudotcp_->Connect(base::BindOnce(&DeleteOnConnected::OnConnected, base::Unretained(&host_delete))); client_pseudotcp_->Connect(client_connect_cb.callback()); - base::RunLoop().Run(); + loop.Run(); ASSERT_EQ(NULL, host_pseudotcp_.get()); } @@ -415,6 +422,7 @@ net::TestCompletionCallback host_connect_cb; net::TestCompletionCallback client_connect_cb; + base::RunLoop loop; host_pseudotcp_->SetWriteWaitsForSend(true); client_pseudotcp_->SetWriteWaitsForSend(true); @@ -432,12 +440,12 @@ EXPECT_EQ(net::OK, host_connect_cb.WaitForResult()); EXPECT_EQ(net::OK, client_connect_cb.WaitForResult()); - scoped_refptr<TCPChannelTester> tester = - new TCPChannelTester(base::SingleThreadTaskRunner::GetCurrentDefault(), - host_pseudotcp_.get(), client_pseudotcp_.get()); + scoped_refptr<TCPChannelTester> tester = new TCPChannelTester( + base::SingleThreadTaskRunner::GetCurrentDefault(), host_pseudotcp_.get(), + client_pseudotcp_.get(), &loop); tester->Start(); - base::RunLoop().Run(); + loop.Run(); tester->CheckResults(); }
diff --git a/services/on_device_model/ml/chrome_ml_api.h b/services/on_device_model/ml/chrome_ml_api.h index 7b0ebf3b..8f68402 100644 --- a/services/on_device_model/ml/chrome_ml_api.h +++ b/services/on_device_model/ml/chrome_ml_api.h
@@ -60,15 +60,22 @@ // The maximum input+output tokens the model can handle. uint32_t max_tokens; + + // Packed TS data. + const void* ts_data; + size_t ts_size; + const void* ts_spm_data; + size_t ts_spm_size; }; // Function provided from the library that will cancel the corresponding input // and output when called. This is safe to call on any thread. using ChromeMLCancelFn = std::function<void()>; -// Receives tokens from a call to RunModel(). If the output is complete or -// there is an error the token will be std::nullopt. This will be called on the -// internal thread executing the model. +// Receives tokens from a call to RunModel(). This will be called on the +// internal thread executing the model. If no completion callback is provided to +// ExecuteModel(), this function will be invoked with std::nullopt to signify +// that model execution is complete. using ChromeMLOutputFn = std::function<void(const std::optional<std::string>&)>; // Called with the number of tokens processed after a call to RunModel() @@ -76,6 +83,18 @@ // thread executing the model. using ChromeMLContextSavedFn = std::function<void(int)>; +// Conveys details regarding a completed model execution. +struct ChromeMLExecutionResult { + // If true, all prior output received for this model execution is effectively + // retracted by the library and should be discarded by the client. + bool retracted; +}; + +// Called when a model has finished executing. No other functions given to +// ExecuteModel() will be invoked after this. +using ChromeMLCompletionFn = + std::function<void(const ChromeMLExecutionResult&)>; + struct ChromeMLExecuteOptions { const char* prompt = nullptr; int context_mode = ContextMode::kNone; @@ -83,6 +102,7 @@ uint32_t token_offset = 0; const ChromeMLOutputFn* output_fn = nullptr; const ChromeMLContextSavedFn* context_saved_fn = nullptr; + const ChromeMLCompletionFn* completion_fn = nullptr; }; // Performance data filled out by GetEstimatedPerformance().
diff --git a/services/on_device_model/ml/on_device_model_executor.cc b/services/on_device_model/ml/on_device_model_executor.cc index 95971623..8650f2f 100644 --- a/services/on_device_model/ml/on_device_model_executor.cc +++ b/services/on_device_model/ml/on_device_model_executor.cc
@@ -14,6 +14,7 @@ #include "services/on_device_model/ml/chrome_ml.h" #include "services/on_device_model/public/cpp/features.h" #include "services/on_device_model/public/mojom/on_device_model.mojom.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" #if BUILDFLAG(IS_MAC) #include "base/apple/foundation_util.h" @@ -27,6 +28,19 @@ const base::FeatureParam<std::string> kGpuBlockList{ &on_device_model::features::kOnDeviceModelService, "gpu_block_list", ""}; +// Helper to bind object methods as weak task-posting callback functions. +template <typename R, typename C, typename... Args> +std::function<R(Args...)> CreateWeakCallbackFn(R (C::*method)(Args...), + C* that) { + return [weak_ptr = that->AsWeakPtr(), method, + task_runner = + base::SequencedTaskRunner::GetCurrentDefault()](Args&&... args) { + task_runner->PostTask( + FROM_HERE, + base::BindOnce(method, weak_ptr, std::forward<Args>(args)...)); + }; +} + // Handles sending and canceling responses. class Responder : public base::SupportsWeakPtr<Responder> { public: @@ -41,12 +55,11 @@ ChromeMLCancelFn* GetCancelFn() { return &cancel_; } ChromeMLOutputFn CreateOutputFn() { - return [weak_ptr = AsWeakPtr(), - task_runner = base::SequencedTaskRunner::GetCurrentDefault()]( - const std::optional<std::string>& token) { - task_runner->PostTask( - FROM_HERE, base::BindOnce(&Responder::OnResponse, weak_ptr, token)); - }; + return CreateWeakCallbackFn(&Responder::OnResponse, this); + } + + ChromeMLCompletionFn CreateCompletionFn() { + return CreateWeakCallbackFn(&Responder::OnComplete, this); } private: @@ -54,7 +67,22 @@ if (token.has_value()) { responder_->OnResponse(*token); } else { - responder_->OnComplete(); + // If the model invokes OnResponse() with no token, this implies + // completion without retraction. + OnComplete(ChromeMLExecutionResult{.retracted = false}); + } + } + + void OnComplete(const ChromeMLExecutionResult& result) { + if (!responder_) { + return; + } + + using ResponseStatus = on_device_model::mojom::ResponseStatus; + if (result.retracted) { + responder_->OnComplete(ResponseStatus::kRetracted); + } else { + responder_->OnComplete(ResponseStatus::kOk); } } @@ -152,6 +180,7 @@ response) override { responder_ = std::make_unique<Responder>(std::move(response)); ChromeMLOutputFn output_fn = responder_->CreateOutputFn(); + ChromeMLCompletionFn completion_fn = responder_->CreateCompletionFn(); std::string adjusted_input = input->text + " <ctrl23>"; ChromeMLExecuteOptions options{ .prompt = adjusted_input.c_str(), @@ -159,6 +188,7 @@ .max_tokens = input->max_tokens.value_or(0), .token_offset = input->token_offset.value_or(0), .output_fn = &output_fn, + .completion_fn = &completion_fn, }; chrome_ml_->api().ExecuteModel(model_, &options, responder_->GetCancelFn()); } @@ -267,18 +297,34 @@ return LoadModelResult::kFailedToLoadLibrary; } + if (assets.ts_data.IsValid()) { + if (!ts_data_.Initialize(std::move(assets.ts_data)) || + !assets.ts_sp_model.IsValid() || + !ts_sp_model_.Initialize(std::move(assets.ts_sp_model))) { + LOG(ERROR) << "Invalid TS model data supplied"; + return LoadModelResult::kFailedToLoadLibrary; + } + } + const ChromeMLModelData data = { .model_proto_data = model_proto_.data(), .model_proto_size = model_proto_.length(), .weights_data = weights_.mutable_bytes().data(), .weights_size = weights_.length(), }; - const ChromeMLModelDescriptor descriptor = { + ChromeMLModelDescriptor descriptor = { .sentencepiece_model_proto_data = sentencepiece_model_proto_.data(), .sentencepiece_model_proto_size = sentencepiece_model_proto_.length(), .model_data = &data, .max_tokens = params->max_tokens, }; + if (ts_data_.IsValid()) { + CHECK(ts_sp_model_.IsValid()); + descriptor.ts_data = ts_data_.data(); + descriptor.ts_size = ts_data_.length(); + descriptor.ts_spm_data = ts_sp_model_.data(); + descriptor.ts_spm_size = ts_sp_model_.length(); + }; model_ = chrome_ml_->api().CreateModel(&descriptor, reinterpret_cast<uintptr_t>(this), OnDeviceModelExecutor::Schedule);
diff --git a/services/on_device_model/ml/on_device_model_executor.h b/services/on_device_model/ml/on_device_model_executor.h index 1e4e609..fccf958 100644 --- a/services/on_device_model/ml/on_device_model_executor.h +++ b/services/on_device_model/ml/on_device_model_executor.h
@@ -16,6 +16,7 @@ #include "services/on_device_model/public/cpp/model_assets.h" #include "services/on_device_model/public/cpp/on_device_model.h" #include "services/on_device_model/public/mojom/on_device_model.mojom.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace ml { @@ -49,6 +50,8 @@ base::MemoryMappedFile sentencepiece_model_proto_; base::MemoryMappedFile model_proto_; base::MemoryMappedFile weights_; + base::MemoryMappedFile ts_data_; + base::MemoryMappedFile ts_sp_model_; ChromeMLModel model_ = 0; scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/services/on_device_model/on_device_model.cc b/services/on_device_model/on_device_model.cc index 1427cc7..99a92be7 100644 --- a/services/on_device_model/on_device_model.cc +++ b/services/on_device_model/on_device_model.cc
@@ -43,7 +43,7 @@ } } remote->OnResponse("Input: " + input->text + "\n"); - remote->OnComplete(); + remote->OnComplete(mojom::ResponseStatus::kOk); } private:
diff --git a/services/on_device_model/on_device_model_service.h b/services/on_device_model/on_device_model_service.h index cbd9090..002b76336 100644 --- a/services/on_device_model/on_device_model_service.h +++ b/services/on_device_model/on_device_model_service.h
@@ -12,6 +12,7 @@ #include "mojo/public/cpp/bindings/unique_receiver_set.h" #include "services/on_device_model/public/cpp/on_device_model.h" #include "services/on_device_model/public/mojom/on_device_model.mojom.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #include "sandbox/policy/linux/sandbox_linux.h"
diff --git a/services/on_device_model/on_device_model_service_unittest.cc b/services/on_device_model/on_device_model_service_unittest.cc index cb60931..7dc8ed8 100644 --- a/services/on_device_model/on_device_model_service_unittest.cc +++ b/services/on_device_model/on_device_model_service_unittest.cc
@@ -25,7 +25,7 @@ responses_.push_back(text); } - void OnComplete() override { run_loop_.Quit(); } + void OnComplete(mojom::ResponseStatus status) override { run_loop_.Quit(); } void WaitForCompletion() { run_loop_.Run(); }
diff --git a/services/on_device_model/public/cpp/model_assets.cc b/services/on_device_model/public/cpp/model_assets.cc index e7e57ed..1a139656 100644 --- a/services/on_device_model/public/cpp/model_assets.cc +++ b/services/on_device_model/public/cpp/model_assets.cc
@@ -17,15 +17,31 @@ constexpr std::string_view kSpModelFile = "spm.model"; constexpr std::string_view kModelFile = "model.pb"; constexpr std::string_view kWeightsFile = "weights.bin"; +constexpr std::string_view kTsDataFile = "ts.bin"; +constexpr std::string_view kTsSpModelFile = "ts_spm.model"; } // namespace -ModelAssets LoadModelAssets(const base::FilePath& model_path) { +ModelAssets::ModelAssets() = default; + +ModelAssets::ModelAssets(ModelAssets&&) = default; + +ModelAssets& ModelAssets::operator=(ModelAssets&&) = default; + +ModelAssets::~ModelAssets() = default; + +ModelAssets LoadModelAssets(const base::FilePath& model_path, + const base::FilePath& ts_path) { ModelAssets assets; assets.sp_model = base::File(model_path.AppendASCII(kSpModelFile), base::File::FLAG_OPEN | base::File::FLAG_READ); assets.model = base::File(model_path.AppendASCII(kModelFile), base::File::FLAG_OPEN | base::File::FLAG_READ); + assets.ts_data = base::File(ts_path.AppendASCII(kTsDataFile), + base::File::FLAG_OPEN | base::File::FLAG_READ); + assets.ts_sp_model = + base::File(ts_path.AppendASCII(kTsSpModelFile), + base::File::FLAG_OPEN | base::File::FLAG_READ); // NOTE: Weights ultimately need to be mapped copy-on-write, but Fuchsia // (due to an apparent bug?) doesn't seem to support copy-on-write mapping of
diff --git a/services/on_device_model/public/cpp/model_assets.h b/services/on_device_model/public/cpp/model_assets.h index 5656e22..c5c47137 100644 --- a/services/on_device_model/public/cpp/model_assets.h +++ b/services/on_device_model/public/cpp/model_assets.h
@@ -14,19 +14,22 @@ // A bundle of opened file assets comprising model description to use for // execution. struct COMPONENT_EXPORT(ON_DEVICE_MODEL_ASSETS_CPP) ModelAssets { - ModelAssets() = default; - ModelAssets(ModelAssets&&) = default; - ModelAssets& operator=(ModelAssets&&) = default; - ~ModelAssets() = default; + ModelAssets(); + ModelAssets(ModelAssets&&); + ModelAssets& operator=(ModelAssets&&); + ~ModelAssets(); base::File sp_model; base::File model; base::File weights; + base::File ts_data; + base::File ts_sp_model; }; -// Helper to open files for ModelAssets given a base path. +// Helper to open files for ModelAssets given their containing paths. COMPONENT_EXPORT(ON_DEVICE_MODEL_ASSETS_CPP) -ModelAssets LoadModelAssets(const base::FilePath& model_path); +ModelAssets LoadModelAssets(const base::FilePath& model_path, + const base::FilePath& ts_path); } // namespace on_device_model
diff --git a/services/on_device_model/public/cpp/model_assets_mojom_traits.cc b/services/on_device_model/public/cpp/model_assets_mojom_traits.cc index 96978245..6e6b07b 100644 --- a/services/on_device_model/public/cpp/model_assets_mojom_traits.cc +++ b/services/on_device_model/public/cpp/model_assets_mojom_traits.cc
@@ -4,7 +4,7 @@ #include "services/on_device_model/public/cpp/model_assets_mojom_traits.h" -#include "services/on_device_model/public/mojom/on_device_model.mojom-shared.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom-shared.h" namespace mojo { @@ -14,7 +14,9 @@ Read(on_device_model::mojom::ModelAssetsDataView data, on_device_model::ModelAssets* assets) { return data.ReadSpModel(&assets->sp_model) && - data.ReadModel(&assets->model) && data.ReadWeights(&assets->weights); + data.ReadModel(&assets->model) && data.ReadWeights(&assets->weights) && + data.ReadTsData(&assets->ts_data) && + data.ReadTsSpModel(&assets->ts_sp_model); } } // namespace mojo
diff --git a/services/on_device_model/public/cpp/model_assets_mojom_traits.h b/services/on_device_model/public/cpp/model_assets_mojom_traits.h index a1db138..b236e9a 100644 --- a/services/on_device_model/public/cpp/model_assets_mojom_traits.h +++ b/services/on_device_model/public/cpp/model_assets_mojom_traits.h
@@ -8,8 +8,9 @@ #include "base/component_export.h" #include "base/files/file.h" #include "mojo/public/cpp/base/file_mojom_traits.h" +#include "mojo/public/cpp/base/read_only_file_mojom_traits.h" #include "services/on_device_model/public/cpp/model_assets.h" -#include "services/on_device_model/public/mojom/on_device_model.mojom-shared.h" +#include "services/on_device_model/public/mojom/on_device_model_service.mojom-shared.h" namespace mojo { @@ -29,6 +30,14 @@ return std::move(assets.weights); } + static base::File ts_data(on_device_model::ModelAssets& assets) { + return std::move(assets.ts_data); + } + + static base::File ts_sp_model(on_device_model::ModelAssets& assets) { + return std::move(assets.ts_sp_model); + } + static bool Read(on_device_model::mojom::ModelAssetsDataView data, on_device_model::ModelAssets* assets); };
diff --git a/services/on_device_model/public/mojom/BUILD.gn b/services/on_device_model/public/mojom/BUILD.gn index adaa1c8..a3687a95 100644 --- a/services/on_device_model/public/mojom/BUILD.gn +++ b/services/on_device_model/public/mojom/BUILD.gn
@@ -5,7 +5,10 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("mojom") { - sources = [ "on_device_model.mojom" ] + sources = [ + "on_device_model.mojom", + "on_device_model_service.mojom", + ] public_deps = [ "//mojo/public/mojom/base", "//sandbox/policy/mojom",
diff --git a/services/on_device_model/public/mojom/on_device_model.mojom b/services/on_device_model/public/mojom/on_device_model.mojom index 6578d4a..fa981aec 100644 --- a/services/on_device_model/public/mojom/on_device_model.mojom +++ b/services/on_device_model/public/mojom/on_device_model.mojom
@@ -4,9 +4,17 @@ module on_device_model.mojom; -import "mojo/public/mojom/base/file.mojom"; -import "sandbox/policy/mojom/context.mojom"; -import "sandbox/policy/mojom/sandbox.mojom"; +// Specifies how a client should regard a completed response from a +// StreamingResponder. +enum ResponseStatus { + // The full response has been streamed successfully and should be taken as-is + // by the client. + kOk, + + // The response is done streaming, but it has been retracted by the service. + // The client should discard this response. + kRetracted, +}; // Streams a response from a call to execute a model. Close this pipe to cancel // the call to |Execute()|. @@ -16,7 +24,8 @@ // This is called once when all text for the query has been returned. // OnResponse() will not be called after OnComplete() has been called. - OnComplete(); + // `status` specifies how the client should regard this completion. + OnComplete(ResponseStatus status); }; // Notifies the caller when the model is done processing context. Close this @@ -67,13 +76,6 @@ StartSession(pending_receiver<Session> session); }; -// Opened file resources needed to define the model. -struct ModelAssets { - mojo_base.mojom.File? sp_model; - mojo_base.mojom.File? model; - mojo_base.mojom.File? weights; -}; - // Classifies the device based on how fast it is estimated to be able to run a // model. enum PerformanceClass { @@ -89,32 +91,8 @@ kVeryHigh, }; -// Params to describe the model to load. -struct LoadModelParams { - // Assets for the model. - ModelAssets assets; - - // The maximum number of input+output tokens the model can handle. This is - // needed when initializing the model. - uint32 max_tokens; -}; - enum LoadModelResult { kSuccess, kGpuBlocked, kFailedToLoadLibrary, }; - -// A service which allows loading trusted models which are stored on-device and -// which may process untrustworthy data. -[ServiceSandbox=sandbox.mojom.Sandbox.kOnDeviceModelExecution, - RequireContext=sandbox.mojom.Context.kBrowser] -interface OnDeviceModelService { - // Initializes a new model instance given `assets`. If the model can not be - // created the model pipe will be reset. - LoadModel(LoadModelParams params, pending_receiver<OnDeviceModel> model) => - (LoadModelResult result); - - // Returns the performance class based on benchmarks run on the device. - GetEstimatedPerformanceClass() => (PerformanceClass performance_class); -};
diff --git a/services/on_device_model/public/mojom/on_device_model_service.mojom b/services/on_device_model/public/mojom/on_device_model_service.mojom new file mode 100644 index 0000000..1ce35824 --- /dev/null +++ b/services/on_device_model/public/mojom/on_device_model_service.mojom
@@ -0,0 +1,47 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module on_device_model.mojom; + +import "mojo/public/mojom/base/file.mojom"; +import "mojo/public/mojom/base/read_only_file.mojom"; +import "sandbox/policy/mojom/context.mojom"; +import "sandbox/policy/mojom/sandbox.mojom"; +import "services/on_device_model/public/mojom/on_device_model.mojom"; + +// Opened file resources needed to define the model. +struct ModelAssets { + mojo_base.mojom.ReadOnlyFile? sp_model; + mojo_base.mojom.ReadOnlyFile? model; + + // TODO(b/313919363): This should also be a ReadOnlyFile. + mojo_base.mojom.File? weights; + + mojo_base.mojom.ReadOnlyFile? ts_data; + mojo_base.mojom.ReadOnlyFile? ts_sp_model; +}; + +// Params to describe the model to load. +struct LoadModelParams { + // Assets for the model. + ModelAssets assets; + + // The maximum number of input+output tokens the model can handle. This is + // needed when initializing the model. + uint32 max_tokens; +}; + +// A service which allows loading trusted models which are stored on-device and +// which may process untrustworthy data. +[ServiceSandbox=sandbox.mojom.Sandbox.kOnDeviceModelExecution, + RequireContext=sandbox.mojom.Context.kBrowser] +interface OnDeviceModelService { + // Initializes a new model instance given `assets`. If the model can not be + // created the model pipe will be reset. + LoadModel(LoadModelParams params, pending_receiver<OnDeviceModel> model) => + (LoadModelResult result); + + // Returns the performance class based on benchmarks run on the device. + GetEstimatedPerformanceClass() => (PerformanceClass performance_class); +};
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc index 6139400..a585d26 100644 --- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc +++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
@@ -174,13 +174,13 @@ } // The transfer buffer is used to serialize Dawn commands - transfer_buffer_ = + auto transfer_buffer = std::make_unique<gpu::TransferBuffer>(webgpu_helper.get()); // The WebGPUImplementation exposes the WebGPUInterface, as well as the // gpu::ContextSupport interface. auto webgpu_impl = std::make_unique<gpu::webgpu::WebGPUImplementation>( - webgpu_helper.get(), transfer_buffer_.get(), command_buffer_.get()); + webgpu_helper.get(), transfer_buffer.get(), command_buffer_.get()); bind_result_ = webgpu_impl->Initialize(memory_limits_); if (bind_result_ != gpu::ContextResult::kSuccess) { DLOG(ERROR) << "Failed to initialize WebGPUImplementation."; @@ -192,8 +192,11 @@ std::string unique_context_name = base::StringPrintf("%s-%p", type_name.c_str(), webgpu_impl.get()); + // IMPORTANT: These hold raw_ptrs to each other, so must be set together. + // See note in the header (and keep it up to date if things change). impl_ = webgpu_impl.get(); webgpu_interface_ = std::move(webgpu_impl); + transfer_buffer_ = std::move(transfer_buffer); helper_ = std::move(webgpu_helper); } else if (attributes_.enable_raster_interface && !attributes_.enable_gles2_interface && @@ -210,14 +213,14 @@ } // The transfer buffer is used to copy resources between the client // process and the GPU process. - transfer_buffer_ = + auto transfer_buffer = std::make_unique<gpu::TransferBuffer>(raster_helper.get()); // The RasterImplementation exposes the RasterInterface, as well as the // gpu::ContextSupport interface. DCHECK(channel_); auto raster_impl = std::make_unique<gpu::raster::RasterImplementation>( - raster_helper.get(), transfer_buffer_.get(), + raster_helper.get(), transfer_buffer.get(), attributes_.bind_generates_resource, attributes_.lose_context_when_out_of_memory, command_buffer_.get(), channel_->image_decode_accelerator_proxy()); @@ -234,8 +237,11 @@ raster_impl->TraceBeginCHROMIUM("gpu_toplevel", unique_context_name.c_str()); + // IMPORTANT: These hold raw_ptrs to each other, so must be set together. + // See note in the header (and keep it up to date if things change). impl_ = raster_impl.get(); raster_interface_ = std::move(raster_impl); + transfer_buffer_ = std::move(transfer_buffer); helper_ = std::move(raster_helper); } else { // The GLES2 helper writes the command buffer protocol. @@ -250,7 +256,7 @@ // The transfer buffer is used to copy resources between the client // process and the GPU process. - transfer_buffer_ = + auto transfer_buffer = std::make_unique<gpu::TransferBuffer>(gles2_helper.get()); // The GLES2Implementation exposes the OpenGLES2 API, as well as the @@ -263,13 +269,13 @@ // we only use it if grcontext_support was requested. gles2_impl = std::make_unique< skia_bindings::GLES2ImplementationWithGrContextSupport>( - gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer_.get(), + gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer.get(), attributes_.bind_generates_resource, attributes_.lose_context_when_out_of_memory, support_client_side_arrays, command_buffer_.get()); } else { gles2_impl = std::make_unique<gpu::gles2::GLES2Implementation>( - gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer_.get(), + gles2_helper.get(), /*share_group=*/nullptr, transfer_buffer.get(), attributes_.bind_generates_resource, attributes_.lose_context_when_out_of_memory, support_client_side_arrays, command_buffer_.get()); @@ -280,8 +286,11 @@ return bind_result_; } + // IMPORTANT: These hold raw_ptrs to each other, so must be set together. + // See note in the header (and keep it up to date if things change). impl_ = gles2_impl.get(); gles2_impl_ = std::move(gles2_impl); + transfer_buffer_ = std::move(transfer_buffer); helper_ = std::move(gles2_helper); } @@ -315,6 +324,7 @@ switches::kEnableGpuClientTracing)) { // This wraps the real GLES2Implementation and we should always use this // instead when it's present. + // IMPORTANT: This holds a raw_ptr to gles2_impl_. trace_impl_ = std::make_unique<gpu::gles2::GLES2TraceImplementation>( gles2_impl_.get()); gl = trace_impl_.get();
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/services/viz/public/cpp/gpu/context_provider_command_buffer.h index 0e8cb93..0c2c558 100644 --- a/services/viz/public/cpp/gpu/context_provider_command_buffer.h +++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -153,20 +153,43 @@ // associated shared images are destroyed. std::unique_ptr<gpu::ClientSharedImageInterface> shared_image_interface_; - base::Lock context_lock_; // Referenced by command_buffer_. + ////////////////////////////////////////////////////////////////////////////// + // IMPORTANT NOTE: All of the objects in this block are part of a complex // + // graph of raw pointers (holder or pointee of various raw_ptrs). They are // + // defined in topological order: only later items point to earlier items. // + // - When writing any member, always ensure its pointers to earlier members + // are guaranteed to stay alive. + // - When clearing OR overwriting any member, always ensure objects that + // point to it have already been cleared. + // - The topological order of definitions guarantees that the + // destructors will be called in the correct order (bottom to top). + // - When overwriting multiple members, similarly do so in reverse order. + // + // Please note these comments are likely not to stay perfectly up-to-date. + + base::Lock context_lock_; + // Points to the context_lock_ field of `this`. std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_; + + // Points to command_buffer_. std::unique_ptr<gpu::CommandBufferHelper> helper_; + // Points to helper_. std::unique_ptr<gpu::TransferBuffer> transfer_buffer_; + // Points to transfer_buffer_, helper_, and command_buffer_. std::unique_ptr<gpu::gles2::GLES2Implementation> gles2_impl_; + // Points to gles2_impl_. std::unique_ptr<gpu::gles2::GLES2TraceImplementation> trace_impl_; + // Points to transfer_buffer_, helper_, and command_buffer_. std::unique_ptr<gpu::raster::RasterInterface> raster_interface_; + // Points to transfer_buffer_, helper_, and command_buffer_. std::unique_ptr<gpu::webgpu::WebGPUInterface> webgpu_interface_; - - // Owned by one of gles2_impl_, raster_interface_, or webgpu_interface_. It - // must be declared last and cleared first. + // This is an alias for gles2_impl_, raster_interface_, or webgpu_interface_. raw_ptr<gpu::ImplementationBase> impl_ = nullptr; + // END IMPORTANT NOTE // + ////////////////////////////////////////////////////////////////////////////// + std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_; std::unique_ptr<ContextCacheController> cache_controller_;
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index d0d8c83..ab18a1e6 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -6218,9 +6218,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -6230,8 +6230,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -6368,9 +6368,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -6380,8 +6380,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index 8415456..61ad3d87e 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -20593,9 +20593,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20605,8 +20605,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -20743,9 +20743,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20755,8 +20755,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 3164fd05..1813af3 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -43754,9 +43754,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -43765,8 +43765,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -43904,9 +43904,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -43915,8 +43915,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -45228,9 +45228,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45239,8 +45239,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -45378,9 +45378,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45389,8 +45389,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -46088,9 +46088,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_v121.0.6155.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -46099,8 +46099,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -50938,7 +50938,7 @@ { "args": [ "--windows-virtual-display-driver", - "--gtest_filter=*MultiScreen*,*VirtualDisplayWinUtil*" + "--gtest_filter=*MultiScreen*:*VirtualDisplayWinUtil*" ], "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 539cfb9..a4b92c8 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -16312,12 +16312,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_v121.0.6155.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16327,8 +16327,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": { @@ -16482,12 +16482,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_v121.0.6155.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 121.0.6155.0", + "description": "Run with ash-chrome version 121.0.6156.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16497,8 +16497,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v121.0.6155.0", - "revision": "version:121.0.6155.0" + "location": "lacros_version_skew_tests_v121.0.6156.0", + "revision": "version:121.0.6156.0" } ], "dimensions": {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index df03249..1c94dfaf 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -968,7 +968,7 @@ 'test': 'interactive_ui_tests', 'args': [ '--windows-virtual-display-driver', - '--gtest_filter=*MultiScreen*,*VirtualDisplayWinUtil*', + '--gtest_filter=*MultiScreen*:*VirtualDisplayWinUtil*', ], }, },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index af4fbb9..bbf30ba 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -70,16 +70,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 121.0.6155.0', + 'description': 'Run with ash-chrome version 121.0.6156.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6155.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6156.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v121.0.6155.0', - 'revision': 'version:121.0.6155.0', + 'location': 'lacros_version_skew_tests_v121.0.6156.0', + 'revision': 'version:121.0.6156.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index a8e23ce2..5c19428 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -10131,12 +10131,11 @@ "ReducedNTPTopSpace": "20", "SetUpListCompactedTimeThresholdDays": "0", "enable_default_model": "true", - "variant": "tab-resumption-all-tabs" + "variant": "tab-resumption-recent-tab-only" }, "enable_features": [ "IOSParcelTracking", "MagicStack", - "SafetyCheckMagicStack", "SegmentationPlatformIosModuleRanker", "SegmentationPlatformUserVisibleTaskRunner", "TabResumption" @@ -13211,26 +13210,6 @@ ] } ], - "PopulateVisitedLinkDatabase": [ - { - "platforms": [ - "android", - "chromeos", - "chromeos_lacros", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "PopulateVisitedLinkDatabase", - "enable_features": [ - "PopulateVisitedLinkDatabase" - ] - } - ] - } - ], "PostQuantumKyber": [ { "platforms": [ @@ -15231,9 +15210,6 @@ "experiments": [ { "name": "Enabled", - "params": { - "background-password-check-interval": "1d" - }, "enable_features": [ "SafetyHub" ] @@ -18667,6 +18643,7 @@ { "platforms": [ "android", + "android_webview", "chromeos", "chromeos_lacros", "fuchsia",
diff --git a/third_party/angle b/third_party/angle index aaafece..d696b40 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit aaafecee56791dc8431d0446403f25e73f00b59c +Subproject commit d696b40fad24202791ecb40d9ea13a2ab4be15cf
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 0d6ab075..980102e8 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -822,7 +822,7 @@ BASE_FEATURE(kFixGestureScrollQueuingBug, "FixGestureScrollQueuingBug", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // See https://github.com/WICG/turtledove/blob/main/FLEDGE.md // Enables FLEDGE implementation. See https://crbug.com/1186444. @@ -1554,7 +1554,7 @@ BASE_FEATURE(kQueueBlockingGestureScrolls, "QueueBlockingGestureScrolls", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kQuoteEmptySecChUaStringHeadersConsistently, "QuoteEmptySecChUaStringHeadersConsistently",
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 0617006..3ba7f9c 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -7651,6 +7651,7 @@ sync-xhr unload usb + usb-unrestricted vertical-scroll web-printing web-share
diff --git a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom index e94b5a7..c4521696 100644 --- a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom +++ b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
@@ -225,9 +225,15 @@ // Client hint for prefers-reduced-transparency kClientHintPrefersReducedTransparency = 112, - // Web Printing API + // "web-printing" is a isolated context only permissions policy that controls + // the use of Web Printing API. kWebPrinting = 113, + // "usb-unrestricted" is a isolated context only permissions policy that + // controls whether protected USB interfaces and blocklisted USB devices can + // be accessed with WebUSB. + kUsbUnrestricted = 114, + // Don't change assigned numbers of any item, and don't reuse removed slots. // Add new features at the end of the enum. // Also, run update_permissions_policy_enum.py in
diff --git a/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h b/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h index d2c4da3..a23615be 100644 --- a/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h +++ b/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h" namespace blink { + // Derived by wrappable objects which need to remain alive due to ongoing // asynchronous activity, even if they are not referenced in the JavaScript or // Blink heap. @@ -28,8 +29,8 @@ // ActiveScriptWrappableCreationKey as a friend. // // The objects should derive from ActiveScriptWrappable<T>, and override -// `ScriptWrappable::HasPendingActivity()`. The method is not allowed to -// allocate. +// `ActiveScriptWrappableBase::HasPendingActivity()`. The method is not allowed +// to allocate. // // Caveat: // - To avoid leaking objects after the context is destroyed, users of @@ -61,10 +62,6 @@ return IsContextDestroyedForActiveScriptWrappable( static_cast<const T*>(this)->GetExecutionContext()); } - - bool DispatchHasPendingActivity() const final { - return static_cast<const T*>(this)->HasPendingActivity(); - } }; // Same as ActiveScriptWrappable with the difference the the object is not @@ -90,10 +87,6 @@ static_cast<const T*>(this)->GetExecutionContext()); } - bool DispatchHasPendingActivity() const final { - return static_cast<const T*>(this)->HasPendingActivity(); - } - protected: explicit LazyActiveScriptWrappable(ActiveScriptWrappableCreationKey) {} };
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc b/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc index 6bd4406..110b23b 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
@@ -140,7 +140,7 @@ TRACE_EVENT_INSTANT1( TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", [&](perfetto::TracedValue context) { - inspector_update_counters_event::Data(std::move(context)); + inspector_update_counters_event::Data(std::move(context), isolate); }); }
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 ea4705e..a1c8cc21 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
@@ -542,7 +542,7 @@ v8::Context::Scope scope(script_state->GetContext()); DEVTOOLS_TIMELINE_TRACE_EVENT( - "EvaluateScript", inspector_evaluate_script_event::Data, frame, + "EvaluateScript", inspector_evaluate_script_event::Data, isolate, frame, classic_script->SourceUrl().GetString(), classic_script->StartPosition()); // Scope for |v8::TryCatch|.
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index dda8289..6b67a89 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -6389,11 +6389,6 @@ static_assert( std::is_base_of<ActiveScriptWrappableBase, {blink_class}>::value, "{blink_class} does not inherit from ActiveScriptWrappable<> despite " - "the IDL has [ActiveScriptWrappable] extended attribute."); -static_assert( - !std::is_same<decltype(&{blink_class}::HasPendingActivity), - decltype(&ScriptWrappable::HasPendingActivity)>::value, - "{blink_class} is not overriding hasPendingActivity() despite " "the IDL has [ActiveScriptWrappable] extended attribute.");""" else: pattern = """\ @@ -6401,11 +6396,6 @@ static_assert( !std::is_base_of<ActiveScriptWrappableBase, {blink_class}>::value, "{blink_class} inherits from ActiveScriptWrappable<> without " - "[ActiveScriptWrappable] extended attribute."); -static_assert( - std::is_same<decltype(&{blink_class}::HasPendingActivity), - decltype(&ScriptWrappable::HasPendingActivity)>::value, - "{blink_class} is overriding hasPendingActivity() without " "[ActiveScriptWrappable] extended attribute.");""" if class_like.is_interface: wrapper_type_info_def.append(F(pattern, blink_class=blink_class))
diff --git a/third_party/blink/renderer/core/css/font_face.cc b/third_party/blink/renderer/core/css/font_face.cc index c9659b4..9e292e8 100644 --- a/third_party/blink/renderer/core/css/font_face.cc +++ b/third_party/blink/renderer/core/css/font_face.cc
@@ -642,7 +642,6 @@ FontSelectionRange::RangeType::kSetExplicitly}; break; case CSSValueID::kAuto: - DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled()); capabilities.width = {kNormalWidthValue, kNormalWidthValue, FontSelectionRange::RangeType::kSetFromAuto}; break; @@ -708,7 +707,6 @@ FontSelectionRange::RangeType::kSetExplicitly}; break; case CSSValueID::kAuto: - DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled()); capabilities.slope = {kNormalSlopeValue, kNormalSlopeValue, FontSelectionRange::RangeType::kSetFromAuto}; break; @@ -782,7 +780,6 @@ FontSelectionRange::RangeType::kSetExplicitly}; break; case CSSValueID::kAuto: - DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled()); capabilities.weight = {kNormalWeightValue, kNormalWeightValue, FontSelectionRange::RangeType::kSetFromAuto}; break;
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 563b739..c749bba 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -5143,8 +5143,7 @@ return ConsumeIdent(range); } - if (RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled() && - range.Peek().Id() == CSSValueID::kAuto && + if (range.Peek().Id() == CSSValueID::kAuto && context.Mode() == kCSSFontFaceRuleMode) { return ConsumeIdent(range); } @@ -5195,8 +5194,7 @@ token.Id() <= CSSValueID::kUltraExpanded)) { return ConsumeIdent(range); } - if (RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled() && - token.Id() == CSSValueID::kAuto && + if (token.Id() == CSSValueID::kAuto && context.Mode() == kCSSFontFaceRuleMode) { return ConsumeIdent(range); } @@ -5240,10 +5238,8 @@ return ConsumeIdent(range); } } else { - if ((token.Id() == CSSValueID::kNormal || - token.Id() == CSSValueID::kBold) || - (RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled() && - token.Id() == CSSValueID::kAuto)) { + if (token.Id() == CSSValueID::kNormal || token.Id() == CSSValueID::kBold || + token.Id() == CSSValueID::kAuto) { return ConsumeIdent(range); } }
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index 11f65faa..40fcf13 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -46,6 +46,7 @@ #include "third_party/blink/renderer/core/events/mouse_event.h" #include "third_party/blink/renderer/core/events/simulated_event_util.h" #include "third_party/blink/renderer/core/events/text_event.h" +#include "third_party/blink/renderer/core/execution_context/agent.h" #include "third_party/blink/renderer/core/frame/ad_tracker.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -272,7 +273,8 @@ #endif DCHECK(event_->target()); DEVTOOLS_TIMELINE_TRACE_EVENT("EventDispatch", - inspector_event_dispatch_event::Data, *event_); + inspector_event_dispatch_event::Data, *event_, + document.GetAgent().isolate()); EventDispatchHandlingState* pre_dispatch_event_handler_result = nullptr; if (DispatchEventPreProcess(activation_target, pre_dispatch_event_handler_result) ==
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index 014a6d6..5e23d2f 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1869,14 +1869,22 @@ page->GetChromeClient().SetWindowRect(window_rect, *frame); } -void LocalDOMWindow::resizeBy(int x, int y) const { +void LocalDOMWindow::resizeBy(int x, + int y, + ExceptionState& exception_state) const { if (!GetFrame() || !GetFrame()->IsOutermostMainFrame() || document()->IsPrerendering()) { return; } - if (IsPictureInPictureWindow()) - return; + if (IsPictureInPictureWindow()) { + if (!LocalFrame::ConsumeTransientUserActivation(GetFrame())) { + exception_state.ThrowDOMException( + DOMExceptionCode::kNotAllowedError, + "resizeBy() requires user activation in document picture-in-picture"); + return; + } + } LocalFrame* frame = GetFrame(); Page* page = frame->GetPage(); @@ -1889,14 +1897,22 @@ page->GetChromeClient().SetWindowRect(update, *frame); } -void LocalDOMWindow::resizeTo(int width, int height) const { +void LocalDOMWindow::resizeTo(int width, + int height, + ExceptionState& exception_state) const { if (!GetFrame() || !GetFrame()->IsOutermostMainFrame() || document()->IsPrerendering()) { return; } - if (IsPictureInPictureWindow()) - return; + if (IsPictureInPictureWindow()) { + if (!LocalFrame::ConsumeTransientUserActivation(GetFrame())) { + exception_state.ThrowDOMException( + DOMExceptionCode::kNotAllowedError, + "resizeTo() requires user activation in document picture-in-picture"); + return; + } + } LocalFrame* frame = GetFrame(); Page* page = frame->GetPage(); @@ -2069,7 +2085,8 @@ event.SetEventPhase(Event::PhaseType::kAtTarget); DEVTOOLS_TIMELINE_TRACE_EVENT("EventDispatch", - inspector_event_dispatch_event::Data, event); + inspector_event_dispatch_event::Data, event, + GetIsolate()); return FireEventListeners(event); }
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h index 2ab203c..50e32cf6 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.h +++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -332,8 +332,8 @@ void moveBy(int x, int y) const; void moveTo(int x, int y) const; - void resizeBy(int x, int y) const; - void resizeTo(int width, int height) const; + void resizeBy(int x, int y, ExceptionState&) const; + void resizeTo(int width, int height, ExceptionState&) const; MediaQueryList* matchMedia(const String&);
diff --git a/third_party/blink/renderer/core/frame/window.idl b/third_party/blink/renderer/core/frame/window.idl index 4e3f7b2..e3d96d9 100644 --- a/third_party/blink/renderer/core/frame/window.idl +++ b/third_party/blink/renderer/core/frame/window.idl
@@ -130,8 +130,8 @@ // browsing context [MeasureAs=WindowMove] void moveTo(long x, long y); [MeasureAs=WindowMove] void moveBy(long x, long y); - [MeasureAs=WindowResize] void resizeTo(long x, long y); - [MeasureAs=WindowResize] void resizeBy(long x, long y); + [MeasureAs=WindowResize, RaisesException] void resizeTo(long x, long y); + [MeasureAs=WindowResize, RaisesException] void resizeBy(long x, long y); // viewport [HighEntropy=Direct, MeasureAs=WindowInnerWidth, Replaceable] readonly attribute long innerWidth;
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc index bfabb7e..b904bc6f 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -1412,6 +1412,7 @@ } void InspectorNetworkAgent::WillSendRequest( + ExecutionContext*, DocumentLoader* loader, const KURL& fetch_context_url, const ResourceRequest& request,
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.h b/third_party/blink/renderer/core/inspector/inspector_network_agent.h index de1e146..4c33888 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
@@ -103,7 +103,8 @@ ResourceRequest&, ResourceLoaderOptions&, ResourceType); - void WillSendRequest(DocumentLoader*, + void WillSendRequest(ExecutionContext*, + DocumentLoader*, const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 08b922778..047e63f 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -18,6 +18,7 @@ #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/events/wheel_event.h" +#include "third_party/blink/renderer/core/execution_context/agent.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" @@ -65,7 +66,7 @@ dict.Add("startLine", start_line); dict.Add("frame", IdentifiersFactory::FrameId(document->GetFrame())); dict.Add("url", document->Url().GetString()); - SetCallStack(dict); + SetCallStack(document->GetAgent().isolate(), dict); } void InspectorParseHtmlEndData(perfetto::TracedValue context, int end_line) { @@ -101,7 +102,7 @@ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(p))); } -void SetCallStack(perfetto::TracedDictionary& dict) { +void SetCallStack(v8::Isolate* isolate, perfetto::TracedDictionary& dict) { static const unsigned char* trace_category_enabled = nullptr; WTF_ANNOTATE_BENIGN_RACE(&trace_category_enabled, "trace_event category"); if (!trace_category_enabled) { @@ -116,10 +117,11 @@ auto source_location = CaptureSourceLocation(); if (source_location->HasStackTrace()) dict.Add("stackTrace", source_location); - v8::CpuProfiler::CollectSample(v8::Isolate::GetCurrent()); + v8::CpuProfiler::CollectSample(isolate); } void InspectorTraceEvents::WillSendRequest( + ExecutionContext* execution_context, DocumentLoader* loader, const KURL& fetch_context_url, const ResourceRequest& request, @@ -132,8 +134,8 @@ TRACE_EVENT_INSTANT_WITH_TIMESTAMP1( "devtools.timeline", "ResourceSendRequest", TRACE_EVENT_SCOPE_THREAD, timestamp, "data", [&](perfetto::TracedValue ctx) { - inspector_send_request_event::Data(std::move(ctx), loader, - request.InspectorId(), frame, + inspector_send_request_event::Data(std::move(ctx), execution_context, + loader, request.InspectorId(), frame, request, render_blocking_behavior); }); } @@ -201,12 +203,13 @@ void InspectorTraceEvents::Will(const probe::ExecuteScript&) {} -void InspectorTraceEvents::Did(const probe::ExecuteScript&) { - TRACE_EVENT_INSTANT1( - TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", - TRACE_EVENT_SCOPE_THREAD, "data", [](perfetto::TracedValue context) { - inspector_update_counters_event::Data(std::move(context)); - }); +void InspectorTraceEvents::Did(const probe::ExecuteScript& probe) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", + [&](perfetto::TracedValue context) { + inspector_update_counters_event::Data( + std::move(context), probe.context->GetIsolate()); + }); } void InspectorTraceEvents::Will(const probe::ParseHTML& probe) { @@ -228,8 +231,9 @@ }); TRACE_EVENT_INSTANT1( TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", - TRACE_EVENT_SCOPE_THREAD, "data", [](perfetto::TracedValue context) { - inspector_update_counters_event::Data(std::move(context)); + TRACE_EVENT_SCOPE_THREAD, "data", [&](perfetto::TracedValue context) { + inspector_update_counters_event::Data( + std::move(context), probe.document->GetAgent().isolate()); }); } @@ -238,11 +242,12 @@ void InspectorTraceEvents::Did(const probe::CallFunction& probe) { if (probe.depth) return; - TRACE_EVENT_INSTANT1( - TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", - TRACE_EVENT_SCOPE_THREAD, "data", [](perfetto::TracedValue context) { - inspector_update_counters_event::Data(std::move(context)); - }); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", + [&](perfetto::TracedValue context) { + inspector_update_counters_event::Data( + std::move(context), probe.context->GetIsolate()); + }); } void InspectorTraceEvents::PaintTiming(Document* document, @@ -669,7 +674,7 @@ dict.Add("totalObjects", total_objects); dict.Add("partialLayout", is_partial); dict.Add("frame", IdentifiersFactory::FrameId(&frame)); - SetCallStack(dict); + SetCallStack(frame.DomWindow()->GetIsolate(), dict); } static void CreateQuad(perfetto::TracedValue context, const gfx::QuadF& quad) { @@ -828,6 +833,7 @@ void inspector_send_request_event::Data( perfetto::TracedValue context, + ExecutionContext* execution_context, DocumentLoader* loader, uint64_t identifier, LocalFrame* frame, @@ -846,7 +852,7 @@ const char* priority = ResourcePriorityString(request.Priority()); if (priority) dict.Add("priority", priority); - SetCallStack(dict); + SetCallStack(execution_context->GetIsolate(), dict); } void inspector_change_render_blocking_behavior_event::Data( @@ -883,7 +889,7 @@ ResourcePriorityString(ResourceLoadPriority::kVeryHigh); if (priority) dict.Add("priority", priority); - SetCallStack(dict); + SetCallStack(frame->DomWindow()->GetIsolate(), dict); } namespace { @@ -1030,7 +1036,7 @@ GenericTimerData(dict, context, timer_id); dict.Add("timeout", timeout.InMillisecondsF()); dict.Add("singleShot", single_shot); - SetCallStack(dict); + SetCallStack(context->GetIsolate(), dict); } void inspector_timer_remove_event::Data(perfetto::TracedValue trace_context, @@ -1038,7 +1044,7 @@ int timer_id) { auto dict = std::move(trace_context).WriteDictionary(); GenericTimerData(dict, context, timer_id); - SetCallStack(dict); + SetCallStack(context->GetIsolate(), dict); } void inspector_timer_fire_event::Data(perfetto::TracedValue trace_context, @@ -1058,7 +1064,7 @@ } else if (auto* scope = DynamicTo<WorkerGlobalScope>(context)) { dict.Add("worker", ToHexString(scope)); } - SetCallStack(dict); + SetCallStack(context->GetIsolate(), dict); } void GenericIdleCallbackEvent(perfetto::TracedDictionary& dict, @@ -1067,7 +1073,7 @@ dict.Add("id", id); if (LocalFrame* frame = FrameForExecutionContext(context)) dict.Add("frame", IdentifiersFactory::FrameId(frame)); - SetCallStack(dict); + SetCallStack(context->GetIsolate(), dict); } void inspector_idle_callback_request_event::Data( @@ -1116,7 +1122,7 @@ dict.Add("readyState", request->readyState()); if (LocalFrame* frame = FrameForExecutionContext(context)) dict.Add("frame", IdentifiersFactory::FrameId(frame)); - SetCallStack(dict); + SetCallStack(context->GetIsolate(), dict); } void inspector_xhr_load_event::Data(perfetto::TracedValue trace_context, @@ -1126,11 +1132,11 @@ dict.Add("url", request->Url().GetString()); if (LocalFrame* frame = FrameForExecutionContext(context)) dict.Add("frame", IdentifiersFactory::FrameId(frame)); - SetCallStack(dict); + SetCallStack(context->GetIsolate(), dict); } void inspector_paint_event::Data(perfetto::TracedValue context, - Frame* frame, + LocalFrame* frame, const LayoutObject* layout_object, const gfx::QuadF& quad, int layer_id) { @@ -1139,7 +1145,7 @@ CreateQuad(dict.AddItem("clip"), quad); SetGeneratingNodeInfo(dict, layout_object, "nodeId"); dict.Add("layerId", layer_id); - SetCallStack(dict); + SetCallStack(frame->DomWindow()->GetIsolate(), dict); } void FrameEventData(perfetto::TracedDictionary& dict, LocalFrame* frame) { @@ -1212,13 +1218,14 @@ } // namespace void inspector_evaluate_script_event::Data(perfetto::TracedValue context, + v8::Isolate* isolate, LocalFrame* frame, const String& url, const TextPosition& text_position) { auto dict = std::move(context).WriteDictionary(); FillLocation(dict, url, text_position); dict.Add("frame", IdentifiersFactory::FrameId(frame)); - SetCallStack(dict); + SetCallStack(isolate, dict); } void inspector_parse_script_event::Data(perfetto::TracedValue context, @@ -1363,13 +1370,14 @@ dict.Add("url", image_content.Url().ElidedString()); } -static size_t UsedHeapSize() { +static size_t UsedHeapSize(v8::Isolate* isolate) { v8::HeapStatistics heap_statistics; - v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_statistics); + isolate->GetHeapStatistics(&heap_statistics); return heap_statistics.used_heap_size(); } -void inspector_update_counters_event::Data(perfetto::TracedValue context) { +void inspector_update_counters_event::Data(perfetto::TracedValue context, + v8::Isolate* isolate) { auto dict = std::move(context).WriteDictionary(); if (IsMainThread()) { dict.Add("documents", InstanceCounters::CounterValue( @@ -1380,7 +1388,7 @@ InstanceCounters::CounterValue( InstanceCounters::kJSEventListenerCounter)); } - dict.Add("jsHeapSizeUsed", static_cast<double>(UsedHeapSize())); + dict.Add("jsHeapSizeUsed", static_cast<double>(UsedHeapSize(isolate))); } void inspector_invalidate_layout_event::Data(perfetto::TracedValue context, @@ -1389,18 +1397,19 @@ auto dict = std::move(context).WriteDictionary(); dict.Add("frame", IdentifiersFactory::FrameId(frame)); dict.Add("nodeId", nodeId); - SetCallStack(dict); + SetCallStack(frame->DomWindow()->GetIsolate(), dict); } void inspector_recalculate_styles_event::Data(perfetto::TracedValue context, LocalFrame* frame) { auto dict = std::move(context).WriteDictionary(); dict.Add("frame", IdentifiersFactory::FrameId(frame)); - SetCallStack(dict); + SetCallStack(frame->DomWindow()->GetIsolate(), dict); } void inspector_event_dispatch_event::Data(perfetto::TracedValue context, - const Event& event) { + const Event& event, + v8::Isolate* isolate) { auto dict = std::move(context).WriteDictionary(); dict.Add("type", event.type()); bool record_input_enabled; @@ -1436,7 +1445,7 @@ } } } - SetCallStack(dict); + SetCallStack(isolate, dict); } void inspector_time_stamp_event::Data(perfetto::TracedValue trace_context,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.h b/third_party/blink/renderer/core/inspector/inspector_trace_events.h index e959eec6..aee1dff6 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.h +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.h
@@ -50,7 +50,6 @@ class EncodedFormData; class Event; class ExecutionContext; -class Frame; class HitTestLocation; class HitTestRequest; class HitTestResult; @@ -90,7 +89,8 @@ InspectorTraceEvents(const InspectorTraceEvents&) = delete; InspectorTraceEvents& operator=(const InspectorTraceEvents&) = delete; - void WillSendRequest(DocumentLoader*, + void WillSendRequest(ExecutionContext*, + DocumentLoader*, const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response, @@ -315,6 +315,7 @@ namespace inspector_send_request_event { void Data(perfetto::TracedValue context, + ExecutionContext* execution_context, DocumentLoader*, uint64_t identifier, LocalFrame*, @@ -430,7 +431,7 @@ // associated with this event is the bounding damage rect. namespace inspector_paint_event { void Data(perfetto::TracedValue context, - Frame*, + LocalFrame*, const LayoutObject*, const gfx::QuadF& quad, int layer_id); @@ -476,6 +477,7 @@ namespace inspector_evaluate_script_event { void Data(perfetto::TracedValue context, + v8::Isolate*, LocalFrame*, const String& url, const WTF::TextPosition&); @@ -525,7 +527,7 @@ } namespace inspector_update_counters_event { -void Data(perfetto::TracedValue context); +void Data(perfetto::TracedValue context, v8::Isolate* isolate); } namespace inspector_invalidate_layout_event { @@ -537,7 +539,7 @@ } namespace inspector_event_dispatch_event { -void Data(perfetto::TracedValue context, const Event&); +void Data(perfetto::TracedValue context, const Event&, v8::Isolate*); } namespace inspector_time_stamp_event { @@ -588,7 +590,8 @@ } CORE_EXPORT String ToHexString(const void* p); -CORE_EXPORT void SetCallStack(perfetto::TracedDictionary&); +CORE_EXPORT void SetCallStack(v8::Isolate* isolate, + perfetto::TracedDictionary&); } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 6f83d21..96f83f7 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2197,14 +2197,29 @@ // // Note: Sandboxed about:srcdoc iframe without "allow-same-origin" aren't // allowed to load user's file, even if its parent can. - if (owner_document) { + if (url_.IsAboutSrcdocURL()) { + // We should only have a sandboxed, srcdoc frame without an owner document + // if isolated-sandboxed-iframes is enabled. Only cases that would + // normally inherit the origin need to be handled here, and a sandboxed + // about:blank document won't be moved out of process. Also, data: urls + // don't get secure contexts, so needn't be considered here. + CHECK(owner_document || + base::FeatureList::IsEnabled(features::kIsolateSandboxedIframes)); + + bool is_potentially_trustworthy = + origin->GetOriginOrPrecursorOriginIfOpaque() + ->IsPotentiallyTrustworthy(); + if (is_potentially_trustworthy) { + sandbox_origin->SetOpaqueOriginIsPotentiallyTrustworthy(true); + debug_info_builder.Append(", _potentially_trustworthy"); + } + } else if (owner_document) { if (origin->IsPotentiallyTrustworthy()) { sandbox_origin->SetOpaqueOriginIsPotentiallyTrustworthy(true); debug_info_builder.Append(", _potentially_trustworthy"); } - if (origin->CanLoadLocalResources() && !loading_srcdoc_) { + if (origin->CanLoadLocalResources()) { sandbox_origin->GrantLoadLocalResources(); - debug_info_builder.Append(", _load_local"); } }
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource.cc b/third_party/blink/renderer/core/loader/resource/image_resource.cc index 2fe134c..06ad296 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -310,12 +310,6 @@ void ImageResource::DestroyDecodedDataIfPossible() { GetContent()->DestroyDecodedData(); - if (GetContent()->HasImage() && !IsUnusedPreload() && - GetContent()->IsRefetchableDataFromDiskCache()) { - UMA_HISTOGRAM_MEMORY_KB( - "Memory.Renderer.EstimatedDroppableEncodedSize", - base::saturated_cast<base::Histogram::Sample>(EncodedSize() / 1024)); - } } void ImageResource::AllClientsAndObserversRemoved() {
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc index 9cce497..4217bfb 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -157,7 +157,7 @@ request, redirect_response, resource); probe::WillSendRequest( - GetProbe(), document_loader_, + document_->domWindow(), document_loader_, fetcher_properties_->GetFetchClientSettingsObject().GlobalObjectUrl(), request, redirect_response, options, resource_type, render_blocking_behavior, base::TimeTicks::Now());
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc index 8cfc633..1bdb87d 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
@@ -39,7 +39,7 @@ RenderBlockingBehavior render_blocking_behavior, const Resource* resource) { probe::WillSendRequest( - probe_, nullptr, + worker_fetch_context_->GetExecutionContext(), nullptr, fetcher_properties_->GetFetchClientSettingsObject().GlobalObjectUrl(), request, redirect_response, options, resource_type, render_blocking_behavior, base::TimeTicks::Now());
diff --git a/third_party/blink/renderer/core/paint/background_image_geometry.cc b/third_party/blink/renderer/core/paint/background_image_geometry.cc index 8efc5c8c..c3f263b0 100644 --- a/third_party/blink/renderer/core/paint/background_image_geometry.cc +++ b/third_party/blink/renderer/core/paint/background_image_geometry.cc
@@ -966,10 +966,6 @@ return *(painting_view_ ? box_ : positioning_box_); } -const Document& BackgroundImageGeometry::ImageDocument() const { - return box_->GetDocument(); -} - const ComputedStyle& BackgroundImageGeometry::ImageStyle( const ComputedStyle& fragment_style) const { if (painting_view_ || cell_using_container_background_)
diff --git a/third_party/blink/renderer/core/paint/background_image_geometry.h b/third_party/blink/renderer/core/paint/background_image_geometry.h index 870ce43..f829b4ee 100644 --- a/third_party/blink/renderer/core/paint/background_image_geometry.h +++ b/third_party/blink/renderer/core/paint/background_image_geometry.h
@@ -13,7 +13,6 @@ namespace blink { class ComputedStyle; -class Document; class FillLayer; class ImageResourceObserver; class LayoutBox; @@ -101,7 +100,6 @@ } const ImageResourceObserver& ImageClient() const; - const Document& ImageDocument() const; const ComputedStyle& ImageStyle(const ComputedStyle& fragment_style) const; InterpolationQuality ImageInterpolationQuality() const; cc::PaintFlags::DynamicRangeLimit DynamicRangeLimit() const; @@ -186,7 +184,6 @@ // 2. a table cell using its row/column's background (box_ is the table cell, // and positioning_box_ is the row/column). // When they are different: - // - ImageDocument() uses box_; // - ImageClient() uses box_ if painting view, otherwise positioning_box_; // - ImageStyle() uses positioning_box_; // - ImageInterpolationQuality() uses box_;
diff --git a/third_party/blink/renderer/core/paint/box_model_object_painter.cc b/third_party/blink/renderer/core/paint/box_model_object_painter.cc index b9d95d4..0d5088f 100644 --- a/third_party/blink/renderer/core/paint/box_model_object_painter.cc +++ b/third_party/blink/renderer/core/paint/box_model_object_painter.cc
@@ -34,15 +34,9 @@ box_model_(box) {} PhysicalRect BoxModelObjectPainter::AdjustRectForScrolledContent( - const PaintInfo& paint_info, - const BoxPainterBase::FillLayerInfo& info, - const PhysicalRect& rect) { - if (!info.is_clipped_with_local_scrolling) - return rect; - if (paint_info.IsPaintingBackgroundInContentsSpace()) - return rect; - - GraphicsContext& context = paint_info.context; + GraphicsContext& context, + const PhysicalBoxStrut& border, + const PhysicalRect& rect) const { // Clip to the overflow area. // TODO(chrishtr): this should be pixel-snapped. const auto& this_box = To<LayoutBox>(box_model_); @@ -53,7 +47,6 @@ PhysicalRect scrolled_paint_rect = rect; scrolled_paint_rect.offset -= PhysicalOffset(this_box.PixelSnappedScrolledContentOffset()); - PhysicalBoxStrut border = AdjustedBorderOutsets(info); scrolled_paint_rect.SetWidth(border.HorizontalSum() + this_box.ScrollWidth()); scrolled_paint_rect.SetHeight(this_box.BorderTop() + this_box.ScrollHeight() + this_box.BorderBottom());
diff --git a/third_party/blink/renderer/core/paint/box_model_object_painter.h b/third_party/blink/renderer/core/paint/box_model_object_painter.h index 4f61b654..8980ce8 100644 --- a/third_party/blink/renderer/core/paint/box_model_object_painter.h +++ b/third_party/blink/renderer/core/paint/box_model_object_painter.h
@@ -38,10 +38,9 @@ const gfx::Rect& mask_rect, const PhysicalOffset& paint_offset, bool object_has_multiple_boxes) override {} - PhysicalRect AdjustRectForScrolledContent( - const PaintInfo&, - const BoxPainterBase::FillLayerInfo&, - const PhysicalRect&) override; + PhysicalRect AdjustRectForScrolledContent(GraphicsContext&, + const PhysicalBoxStrut& borders, + const PhysicalRect&) const override; private: const LayoutBoxModelObject& box_model_;
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc index 374fbea..8ff2015 100644 --- a/third_party/blink/renderer/core/paint/box_painter_base.cc +++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -1132,13 +1132,6 @@ border_widths.bottom.ToInt(), border_widths.left.ToInt()); } -PhysicalBoxStrut BoxPainterBase::AdjustedBorderOutsets( - const FillLayerInfo& info) const { - PhysicalBoxStrut snapped_borders = ComputeSnappedBorders(); - snapped_borders.TruncateSides(info.sides_to_include); - return snapped_borders; -} - void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info, const Color& color, const FillLayer& bg_layer, @@ -1161,8 +1154,14 @@ GraphicsContext& context = paint_info.context; GraphicsContextStateSaver clip_with_scrolling_state_saver( context, fill_layer_info.is_clipped_with_local_scrolling); - auto scrolled_paint_rect = - AdjustRectForScrolledContent(paint_info, fill_layer_info, rect); + auto scrolled_paint_rect = rect; + if (fill_layer_info.is_clipped_with_local_scrolling && + !paint_info.IsPaintingBackgroundInContentsSpace()) { + PhysicalBoxStrut snapped_borders = ComputeSnappedBorders(); + snapped_borders.TruncateSides(fill_layer_info.sides_to_include); + scrolled_paint_rect = + AdjustRectForScrolledContent(paint_info.context, snapped_borders, rect); + } const auto did_adjust_paint_rect = scrolled_paint_rect != rect; scoped_refptr<Image> image; @@ -1209,9 +1208,9 @@ } geometry.Calculate(paint_info, bg_layer, scrolled_paint_rect); - image = fill_layer_info.image->GetImage( - geometry.ImageClient(), geometry.ImageDocument(), image_style, - gfx::SizeF(geometry.TileSize())); + image = fill_layer_info.image->GetImage(geometry.ImageClient(), document_, + image_style, + gfx::SizeF(geometry.TileSize())); image_rendering_settings_context.emplace( context, geometry.ImageInterpolationQuality(),
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.h b/third_party/blink/renderer/core/paint/box_painter_base.h index 848eac9..d051d7b7 100644 --- a/third_party/blink/renderer/core/paint/box_painter_base.h +++ b/third_party/blink/renderer/core/paint/box_painter_base.h
@@ -26,6 +26,7 @@ class Document; class FillLayer; class FloatRoundedRect; +class GraphicsContext; class ImageResourceObserver; class LayoutBox; class Node; @@ -143,9 +144,6 @@ }; protected: - virtual PhysicalBoxStrut ComputeBorders() const = 0; - virtual PhysicalBoxStrut ComputePadding() const = 0; - PhysicalBoxStrut AdjustedBorderOutsets(const FillLayerInfo&) const; void PaintFillLayerTextFillBox(const PaintInfo&, const FillLayerInfo&, Image*, @@ -159,9 +157,10 @@ const PhysicalOffset& paint_offset, bool object_has_multiple_boxes) = 0; - virtual PhysicalRect AdjustRectForScrolledContent(const PaintInfo&, - const FillLayerInfo&, - const PhysicalRect&) = 0; + virtual PhysicalRect AdjustRectForScrolledContent( + GraphicsContext&, + const PhysicalBoxStrut& borders, + const PhysicalRect&) const = 0; virtual FillLayerInfo GetFillLayerInfo( const Color&, const FillLayer&, @@ -174,6 +173,8 @@ PhysicalBoxSides sides_to_include = PhysicalBoxSides()); private: + virtual PhysicalBoxStrut ComputeBorders() const = 0; + virtual PhysicalBoxStrut ComputePadding() const = 0; PhysicalBoxStrut ComputeSnappedBorders() const; const Document& document_;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index a4a9caf..ebb8142 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -1839,27 +1839,22 @@ } PhysicalRect NGBoxFragmentPainter::AdjustRectForScrolledContent( - const PaintInfo& paint_info, - const BoxPainterBase::FillLayerInfo& info, - const PhysicalRect& rect) { - PhysicalRect scrolled_paint_rect = rect; - GraphicsContext& context = paint_info.context; + GraphicsContext& context, + const PhysicalBoxStrut& borders, + const PhysicalRect& rect) const { const PhysicalBoxFragment& physical = GetPhysicalFragment(); // Clip to the overflow area. - if (info.is_clipped_with_local_scrolling && - !paint_info.IsPaintingBackgroundInContentsSpace()) { - context.Clip(gfx::RectF(physical.OverflowClipRect(rect.offset))); + context.Clip(gfx::RectF(physical.OverflowClipRect(rect.offset))); - // Adjust the paint rect to reflect a scrolled content box with borders at - // the ends. - scrolled_paint_rect.offset -= - PhysicalOffset(physical.PixelSnappedScrolledContentOffset()); - PhysicalBoxStrut borders = AdjustedBorderOutsets(info); - scrolled_paint_rect.size = - physical.ScrollSize() + - PhysicalSize(borders.HorizontalSum(), borders.VerticalSum()); - } + PhysicalRect scrolled_paint_rect = rect; + // Adjust the paint rect to reflect a scrolled content box with borders at + // the ends. + scrolled_paint_rect.offset -= + PhysicalOffset(physical.PixelSnappedScrolledContentOffset()); + scrolled_paint_rect.size = + physical.ScrollSize() + + PhysicalSize(borders.HorizontalSum(), borders.VerticalSum()); return scrolled_paint_rect; }
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h index 84a89fb..45401d4 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -14,8 +14,6 @@ #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" #include "third_party/blink/renderer/core/paint/box_painter_base.h" #include "third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.h" -#include "third_party/blink/renderer/platform/geometry/layout_point.h" -#include "third_party/blink/renderer/platform/geometry/layout_size.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" namespace blink { @@ -91,10 +89,9 @@ void PaintTextClipMask(const PaintInfo& paint_info, PhysicalOffset paint_offset, NGInlineBoxFragmentPainter* inline_box_painter); - PhysicalRect AdjustRectForScrolledContent( - const PaintInfo&, - const BoxPainterBase::FillLayerInfo&, - const PhysicalRect&) override; + PhysicalRect AdjustRectForScrolledContent(GraphicsContext&, + const PhysicalBoxStrut& borders, + const PhysicalRect&) const override; private: NGBoxFragmentPainter(const PhysicalBoxFragment&,
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy.dict b/third_party/blink/renderer/core/permissions_policy/permissions_policy.dict index 8105c2f..eb4726f 100644 --- a/third_party/blink/renderer/core/permissions_policy/permissions_policy.dict +++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy.dict
@@ -37,6 +37,7 @@ "top-navigation" "unsized-media" "usb" +"usb-unrestricted" "vertical-scroll" "vr" "\"https://example.com/\""
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 index db96397d..39b51c4 100644 --- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 +++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
@@ -399,6 +399,11 @@ depends_on: ["WebUSB"], }, { + name: "UsbUnrestricted", + permissions_policy_name: "usb-unrestricted", + depends_on: ["UnrestrictedUsb"], + }, + { // Unload is special and can default to being disabled by default based // on the DeprecateUnload flag. name: "Unload",
diff --git a/third_party/blink/renderer/core/probe/core_probes.pidl b/third_party/blink/renderer/core/probe/core_probes.pidl index 27dcc94..9a13cc5 100644 --- a/third_party/blink/renderer/core/probe/core_probes.pidl +++ b/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -98,7 +98,7 @@ void DidBlockRequest(CoreProbeSink*, const ResourceRequest&, DocumentLoader*, const KURL& fetch_context_url, const ResourceLoaderOptions&, ResourceRequestBlockedReason, ResourceType); void DidChangeResourcePriority(LocalFrame*, DocumentLoader*, uint64_t identifier, ResourceLoadPriority load_priority); void PrepareRequest(CoreProbeSink*, DocumentLoader*, ResourceRequest&, ResourceLoaderOptions&, ResourceType); - void WillSendRequest(CoreProbeSink*, DocumentLoader*, const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response, const ResourceLoaderOptions&, ResourceType, RenderBlockingBehavior, base::TimeTicks timestamp); + void WillSendRequest([Keep] ExecutionContext*, DocumentLoader*, const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response, const ResourceLoaderOptions&, ResourceType, RenderBlockingBehavior, base::TimeTicks timestamp); void WillSendNavigationRequest(CoreProbeSink*, uint64_t identifier, DocumentLoader*, const KURL&, const AtomicString& http_method, EncodedFormData*); void MarkResourceAsCached(LocalFrame*, DocumentLoader*, uint64_t identifier); void DidReceiveResourceResponse(CoreProbeSink*, uint64_t identifier, DocumentLoader*, const ResourceResponse&, const Resource*);
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index 0b520f8..230f98fe 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -754,6 +754,10 @@ Supplementable<WorkerGlobalScope>::Trace(visitor); } +bool WorkerGlobalScope::HasPendingActivity() const { + return !ExecutionContext::IsContextDestroyed(); +} + FontMatchingMetrics* WorkerGlobalScope::GetFontMatchingMetrics() { if (!font_matching_metrics_) { font_matching_metrics_ = std::make_unique<FontMatchingMetrics>(
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index 336f0a2..dcb7ba3 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -218,6 +218,9 @@ void Trace(Visitor*) const override; + // ActiveScriptWrappable. + bool HasPendingActivity() const override; + virtual InstalledScriptsManager* GetInstalledScriptsManager() { return nullptr; }
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc index 5b6a11c9..fb62b37 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -250,12 +250,6 @@ return v8::Local<v8::Object>(); } -bool WorkerOrWorkletGlobalScope::HasPendingActivity() const { - // The global scope wrapper is kept alive as longs as its execution context is - // active. - return !ExecutionContext::IsContextDestroyed(); -} - void WorkerOrWorkletGlobalScope::CountUse(WebFeature feature) { DCHECK(IsContextThread());
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h index 326940c..2e184b0f 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
@@ -77,7 +77,6 @@ v8::Isolate*, const WrapperTypeInfo*, v8::Local<v8::Object> wrapper) final; - bool HasPendingActivity() const override; // ExecutionContext bool IsWorkerOrWorkletGlobalScope() const final { return true; }
diff --git a/third_party/blink/renderer/core/workers/worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worklet_global_scope.cc index 6934f88..7c4986c 100644 --- a/third_party/blink/renderer/core/workers/worklet_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worklet_global_scope.cc
@@ -346,4 +346,8 @@ WorkerOrWorkletGlobalScope::Trace(visitor); } +bool WorkletGlobalScope::HasPendingActivity() const { + return !ExecutionContext::IsContextDestroyed(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/worklet_global_scope.h b/third_party/blink/renderer/core/workers/worklet_global_scope.h index ac0a1d7..34f4abb1 100644 --- a/third_party/blink/renderer/core/workers/worklet_global_scope.h +++ b/third_party/blink/renderer/core/workers/worklet_global_scope.h
@@ -124,6 +124,9 @@ void Trace(Visitor*) const override; + // ActiveScriptWrappable. + bool HasPendingActivity() const override; + HttpsState GetHttpsState() const override { return https_state_; } // Constructs an instance as a main thread worklet. Must be called on the main
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 79cfc26..e030d68 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -332,14 +332,55 @@ return false; } - // Inline textboxes are included if and only if the parent is unignored. - // If the parent is ignored but included in tree, the inline textbox is - // still withheld. - if (obj->LastKnownIsIgnoredValue()) { + // Requires a layout object for there to be any inline text boxes. + if (!obj->GetLayoutObject()) { return false; } - return obj->GetLayoutObject() && obj->GetLayoutObject()->IsText(); + // Inline text boxes are included if and only if the parent is unignored. + // If the parent is ignored but included in tree, the inline textbox is + // still withheld. + return !obj->LastKnownIsIgnoredValue(); +} + +bool HasLayoutText(const blink::AXObject* obj) { + // This method should only be used when layout is clean. +#if DCHECK_IS_ON() + DCHECK(obj->GetDocument()->Lifecycle().GetState() >= + blink::DocumentLifecycle::kLayoutClean) + << "Unclean document at lifecycle " + << obj->GetDocument()->Lifecycle().ToString(); +#endif + + // If no layout object, could be display:none or display locked. + if (!obj->GetLayoutObject()) { + return false; + } + + // Display-locked nodes do not have layout objects with which to use for + // retrieving inline textbox children. + const blink::AXObject* ax_ancestor_with_node = obj; + while (!ax_ancestor_with_node->GetNode()) { + ax_ancestor_with_node = ax_ancestor_with_node->CachedParentObject(); + } + if (blink::DisplayLockUtilities::LockedAncestorPreventingPaint( + *ax_ancestor_with_node->GetNode())) { + return false; + } + + // Only text has inline textbox children. + if (!obj->GetLayoutObject()->IsText()) { + return false; + } + + // Layout for this node must be clean, since we are in clean layout, and any + // node that needs layout because of display locking would have returned early + // above. + DUMP_WILL_BE_CHECK(!obj->GetLayoutObject()->NeedsLayout()) + << "LayoutText needed layout but was not display locked: " + << obj->ToString(true, true); + + return true; } } // namespace @@ -4301,6 +4342,13 @@ } void AXNodeObject::LoadInlineTextBoxes() { +#if DCHECK_IS_ON() + DCHECK(GetDocument()->Lifecycle().GetState() >= + DocumentLifecycle::kLayoutClean) + << "Unclean document at lifecycle " + << GetDocument()->Lifecycle().ToString(); +#endif + std::queue<AXID> work_queue; work_queue.push(AXObjectID()); @@ -4365,6 +4413,9 @@ void AXNodeObject::AddInlineTextBoxChildren() { CHECK(GetDocument()); CHECK(ShouldLoadInlineTextBoxes()); + CHECK(GetLayoutObject()); + GetLayoutObject()->CheckIsNotDestroyed(); + CHECK(GetLayoutObject()->IsText()); CHECK(!GetLayoutObject()->NeedsLayout()); CHECK(AXObjectCache().GetAXMode().has_mode(ui::AXMode::kInlineTextBoxes)); CHECK(!AXObjectCache().GetAXMode().HasExperimentalFlags( @@ -4531,7 +4582,7 @@ return; } - if (ShouldLoadInlineTextBoxes()) { + if (ShouldLoadInlineTextBoxes() && HasLayoutText(this)) { AddInlineTextBoxChildren(); CHECK_ATTACHED(); return;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 0b4775d7..d4bf06e 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -702,8 +702,7 @@ // Load inline text boxes for just this node, even if // AXObjectCache().GetAXMode().has_mode(ui::AXMode::kInlineTextBoxes) is - // false. Can be called even when layout is not clean, but in that case - // it will force clean layout. + // false. Must be called with clean layout. virtual void LoadInlineTextBoxes(); virtual void LoadInlineTextBoxesHelper(); // When adding children to this node, consider inline textboxes.
diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc index bbfeff0b..afda052 100644 --- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc +++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
@@ -687,10 +687,13 @@ class PictureInPictureControllerChromeClient : public RenderingTestChromeClient { public: - explicit PictureInPictureControllerChromeClient( - DummyPageHolder* dummy_page_holder) - : dummy_page_holder_(dummy_page_holder) {} + PictureInPictureControllerChromeClient() = default; + void set_dummy_page_holder(DummyPageHolder* dummy_page_holder) { + dummy_page_holder_ = dummy_page_holder; + } + + // RenderingTestChromeClient: Page* CreateWindowDelegate(LocalFrame*, const FrameLoadRequest&, const AtomicString&, @@ -698,12 +701,13 @@ network::mojom::blink::WebSandboxFlags, const SessionStorageNamespaceId&, bool& consumed_user_gesture) override { + CHECK(dummy_page_holder_); return &dummy_page_holder_->GetPage(); } MOCK_METHOD(void, SetWindowRect, (const gfx::Rect&, LocalFrame&)); private: - raw_ptr<DummyPageHolder, ExperimentalRenderer> dummy_page_holder_; + raw_ptr<DummyPageHolder, ExperimentalRenderer> dummy_page_holder_ = nullptr; }; // Tests for Picture in Picture with a mockable chrome client. This makes it @@ -714,8 +718,10 @@ public: void SetUp() override { chrome_client_ = - MakeGarbageCollected<PictureInPictureControllerChromeClient>( - &dummy_page_holder_); + MakeGarbageCollected<PictureInPictureControllerChromeClient>(); + dummy_page_holder_ = + std::make_unique<DummyPageHolder>(gfx::Size(), chrome_client_); + chrome_client_->set_dummy_page_holder(dummy_page_holder_.get()); RenderingTest::SetUp(); } @@ -737,7 +743,7 @@ // ownership of it here so that it outlives the GC'd objects. The client // cannot own it because it also has a GC root to the client; everything would // leak if we did so. - DummyPageHolder dummy_page_holder_; + std::unique_ptr<DummyPageHolder> dummy_page_holder_; }; TEST_F(PictureInPictureControllerTestWithChromeClient, @@ -756,12 +762,39 @@ // The Picture in Picture window's base URL should match the opener. EXPECT_EQ(GetOpenerURL().GetString(), document->BaseURL().GetString()); - // Verify that move* and resize* don't call through to the chrome client. + // Verify that move* doesn't call through to the chrome client. EXPECT_CALL(GetPipChromeClient(), SetWindowRect(_, _)).Times(0); document->domWindow()->moveTo(10, 10); document->domWindow()->moveBy(10, 10); - document->domWindow()->resizeTo(10, 10); - document->domWindow()->resizeBy(10, 10); + testing::Mock::VerifyAndClearExpectations(&GetPipChromeClient()); + + { + // Verify that resizeTo consumes a user gesture, and so only one of the + // following calls will succeed. + EXPECT_CALL(GetPipChromeClient(), SetWindowRect(_, _)); + LocalFrame::NotifyUserActivation( + document->GetFrame(), mojom::UserActivationNotificationType::kTest); + ExceptionState exception_state( + ToScriptStateForMainWorld(document->GetFrame())->GetIsolate(), + ExceptionContextType::kOperationInvoke, "Window", "resizeTo"); + document->domWindow()->resizeTo(10, 10, exception_state); + document->domWindow()->resizeTo(20, 20, exception_state); + testing::Mock::VerifyAndClearExpectations(&GetPipChromeClient()); + } + + { + // Verify that resizeBy consumes a user gesture, and so only one of the + // following calls will succeed. + EXPECT_CALL(GetPipChromeClient(), SetWindowRect(_, _)); + LocalFrame::NotifyUserActivation( + document->GetFrame(), mojom::UserActivationNotificationType::kTest); + ExceptionState exception_state( + ToScriptStateForMainWorld(document->GetFrame())->GetIsolate(), + ExceptionContextType::kOperationInvoke, "Window", "resizeBy"); + document->domWindow()->resizeBy(10, 10, exception_state); + document->domWindow()->resizeBy(20, 20, exception_state); + testing::Mock::VerifyAndClearExpectations(&GetPipChromeClient()); + } // Make sure that the `document` is not the same as the opener. EXPECT_NE(document, &GetDocument());
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler_test.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler_test.cc index 5097cb7..7c4d13f 100644 --- a/third_party/blink/renderer/modules/scheduler/dom_scheduler_test.cc +++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler_test.cc
@@ -150,13 +150,4 @@ ScopedAbortSignalCompositionForTest scoped_signal_composition_; }; -TEST_F(DOMSchedulerTestWithCompositionDisabled, FixedPriorirtySignal) { - // Regression test for crbug.com/1431940. - V8TestingScope scope; - auto* signal = GetScheduler()->GetFixedPriorityTaskSignal( - scope.GetScriptState(), WebSchedulingPriority::kUserVisiblePriority); - // This should not crash. - signal->HasPendingActivity(); -} - } // namespace blink
diff --git a/third_party/blink/renderer/modules/scheduler/dom_task.cc b/third_party/blink/renderer/modules/scheduler/dom_task.cc index 7ed5dfe..99b5d26ba 100644 --- a/third_party/blink/renderer/modules/scheduler/dom_task.cc +++ b/third_party/blink/renderer/modules/scheduler/dom_task.cc
@@ -57,7 +57,7 @@ GenericTaskData(dict, execution_context, task_id); dict.Add("priority", priority); dict.Add("delay", delay); - SetCallStack(dict); + SetCallStack(execution_context->GetIsolate(), dict); } void RunPostTaskCallbackTraceEventData(perfetto::TracedValue trace_context, @@ -76,7 +76,7 @@ uint64_t task_id) { auto dict = std::move(trace_context).WriteDictionary(); GenericTaskData(dict, execution_context, task_id); - SetCallStack(dict); + SetCallStack(execution_context->GetIsolate(), dict); } } // namespace
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc index d5498ce..a2d10ed5 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
@@ -340,13 +340,6 @@ void GPUCommandEncoder::writeTimestamp(DawnObject<WGPUQuerySet>* querySet, uint32_t queryIndex, ExceptionState& exception_state) { - if (!RuntimeEnabledFeatures::WebGPUDeveloperFeaturesEnabled()) { - exception_state.ThrowTypeError( - String::Format("Use of the writeTimestamp() method requires the " - "'WebGPU Developer Features' flag to be enabled on %s.", - device_->formattedLabel().c_str())); - return; - } V8GPUFeatureName::Enum requiredFeatureEnum = V8GPUFeatureName::Enum::kTimestampQuery; if (!device_->features()->has(requiredFeatureEnum)) {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl index 987910e..d92596f 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl
@@ -44,7 +44,8 @@ GPUBuffer destination, GPUSize64 destinationOffset); - [NoAllocDirectCall, RaisesException] void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); + [RuntimeEnabled=WebGPUDeveloperFeatures, NoAllocDirectCall, RaisesException] + void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); [NoAllocDirectCall] void clearBuffer( GPUBuffer buffer,
diff --git a/third_party/blink/renderer/modules/websockets/inspector_websocket_events.cc b/third_party/blink/renderer/modules/websockets/inspector_websocket_events.cc index 048f9334..4756afd 100644 --- a/third_party/blink/renderer/modules/websockets/inspector_websocket_events.cc +++ b/third_party/blink/renderer/modules/websockets/inspector_websocket_events.cc
@@ -36,7 +36,7 @@ } if (!protocol.IsNull()) dict.Add("webSocketProtocol", protocol); - SetCallStack(dict); + SetCallStack(execution_context->GetIsolate(), dict); } void InspectorWebSocketEvent::Data(perfetto::TracedValue context, @@ -54,7 +54,7 @@ NOTREACHED() << "WebSocket is available only in Window and WorkerGlobalScope"; } - SetCallStack(dict); + SetCallStack(execution_context->GetIsolate(), dict); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h b/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h index 26f47cb..4cf8ce0 100644 --- a/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h +++ b/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
@@ -25,7 +25,15 @@ virtual ~ActiveScriptWrappableBase() = default; virtual bool IsContextDestroyed() const = 0; - virtual bool DispatchHasPendingActivity() const = 0; + + // `HasPendingActivity()` overrides the lifetime of ScriptWrappable objects + // when needed. If `HasPendingActivity()` returns true and the corresponding + // ExecutionContext is not destroyed, the objects will not be reclaimed by the + // GC, even if they are otherwise unreachable. + // + // Note: These methods are queried during garbage collection and *must not* + // allocate any new objects. + virtual bool HasPendingActivity() const = 0; protected: ActiveScriptWrappableBase() = default;
diff --git a/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc b/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc index c5516ba..4a4c9b6b 100644 --- a/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc +++ b/third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.cc
@@ -27,7 +27,7 @@ if (asw.IsContextDestroyed()) return false; - return asw.DispatchHasPendingActivity(); + return asw.HasPendingActivity(); } } // namespace
diff --git a/third_party/blink/renderer/platform/bindings/script_wrappable.h b/third_party/blink/renderer/platform/bindings/script_wrappable.h index b5ff24b..f51c759 100644 --- a/third_party/blink/renderer/platform/bindings/script_wrappable.h +++ b/third_party/blink/renderer/platform/bindings/script_wrappable.h
@@ -104,15 +104,6 @@ ScriptWrappable& operator=(const ScriptWrappable&) = delete; ~ScriptWrappable() override = default; - // The following methods may override lifetime of ScriptWrappable objects when - // needed. In particular if `HasPendingActivity()` returns true *and* the - // child type also inherits from `ActiveScriptWrappable`, the objects will not - // be reclaimed by the GC, even if they are otherwise unreachable. - // - // Note: These methods are queried during garbage collection and *must not* - // allocate any new objects. - virtual bool HasPendingActivity() const { return false; } - const char* NameInHeapSnapshot() const override; virtual void Trace(Visitor*) const;
diff --git a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc index 2a1f235..275beac2 100644 --- a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc +++ b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
@@ -143,7 +143,6 @@ absl::optional<SkFontParameters::Variation::Axis> wght_parameters = RetrieveVariationDesignParametersByTag(base_typeface_, kWghtTag); if (selection_capabilities.weight.IsRangeSetFromAuto() && wght_parameters) { - DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled()); FontSelectionRange wght_range = { FontSelectionValue(wght_parameters->min), FontSelectionValue(wght_parameters->max)}; @@ -160,7 +159,6 @@ absl::optional<SkFontParameters::Variation::Axis> wdth_parameters = RetrieveVariationDesignParametersByTag(base_typeface_, kWdthTag); if (selection_capabilities.width.IsRangeSetFromAuto() && wdth_parameters) { - DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled()); FontSelectionRange wdth_range = { FontSelectionValue(wdth_parameters->min), FontSelectionValue(wdth_parameters->max)}; @@ -179,7 +177,6 @@ absl::optional<SkFontParameters::Variation::Axis> slnt_parameters = RetrieveVariationDesignParametersByTag(base_typeface_, kSlntTag); if (selection_capabilities.slope.IsRangeSetFromAuto() && slnt_parameters) { - DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled()); FontSelectionRange slnt_range = { FontSelectionValue(slnt_parameters->min), FontSelectionValue(slnt_parameters->max)};
diff --git a/third_party/blink/renderer/platform/fonts/font_selection_types.h b/third_party/blink/renderer/platform/fonts/font_selection_types.h index 3e7c5d7..5c2ea0c0 100644 --- a/third_party/blink/renderer/platform/fonts/font_selection_types.h +++ b/third_party/blink/renderer/platform/fonts/font_selection_types.h
@@ -29,7 +29,6 @@ #include <algorithm> #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h" #include "third_party/blink/renderer/platform/wtf/hash_traits.h" @@ -280,9 +279,7 @@ FontSelectionValue minimum{FontSelectionValue(1)}; FontSelectionValue maximum{FontSelectionValue(0)}; - RangeType type = RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled() - ? kSetFromAuto - : kSetExplicitly; + RangeType type = kSetFromAuto; }; struct PLATFORM_EXPORT FontSelectionRequest {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc index 823391c..0da90a6 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -190,11 +190,11 @@ kTopLeft_GrSurfaceOrigin, alpha_mode, usage, "WebGPUSwapBufferProvider", gpu::kNullSurfaceHandle); CHECK(client_shared_image); - gpu::Mailbox mailbox = client_shared_image->mailbox(); gpu::SyncToken creation_token = sii->GenUnverifiedSyncToken(); unused_swap_buffers_.push_back(base::MakeRefCounted<SwapBuffer>( - std::move(context_provider), mailbox, creation_token, size)); + std::move(context_provider), std::move(client_shared_image), + creation_token, size)); DCHECK_EQ(unused_swap_buffers_.back()->size, size); } @@ -251,7 +251,8 @@ // Make a mailbox texture from the swap buffer. current_swap_buffer_->mailbox_texture = WebGPUMailboxTexture::FromExistingMailbox( - dawn_control_client_, device_, desc, current_swap_buffer_->mailbox, + dawn_control_client_, device_, desc, + current_swap_buffer_->shared_image->mailbox(), // Wait on the last usage of this swap buffer. current_swap_buffer_->access_finished_token, gpu::webgpu::WEBGPU_MAILBOX_DISCARD, @@ -288,7 +289,8 @@ return WebGPUMailboxTextureAndSize( WebGPUMailboxTexture::FromExistingMailbox( - dawn_control_client_, device_, desc, latest_swap_buffer->mailbox, + dawn_control_client_, device_, desc, + latest_swap_buffer->shared_image->mailbox(), latest_swap_buffer->access_finished_token, gpu::webgpu::WEBGPU_MAILBOX_NONE), latest_swap_buffer->size); @@ -312,7 +314,7 @@ // Populate the output resource *out_resource = viz::TransferableResource::MakeGpu( - current_swap_buffer_->mailbox, GetTextureTarget(), + current_swap_buffer_->shared_image, GetTextureTarget(), current_swap_buffer_->access_finished_token, current_swap_buffer_->size, Format(), IsOverlayCandidate(), viz::TransferableResource::ResourceSource::kWebGPUSwapBuffer); @@ -351,9 +353,9 @@ // need to release WebGPU/Dawn's context's access to the texture. ReleaseWGPUTextureAccessIfNeeded(); - gpu::MailboxHolder mailbox_holder(current_swap_buffer_->mailbox, - current_swap_buffer_->access_finished_token, - GetTextureTarget()); + gpu::MailboxHolder mailbox_holder( + current_swap_buffer_->shared_image->mailbox(), + current_swap_buffer_->access_finished_token, GetTextureTarget()); if (frame_pool->CopyRGBATextureToVideoFrame( Format(), current_swap_buffer_->size, @@ -389,11 +391,11 @@ WebGPUSwapBufferProvider::SwapBuffer::SwapBuffer( base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider, - gpu::Mailbox mailbox, + scoped_refptr<gpu::ClientSharedImage> shared_image, gpu::SyncToken creation_token, gfx::Size size) : size(size), - mailbox(mailbox), + shared_image(std::move(shared_image)), context_provider(context_provider), access_finished_token(creation_token) {} @@ -401,12 +403,13 @@ if (context_provider) { gpu::SharedImageInterface* sii = context_provider->ContextProvider()->SharedImageInterface(); - sii->DestroySharedImage(access_finished_token, mailbox); + sii->DestroySharedImage(access_finished_token, std::move(shared_image)); } } gpu::Mailbox WebGPUSwapBufferProvider::GetCurrentMailboxForTesting() const { DCHECK(current_swap_buffer_); - return current_swap_buffer_->mailbox; + DCHECK(current_swap_buffer_->shared_image); + return current_swap_buffer_->shared_image->mailbox(); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h index f95ef3e..ccaa4b0f 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h +++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
@@ -112,7 +112,7 @@ struct SwapBuffer : WTF::RefCounted<SwapBuffer> { SwapBuffer( base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider, - gpu::Mailbox mailbox, + scoped_refptr<gpu::ClientSharedImage> shared_image, gpu::SyncToken creation_token, gfx::Size size); SwapBuffer(const SwapBuffer&) = delete; @@ -120,7 +120,7 @@ ~SwapBuffer(); gfx::Size size; - gpu::Mailbox mailbox; + scoped_refptr<gpu::ClientSharedImage> shared_image; scoped_refptr<WebGPUMailboxTexture> mailbox_texture; // A weak ptr to the context provider so that the destructor can
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 024ed51f..f590512 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -912,13 +912,6 @@ status: "stable", }, { - // @font-face Font property descriptors auto range. - // https://www.w3.org/TR/css-fonts-4/#font-prop-desc - name: "CSSFontFaceAutoVariableRange", - status: "stable", - base_feature: "none", - }, - { name: "CSSFontSizeAdjust", status: "experimental", base_feature: "none", @@ -3806,6 +3799,14 @@ origin_trial_feature_name: "UnrestrictedSharedArrayBuffer", origin_trial_os: ["win", "mac", "linux", "fuchsia", "chromeos"], }, + // Enables using policy-controlled feature "usb-unrestricted" to allow + // isolated context to access protected USB interface classes and to + // bypass the USB blocklist. + { + name: "UnrestrictedUsb", + status: "experimental", + depends_on: ["WebUSB"], + }, { // This flag makes IDL reflected attributes with the "URL" IDL attribute // return the original string of the attribute when a complete URL can't @@ -4123,7 +4124,7 @@ }, { name: "WebCodecsContentHint", - status: "experimental", + status: "stable", }, { name: "WebCodecsCopyToRGB",
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc index 0e5ecb9..ab5742a 100644 --- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc +++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
@@ -48,15 +48,6 @@ "ScaleScrollbarAnimationTiming", base::FEATURE_DISABLED_BY_DEFAULT); -#if BUILDFLAG(IS_ANDROID) -// Whether to use a simpler way to compute compositor memory limits on -// Android. Intended to become default, but introduced temporarily to check -// it's not breaking things. -BASE_FEATURE(kSimpleCompositorMemoryLimits, - "SimpleCompositorMemoryLimits", - base::FEATURE_DISABLED_BY_DEFAULT); -#endif - constexpr base::FeatureParam<double> kFadeDelayScalingFactor{ &kScaleScrollbarAnimationTiming, "fade_delay_scaling_factor", /*default_value=*/1.0}; @@ -190,84 +181,17 @@ } #if BUILDFLAG(IS_ANDROID) - if (base::FeatureList::IsEnabled(kSimpleCompositorMemoryLimits)) { - if (base::SysInfo::IsLowEndDevice() || - base::SysInfo::AmountOfPhysicalMemoryMB() < 2000) { - actual.bytes_limit_when_visible = 96 * 1024 * 1024; - } else { - actual.bytes_limit_when_visible = 256 * 1024 * 1024; - } - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; + if (base::SysInfo::IsLowEndDevice() || + base::SysInfo::AmountOfPhysicalMemoryMB() < 2000) { + actual.bytes_limit_when_visible = 96 * 1024 * 1024; } else { - // We can't query available GPU memory from the system on Android. - // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports - // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports - // 128MB java heap size). First we estimate physical memory using both. - size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB(); - size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB(); - size_t physical_memory_mb = 0; - if (base::SysInfo::IsLowEndDevice()) { - // TODO(crbug.com/742534): The code below appears to no longer work. - // |dalvik_mb| no longer follows the expected heuristic pattern, causing - // us to over-estimate memory on low-end devices. This entire section - // probably needs to be re-written, but for now we can address the low-end - // Android issues by ignoring |dalvik_mb|. - physical_memory_mb = physical_mb; - } else if (dalvik_mb >= 256) { - physical_memory_mb = dalvik_mb * 4; - } else { - physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3); - } - - // Now we take a default of 1/8th of memory on high-memory devices, - // and gradually scale that back for low-memory devices (to be nicer - // to other apps so they don't get killed). Examples: - // Nexus 4/10(2GB) 256MB (normally 128MB) - // Droid Razr M(1GB) 114MB (normally 57MB) - // Galaxy Nexus(1GB) 100MB (normally 50MB) - // Xoom(1GB) 100MB (normally 50MB) - // Nexus S(low-end) 8MB (normally 8MB) - // Note that the compositor now uses only some of this memory for - // pre-painting and uses the rest only for 'emergencies'. - if (actual.bytes_limit_when_visible == 0) { - // NOTE: Non-low-end devices use only 50% of these limits, - // except during 'emergencies' where 100% can be used. - if (physical_memory_mb >= 1536) { - actual.bytes_limit_when_visible = physical_memory_mb / 8; // >192MB - } else if (physical_memory_mb >= 1152) { - actual.bytes_limit_when_visible = physical_memory_mb / 8; // >144MB - } else if (physical_memory_mb >= 768) { - actual.bytes_limit_when_visible = physical_memory_mb / 10; // >76MB - } else if (physical_memory_mb >= 513) { - actual.bytes_limit_when_visible = physical_memory_mb / 12; // <64MB - } else { - // Devices with this little RAM have very little headroom so we hardcode - // the limit rather than relying on the heuristics above. (They also - // use 4444 textures so we can use a lower limit.) - actual.bytes_limit_when_visible = 8; - } - - actual.bytes_limit_when_visible = - actual.bytes_limit_when_visible * 1024 * 1024; - // Clamp the observed value to a specific range on Android. - actual.bytes_limit_when_visible = - std::max(actual.bytes_limit_when_visible, - static_cast<size_t>(8 * 1024 * 1024)); - actual.bytes_limit_when_visible = - std::min(actual.bytes_limit_when_visible, - static_cast<size_t>(256 * 1024 * 1024)); - } - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING; + actual.bytes_limit_when_visible = 256 * 1024 * 1024; } #else if (base::FeatureList::IsEnabled(kIncreaseTileMemorySizeProportionally)) { // This calculation will increase the tile memory size. It should apply to // the other plateforms if no regression on Mac. - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; - + // // For large monitors with high resolution, increase the tile memory to // avoid frequent out of memory problems. With Mac M1 on // https://www.334-28th.com/, it seems 512 MB works fine on 1920x1080 * 2 @@ -300,8 +224,6 @@ // Ignore what the system said and give all clients the same maximum // allocation on desktop platforms. actual.bytes_limit_when_visible = 512 * 1024 * 1024; - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; // For large monitors (4k), double the tile memory to avoid frequent out of // memory problems. 4k could mean a screen width of anywhere from 3840 to @@ -315,6 +237,8 @@ } } #endif + actual.priority_cutoff_when_visible = + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; return actual; }
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py index 69d42b76..d7ddf42 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/base.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -470,6 +470,9 @@ @memoized def _build_is_chrome_branded(self): + chrome_branded = self.get_option('chrome_branded') + if chrome_branded: + return bool(chrome_branded) contents = self._build_args_gn_content() return bool( re.search(r'^\s*is_chrome_branded\s*=\s*true\s*(#.*)?$', contents,
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/factory.py b/third_party/blink/tools/blinkpy/web_tests/port/factory.py index ea890b6a..cb525cf 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/factory.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/factory.py
@@ -219,6 +219,9 @@ const='Release', dest='configuration', help='Set the configuration to Release') + group.add_argument('--chrome-branded', + action='store_true', + help='Set the configuration as chrome_branded.') add_common_wpt_options(group) if rwt: group.add_argument('--no-xvfb',
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 558648a..365063d 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1537,7 +1537,6 @@ crbug.com/1488371 virtual/deprecate-unload/http/tests/history/history-replace-updates-current-item.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/http/tests/navigation/image-load-in-subframe-unload-handler.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/http/tests/navigation/image-load-in-unload-handler.html [ Failure Skip Timeout ] -crbug.com/1488371 virtual/deprecate-unload/http/tests/notifications/close-on-document-unload.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/navigate-to-unparseable-url.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/001.html [ Failure Skip Timeout ] @@ -1549,7 +1548,6 @@ crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/009.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/history/the-history-interface/traverse_the_history_unload_1.html [ Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/BarProp.window.html [ Failure Skip Timeout ] -crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/close-method.window.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/open-close/close_unload.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/self-et-al.window.html [ Failure Skip Timeout ] crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.html [ Failure Skip Timeout ] @@ -5233,6 +5231,9 @@ crbug.com/1256763 [ Linux ] images/color-profile-background-clip-text.html [ Failure Pass ] crbug.com/1259277 fast/events/message-port-multi.html [ Crash Failure Pass Timeout ] +# Temporarily disable to roll DevTools into Chromium +crbug.com/1264670 http/tests/devtools/resource-tree/resource-tree-frame-add.js [ Failure Pass ] + # TODO(https://crbug.com/1265311): Make the test behave the same way on all platforms crbug.com/1265311 http/tests/navigation/location-change-repeated-from-blank.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 3e7f3aa..9d792d2 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1978,7 +1978,10 @@ { "prefix": "isolate-sandboxed-iframes", "platforms": ["Linux", "Mac", "Win"], - "bases": [ "external/wpt/html/infrastructure/urls/terminology-0/" ], + "bases": [ + "external/wpt/html/infrastructure/urls/terminology-0/", + "external/wpt/cookie-store/cookieStore_opaque_origin.https.html" + ], "args": ["--enable-features=IsolateSandboxedIframes", "--disable-threaded-compositing", "--disable-threaded-animation"], "expires": "Jul 1, 2024" @@ -2669,7 +2672,6 @@ "http/tests/navigation/redirect-on-back-updates-history-item.html", "http/tests/navigation/redirect-on-reload-updates-history-item.html", "http/tests/navigation/targeted-navigation-in-unload-handler.html", - "http/tests/notifications/close-on-document-unload.html", "http/tests/security/isolatedWorld/context-destroy.html", "http/tests/security/window-events-clear-domain.html", "http/tests/security/window-events-clear-port.html", @@ -2695,7 +2697,6 @@ "external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/unload-main-frame-same-origin.window.js", "external/wpt/html/browsers/history/the-history-interface/traverse_the_history_unload_1.html", "external/wpt/html/browsers/the-window-object/BarProp.window.js", - "external/wpt/html/browsers/the-window-object/close-method.window.js", "external/wpt/html/browsers/the-window-object/open-close/close_unload.html", "external/wpt/html/browsers/the-window-object/self-et-al.window.js", "external/wpt/html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.js", @@ -2719,18 +2720,5 @@ "args": ["--enable-features=DeprecateUnload"], "expires": "Jun 1, 2024", "owners": ["fergal@chromium.org", "rakina@chromium.org"] - }, - { - "prefix": "webrtc-transforms-per-stream-disabled", - "platforms": ["Linux"], - "bases": [ - "external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-audio.https.html", - "external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-errors.https.html", - "external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-video.https.html", - "fast/peerconnection/RTCPeerconnection-insertable-streams.html" - ], - "args": ["--disable-features=WebRtcEncodedTransformsPerStreamCreation"], - "expires": "Mar 1, 2024", - "owners": ["herre@google.com", "video-cmi-apis@google.com"] } ]
diff --git a/third_party/blink/web_tests/external/wpt/document-picture-in-picture/resize-requires-user-gesture.https.html b/third_party/blink/web_tests/external/wpt/document-picture-in-picture/resize-requires-user-gesture.https.html new file mode 100644 index 0000000..f6c4aa4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/document-picture-in-picture/resize-requires-user-gesture.https.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<title>Test that calling resizeTo() or resizeBy() on a document + picture-in-picture window requires user gesture</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<body> +<script> +promise_test(async (t) => { + await test_driver.bless('request PiP window from top window'); + const pipWindow = await documentPictureInPicture.requestWindow(); + + await assert_throws_dom('NotAllowedError', pipWindow.DOMException, () => { + pipWindow.resizeBy(10, 10); + }, 'resizeBy() requires a user gesture for document picture-in-picture'); + await assert_throws_dom('NotAllowedError', pipWindow.DOMException, () => { + pipWindow.resizeTo(400, 400); + }, 'resizeTo() requires a user gesture for document picture-in-picture'); +}); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/close-method.window.js b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/close-method.window.js index 0288f9ca..048c5f7 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/close-method.window.js +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/close-method.window.js
@@ -6,7 +6,7 @@ async_test(t => { const openee = window.open(); assert_closed_opener(openee, false, self); - openee.onunload = t.step_func(() => { + openee.onpagehide = t.step_func(() => { assert_closed_opener(openee, true, self); t.step_timeout(() => { assert_closed_opener(openee, true, null); @@ -25,7 +25,7 @@ const openee2 = window.open("", "greatname"); assert_not_equals(openee, openee2); assert_closed_opener(openee, true, self); // Ensure second window.open() call was synchronous - openee2.onunload = t.step_func(() => { + openee2.onpagehide = t.step_func(() => { assert_closed_opener(openee2, true, self); t.step_timeout(() => { assert_closed_opener(openee, true, null);
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add-expected.txt b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add-expected.txt index 07164c2..3b2abd3 100644 --- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add-expected.txt
@@ -13,7 +13,7 @@ Resources Tree: Frames top - CSS + Stylesheets styles-initial.css inspected-page.html Sources: @@ -70,12 +70,12 @@ Frames top resource-tree-frame-add-iframe.html - CSS - styles-navigated.css - JavaScript + Scripts script-navigated.js + Stylesheets + styles-navigated.css resource-tree-frame-add-iframe.html - CSS + Stylesheets styles-initial.css inspected-page.html Sources:
diff --git a/third_party/blink/web_tests/http/tests/notifications/close-on-document-unload.html b/third_party/blink/web_tests/http/tests/notifications/close-on-document-pagehide.html similarity index 75% rename from third_party/blink/web_tests/http/tests/notifications/close-on-document-unload.html rename to third_party/blink/web_tests/http/tests/notifications/close-on-document-pagehide.html index 52a3b56..57a92af 100644 --- a/third_party/blink/web_tests/http/tests/notifications/close-on-document-unload.html +++ b/third_party/blink/web_tests/http/tests/notifications/close-on-document-pagehide.html
@@ -1,14 +1,14 @@ <!doctype html> <html> <head> - <title>Notifications: Closing a notification in the "unload" event does not crash.</title> + <title>Notifications: Closing a notification in the "pagehide" event does not crash.</title> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="resources/test-helpers.js"></script> </head> <body> <script> - // Tests that closing a displayed Web Notification in the unload event does not + // Tests that closing a displayed Web Notification in the pagehide event does not // cause the browser to crash. if (window.testRunner) { testRunner.setPermission('notifications', 'granted', location.origin, location.origin); @@ -16,7 +16,7 @@ } async_test(function (test) { - var win = window.open('resources/window-close-in-unload-event.html'); + var win = window.open('resources/window-close-in-pagehide-event.html'); window.addEventListener('message', function (event) { if (event.data == 'opened') { win.close(); @@ -25,7 +25,7 @@ } }); - }, 'Closing a notification in the "unload" event does not crash.'); + }, 'Closing a notification in the "pagehide" event does not crash.'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/http/tests/notifications/resources/window-close-in-unload-event.html b/third_party/blink/web_tests/http/tests/notifications/resources/window-close-in-pagehide-event.html similarity index 83% rename from third_party/blink/web_tests/http/tests/notifications/resources/window-close-in-unload-event.html rename to third_party/blink/web_tests/http/tests/notifications/resources/window-close-in-pagehide-event.html index 4dadadd..bea2e7a 100644 --- a/third_party/blink/web_tests/http/tests/notifications/resources/window-close-in-unload-event.html +++ b/third_party/blink/web_tests/http/tests/notifications/resources/window-close-in-pagehide-event.html
@@ -1,7 +1,7 @@ <!doctype html> <html> <head> - <title>Notifications: Document for closing a notification in the "unload" event.</title> + <title>Notifications: Document for closing a notification in the "pagehide" event.</title> </head> <body> <script> @@ -12,7 +12,7 @@ opener.postMessage('opened', '*'); - window.addEventListener('unload', function() { + window.addEventListener('pagehide', function() { notification.close(); opener.postMessage('closed', '*');
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 88a7b1f..3fcdbb1 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -667,7 +667,6 @@ [Worker] method popDebugGroup [Worker] method pushDebugGroup [Worker] method resolveQuerySet -[Worker] method writeTimestamp [Worker] setter label [Worker] interface GPUCompilationInfo [Worker] attribute @@toStringTag
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index d884986..4c9b760 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -2497,7 +2497,6 @@ method popDebugGroup method pushDebugGroup method resolveQuerySet - method writeTimestamp setter label interface GPUCompilationInfo attribute @@toStringTag
diff --git a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/README.txt b/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/README.txt deleted file mode 100644 index 211760e..0000000 --- a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/README.txt +++ /dev/null
@@ -1 +0,0 @@ -Expectations for encoded transforms tests with WebRtcEncodedTransformsPerStreamCreation disabled
diff --git a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-audio.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-audio.https-expected.txt deleted file mode 100644 index 90670ac1..0000000 --- a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-audio.https-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -[FAIL] Frames flow correctly using insertable streams - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded audio streams not requested at PC initialization" -[FAIL] Frames flow correctly using insertable streams when receiver starts negotiation - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded audio streams not requested at PC initialization" -[FAIL] Encoded frames serialize and deserialize into a deep clone - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded audio streams not requested at PC initialization" -[FAIL] Modifying rtp timestamp - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded audio streams not requested at PC initialization" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-video.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-video.https-expected.txt deleted file mode 100644 index 0d3f507..0000000 --- a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-video.https-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -[FAIL] Frames flow correctly using insertable streams - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded video streams not requested at PC initialization" -[FAIL] Frames flow correctly using insertable streams when receiver starts negotiation - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded video streams not requested at PC initialization" -[FAIL] Creating streams twice throws - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded video streams not requested at PC initialization" -[FAIL] Encoded frames serialize and deserialize into a deep clone - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded video streams not requested at PC initialization" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/fast/peerconnection/README.txt b/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/fast/peerconnection/README.txt deleted file mode 100644 index d1814d8..0000000 --- a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/fast/peerconnection/README.txt +++ /dev/null
@@ -1 +0,0 @@ -Expectations for internal encoded transforms tests with WebRtcEncodedTransformsPerStreamCreation disabled
diff --git a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/fast/peerconnection/RTCPeerconnection-insertable-streams-expected.txt b/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/fast/peerconnection/RTCPeerconnection-insertable-streams-expected.txt deleted file mode 100644 index 645b7b25..0000000 --- a/third_party/blink/web_tests/virtual/webrtc-transforms-per-stream-disabled/fast/peerconnection/RTCPeerconnection-insertable-streams-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -[FAIL] createEncodedStreams can be called synchronously after sender creation without encodedInsertableStreams param - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpSender': Encoded video streams not requested at PC initialization" -[FAIL] createEncodedStreams can be called synchronously after receiver creation without encodedInsertableStreams param - promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'createEncodedStreams' on 'RTCRtpReceiver': Encoded video streams not requested at PC initialization" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt index 7281f9ee..efbabb5 100644 --- a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
@@ -72,6 +72,7 @@ sync-xhr unload usb +usb-unrestricted vertical-scroll web-printing window-management
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 9374775..d642d8a 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -696,7 +696,6 @@ [Worker] method popDebugGroup [Worker] method pushDebugGroup [Worker] method resolveQuerySet -[Worker] method writeTimestamp [Worker] setter label [Worker] interface GPUCompilationInfo [Worker] attribute @@toStringTag
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 1660634..b8f62ee 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -2951,7 +2951,6 @@ method popDebugGroup method pushDebugGroup method resolveQuerySet - method writeTimestamp setter label interface GPUCompilationInfo attribute @@toStringTag
diff --git a/third_party/catapult b/third_party/catapult index 2823d8f..d9aa189 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit 2823d8f8bea1f1324448fcc2423200b9ad7939ed +Subproject commit d9aa189385c2a4ec17be2f88291a6cd826ca62fd
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index 484c659..d567cf2 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit 484c659ff02abe8b427ceec35911c914b794d59d +Subproject commit d567cf29ad32e9aaeac80a6f7f69a978c28c2aa0
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 2979e07..2c58d1b 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 2979e07e0a704c3ada139cb6f2757c56c61bf73e +Subproject commit 2c58d1b91203d9e638f50506b6d9532189d3a671
diff --git a/third_party/libavif/src b/third_party/libavif/src index 7845153..286f1b9 160000 --- a/third_party/libavif/src +++ b/third_party/libavif/src
@@ -1 +1 @@ -Subproject commit 7845153645cfe245de5add94fb07c227c2d16402 +Subproject commit 286f1b9a66e7f05ac5a32510e4c08ecd03f0ba0f
diff --git a/third_party/libunwind/src b/third_party/libunwind/src index 85df028..bbe2764 160000 --- a/third_party/libunwind/src +++ b/third_party/libunwind/src
@@ -1 +1 @@ -Subproject commit 85df028e4c5e8a3eaa38fe75e0d78157bee2d668 +Subproject commit bbe2764382995e4ec9a8c26c50018afc9520ea4f
diff --git a/third_party/webrtc b/third_party/webrtc index ad3e661..ee46340 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit ad3e66138dff54063ad7bbef8cf9c365b89e1d3e +Subproject commit ee46340054fac6072259be0d7f43263299d9b88b
diff --git a/third_party/zlib/CMakeLists.txt b/third_party/zlib/CMakeLists.txt index a9cf9c5f..5541985f 100644 --- a/third_party/zlib/CMakeLists.txt +++ b/third_party/zlib/CMakeLists.txt
@@ -3,7 +3,7 @@ project(zlib C) -set(VERSION "1.3") +set(VERSION "1.3.0.1") set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c index 779bd294b..b3ecb5c8 100644 --- a/third_party/zlib/deflate.c +++ b/third_party/zlib/deflate.c
@@ -65,7 +65,7 @@ #endif const char deflate_copyright[] = - " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; + " deflate 1.3.0.1 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot
diff --git a/third_party/zlib/inftrees.c b/third_party/zlib/inftrees.c index 8a208c2..73d5a77 100644 --- a/third_party/zlib/inftrees.c +++ b/third_party/zlib/inftrees.c
@@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.3 Copyright 1995-2023 Mark Adler "; + " inflate 1.3.0.1 Copyright 1995-2023 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -57,7 +57,7 @@ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 70, 200}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
diff --git a/third_party/zlib/zlib.3 b/third_party/zlib/zlib.3 index e733b5ab..adc5b7f 100644 --- a/third_party/zlib/zlib.3 +++ b/third_party/zlib/zlib.3
@@ -1,4 +1,4 @@ -.TH ZLIB 3 "xx Oct 2022" +.TH ZLIB 3 "xx Aug 2023" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS @@ -105,7 +105,7 @@ Send questions and/or comments to zlib@gzip.org, or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). .SH AUTHORS AND LICENSE -Version 1.2.13.1 +Version 1.2.3.0.1 .LP Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler .LP
diff --git a/third_party/zlib/zlib.h b/third_party/zlib/zlib.h index 8f296ec4..f1b149b 100644 --- a/third_party/zlib/zlib.h +++ b/third_party/zlib/zlib.h
@@ -1,5 +1,5 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.3, August 18th, 2023 + version 1.3.0.1, August xxth, 2023 Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler @@ -37,12 +37,12 @@ extern "C" { #endif -#define ZLIB_VERSION "1.3" -#define ZLIB_VERNUM 0x1300 +#define ZLIB_VERSION "1.3.0.1-motley" +#define ZLIB_VERNUM 0x1301 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 3 #define ZLIB_VER_REVISION 0 -#define ZLIB_VER_SUBREVISION 0 +#define ZLIB_VER_SUBREVISION 1 /* The 'zlib' compression library provides in-memory compression and
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 86d1371..a99da39f 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -965,6 +965,10 @@ "components/autofill/core/browser/autofill_address_rewriter_resources.grd":{ "includes": [7220] }, + + "components/search_engine_descriptions_strings.grd": { + "messages": [7260], + }, # END components/ section. # START ios/ section.
diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl index a16d80d..d1073c8f 100644 --- a/tools/gritsettings/translation_expectations.pyl +++ b/tools/gritsettings/translation_expectations.pyl
@@ -123,6 +123,7 @@ "chrome/app/resources/locale_settings_win.grd": "Not UI strings; localized separately", "chromecast/app/resources/chromecast_settings.grd": "Not UI strings; localized separately", "components/components_locale_settings.grd": "Not UI strings; localized separately", + "components/search_engine_descriptions_strings.grd": "The strings are already translated when provided", "components/policy/resources/policy_templates.build.grd": "Copy of policy_templates.grd used locally for build only", "tools/grit/grit/testdata/allowlist_resources.grd": "Test data", "tools/grit/grit/testdata/allowlist_strings.grd": "Test data",
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 3566d27..59b2b9d 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -9762,6 +9762,14 @@ <int value="47" label="duplicate trigger data"/> <int value="48" label="invalid trigger data for matching mode"/> <int value="49" label="filter_data key reserved (starts with "_")"/> + <int value="50" label="summary_window_operator has wrong type"/> + <int value="51" label="summary_window_operator value is invalid"/> + <int value="52" label="summary_buckets has wrong type"/> + <int value="53" label="summary_buckets empty"/> + <int value="54" label="summary_buckets too long"/> + <int value="55" label="summary_buckets value wrong type"/> + <int value="56" label="summary_buckets value out of range"/> + <int value="57" label="summary_buckets non-increasing"/> </enum> <enum name="ConversionStorageCreateReportStatus"> @@ -24729,6 +24737,7 @@ <int value="111" label="ClientHintUAFormFactor"/> <int value="112" label="ClientHintPrefersReducedTransparency"/> <int value="113" label="WebPrinting"/> + <int value="114" label="UsbUnrestricted"/> </enum> <enum name="FedCmAccountsResponseInvalidReason">
diff --git a/tools/metrics/histograms/metadata/ash/enums.xml b/tools/metrics/histograms/metadata/ash/enums.xml index 1aa0de4..880b7b4 100644 --- a/tools/metrics/histograms/metadata/ash/enums.xml +++ b/tools/metrics/histograms/metadata/ash/enums.xml
@@ -371,6 +371,10 @@ <int value="3" label="User pref is not available at campaigns matching"/> <int value="4" label="Invalid campaign"/> <int value="5" label="Invalid targeting"/> + <int value="6" label="Invalid scheduling targeting"/> + <int value="7" label="Invalid scheduling"/> + <int value="8" label="Demo Mode app version is not available at matching"/> + <int value="9" label="Serializing Demo Mode payload failed"/> </enum> <enum name="CaptureModeBarButtonType">
diff --git a/tools/metrics/histograms/metadata/ash_user_education/enums.xml b/tools/metrics/histograms/metadata/ash_user_education/enums.xml index 0cd12ee..0619b28 100644 --- a/tools/metrics/histograms/metadata/ash_user_education/enums.xml +++ b/tools/metrics/histograms/metadata/ash_user_education/enums.xml
@@ -82,6 +82,16 @@ <int value="7" label="kStatusArea"/> </enum> +<enum name="WelcomeTourTimeBucket"> + <int value="0" label="kOneMinute"/> + <int value="1" label="kTenMinutes"/> + <int value="2" label="kOneHour"/> + <int value="3" label="kOneDay"/> + <int value="4" label="kOneWeek"/> + <int value="5" label="kTwoWeeks"/> + <int value="6" label="kOverTwoWeeks"/> +</enum> + </enums> </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml index 631d7ab..46d8409 100644 --- a/tools/metrics/histograms/metadata/event/histograms.xml +++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -69,18 +69,6 @@ </summary> </histogram> -<histogram name="Event.BrowserVerifiedUserActivation" enum="BooleanSuccess" - expires_after="2021-10-17"> - <owner>liviutinta@chromium.org</owner> - <owner>mustaq@chromium.org</owner> - <owner>input-dev@chromium.org</owner> - <summary> - Records whether Browser User Activation Verification is successful or not. - We are interested in how many times the Browser User Activation Verification - fails vs how many times it succeeds. - </summary> -</histogram> - <histogram name="Event.DownEventCount.PerInputFormFactorDestinationCombination2" enum="DownEventInputFormFactorDestinationCombination2"
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml index c0d8cdf..0a5b8302 100644 --- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -3291,8 +3291,6 @@ label="Link triggered prerender, rel=prerender, same domain."/> <affected-histogram name="Prerender.FinalStatus"/> <affected-histogram name="Prerender.NetworkBytesWasted"/> - <affected-histogram name="Prerender.NoStatePrefetchMainResourceRedirects"/> - <affected-histogram name="Prerender.NoStatePrefetchSubResourceRedirects"/> <affected-histogram name="Prerender.PrerendersPerSessionCount"/> </histogram_suffixes>
diff --git a/tools/metrics/histograms/metadata/ios/enums.xml b/tools/metrics/histograms/metadata/ios/enums.xml index 302743c..e2bb8e8 100644 --- a/tools/metrics/histograms/metadata/ios/enums.xml +++ b/tools/metrics/histograms/metadata/ios/enums.xml
@@ -510,6 +510,7 @@ <int value="7" label="Choice Promo"/> <int value="8" label="Post Restore Default Browser (Alert)"/> <int value="9" label="Default Browser Remind Me Later"/> + <int value="10" label="Omnibox Position"/> </enum> <enum name="IOSPromosManagerPromoImpressionLimitEvaluationType">
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml index 5acc9dd0..0dc9c47b 100644 --- a/tools/metrics/histograms/metadata/memory/histograms.xml +++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -1789,17 +1789,6 @@ </summary> </histogram> -<histogram name="Memory.Renderer.EstimatedDroppableEncodedSize" units="KB" - expires_after="M77"> - <owner>hajimehoshi@chromium.org</owner> - <summary> - The esitimated memory size which would be reduced when reusing disk cache is - implemented. If it is 100% sure that the encoded data is in disk cache, the - same data in memory can be dropped to reduce memory usage. This is rencorded - when an ImageResource is pruned. See crbug/664437. - </summary> -</histogram> - <histogram name="Memory.Renderer.EvictedLockedResources.{Source}" units="KB" expires_after="2024-06-01"> <owner>jonross@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/mobile/histograms.xml b/tools/metrics/histograms/metadata/mobile/histograms.xml index 54bb9cb..20f4132 100644 --- a/tools/metrics/histograms/metadata/mobile/histograms.xml +++ b/tools/metrics/histograms/metadata/mobile/histograms.xml
@@ -770,14 +770,6 @@ </summary> </histogram> -<histogram name="MobileDownload.StoragePermission" - enum="MobileDownloadStoragePermission" expires_after="M82"> - <owner>qinmin@chromium.org</owner> - <summary> - Android: Records various counts when requesting the storage permission. - </summary> -</histogram> - <histogram name="MobileFre.CctTos.EnterprisePolicyCheckSpeed2{MobileFreInflationSpeedComparison}" units="ms" expires_after="2022-05-01">
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index 846c91c..9113d27 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -2026,28 +2026,6 @@ </summary> </histogram> -<histogram name="Prerender.NoStatePrefetchMainResourceRedirects" - units="redirects" expires_after="M85"> - <owner>droger@chromium.org</owner> - <owner>mattcary@chromium.org</owner> - <owner>pasko@chromium.org</owner> - <summary> - Length of the redirect chain for main resources loaded by NoStatePrefetch. - Recorded when the final response in the chain is received. - </summary> -</histogram> - -<histogram name="Prerender.NoStatePrefetchSubResourceRedirects" - units="redirects" expires_after="M85"> - <owner>droger@chromium.org</owner> - <owner>mattcary@chromium.org</owner> - <owner>pasko@chromium.org</owner> - <summary> - Length of the redirect chain for sub-resources loaded by NoStatePrefetch. - Recorded when the final response in the chain is received. - </summary> -</histogram> - <histogram name="Prerender.PrerenderLoadComplete" enum="BooleanSuccess" expires_after="2024-04-28"> <owner>gambard@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 8954efb..0f7a0fd6 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -3303,7 +3303,7 @@ </summary> </histogram> -<histogram name="Conversions.SourceRegistrationError8" +<histogram name="Conversions.SourceRegistrationError9" enum="ConversionSourceRegistrationError" expires_after="2024-03-24"> <owner>tquintanilla@chromium.org</owner> <owner>linnan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index b504b00..4c8b822e 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -4019,8 +4019,8 @@ </histogram> <histogram name="PasswordProtection.VisualFeatureExtractionDuration" units="ms" - expires_after="2023-12-10"> - <owner>drubery@chromium.org</owner> + expires_after="2024-12-10"> + <owner>andysjlim@chromium.org</owner> <owner>chrome-counter-abuse-alerts@google.com</owner> <summary> The time it takes to extract the visual features of a login page before
diff --git a/tools/metrics/histograms/metadata/privacy/histograms.xml b/tools/metrics/histograms/metadata/privacy/histograms.xml index 9b5e2fa99..4143d4a 100644 --- a/tools/metrics/histograms/metadata/privacy/histograms.xml +++ b/tools/metrics/histograms/metadata/privacy/histograms.xml
@@ -27,6 +27,24 @@ summary="in an off-the-record profile, with third-party cookies blocked"/> </variants> +<variants name="DIPSDatabaseOperation"> + <variant name="ClearTimestamps" summary="ClearTimestamps"/> + <variant name="FilterSitesWithInteractionOrWaa" + summary="FilterSitesWithInteractionOrWaa"/> + <variant name="GetSitesThatBounced" summary="GetSitesThatBounced"/> + <variant name="GetSitesThatBouncedWithState" + summary="GetSitesThatBouncedWithState"/> + <variant name="GetSitesThatUsedStorage" summary="GetSitesThatUsedStorage"/> + <variant name="Init" summary="Init"/> + <variant name="Read" summary="Read"/> + <variant name="ReadPopup" summary="ReadPopup"/> + <variant name="ReadRecentPopupsWithInteraction" + summary="ReadRecentPopupsWithInteraction"/> + <variant name="RemoveRows" summary="RemoveRows"/> + <variant name="Write" summary="Write"/> + <variant name="WritePopup" summary="WritePopup"/> +</variants> + <variants name="DIPSRedirectType"> <variant name="Client" summary="client-side"/> <variant name="Server" summary="server-side"/> @@ -256,6 +274,20 @@ <token key="DIPSCookieMode" variants="DIPSCookieMode"/> </histogram> +<histogram name="Privacy.DIPS.Database.Operation.{DIPSDatabaseOperation}Time" + units="ms" expires_after="2024-09-01"> + <owner>etienneb@chromium.org</owner> + <owner>jdh@chromium.org</owner> + <owner>src/chrome/browser/dips/OWNERS</owner> + <summary> + The time taken to execute the {DIPSDatabaseOperation} DIPS database + operation. + + Recorded for each call to the operation. + </summary> + <token key="DIPSDatabaseOperation" variants="DIPSDatabaseOperation"/> +</histogram> + <histogram name="Privacy.DIPS.DatabaseEntryCount" units="entries" expires_after="2024-04-28"> <owner>wanderview@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml index b65bd43..f1cbf9b 100644 --- a/tools/metrics/histograms/metadata/sb_client/histograms.xml +++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -308,17 +308,6 @@ </summary> </histogram> -<histogram name="SBClientDownload.SevenZipEntryResult" enum="SevenZipResult" - expires_after="2023-12-04"> - <owner>drubery@chromium.org</owner> - <owner>chrome-counter-abuse-alerts@google.com</owner> - <summary> - Records the result of unpacking a single entry from a 7z archive. The result - includes either success or a coarse-grained error. This is logged for each - entry of each download of a 7z archive. - </summary> -</histogram> - <histogram name="SBClientDownload.TailoredWarning.HasVaidEmailForAccountInfo" enum="BooleanValid" expires_after="2024-03-02"> <owner>xinghuilu@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 3e47db1..0c4c314 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,16 +5,16 @@ "full_remote_path": "perfetto-luci-artifacts/6ba75cc5d93c39d4f86e2777709a460b30ce06fc/linux-arm64/trace_processor_shell" }, "win": { - "hash": "55cfd36fca89b917cea35b4f962bcd4d93013d38", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/198c2c068023308c23fc424a897c503bd05416e4/trace_processor_shell.exe" + "hash": "d648efa8eb7a7674b9f70c775cd9b112f55b6e92", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/d8a8260e8a08b166547eecd5b6ffcbdb30421109/trace_processor_shell.exe" }, "linux_arm": { "hash": "fa20dcbcab1b02524b23bb375c38fd8211e1268c", "full_remote_path": "perfetto-luci-artifacts/6ba75cc5d93c39d4f86e2777709a460b30ce06fc/linux-arm/trace_processor_shell" }, "mac": { - "hash": "aad0e7d308458ff8b860363f4ebb40b454153873", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/3348c1fb173ed5ceeb4f37b9644742c460d50473/trace_processor_shell" + "hash": "84def48d42966f11443fc3447bb8e0bf0d1dbe9e", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/d8a8260e8a08b166547eecd5b6ffcbdb30421109/trace_processor_shell" }, "mac_arm64": { "hash": "10ae4aaabedc85f42808a67cbb5951199d4c326e",
diff --git a/tools/perf/core/tbmv3/metrics/console_error_metric.proto b/tools/perf/core/tbmv3/metrics/console_error_metric.proto index 3424aea..e62a004d 100644 --- a/tools/perf/core/tbmv3/metrics/console_error_metric.proto +++ b/tools/perf/core/tbmv3/metrics/console_error_metric.proto
@@ -6,8 +6,6 @@ package perfetto.protos; import "protos/perfetto/metrics/metrics.proto"; -// TODO(crbug.com/1012687): Ideally we won't need this second import. -import "protos/perfetto/metrics/custom_options.proto"; message ConsoleErrorMetric { optional int64 all_errors = 1 [(unit) = "count_smallerIsBetter"];
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 702ff0d..35cacca2 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -18,8 +18,8 @@ <item id="auction_downloader" added_in_milestone="92" content_hash_code="01f53427" os_list="linux,windows,chromeos,android" file_path="content/services/auction_worklet/public/cpp/auction_downloader.cc" /> <item id="auction_report_sender" added_in_milestone="92" content_hash_code="029b766e" os_list="linux,windows,chromeos,android" file_path="content/browser/interest_group/interest_group_manager_impl.cc" /> <item id="autofill_image_fetcher_card_art_image" added_in_milestone="93" content_hash_code="038b8696" os_list="linux,windows,chromeos" file_path="components/autofill/core/browser/ui/autofill_image_fetcher.cc" /> - <item id="autofill_query" added_in_milestone="62" content_hash_code="006ccff5" os_list="linux,windows,chromeos,android" file_path="components/autofill/core/browser/autofill_download_manager.cc" /> - <item id="autofill_upload" added_in_milestone="62" content_hash_code="04a7eb65" os_list="linux,windows,chromeos,android" file_path="components/autofill/core/browser/autofill_download_manager.cc" /> + <item id="autofill_query" added_in_milestone="62" content_hash_code="006ccff5" os_list="linux,windows,chromeos,android" file_path="components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc" /> + <item id="autofill_upload" added_in_milestone="62" content_hash_code="04a7eb65" os_list="linux,windows,chromeos,android" file_path="components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager.cc" /> <item id="backdrop_collection_images_download" added_in_milestone="68" content_hash_code="009770fb" os_list="linux,windows,chromeos" file_path="chrome/browser/search/background/ntp_background_service.cc" /> <item id="backdrop_collection_names_download" added_in_milestone="68" content_hash_code="048c7a89" os_list="linux,windows,chromeos" file_path="chrome/browser/search/background/ntp_background_service.cc" /> <item id="backdrop_next_image_download" added_in_milestone="77" content_hash_code="003626bf" os_list="linux,windows,chromeos" file_path="chrome/browser/search/background/ntp_background_service.cc" />
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 097e7cf4..e563c3b 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -306,6 +306,7 @@ "java/src/org/chromium/ui/base/SPenSupport.java", "java/src/org/chromium/ui/base/SelectFileDialog.java", "java/src/org/chromium/ui/base/TouchDevice.java", + "java/src/org/chromium/ui/base/UiAndroidFeatureList.java", "java/src/org/chromium/ui/base/UiAndroidFeatureMap.java", "java/src/org/chromium/ui/base/ViewAndroidDelegate.java", "java/src/org/chromium/ui/base/ViewUtils.java", @@ -537,7 +538,7 @@ ] } -android_resources("ui_javatest_resources") { +android_resources("ui_junit_resources") { testonly = true sources = [ "junit/res/layout/inflated_view.xml", @@ -598,7 +599,7 @@ ":ui_java", ":ui_java_resources", ":ui_java_test_support", - ":ui_javatest_resources", + ":ui_junit_resources", ":ui_junit_test_support", "//base:base_java", "//base:base_java_test_support", @@ -672,6 +673,20 @@ ] } +android_resources("test_java_resources") { + testonly = true + sources = [ + "test/java/res/layout/text_view_with_leading_bad_text_appearance.xml", + "test/java/res/layout/text_view_with_leading_direct.xml", + "test/java/res/layout/text_view_with_leading_no_leading.xml", + "test/java/res/layout/text_view_with_leading_style.xml", + "test/java/res/layout/text_view_with_leading_style_into_text_appearance.xml", + "test/java/res/layout/text_view_with_leading_text_appearance.xml", + "test/java/res/values/attrs.xml", + "test/java/res/values/styles.xml", + ] +} + android_library("ui_unit_device_javatests") { testonly = true resources_package = "org.chromium.ui" @@ -681,10 +696,13 @@ "java/src/org/chromium/ui/resources/dynamics/HardwareDrawTest.java", "java/src/org/chromium/ui/widget/TextViewWithTightWrapTest.java", "javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java", + "junit/src/org/chromium/ui/widget/TextViewWithLeadingTest.java", ] deps = [ ":clipboard_java_test_support", + ":test_java_resources", + ":ui_android_features_java", ":ui_java", ":ui_java_test_support", "//base:base_java",
diff --git a/ui/android/java/res/values/attrs.xml b/ui/android/java/res/values/attrs.xml index 14ac506..b37b208 100644 --- a/ui/android/java/res/values/attrs.xml +++ b/ui/android/java/res/values/attrs.xml
@@ -46,6 +46,8 @@ <declare-styleable name="TextViewWithLeading"> <attr name="leading" format="reference|dimension"/> + <!-- The name must match what [AppCompat]TextView uses. --> + <attr name="android:textAppearance" /> </declare-styleable> <declare-styleable name="AsyncViewStub">
diff --git a/ui/android/java/res/values/styles.xml b/ui/android/java/res/values/styles.xml index c9e27cdf..dbcb07b 100644 --- a/ui/android/java/res/values/styles.xml +++ b/ui/android/java/res/values/styles.xml
@@ -85,36 +85,45 @@ <style name="TextAppearance.Headline"> <item name="android:fontFamily">@font/accent_font</item> <item name="android:textSize">@dimen/headline_size</item> + <item name="leading">@dimen/headline_size_leading</item> </style> <style name="TextAppearance.Headline2"> <item name="android:fontFamily">@font/accent_font</item> <item name="android:textSize">@dimen/headline2_size</item> + <item name="leading">@dimen/headline2_size_leading</item> </style> <style name="TextAppearance.HeadlineThick" parent="TextAppearance.AccentMediumStyle"> <item name="android:textSize">@dimen/headline_size</item> + <item name="leading">@dimen/headline_size_leading</item> </style> <style name="TextAppearance.Headline2Thick" parent="TextAppearance.AccentMediumStyle"> <item name="android:textSize">@dimen/headline2_size</item> + <item name="leading">@dimen/headline2_size_leading</item> </style> <style name="TextAppearance.TextLarge"> <item name="android:textSize">@dimen/text_size_large</item> + <item name="leading">@dimen/text_size_large_leading</item> </style> <style name="TextAppearance.TextAccentLarge" parent="TextAppearance.TextLarge"> <item name="android:fontFamily">@font/accent_font</item> </style> <style name="TextAppearance.TextMediumThick" parent="TextAppearance.RobotoMediumStyle"> <item name="android:textSize">@dimen/text_size_medium</item> + <item name="leading">@dimen/text_size_medium_leading</item> </style> <style name="TextAppearance.TextAccentMediumThick" parent="TextAppearance.AccentMediumStyle"> <item name="android:textSize">@dimen/text_size_medium</item> + <item name="leading">@dimen/text_size_medium_leading</item> </style> <style name="TextAppearance.TextMedium"> <item name="android:textSize">@dimen/text_size_medium</item> + <item name="leading">@dimen/text_size_medium_leading</item> </style> <style name="TextAppearance.TextSmall"> <item name="android:textSize">@dimen/text_size_small</item> + <item name="leading">@dimen/text_size_small_leading</item> </style> <!-- Non Adaptive Text Styles --> @@ -170,6 +179,7 @@ <style name="TextAppearance.WhiteLink" tools:ignore="UnusedResources"> <item name="android:textColor">@android:color/white</item> <item name="android:textSize">@dimen/text_size_medium</item> + <item name="leading">@dimen/text_size_medium_leading</item> <item name="android:textStyle">bold</item> </style> @@ -250,6 +260,7 @@ </style> <style name="TextAppearance.MenuChip.Text.Blue" parent="TextAppearance.Button.Text.Blue"> <item name="android:textSize">@dimen/text_size_small</item> + <item name="leading">@dimen/text_size_small_leading</item> </style> <!-- Blue Non Adaptive button text styles --> @@ -328,10 +339,12 @@ <style name="TextAppearance.ErrorCaption" tools:ignore="UnusedResources"> <item name="android:textColor">@color/default_text_color_error</item> <item name="android:textSize">@dimen/text_size_small</item> + <item name="leading">@dimen/text_size_small_leading</item> </style> <style name="TextAppearance.TextMedium.Error"> <item name="android:textColor">@color/default_text_color_error</item> <item name="android:textSize">@dimen/text_size_medium</item> + <item name="leading">@dimen/text_size_medium_leading</item> </style> <!-- Toast UI -->
diff --git a/ui/android/java/src/org/chromium/ui/base/UiAndroidFeatureList.java b/ui/android/java/src/org/chromium/ui/base/UiAndroidFeatureList.java new file mode 100644 index 0000000..8f37d4d --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/base/UiAndroidFeatureList.java
@@ -0,0 +1,20 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.base; + +import org.chromium.base.MutableFlagWithSafeDefault; + +/** Helpers and state for features from {@link UiAndroidFeatures}. */ +public class UiAndroidFeatureList { + private static MutableFlagWithSafeDefault newMutableFlagWithSafeDefault( + String featureName, boolean defaultValue) { + return UiAndroidFeatureMap.getInstance() + .mutableFlagWithSafeDefault(featureName, defaultValue); + } + + public static final MutableFlagWithSafeDefault sRequireLeadingInTextViewWithLeading = + newMutableFlagWithSafeDefault( + UiAndroidFeatures.REQUIRE_LEADING_IN_TEXT_VIEW_WITH_LEADING, false); +}
diff --git a/ui/android/java/src/org/chromium/ui/widget/TextViewWithLeading.java b/ui/android/java/src/org/chromium/ui/widget/TextViewWithLeading.java index 866b3bc..f262a1e 100644 --- a/ui/android/java/src/org/chromium/ui/widget/TextViewWithLeading.java +++ b/ui/android/java/src/org/chromium/ui/widget/TextViewWithLeading.java
@@ -5,11 +5,17 @@ package org.chromium.ui.widget; import android.content.Context; +import android.content.res.Resources; import android.content.res.TypedArray; import android.util.AttributeSet; import android.widget.TextView; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.annotation.StyleableRes; + import org.chromium.ui.R; +import org.chromium.ui.base.UiAndroidFeatureList; /** * A TextView with the added leading property. Leading is the distance between the baselines of @@ -31,18 +37,67 @@ public TextViewWithLeading(Context context, AttributeSet attrs) { super(context, attrs); checkForLineSpacingAttributes(attrs); + Float nullableLeading = getLeadingDimen(attrs); + // TODO(https://crbug.com:1499069): Remove feature/kill switch once certain this is safe. + if (UiAndroidFeatureList.sRequireLeadingInTextViewWithLeading.isEnabled()) { + assert nullableLeading != null : "Couldn't find leading for TextViewWithLeading"; + applyLeading(nullableLeading); + } else if (nullableLeading != null) { + applyLeading(nullableLeading); + } + } - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextViewWithLeading, 0, 0); - if (a.hasValue(R.styleable.TextViewWithLeading_leading)) { - final float leading = a.getDimension(R.styleable.TextViewWithLeading_leading, 0f); - final float oldLeading = getPaint().getFontMetrics(null); - setLineSpacing(leading - oldLeading, 1f); + private @Nullable Float getLeadingDimen(AttributeSet attrs) { + // This result variable holds the return value so a single return can be used, allowing + // easier recycling of TypedArrays. + final Float result; + + Context context = getContext(); + TypedArray selfTypedArray = + context.obtainStyledAttributes(attrs, R.styleable.TextViewWithLeading, 0, 0); + @StyleableRes int leadingIndex = R.styleable.TextViewWithLeading_leading; + @StyleableRes int textAppIndex = R.styleable.TextViewWithLeading_android_textAppearance; + + if (selfTypedArray.hasValue(leadingIndex)) { + // Found the attr directly inside the layout or style. This has a higher priority. + float leading = selfTypedArray.getDimension(leadingIndex, 0f); + result = leading; + } else if (selfTypedArray.hasValue(textAppIndex)) { + // Resolve the text appearance, hopefully the leading is there instead. + @StyleRes int textAppRes = selfTypedArray.getResourceId(textAppIndex, 0); + if (textAppRes == Resources.ID_NULL) { + result = null; + } else { + // Using R.styleable.TextViewWithLeading to specify the list of desired attributes, + // as this is what getLeadingFromTextAppearance will use. + TypedArray textAppTypedArray = + context.obtainStyledAttributes(textAppRes, R.styleable.TextViewWithLeading); + result = getLeadingFromTextAppearance(textAppTypedArray); + textAppTypedArray.recycle(); + } + } else { + result = null; } - a.recycle(); + selfTypedArray.recycle(); + return result; + } + + private @Nullable Float getLeadingFromTextAppearance(TypedArray textAppTypedArray) { + if (textAppTypedArray.hasValue(R.styleable.TextViewWithLeading_leading)) { + return textAppTypedArray.getDimension(R.styleable.TextViewWithLeading_leading, 0); + } else { + return null; + } + } + + private void applyLeading(float newLeading) { + float oldLeading = getPaint().getFontMetrics(null); + setLineSpacing(newLeading - oldLeading, 1f); } private void checkForLineSpacingAttributes(AttributeSet attrs) { + // TODO(https://crbug.com:1499069): Fix namespaces, this check does not currently work. assert attrs.getAttributeValue(null, "android:lineSpacingExtra") == null && attrs.getAttributeValue(null, "android:lineSpacingMultiplier") == null : "Do not use android:lineSpacingExtra or android:lineSpacingMultiplier in"
diff --git a/ui/android/junit/src/org/chromium/ui/widget/TextViewWithLeadingTest.java b/ui/android/junit/src/org/chromium/ui/widget/TextViewWithLeadingTest.java new file mode 100644 index 0000000..02125acc --- /dev/null +++ b/ui/android/junit/src/org/chromium/ui/widget/TextViewWithLeadingTest.java
@@ -0,0 +1,118 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.widget; + +import static org.junit.Assert.assertNotEquals; + +import android.content.Context; +import android.view.InflateException; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.LayoutRes; +import androidx.test.filters.MediumTest; + +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.FeatureList; +import org.chromium.base.test.BaseActivityTestRule; +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.Batch; +import org.chromium.ui.R; +import org.chromium.ui.base.UiAndroidFeatures; +import org.chromium.ui.test.util.BlankUiTestActivity; + +import java.util.Collections; + +/** Unit tests for {@link TextViewWithLeading}. */ +@RunWith(BaseJUnit4ClassRunner.class) +@Batch(Batch.PER_CLASS) +public class TextViewWithLeadingTest { + @ClassRule + public static BaseActivityTestRule<BlankUiTestActivity> sActivityTestRule = + new BaseActivityTestRule<>(BlankUiTestActivity.class); + + @BeforeClass + public static void beforeClass() { + sActivityTestRule.launchActivity(null); + } + + @After + public void after() { + FeatureList.setTestFeatures(null); + } + + private void inflateAndVerify(@LayoutRes int layoutRes) { + TextView textView = (TextView) inflate(layoutRes); + assertNotEquals(/* expected= */ 0, textView.getLineSpacingExtra(), /* delta= */ 1); + } + + private View inflate(@LayoutRes int layoutRes) { + Context context = sActivityTestRule.getActivity(); + return LayoutInflater.from(context).inflate(layoutRes, /* root= */ null); + } + + @Test + @MediumTest + public void testDirect() { + inflateAndVerify(R.layout.text_view_with_leading_direct); + } + + @Test + @MediumTest + public void testStyle() { + inflateAndVerify(R.layout.text_view_with_leading_style); + } + + @Test + @MediumTest + public void testTextAppearance() { + inflateAndVerify(R.layout.text_view_with_leading_text_appearance); + } + + @Test + @MediumTest + public void testBadTextAppearance() { + inflate(R.layout.text_view_with_leading_bad_text_appearance); + } + + @Test + @MediumTest + public void testStyleIntoTextAppearance() { + inflateAndVerify(R.layout.text_view_with_leading_style_into_text_appearance); + } + + @Test(expected = InflateException.class) + @MediumTest + public void testNoLeading() { + FeatureList.setTestFeatures( + Collections.singletonMap( + UiAndroidFeatures.REQUIRE_LEADING_IN_TEXT_VIEW_WITH_LEADING, true)); + inflate(R.layout.text_view_with_leading_no_leading); + } + + @Test + @MediumTest + public void testLeadingKillSwitch() { + FeatureList.setTestFeatures( + Collections.singletonMap( + UiAndroidFeatures.REQUIRE_LEADING_IN_TEXT_VIEW_WITH_LEADING, false)); + inflateAndVerify(R.layout.text_view_with_leading_direct); + } + + @Test + @MediumTest + public void testNoLeadingKillSwitch() { + FeatureList.setTestFeatures( + Collections.singletonMap( + UiAndroidFeatures.REQUIRE_LEADING_IN_TEXT_VIEW_WITH_LEADING, false)); + inflate(R.layout.text_view_with_leading_no_leading); + } +}
diff --git a/ui/android/test/java/res/layout/text_view_with_leading_bad_text_appearance.xml b/ui/android/test/java/res/layout/text_view_with_leading_bad_text_appearance.xml new file mode 100644 index 0000000..35bbf36a --- /dev/null +++ b/ui/android/test/java/res/layout/text_view_with_leading_bad_text_appearance.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<org.chromium.ui.widget.TextViewWithLeading + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?attr/badAttr" />
diff --git a/ui/android/test/java/res/layout/text_view_with_leading_direct.xml b/ui/android/test/java/res/layout/text_view_with_leading_direct.xml new file mode 100644 index 0000000..2d6a214e --- /dev/null +++ b/ui/android/test/java/res/layout/text_view_with_leading_direct.xml
@@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<org.chromium.ui.widget.TextViewWithLeading + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.WithoutLeading" + app:leading="@dimen/text_size_medium_leading" />
diff --git a/ui/android/test/java/res/layout/text_view_with_leading_no_leading.xml b/ui/android/test/java/res/layout/text_view_with_leading_no_leading.xml new file mode 100644 index 0000000..eb6de67d --- /dev/null +++ b/ui/android/test/java/res/layout/text_view_with_leading_no_leading.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<org.chromium.ui.widget.TextViewWithLeading + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.WithoutLeading" />
diff --git a/ui/android/test/java/res/layout/text_view_with_leading_style.xml b/ui/android/test/java/res/layout/text_view_with_leading_style.xml new file mode 100644 index 0000000..da72bcc --- /dev/null +++ b/ui/android/test/java/res/layout/text_view_with_leading_style.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<org.chromium.ui.widget.TextViewWithLeading + xmlns:android="http://schemas.android.com/apk/res/android" + style="@style/StyleWithLeading" + android:layout_width="wrap_content" + android:layout_height="wrap_content" />
diff --git a/ui/android/test/java/res/layout/text_view_with_leading_style_into_text_appearance.xml b/ui/android/test/java/res/layout/text_view_with_leading_style_into_text_appearance.xml new file mode 100644 index 0000000..85c806a --- /dev/null +++ b/ui/android/test/java/res/layout/text_view_with_leading_style_into_text_appearance.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<org.chromium.ui.widget.TextViewWithLeading + xmlns:android="http://schemas.android.com/apk/res/android" + style="@style/StyleIntoTextAppearance" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + />
diff --git a/ui/android/test/java/res/layout/text_view_with_leading_text_appearance.xml b/ui/android/test/java/res/layout/text_view_with_leading_text_appearance.xml new file mode 100644 index 0000000..964f350 --- /dev/null +++ b/ui/android/test/java/res/layout/text_view_with_leading_text_appearance.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<org.chromium.ui.widget.TextViewWithLeading + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.WithLeading" />
diff --git a/ui/android/test/java/res/values/attrs.xml b/ui/android/test/java/res/values/attrs.xml new file mode 100644 index 0000000..40c63b3 --- /dev/null +++ b/ui/android/test/java/res/values/attrs.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<resources> + <attr name="badAttr" format="reference"/> +</resources>
diff --git a/ui/android/test/java/res/values/styles.xml b/ui/android/test/java/res/values/styles.xml new file mode 100644 index 0000000..6dbe263 --- /dev/null +++ b/ui/android/test/java/res/values/styles.xml
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<resources> + <style name="TextAppearance.WithoutLeading"> + <item name="android:textSize">@dimen/text_size_medium</item> + </style> + + <style name="TextAppearance.WithLeading" parent="TextAppearance.WithoutLeading"> + <item name="leading">@dimen/text_size_medium_leading</item> + </style> + + <style name="StyleWithLeading" parent="TextAppearance.WithLeading"/> + + <style name="StyleIntoTextAppearance"> + <item name="android:textAppearance">@style/StyleWithLeading</item> + </style> +</resources>
diff --git a/ui/android/ui_android_feature_map.cc b/ui/android/ui_android_feature_map.cc index ae4109c..bf340a6 100644 --- a/ui/android/ui_android_feature_map.cc +++ b/ui/android/ui_android_feature_map.cc
@@ -17,6 +17,7 @@ &ui::kConvertTrackpadEventsToMouse, &ui::kDeprecatedExternalPickerFunction, &ui::kReportAllAvailablePointerTypes, + &ui::kRequireLeadingInTextViewWithLeading, }; // static
diff --git a/ui/android/ui_android_features.cc b/ui/android/ui_android_features.cc index cc6d0794..ba29f9ee 100644 --- a/ui/android/ui_android_features.cc +++ b/ui/android/ui_android_features.cc
@@ -21,4 +21,8 @@ "ReportAllAvailablePointerTypes", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kRequireLeadingInTextViewWithLeading, + "RequireLeadingInTextViewWithLeading", + base::FEATURE_ENABLED_BY_DEFAULT); + } // namespace ui
diff --git a/ui/android/ui_android_features.h b/ui/android/ui_android_features.h index acfc655..3275bac 100644 --- a/ui/android/ui_android_features.h +++ b/ui/android/ui_android_features.h
@@ -29,6 +29,10 @@ // rather than just the first one detected. UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kReportAllAvailablePointerTypes); +// Kill switch to turn off validation in TextViewWithLeading that requires a +// leading value to be configured. +UI_ANDROID_EXPORT BASE_DECLARE_FEATURE(kRequireLeadingInTextViewWithLeading); + } // namespace ui #endif // UI_ANDROID_UI_ANDROID_FEATURES_H_
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h index d5112b52..7d0d72d 100644 --- a/ui/message_center/views/message_view.h +++ b/ui/message_center/views/message_view.h
@@ -92,6 +92,14 @@ ~MessageView() override; + // Animates the grouped child notification when switching between expand and + // collapse state. + virtual void AnimateGroupedChildExpandedCollapse(bool expanded) {} + + // Animations when converting from single to group notification. + virtual void AnimateSingleToGroup(const std::string& notification_id, + std::string parent_id) {} + // Updates this view with an additional grouped notification. If the view // wasn't previously grouped it also takes care of converting the view to // the grouped notification state. @@ -108,8 +116,13 @@ virtual void PopulateGroupNotifications( const std::vector<const Notification*>& notifications) {} + // Removes the grouped notification view associated with the provided + // `notification_id`. virtual void RemoveGroupNotification(const std::string& notification_id) {} + // Updates the expanded state for grouped child notification. + virtual void SetGroupedChildExpanded(bool expanded) {} + // Creates text for spoken feedback from the data contained in the // notification. std::u16string CreateAccessibleName(const Notification& notification);
diff --git a/ui/webui/resources/cr_elements/store_client/store_client.ts b/ui/webui/resources/cr_elements/store_client/store_client.ts index 4c8fed5..655a13a 100644 --- a/ui/webui/resources/cr_elements/store_client/store_client.ts +++ b/ui/webui/resources/cr_elements/store_client/store_client.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 {Action, DeferredAction, Store} from '//resources/js/store_ts.js'; +import {Action, DeferredAction, Store} from '//resources/js/store.js'; import {dedupingMixin, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; /**
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index 1812464d..11214e5 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -35,7 +35,7 @@ "promise_resolver.ts", "search_highlight_utils.ts", "static_types.ts", - "store_ts.ts", + "store.ts", "test_loader.ts", "test_loader_util.ts", "util.ts",
diff --git a/ui/webui/resources/js/store_ts.ts b/ui/webui/resources/js/store.ts similarity index 100% rename from ui/webui/resources/js/store_ts.ts rename to ui/webui/resources/js/store.ts
diff --git a/v8 b/v8 index 225e4ba..30e8263 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 225e4baa97487bad251fffec7f5460845c394f6c +Subproject commit 30e826391ad51011e6829dde5a1b246dd1588f19