diff --git a/DEPS b/DEPS index 4e9aca0..40edd432 100644 --- a/DEPS +++ b/DEPS
@@ -312,11 +312,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '28579a88aa9c12ef23c1d3ab798aba40f85ea0d8', + 'skia_revision': '2a2fe430350798bf10c28ad55daf61c08c6a4121', # 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': 'de7ce8021831d4f3c4e49336623f25b2fc406fbc', + 'v8_revision': '555084e67f98736a41e52d13e485ab0febc3cbae', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -399,7 +399,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling fuzztest # and whatever else without interference from each other. - 'fuzztest_revision': 'd7c63cd216941e297569428e40f9b8bc155e0423', + 'fuzztest_revision': '65354bf09a2479945b4683c42948695d4f2f7c07', # 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. @@ -431,7 +431,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': 'acbdda4e4aa43e72a19aa72115b71e8eba57babb', + 'quiche_revision': '718c9019fe67253ca9aa76498dff0f35ef97b15e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -459,7 +459,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '78505e91f7e054444030aec55110893b4fc62500', + 'nearby_revision': '03f0b3dae98d218e8420add5a13893822d290855', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -827,7 +827,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '682118afe56ac594ac2a4343274a9bed1dac8710', + '2d1d020843dabd7ef41ae7a261f81b381281dbf4', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1517,7 +1517,7 @@ Var('chromium_git') + '/external/github.com/google/libprotobuf-mutator.git' + '@' + Var('libprotobuf-mutator'), 'src/third_party/libsrtp': - Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '5b7c744eb8310250ccc534f3f86a2015b3887a0a', + Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '7a7e64c8b5a632f55929cb3bb7d3e6fb48c3205a', # Android Explicit Synchronization. 'src/third_party/libsync/src': { @@ -1848,10 +1848,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'f4bf599a8b575df685c31d9c4729a70a04e377ed', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'acb475026d7ac90725c629ef3664267c7aed72a1', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e5fb8824ade85fae690f2bb45cc347a1398cca2f', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '0bb59b4edd23d4e69de14b316312571146b6448d', + Var('webrtc_git') + '/src.git' + '@' + 'f942a2901aa45546ec525c0adf977071f312f6f3', # 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. @@ -4125,7 +4125,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - 'c448ce76c3e84201da5db9ac4a2a579c2fabfdf3', + 'debd0ef81bb8df6520b9cc80141ec587cd8e1c56', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index 070de21..39f5a80 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -1959,6 +1959,10 @@ capture_params.window, capture_params.bounds, base::BindOnce(&CaptureModeController::InterruptVideoRecording, weak_ptr_factory_.GetWeakPtr())); + + if (on_video_recording_started_callback_for_test_) { + std::move(on_video_recording_started_callback_for_test_).Run(); + } } void CaptureModeController::InterruptVideoRecording() {
diff --git a/ash/capture_mode/capture_mode_controller.h b/ash/capture_mode/capture_mode_controller.h index aced8f78..3be1898 100644 --- a/ash/capture_mode/capture_mode_controller.h +++ b/ash/capture_mode/capture_mode_controller.h
@@ -702,6 +702,8 @@ base::OnceClosure on_countdown_finished_callback_for_test_; + base::OnceClosure on_video_recording_started_callback_for_test_; + // Timers used to schedule recording of the number of screenshots taken. base::RepeatingTimer num_screenshots_taken_in_last_day_scheduler_; base::RepeatingTimer num_screenshots_taken_in_last_week_scheduler_;
diff --git a/ash/capture_mode/capture_mode_test_api.cc b/ash/capture_mode/capture_mode_test_api.cc index 4425416..1f6e666 100644 --- a/ash/capture_mode/capture_mode_test_api.cc +++ b/ash/capture_mode/capture_mode_test_api.cc
@@ -116,6 +116,12 @@ ->IsInCountDownAnimation(); } +void CaptureModeTestApi::SetOnVideoRecordingStartedCallback( + base::OnceClosure callback) { + controller_->on_video_recording_started_callback_for_test_ = + std::move(callback); +} + void CaptureModeTestApi::StopVideoRecording() { DCHECK(controller_->is_recording_in_progress()); controller_->EndVideoRecording(EndRecordingReason::kStopRecordingButton);
diff --git a/ash/capture_mode/capture_mode_test_util.cc b/ash/capture_mode/capture_mode_test_util.cc index 9945af5..505d6c9a 100644 --- a/ash/capture_mode/capture_mode_test_util.cc +++ b/ash/capture_mode/capture_mode_test_util.cc
@@ -98,11 +98,9 @@ auto* controller = CaptureModeController::Get(); if (controller->is_recording_in_progress()) return; - auto* test_delegate = - static_cast<TestCaptureModeDelegate*>(controller->delegate_for_testing()); - ASSERT_TRUE(test_delegate); base::RunLoop run_loop; - test_delegate->set_on_recording_started_callback(run_loop.QuitClosure()); + ash::CaptureModeTestApi().SetOnVideoRecordingStartedCallback( + run_loop.QuitClosure()); run_loop.Run(); ASSERT_TRUE(controller->is_recording_in_progress()); }
diff --git a/ash/capture_mode/test_capture_mode_delegate.cc b/ash/capture_mode/test_capture_mode_delegate.cc index 607f59e..64e30ad 100644 --- a/ash/capture_mode/test_capture_mode_delegate.cc +++ b/ash/capture_mode/test_capture_mode_delegate.cc
@@ -124,12 +124,7 @@ void TestCaptureModeDelegate::StartObservingRestrictedContent( const aura::Window* window, const gfx::Rect& bounds, - base::OnceClosure stop_callback) { - // This is called at the last stage of recording initialization to signal that - // recording has actually started. - if (on_recording_started_callback_) - std::move(on_recording_started_callback_).Run(); -} + base::OnceClosure stop_callback) {} void TestCaptureModeDelegate::StopObservingRestrictedContent( OnCaptureModeDlpRestrictionChecked callback) {
diff --git a/ash/capture_mode/test_capture_mode_delegate.h b/ash/capture_mode/test_capture_mode_delegate.h index 0ecee6b..f8f18038 100644 --- a/ash/capture_mode/test_capture_mode_delegate.h +++ b/ash/capture_mode/test_capture_mode_delegate.h
@@ -43,9 +43,6 @@ void set_on_session_state_changed_callback(base::OnceClosure callback) { on_session_state_changed_callback_ = std::move(callback); } - void set_on_recording_started_callback(base::OnceClosure callback) { - on_recording_started_callback_ = std::move(callback); - } void set_is_allowed_by_dlp(bool value) { is_allowed_by_dlp_ = value; } void set_is_allowed_by_policy(bool value) { is_allowed_by_policy_ = value; } void set_should_save_after_dlp_check(bool value) { @@ -146,7 +143,6 @@ std::unique_ptr<FakeVideoSourceProvider> video_source_provider_; base::ScopedTempDir fake_downloads_dir_; base::OnceClosure on_session_state_changed_callback_; - base::OnceClosure on_recording_started_callback_; bool is_session_active_ = false; bool is_allowed_by_dlp_ = true; bool is_allowed_by_policy_ = true;
diff --git a/ash/picker/search/picker_search_request.cc b/ash/picker/search/picker_search_request.cc index 6bc3506..986144f 100644 --- a/ash/picker/search/picker_search_request.cc +++ b/ash/picker/search/picker_search_request.cc
@@ -70,6 +70,12 @@ query, category, base::BindRepeating(&PickerSearchRequest::HandleCrosSearchResults, weak_ptr_factory_.GetWeakPtr())); + + if (!category.has_value() || category == PickerCategory::kDriveFiles) { + drive_search_timeout_timer_.Start( + FROM_HERE, kDriveSearchTimeout, this, + &PickerSearchRequest::OnDriveSearchTimeout); + } } if (!category.has_value() || category == PickerCategory::kClipboard) { @@ -166,6 +172,10 @@ /*has_more_results=*/!is_category_specific_search_); break; case AppListSearchResultType::kDriveSearch: { + if (!drive_search_timeout_timer_.IsRunning()) { + return; + } + if (cros_search_start_.has_value()) { base::TimeDelta elapsed = base::TimeTicks::Now() - *cros_search_start_; base::UmaHistogramTimes("Ash.Picker.Search.DriveProvider.QueryTime", @@ -178,6 +188,7 @@ HandleSearchSourceResults(PickerSearchSource::kDrive, std::move(results), /*has_more_results=*/files_to_remove > 0); + drive_search_timeout_timer_.Stop(); break; } case AppListSearchResultType::kFileSearch: { @@ -295,4 +306,9 @@ /*has_more_results=*/false); } +void PickerSearchRequest::OnDriveSearchTimeout() { + HandleSearchSourceResults(PickerSearchSource::kDrive, {}, + /*has_more_results=*/false); +} + } // namespace ash
diff --git a/ash/picker/search/picker_search_request.h b/ash/picker/search/picker_search_request.h index 89e1a0d..5dd0d73 100644 --- a/ash/picker/search/picker_search_request.h +++ b/ash/picker/search/picker_search_request.h
@@ -53,6 +53,7 @@ static constexpr base::TimeDelta kGifDebouncingDelay = base::Milliseconds(200); + static constexpr base::TimeDelta kDriveSearchTimeout = base::Seconds(1); private: void StartGifSearch(const std::string& query); @@ -71,6 +72,8 @@ void HandleMathSearchResults(std::optional<PickerSearchResult> result); void HandleClipboardSearchResults(std::vector<PickerSearchResult> results); + void OnDriveSearchTimeout(); + bool is_category_specific_search_; const raw_ref<PickerClient> client_; @@ -90,6 +93,8 @@ PickerSearchDebouncer gif_search_debouncer_; + base::OneShotTimer drive_search_timeout_timer_; + base::WeakPtrFactory<PickerSearchRequest> weak_ptr_factory_{this}; };
diff --git a/ash/picker/search/picker_search_request_unittest.cc b/ash/picker/search/picker_search_request_unittest.cc index 61e71c0..65bfd4b 100644 --- a/ash/picker/search/picker_search_request_unittest.cc +++ b/ash/picker/search/picker_search_request_unittest.cc
@@ -639,6 +639,71 @@ ash::PickerSearchResult::Text(u"4.jpg")}); } +TEST_F(PickerSearchRequestTest, SendsEmptyDriveResultsOnTimeout) { + MockSearchResultsCallback search_results_callback; + EXPECT_CALL(search_results_callback, Call).Times(AnyNumber()); + EXPECT_CALL(search_results_callback, + Call(PickerSearchSource::kDrive, IsEmpty(), + /*has_more_results=*/false)) + .Times(1); + + PickerSearchRequest request( + u"cat", std::nullopt, + base::BindRepeating(&MockSearchResultsCallback::Call, + base::Unretained(&search_results_callback)), + &client(), &emoji_search(), kAllCategories); + task_environment().FastForwardBy(PickerSearchRequest::kDriveSearchTimeout); +} + +TEST_F(PickerSearchRequestTest, IgnoresDriveResultsAfterTimeout) { + MockSearchResultsCallback search_results_callback; + EXPECT_CALL(search_results_callback, Call).Times(AnyNumber()); + EXPECT_CALL(search_results_callback, + Call(PickerSearchSource::kDrive, IsEmpty(), + /*has_more_results=*/false)) + .Times(1); + EXPECT_CALL(search_results_callback, + Call(PickerSearchSource::kDrive, Not(IsEmpty()), _)) + .Times(0); + + PickerSearchRequest request( + u"cat", std::nullopt, + base::BindRepeating(&MockSearchResultsCallback::Call, + base::Unretained(&search_results_callback)), + &client(), &emoji_search(), kAllCategories); + task_environment().FastForwardBy(PickerSearchRequest::kDriveSearchTimeout); + client().cros_search_callback().Run( + ash::AppListSearchResultType::kDriveSearch, + {ash::PickerSearchResult::Text(u"1.jpg")}); +} + +TEST_F(PickerSearchRequestTest, CancelsTimeoutTimerOnReceivingDriveResults) { + MockSearchResultsCallback search_results_callback; + EXPECT_CALL(search_results_callback, Call).Times(AnyNumber()); + EXPECT_CALL(search_results_callback, + Call(PickerSearchSource::kDrive, + ElementsAre(Property( + "data", &PickerSearchResult::data, + VariantWith<PickerSearchResult::TextData>(Field( + "text", &PickerSearchResult::TextData::primary_text, + u"1.jpg")))), + /*has_more_results=*/false)) + .Times(1); + EXPECT_CALL(search_results_callback, + Call(PickerSearchSource::kDrive, IsEmpty(), _)) + .Times(0); + + PickerSearchRequest request( + u"cat", std::nullopt, + base::BindRepeating(&MockSearchResultsCallback::Call, + base::Unretained(&search_results_callback)), + &client(), &emoji_search(), kAllCategories); + client().cros_search_callback().Run( + ash::AppListSearchResultType::kDriveSearch, + {ash::PickerSearchResult::Text(u"1.jpg")}); + task_environment().FastForwardBy(PickerSearchRequest::kDriveSearchTimeout); +} + TEST_F(PickerSearchRequestTest, RecordsDriveMetrics) { base::HistogramTester histogram; NiceMock<MockSearchResultsCallback> search_results_callback;
diff --git a/ash/public/cpp/capture_mode/capture_mode_test_api.h b/ash/public/cpp/capture_mode/capture_mode_test_api.h index 827d604..c010ed27 100644 --- a/ash/public/cpp/capture_mode/capture_mode_test_api.h +++ b/ash/public/cpp/capture_mode/capture_mode_test_api.h
@@ -84,6 +84,9 @@ // Returns true if the 3-second countdown animation is in progress. bool IsInCountDownAnimation() const; + // Sets a callback that will be triggered once the video recording is started. + void SetOnVideoRecordingStartedCallback(base::OnceClosure callback); + // Stops the video recording. Can only be called if a video recording was // in progress. void StopVideoRecording();
diff --git a/ash/system/camera/camera_effects_controller_unittest.cc b/ash/system/camera/camera_effects_controller_unittest.cc index b504c0b..22e30f7 100644 --- a/ash/system/camera/camera_effects_controller_unittest.cc +++ b/ash/system/camera/camera_effects_controller_unittest.cc
@@ -249,7 +249,7 @@ cros::mojom::CameraEffect::kBackgroundBlur)); EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kPortraitRelight)); - EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable( + EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kBackgroundReplace)); } @@ -261,7 +261,7 @@ cros::mojom::CameraEffect::kBackgroundBlur)); EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kPortraitRelight)); - EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable( + EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kBackgroundReplace)); } @@ -274,21 +274,20 @@ cros::mojom::CameraEffect::kBackgroundBlur)); EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kPortraitRelight)); - EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable( + EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kBackgroundReplace)); } { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures( - {features::kFeatureManagementVideoConference, - features::kVcBackgroundReplace}, - {}); + {features::kFeatureManagementVideoConference}, + {features::kVcBackgroundReplace}); EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kBackgroundBlur)); EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kPortraitRelight)); - EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable( + EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable( cros::mojom::CameraEffect::kBackgroundReplace)); } }
diff --git a/build/config/siso/clang_linux.star b/build/config/siso/clang_linux.star index 4c0229c..f0ad598 100644 --- a/build/config/siso/clang_linux.star +++ b/build/config/siso/clang_linux.star
@@ -161,36 +161,6 @@ "timeout": "2m", }, { - "name": "clang/alink", - "action": "(.*_)?alink", - "inputs": [ - "third_party/llvm-build/Release+Asserts/bin/llvm-ar", - ], - "remote": config.get(ctx, "cog"), - "canonicalize_dir": True, - "accumulate": True, - "timeout": "4m", - }, - { - "name": "clang/link", - "action": "(.*_)?link", - "command_prefix": "\"python3\" \"../../build/toolchain/gcc_link_wrapper.py\"", - "inputs": [ - "third_party/llvm-build/Release+Asserts/bin/clang", - "third_party/llvm-build/Release+Asserts/bin/clang++", - "third_party/llvm-build/Release+Asserts/bin/ld.lld", - "third_party/llvm-build/Release+Asserts/bin/lld", - "build/toolchain/whole_archive.py", - "build/toolchain/wrapper_utils.py", - "build/toolchain/gcc_link_wrapper.py", - "build/linux/debian_bullseye_amd64-sysroot:link", - ], - "remote": config.get(ctx, "cog"), - "platform_ref": "large", - "canonicalize_dir": True, - "timeout": "10m", - }, - { "name": "clang-coverage/cxx", "action": "(.*_)?cxx", "command_prefix": "\"python3\" ../../build/toolchain/clang_code_coverage_wrapper.py", @@ -237,6 +207,7 @@ "*.stamp", ], "remote": config.get(ctx, "remote-library-link"), + "canonicalize_dir": True, "platform_ref": "large", "accumulate": True, }, @@ -260,6 +231,7 @@ "*.stamp", ], "remote": config.get(ctx, "remote-library-link"), + "canonicalize_dir": True, "platform_ref": "large", }, { @@ -282,7 +254,9 @@ "*.stamp", ], "remote": config.get(ctx, "remote-exec-link"), + "canonicalize_dir": True, "platform_ref": "large", + "timeout": "10m", }, ]) return step_config
diff --git a/build/config/siso/main.star b/build/config/siso/main.star index 4a5a619..23a02ea8 100644 --- a/build/config/siso/main.star +++ b/build/config/siso/main.star
@@ -35,10 +35,13 @@ # target_os = "chromeos" # use_cups = true # use_remoteexec = true + "./lacros_clang_x64/obj/chrome/browser/browser/chrome_browser_interface_binders.o", "./lacros_clang_x64/obj/chrome/browser/browser/chrome_content_browser_client.o", "./lacros_clang_x64/obj/content/browser/browser/browser_interface_binders.o", + "./lacros_clang_x64/obj/third_party/blink/public/mojom/mojom_platform/speech_recognition_grammar.mojom.o", "./obj/chrome/browser/ash/ash/autotest_private_api.o", "./obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o", + "./obj/chrome/browser/ash/ash/user_session_manager.o", "./obj/chrome/browser/ash/ash/webui_login_view.o", "./obj/chrome/browser/ash/system_web_apps/apps/browser_tests/media_app_integration_browsertest.o", "./obj/chrome/browser/ash/system_web_apps/browser_tests/system_web_app_manager_browsertest.o", @@ -46,6 +49,7 @@ "./obj/chrome/browser/browser/browser_prefs.o", "./obj/chrome/browser/browser/chrome_browser_interface_binders.o", "./obj/chrome/browser/browser/chrome_content_browser_client.o", + "./obj/chrome/browser/browser/render_view_context_menu.o", "./obj/chrome/browser/ui/ash/holding_space/browser_tests/holding_space_ui_browsertest.o", "./obj/chrome/test/browser_tests/app_list_client_impl_browsertest.o", "./obj/chrome/test/browser_tests/browser_non_client_frame_view_chromeos_browsertest.o",
diff --git a/chrome/android/java/res/xml/unified_account_settings_preferences.xml b/chrome/android/java/res/xml/unified_account_settings_preferences.xml index f38c8872..d2765b3 100644 --- a/chrome/android/java/res/xml/unified_account_settings_preferences.xml +++ b/chrome/android/java/res/xml/unified_account_settings_preferences.xml
@@ -61,4 +61,9 @@ android:key="encryption" android:title="@string/sync_encryption"/> + <org.chromium.components.browser_ui.settings.ChromeBasePreference + android:key="sync_review_data" + android:title="@string/signin_review_data_title" + android:summary="@string/signin_review_data_summary"/> + </PreferenceScreen> \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java index 9aad3a7..8daf5925 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java
@@ -737,6 +737,8 @@ public void isAccountManaged( @NonNull CoreAccountInfo account, final Callback<Boolean> callback) { assert account != null; + if (account == null) throw new RuntimeException("Null account"); + if (callback == null) throw new RuntimeException("Null callback"); SigninManagerImplJni.get().isAccountManaged(mNativeSigninManagerAndroid, account, callback); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java index ab8c6cbd..aa3b12c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java
@@ -247,11 +247,6 @@ findPreference(PREF_ADVANCED_CATEGORY).setVisible(true); } - Preference reviewSyncData = findPreference(PREF_SYNC_REVIEW_DATA); - reviewSyncData.setOnPreferenceClickListener( - SyncSettingsUtils.toOnClickListener( - this, () -> SyncSettingsUtils.openSyncDashboard(getActivity()))); - mSyncTypeCheckBoxPreferencesMap = new HashMap<>(); mSyncTypeCheckBoxPreferencesMap.put( UserSelectableType.AUTOFILL, findPreference(PREF_SYNC_AUTOFILL)); @@ -315,6 +310,11 @@ mSyncEncryption = findPreference(PREF_ENCRYPTION); mSyncEncryption.setOnPreferenceClickListener( SyncSettingsUtils.toOnClickListener(this, this::onSyncEncryptionClicked)); + + Preference reviewSyncData = findPreference(PREF_SYNC_REVIEW_DATA); + reviewSyncData.setOnPreferenceClickListener( + SyncSettingsUtils.toOnClickListener( + this, () -> SyncSettingsUtils.openSyncDashboard(getActivity()))); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java index 377d7a6..ab791fe9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java
@@ -15,6 +15,7 @@ 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.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.base.ColdStartTracker; @@ -91,6 +92,7 @@ @Test @MediumTest @Restriction(StartupPaintPreviewHelperTestRunner.RESTRICTION_TYPE_KEEP_ACTIVITIES) + @DisabledTest(message = "Very flaky. See crbug.com/333779543.") public void testDisplayOnStartup() throws ExecutionException { mActivityTestRule.startMainActivityWithURL( mActivityTestRule.getTestServer().getURL(TEST_URL));
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index c397708..3af9130 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -7485,6 +7485,9 @@ <message name="IDS_APP_INSTALL_DIALOG_FAILED_INSTALL_TITLE" desc="Title shown in the app install dialog if the app failed to install."> Can't install app. Something went wrong. </message> + <message name="IDS_APP_INSTALL_DIALOG_APP_ICON_ALT" desc="Alt text for the app icon displayed in the app install dialog. This is the text that will be read by screen reader when the app icon is focused."> + <ph name="APP">$1<ex>Google Docs</ex></ph> logo + </message> <!-- Extended Updates Dialog --> <message name="IDS_EXTENDED_UPDATES_DIALOG_DIALOG_HEADING" desc="Dialog heading of the Extended Updates Dialog" translateable="false">
diff --git a/chrome/app/chromeos_strings_grdp/IDS_APP_INSTALL_DIALOG_APP_ICON_ALT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_APP_INSTALL_DIALOG_APP_ICON_ALT.png.sha1 new file mode 100644 index 0000000..876fa529 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_APP_INSTALL_DIALOG_APP_ICON_ALT.png.sha1
@@ -0,0 +1 @@ +29a4ea4af20d9c662f3fb44da7d19076b532f9e2 \ No newline at end of file
diff --git a/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc b/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc index e8f2b8a7..61e84b2 100644 --- a/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc +++ b/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/command_line.h" -#include "base/files/file_util.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -17,12 +13,12 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_accessibility_state.h" +#include "content/public/test/accessibility_notification_waiter.h" #include "content/public/test/browser_test.h" #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/ash/accessibility/accessibility_manager.h" #include "chrome/browser/ash/accessibility/speech_monitor.h" -#include "chrome/browser/ash/profiles/profile_helper.h" #include "extensions/browser/browsertest_util.h" #include "extensions/common/constants.h" #else @@ -107,6 +103,12 @@ chrome::NewTab(browser()); web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + // Wait for ChromeVox to attach to the new tab if needed. + if (!web_contents->GetAccessibilityMode().has_mode( + ui::AXMode::kScreenReader)) { + content::AccessibilityNotificationWaiter waiter(web_contents); + ASSERT_TRUE(waiter.WaitForNotification()); + } ax_mode = web_contents->GetAccessibilityMode(); EXPECT_TRUE(ax_mode.has_mode(ui::AXMode::kLabelImages)); @@ -179,51 +181,48 @@ prefs::kAccessibilityImageLabelsEnabled, false); } -IN_PROC_BROWSER_TEST_F(AccessibilityLabelsBrowserTest, EnabledOnStartup) { -#if BUILDFLAG(IS_CHROMEOS_ASH) - ash::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(true); -#endif - - // Make a testing profile so we can mimic prefs set before startup. - ProfileManager* profile_manager = g_browser_process->profile_manager(); - std::unique_ptr<Profile> other_profile; - { - base::FilePath path = - profile_manager->user_data_dir().AppendASCII("test_profile"); - base::ScopedAllowBlockingForTesting allow_blocking; - if (!base::PathExists(path)) { - ASSERT_TRUE(base::CreateDirectory(path)); - } - other_profile = - Profile::CreateProfile(path, nullptr, Profile::CREATE_MODE_SYNCHRONOUS); - } - Profile* other_profile_ptr = other_profile.get(); - profile_manager->RegisterTestingProfile(std::move(other_profile), true); - +// Turning on the preference while a screenreader is present should enable the +// feature for existing tabs. +IN_PROC_BROWSER_TEST_F(AccessibilityLabelsBrowserTest, + PRE_EnabledByPreference) { EnableScreenReader(true); - // Verify clean state. - Browser* other_profile_browser = CreateBrowser(other_profile_ptr); - content::WebContents* web_contents = - other_profile_browser->tab_strip_model()->GetActiveWebContents(); - ui::AXMode ax_mode = web_contents->GetAccessibilityMode(); - EXPECT_FALSE(ax_mode.has_mode(ui::AXMode::kLabelImages)); + // The preference is not yet set, so the feature is off. + auto* const web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_FALSE( + web_contents->GetAccessibilityMode().has_mode(ui::AXMode::kLabelImages)); - // Simulate the pref being set prior to startup. - other_profile_ptr->GetPrefs()->SetBoolean( + browser()->profile()->GetPrefs()->SetBoolean( prefs::kAccessibilityImageLabelsEnabled, true); - // Now, simulate the initialization path which ordinarily gets called by - // ProfileManager on startup/profile creation. - AccessibilityLabelsService* a11y_labels_service = - AccessibilityLabelsServiceFactory::GetForProfile(other_profile_ptr); - a11y_labels_service->Init(); + // Now the feature is on. + EXPECT_TRUE( + web_contents->GetAccessibilityMode().has_mode(ui::AXMode::kLabelImages)); +} - // Verify that tabs now get the mode. Open a new tab to avoid races for - // setting modes. - AddBlankTabAndShow(other_profile_browser); - web_contents = - other_profile_browser->tab_strip_model()->GetActiveWebContents(); - ax_mode = web_contents->GetAccessibilityMode(); - EXPECT_TRUE(ax_mode.has_mode(ui::AXMode::kLabelImages)); +// When the preference is present at startup, the feature should become enabled +// when a screenreader is discovered. +IN_PROC_BROWSER_TEST_F(AccessibilityLabelsBrowserTest, EnabledByPreference) { + // The preference was set for the profile by PRE_EnabledByPreference. + ASSERT_TRUE(browser()->profile()->GetPrefs()->GetBoolean( + prefs::kAccessibilityImageLabelsEnabled)); + + auto* const web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + // If the test is run without --force-renderer-accessibility, then no screen + // reader should have been detected yet, and the feature should be off. + if (!content::BrowserAccessibilityState::GetInstance() + ->GetAccessibilityMode() + .has_mode(ui::AXMode::kScreenReader)) { + EXPECT_FALSE(web_contents->GetAccessibilityMode().has_mode( + ui::AXMode::kLabelImages)); + + EnableScreenReader(true); + } + + // Now the feature is on. + EXPECT_TRUE( + web_contents->GetAccessibilityMode().has_mode(ui::AXMode::kLabelImages)); }
diff --git a/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc b/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc index e768890..187e6d6 100644 --- a/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc +++ b/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc
@@ -62,7 +62,7 @@ return receiver_.BindNewPipeAndPassRemote(); } - void REMOVED_0(REMOVED_0Callback callback) override { NOTIMPLEMENTED(); } + void REMOVED_0() override { NOTIMPLEMENTED(); } void REMOVED_2(crosapi::mojom::BrowserInitParamsPtr) override { NOTIMPLEMENTED(); }
diff --git a/chrome/browser/ash/file_system_provider/content_cache/context_database.cc b/chrome/browser/ash/file_system_provider/content_cache/context_database.cc index 3753337..13c8f6a 100644 --- a/chrome/browser/ash/file_system_provider/content_cache/context_database.cc +++ b/chrome/browser/ash/file_system_provider/content_cache/context_database.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/ash/file_system_provider/content_cache/context_database.h" #include "base/sequence_checker.h" -#include "sql/init_status.h" +#include "sql/statement.h" #include "sql/transaction.h" namespace ash::file_system_provider { @@ -23,6 +23,18 @@ "PRIMARY KEY(id AUTOINCREMENT))"; // clang-format on +static constexpr char kInsertItemSql[] = + // clang-format off + "INSERT INTO items " + "(fsp_path, version_tag, accessed_time) VALUES (?, ?, ?) " + "RETURNING id"; +// clang-format on + +static constexpr char kSelectItemByIdSql[] = + // clang-format off + "SELECT fsp_path, version_tag, accessed_time FROM items WHERE id=? LIMIT 1"; +// clang-format on + } // namespace ContextDatabase::ContextDatabase(const base::FilePath& db_path) @@ -81,6 +93,69 @@ return committer.Commit(); } +bool ContextDatabase::AddItem(const base::FilePath& fsp_path, + const std::string& version_tag, + base::Time accessed_time, + int64_t* inserted_id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (fsp_path.empty() || version_tag.empty() || accessed_time.is_null()) { + return false; + } + + std::unique_ptr<sql::Statement> statement = std::make_unique<sql::Statement>( + db_.GetCachedStatement(SQL_FROM_HERE, kInsertItemSql)); + if (!statement) { + LOG(ERROR) << "Couldn't create SQL statement"; + return false; + } + + statement->BindString(0, fsp_path.value()); + statement->BindString(1, version_tag); + statement->BindInt64(2, accessed_time.InMillisecondsSinceUnixEpoch()); + if (!statement->Step()) { + LOG(ERROR) << "Couldn't execute statement"; + return false; + } + + *inserted_id = statement->ColumnInt64(0); + return true; +} + +bool ContextDatabase::GetItemById(int64_t item_id, Item& item) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (item_id < 0) { + return false; + } + + std::unique_ptr<sql::Statement> statement = std::make_unique<sql::Statement>( + db_.GetCachedStatement(SQL_FROM_HERE, kSelectItemByIdSql)); + if (!statement) { + LOG(ERROR) << "Couldn't create SQL statement"; + return false; + } + + statement->BindInt64(0, item_id); + if (!statement->Step()) { + // In the event the `Step()` failed, this could simply mean there is no item + // for the `item_id`. `Succeeded` will return true in this case. + if (statement->Succeeded()) { + item.item_exists = false; + return true; + } + LOG(ERROR) << "Couldn't execute statement"; + return false; + } + + item.fsp_path = base::FilePath(statement->ColumnString(0)); + item.version_tag = statement->ColumnString(1); + item.accessed_time = + base::Time::FromMillisecondsSinceUnixEpoch(statement->ColumnInt64(2)); + + return true; +} + bool ContextDatabase::Raze() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/ash/file_system_provider/content_cache/context_database.h b/chrome/browser/ash/file_system_provider/content_cache/context_database.h index 9678ea75..96fc894 100644 --- a/chrome/browser/ash/file_system_provider/content_cache/context_database.h +++ b/chrome/browser/ash/file_system_provider/content_cache/context_database.h
@@ -28,6 +28,30 @@ // empty) or at the path specified by the `db_path` in the constructor. bool Initialize(); + // Insert an item into the database and returns the unique ID that references + // this item. In the event the `fsp_path` and `version_tag` have previously + // been used, this will remove the conflicted record and insert a new one. + bool AddItem(const base::FilePath& fsp_path, + const std::string& version_tag, + base::Time accessed_time, + int64_t* inserted_id); + + // Represents a row returned from the SQLite database with the additional + // field of `item_exists` that will be set to `false` if the item requested is + // not available. + struct Item { + base::FilePath fsp_path; + base::Time accessed_time; + std::string version_tag; + bool item_exists = true; + }; + + // Retrieve an item by `item_id`. If this returns false, indicates a more + // fatal error. If this returns true the supplied `Item` will contain the data + // or alternatively the field `item_exists` will be false indicating the + // requested record is not available. + bool GetItemById(int64_t item_id, Item& item); + private: SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/ash/file_system_provider/content_cache/context_database_unittest.cc b/chrome/browser/ash/file_system_provider/content_cache/context_database_unittest.cc index efd377a..2d5cf602 100644 --- a/chrome/browser/ash/file_system_provider/content_cache/context_database_unittest.cc +++ b/chrome/browser/ash/file_system_provider/content_cache/context_database_unittest.cc
@@ -25,10 +25,74 @@ TEST_F(FileSystemProviderContextDatabaseTest, DbCreatedOnInitialize) { base::FilePath db_path = temp_dir_.GetPath().Append("context.db"); - ContextDatabase context_db(db_path); - EXPECT_TRUE(context_db.Initialize()); + ContextDatabase db(db_path); + EXPECT_TRUE(db.Initialize()); EXPECT_TRUE(base::PathExists(db_path)); } +TEST_F(FileSystemProviderContextDatabaseTest, AddItem) { + std::unique_ptr<ContextDatabase> db = + std::make_unique<ContextDatabase>(base::FilePath()); + EXPECT_TRUE(db->Initialize()); + + // Doesn't accept empty parameters; + int64_t inserted_id = -1; + EXPECT_FALSE(db->AddItem(base::FilePath(), "versionA", base::Time::Now(), + &inserted_id)); + EXPECT_FALSE(db->AddItem(base::FilePath("/fsp_path.txt"), "", + base::Time::Now(), &inserted_id)); + EXPECT_FALSE(db->AddItem(base::FilePath("/fsp_path.txt"), "versionA", + base::Time(), &inserted_id)); + EXPECT_EQ(inserted_id, -1); + + // Item added returns an auto incremented ID. + EXPECT_TRUE(db->AddItem(base::FilePath("/fsp_path.txt"), "versionA", + base::Time::Now(), &inserted_id)); + EXPECT_EQ(inserted_id, 1); + EXPECT_TRUE(db->AddItem(base::FilePath("/fsp_path_1.txt"), "versionA", + base::Time::Now(), &inserted_id)); + EXPECT_EQ(inserted_id, 2); + + // If an item is added that matches the UNIQUE(fsp_path, version_tag) + // constraint the new ID is returned and the old ID gets removed. + EXPECT_TRUE(db->AddItem(base::FilePath("/fsp_path.txt"), "versionA", + base::Time::Now(), &inserted_id)); + EXPECT_EQ(inserted_id, 3); + + // Expect that the item with id 1 is no longer available. + ContextDatabase::Item item; + db->GetItemById(1, item); + EXPECT_FALSE(item.item_exists); +} + +TEST_F(FileSystemProviderContextDatabaseTest, GetItemById) { + std::unique_ptr<ContextDatabase> db = + std::make_unique<ContextDatabase>(base::FilePath()); + EXPECT_TRUE(db->Initialize()); + + // Negative IDs should fail. + ContextDatabase::Item item; + EXPECT_FALSE(db->GetItemById(-1, item)); + + // Insert an item into the database. + int64_t inserted_id = -1; + base::FilePath fsp_path("/fsp_path.txt"); + std::string version_tag("versionA"); + base::Time accessed_time = base::Time::Now(); + EXPECT_TRUE(db->AddItem(fsp_path, version_tag, accessed_time, &inserted_id)); + + // Retrieve the item back from the database. + EXPECT_TRUE(db->GetItemById(inserted_id, item)); + EXPECT_TRUE(item.item_exists); + + // We store the time in ms since unix epoch which doesn't have the same + // granularity as the `EXPECT_EQ` comparison, convert back to ensure the + // values are the same. + EXPECT_EQ(item.accessed_time.InMillisecondsSinceUnixEpoch(), + accessed_time.InMillisecondsSinceUnixEpoch()); + EXPECT_EQ(item.fsp_path, fsp_path); + EXPECT_EQ(item.version_tag, version_tag); +} + } // namespace } // namespace ash::file_system_provider
diff --git a/chrome/browser/ash/file_system_provider/extension_provider.cc b/chrome/browser/ash/file_system_provider/extension_provider.cc index cb2b773..2113e0d6 100644 --- a/chrome/browser/ash/file_system_provider/extension_provider.cc +++ b/chrome/browser/ash/file_system_provider/extension_provider.cc
@@ -33,7 +33,7 @@ // Timeout before an onMountRequested request is considered as stale and hence // aborted. -constexpr base::TimeDelta kDefaultMountTimeout = base::Minutes(5); +constexpr base::TimeDelta kDefaultMountTimeout = base::Minutes(10); extensions::file_system_provider::ServiceWorkerLifetimeManager* GetServiceWorkerLifetimeManager(Profile* profile) {
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_config.h b/chrome/browser/ash/policy/enrollment/enrollment_config.h index 00a5c2b8..881bd413 100644 --- a/chrome/browser/ash/policy/enrollment/enrollment_config.h +++ b/chrome/browser/ash/policy/enrollment/enrollment_config.h
@@ -226,9 +226,6 @@ // match. std::string management_domain; - // The realm the device is joined to (if managed by AD). - std::string management_realm; - // Is a license packaged with device or not. bool is_license_packaged_with_device = false; @@ -245,10 +242,6 @@ // TODO(drcrash): Change to best available once ZTE is everywhere. AuthMechanism auth_mechanism = AUTH_MECHANISM_INTERACTIVE; - // The path for the device policy blob data for the offline demo mode. This - // should be empty and never used for other modes. - base::FilePath offline_policy_path; - // User's email which can be passed from the Gaia screen in the enrollment // nudge flow. std::string enrollment_nudge_email;
diff --git a/chrome/browser/ash/telemetry_extension/routines/routine_converters.cc b/chrome/browser/ash/telemetry_extension/routines/routine_converters.cc index 85935cf6..b0df925 100644 --- a/chrome/browser/ash/telemetry_extension/routines/routine_converters.cc +++ b/chrome/browser/ash/telemetry_extension/routines/routine_converters.cc
@@ -45,9 +45,38 @@ return crosapi::TelemetryDiagnosticRoutineStateInitialized::New(); } +crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetailPtr +UncheckedConvertPtr(healthd::NetworkBandwidthRoutineDetailPtr input) { + auto detail = + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetail::New(); + detail->download_speed_kbps = input->download_speed_kbps; + detail->upload_speed_kbps = input->upload_speed_kbps; + return detail; +} + +crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfoPtr +UncheckedConvertPtr(healthd::NetworkBandwidthRoutineRunningInfoPtr input) { + return crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::New( + Convert(input->type), input->speed_kbps); +} + +crosapi::TelemetryDiagnosticRoutineRunningInfoPtr UncheckedConvertPtr( + healthd::RoutineRunningInfoPtr input) { + switch (input->which()) { + case healthd::RoutineRunningInfo::Tag::kUnrecognizedArgument: + return crosapi::TelemetryDiagnosticRoutineRunningInfo:: + NewUnrecognizedArgument(input->get_unrecognizedArgument()); + case healthd::RoutineRunningInfo::Tag::kNetworkBandwidth: + return crosapi::TelemetryDiagnosticRoutineRunningInfo:: + NewNetworkBandwidth( + ConvertRoutinePtr(std::move(input->get_network_bandwidth()))); + } +} + crosapi::TelemetryDiagnosticRoutineStateRunningPtr UncheckedConvertPtr( healthd::RoutineStateRunningPtr input) { - return crosapi::TelemetryDiagnosticRoutineStateRunning::New(); + return crosapi::TelemetryDiagnosticRoutineStateRunning::New( + ConvertRoutinePtr(std::move(input->info))); } crosapi::TelemetryDiagnosticCheckLedLitUpStateInquiryPtr UncheckedConvertPtr( @@ -100,6 +129,9 @@ case healthd::RoutineDetail::Tag::kFan: return crosapi::TelemetryDiagnosticRoutineDetail::NewFan( ConvertRoutinePtr(std::move(input->get_fan()))); + case healthd::RoutineDetail::Tag::kNetworkBandwidth: + return crosapi::TelemetryDiagnosticRoutineDetail::NewNetworkBandwidth( + ConvertRoutinePtr(std::move(input->get_network_bandwidth()))); // The following routines have not been added to crosapi yet. case healthd::RoutineDetail::Tag::kAudioDriver: case healthd::RoutineDetail::Tag::kUfsLifetime: @@ -108,7 +140,6 @@ case healthd::RoutineDetail::Tag::kBluetoothScanning: case healthd::RoutineDetail::Tag::kBluetoothPairing: case healthd::RoutineDetail::Tag::kCameraAvailability: - case healthd::RoutineDetail::Tag::kNetworkBandwidth: // The actual value of unrecognizedArgument should not be used. Assign an // arbitrary value to it. return crosapi::TelemetryDiagnosticRoutineDetail::NewUnrecognizedArgument( @@ -170,6 +201,9 @@ case crosapi::TelemetryDiagnosticRoutineArgument::Tag::kLedLitUp: return healthd::RoutineArgument::NewLedLitUp( ConvertRoutinePtr(std::move(input->get_led_lit_up()))); + case crosapi::TelemetryDiagnosticRoutineArgument::Tag::kNetworkBandwidth: + return healthd::RoutineArgument::NewNetworkBandwidth( + ConvertRoutinePtr(std::move(input->get_network_bandwidth()))); } } @@ -221,6 +255,11 @@ return arg; } +healthd::NetworkBandwidthRoutineArgumentPtr UncheckedConvertPtr( + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineArgumentPtr input) { + return healthd::NetworkBandwidthRoutineArgument::New(); +} + healthd::RoutineInquiryReplyPtr UncheckedConvertPtr( crosapi::TelemetryDiagnosticRoutineInquiryReplyPtr input) { switch (input->which()) { @@ -374,4 +413,20 @@ NOTREACHED_NORETURN(); } +crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type Convert( + healthd::NetworkBandwidthRoutineRunningInfo::Type input) { + switch (input) { + case healthd::NetworkBandwidthRoutineRunningInfo::Type::kUnmappedEnumField: + return crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo:: + Type::kUnmappedEnumField; + case healthd::NetworkBandwidthRoutineRunningInfo::Type::kDownload: + return crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo:: + Type::kDownload; + case healthd::NetworkBandwidthRoutineRunningInfo::Type::kUpload: + return crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo:: + Type::kUpload; + } + NOTREACHED_NORETURN(); +} + } // namespace ash::converters
diff --git a/chrome/browser/ash/telemetry_extension/routines/routine_converters.h b/chrome/browser/ash/telemetry_extension/routines/routine_converters.h index a52d13c..06872a1 100644 --- a/chrome/browser/ash/telemetry_extension/routines/routine_converters.h +++ b/chrome/browser/ash/telemetry_extension/routines/routine_converters.h
@@ -30,9 +30,20 @@ crosapi::mojom::TelemetryDiagnosticFanRoutineDetailPtr UncheckedConvertPtr( cros_healthd::mojom::FanRoutineDetailPtr input); +crosapi::mojom::TelemetryDiagnosticNetworkBandwidthRoutineDetailPtr +UncheckedConvertPtr( + cros_healthd::mojom::NetworkBandwidthRoutineDetailPtr input); + crosapi::mojom::TelemetryDiagnosticRoutineStateInitializedPtr UncheckedConvertPtr(cros_healthd::mojom::RoutineStateInitializedPtr input); +crosapi::mojom::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfoPtr +UncheckedConvertPtr( + cros_healthd::mojom::NetworkBandwidthRoutineRunningInfoPtr input); + +crosapi::mojom::TelemetryDiagnosticRoutineRunningInfoPtr UncheckedConvertPtr( + cros_healthd::mojom::RoutineRunningInfoPtr input); + crosapi::mojom::TelemetryDiagnosticRoutineStateRunningPtr UncheckedConvertPtr( cros_healthd::mojom::RoutineStateRunningPtr input); @@ -81,6 +92,10 @@ cros_healthd::mojom::RoutineInquiryReplyPtr UncheckedConvertPtr( crosapi::mojom::TelemetryDiagnosticRoutineInquiryReplyPtr input); +cros_healthd::mojom::NetworkBandwidthRoutineArgumentPtr UncheckedConvertPtr( + crosapi::mojom::TelemetryDiagnosticNetworkBandwidthRoutineArgumentPtr + input); + } // namespace unchecked cros_healthd::mojom::LedName Convert( @@ -101,6 +116,9 @@ crosapi::mojom::TelemetryDiagnosticRoutineStateWaiting::Reason Convert( cros_healthd::mojom::RoutineStateWaiting::Reason input); +crosapi::mojom::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type +Convert(cros_healthd::mojom::NetworkBandwidthRoutineRunningInfo::Type input); + template <class InputT, class OutputT = decltype(Convert(std::declval<InputT>())), class = std::enable_if_t<std::is_enum_v<InputT>, bool>>
diff --git a/chrome/browser/ash/telemetry_extension/routines/routine_converters_unittest.cc b/chrome/browser/ash/telemetry_extension/routines/routine_converters_unittest.cc index f14ebf1b..3133e009 100644 --- a/chrome/browser/ash/telemetry_extension/routines/routine_converters_unittest.cc +++ b/chrome/browser/ash/telemetry_extension/routines/routine_converters_unittest.cc
@@ -95,6 +95,16 @@ } TEST(TelemetryDiagnosticRoutineConvertersTest, + ConvertNetworkBandwidthRoutineArgumentPtr) { + auto input = + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineArgument::New(); + + auto result = ConvertRoutinePtr(std::move(input)); + + ASSERT_TRUE(result); +} + +TEST(TelemetryDiagnosticRoutineConvertersTest, ConvertUnrecognizedRoutineInquiryReplyPtr) { auto input = crosapi::TelemetryDiagnosticRoutineInquiryReply::NewUnrecognizedReply( @@ -349,6 +359,19 @@ } TEST(TelemetryDiagnosticRoutineConvertersTest, + ConvertTelemetryDiagnosticNetworkBandwidthRoutineDetailPtr) { + auto input = healthd::NetworkBandwidthRoutineDetail::New(); + input->download_speed_kbps = 123.0; + input->upload_speed_kbps = 456.0; + + auto result = ConvertRoutinePtr(std::move(input)); + + ASSERT_TRUE(result); + EXPECT_EQ(result->download_speed_kbps, 123.0); + EXPECT_EQ(result->upload_speed_kbps, 456.0); +} + +TEST(TelemetryDiagnosticRoutineConvertersTest, ConvertTelemetryDiagnosticRoutineDetailPtr) { EXPECT_EQ( ConvertRoutinePtr(healthd::RoutineDetail::NewUnrecognizedArgument(true)), @@ -363,6 +386,12 @@ healthd::FanRoutineDetail::New())), crosapi::TelemetryDiagnosticRoutineDetail::NewFan( crosapi::TelemetryDiagnosticFanRoutineDetail::New())); + + EXPECT_EQ( + ConvertRoutinePtr(healthd::RoutineDetail::NewNetworkBandwidth( + healthd::NetworkBandwidthRoutineDetail::New())), + crosapi::TelemetryDiagnosticRoutineDetail::NewNetworkBandwidth( + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetail::New())); } TEST(TelemetryDiagnosticRoutineConvertersTest, @@ -432,4 +461,34 @@ crosapi::TelemetryDiagnosticRoutineStateRunning::New())); } +TEST(TelemetryDiagnosticRoutineConvertersTest, + ConvertTelemetryDiagnosticRoutineRunningInfoPtr) { + EXPECT_EQ( + ConvertRoutinePtr( + healthd::RoutineRunningInfo::NewUnrecognizedArgument(true)), + crosapi::TelemetryDiagnosticRoutineRunningInfo::NewUnrecognizedArgument( + true)); + + EXPECT_EQ(ConvertRoutinePtr(healthd::RoutineRunningInfo::NewNetworkBandwidth( + healthd::NetworkBandwidthRoutineRunningInfo::New())), + crosapi::TelemetryDiagnosticRoutineRunningInfo::NewNetworkBandwidth( + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo:: + New())); +} + +TEST(TelemetryDiagnosticRoutineConvertersTest, + ConvertTelemetryDiagnosticNetworkBandwidthRoutineRunningInfoPtr) { + auto input = healthd::NetworkBandwidthRoutineRunningInfo::New(); + input->type = healthd::NetworkBandwidthRoutineRunningInfo::Type::kDownload; + input->speed_kbps = 100.0; + + auto result = ConvertRoutinePtr(std::move(input)); + + ASSERT_TRUE(result); + EXPECT_EQ(result->type, + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo:: + Type::kDownload); + EXPECT_EQ(result->speed_kbps, 100.0); +} + } // namespace ash::converters
diff --git a/chrome/browser/attribution_reporting/chrome_attribution_browsertest.cc b/chrome/browser/attribution_reporting/chrome_attribution_browsertest.cc index 54cc580..0fdfeea 100644 --- a/chrome/browser/attribution_reporting/chrome_attribution_browsertest.cc +++ b/chrome/browser/attribution_reporting/chrome_attribution_browsertest.cc
@@ -247,8 +247,9 @@ proto, base::Version("1.2.3"))); } +// TODO(crbug.com/327794975) Test is flaky on various platforms. IN_PROC_BROWSER_TEST_F(ChromeAttributionAttestationsBrowserTest, - AttribtionUponAttestationsLoading) { + DISABLED_AttribtionUponAttestationsLoading) { PrivacySandboxSettingsFactory::GetForProfile(browser()->profile()) ->SetAllPrivacySandboxAllowedForTesting();
diff --git a/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc b/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc index 30d20a2..988aefe 100644 --- a/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc +++ b/chrome/browser/autofill/android/save_update_address_profile_prompt_controller.cc
@@ -103,7 +103,7 @@ // TODO(crbug.com/40066949): Simplify once ConsentLevel::kSync is not used // anymore, and thus IsSyncFeatureEnabledForAutofill() will always be false. return l10n_util::GetStringFUTF16( - personal_data_->IsSyncFeatureEnabledForAutofill() + personal_data_->address_data_manager().IsSyncFeatureEnabledForAutofill() ? IDS_AUTOFILL_SYNCABLE_PROFILE_MIGRATION_PROMPT_NOTICE : IDS_AUTOFILL_LOCAL_PROFILE_MIGRATION_PROMPT_NOTICE, base::UTF8ToUTF16(account->email));
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h index 3a47bd3..57ae21c 100644 --- a/chrome/browser/browser_features.h +++ b/chrome/browser/browser_features.h
@@ -97,6 +97,12 @@ kNewTabPagePreconnectStartDelayOnMouseHoverByMiliSeconds{ &features::kNewTabPageTriggerForPrerender2, "preconnect_start_delay_on_mouse_hover_ms", 100}; +const base::FeatureParam<bool> kPrerenderNewTabPageOnMousePressedTrigger{ + &features::kNewTabPageTriggerForPrerender2, + "prerender_new_tab_page_on_mouse_pressed_trigger", false}; +const base::FeatureParam<bool> kPrerenderNewTabPageOnMouseHoverTrigger{ + &features::kNewTabPageTriggerForPrerender2, + "prerender_new_tab_page_on_mouse_hover_trigger", false}; #if BUILDFLAG(IS_WIN) BASE_DECLARE_FEATURE(kNoPreReadMainDll);
diff --git a/chrome/browser/chrome_navigation_browsertest.cc b/chrome/browser/chrome_navigation_browsertest.cc index d7af1d5c..53cc74d 100644 --- a/chrome/browser/chrome_navigation_browsertest.cc +++ b/chrome/browser/chrome_navigation_browsertest.cc
@@ -1996,8 +1996,9 @@ // Tests that a main frame hosting pdf does not get skipped because of history // manipulation intervention if there was a user gesture. +// TODO(crbug.com/333829580): Final navigation is flaky on all platforms. IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest, - PDFDoNotSkipOnBackForwardDueToUserGesture) { + DISABLED_PDFDoNotSkipOnBackForwardDueToUserGesture) { GURL pdf_url(embedded_test_server()->GetURL("/pdf/test.pdf")); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), pdf_url));
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api.cc b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api.cc index 61f3c88..35b06846 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/notreached.h" #include "base/time/time.h" @@ -23,6 +24,7 @@ #include "chromeos/crosapi/mojom/nullable_primitives.mojom.h" #include "chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom.h" #include "chromeos/crosapi/mojom/telemetry_extension_exception.mojom.h" +#include "extensions/common/extension_features.h" #include "extensions/common/permissions/permissions_data.h" #if BUILDFLAG(IS_CHROMEOS_LACROS) @@ -61,6 +63,11 @@ NOTREACHED_NORETURN(); } +bool IsPendingApprovalRoutine( + const crosapi::mojom::TelemetryDiagnosticRoutineArgumentPtr& arg) { + return arg->is_network_bandwidth(); +} + } // namespace // DiagnosticsApiFunctionV1AndV2Base ------------------------------------------- @@ -518,6 +525,14 @@ return; } + // Block unreleased features behind the feature flag. + if (IsPendingApprovalRoutine(mojo_arg.value()) && + !base::FeatureList::IsEnabled( + extensions_features::kTelemetryExtensionPendingApprovalApi)) { + mojo_arg = crosapi::mojom::TelemetryDiagnosticRoutineArgument:: + NewUnrecognizedArgument(false); + } + auto* routines_manager = DiagnosticRoutineManager::Get(browser_context()); auto result = routines_manager->CreateRoutine(extension_id(), std::move(mojo_arg.value())); @@ -724,6 +739,14 @@ return; } + // Block unreleased features behind the feature flag. + if (IsPendingApprovalRoutine(mojo_arg.value()) && + !base::FeatureList::IsEnabled( + extensions_features::kTelemetryExtensionPendingApprovalApi)) { + mojo_arg = crosapi::mojom::TelemetryDiagnosticRoutineArgument:: + NewUnrecognizedArgument(false); + } + auto* routines_manager = DiagnosticRoutineManager::Get(browser_context()); routines_manager->IsRoutineArgumentSupported( std::move(mojo_arg.value()),
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_converters.cc b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_converters.cc index ecbf97b..be164b0 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_converters.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_converters.cc
@@ -66,6 +66,14 @@ return true; } +bool PopulateNetworkBandwidthRoutineArguments( + const cx_diag::CreateNetworkBandwidthRoutineArguments& cx_args, + crosapi::TelemetryDiagnosticRoutineArgumentPtr& out) { + out = crosapi::TelemetryDiagnosticRoutineArgument::NewNetworkBandwidth( + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineArgument::New()); + return true; +} + } // namespace bool ConvertMojoRoutine(crosapi::DiagnosticsRoutineEnum in, @@ -311,6 +319,12 @@ return std::nullopt; } } + if (extension_union.network_bandwidth) { + if (result || !PopulateNetworkBandwidthRoutineArguments( + extension_union.network_bandwidth.value(), result)) { + return std::nullopt; + } + } if (result) { return result; }
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_v2_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_v2_browsertest.cc index 54d5931..42d9dd7 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_v2_browsertest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics/diagnostics_api_v2_browsertest.cc
@@ -15,6 +15,7 @@ #include "chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom.h" #include "chromeos/crosapi/mojom/telemetry_extension_exception.mojom.h" #include "content/public/test/browser_test.h" +#include "extensions/common/extension_features.h" #include "testing/gtest/include/gtest/gtest.h" #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -1110,4 +1111,117 @@ )"); } +IN_PROC_BROWSER_TEST_F( + TelemetryExtensionDiagnosticsApiV2BrowserTest, + CreateNetworkBandwidthRoutineWithoutFeatureFlagUnrecognized) { + fake_service().SetOnCreateRoutineCalled(base::BindLambdaForTesting([this]() { + auto* control = fake_service().GetCreatedRoutineControlForRoutineType( + crosapi::TelemetryDiagnosticRoutineArgument::Tag:: + kUnrecognizedArgument); + ASSERT_TRUE(control); + })); + + OpenAppUiAndMakeItSecure(); + + CreateExtensionAndRunServiceWorker(R"( + chrome.test.runTests([ + async function createNetworkBandwidthRoutineUnrecognized() { + const result = await chrome.os.diagnostics.createRoutine({ + networkBandwidth: {}, + }); + + chrome.test.assertTrue(result !== undefined); + chrome.test.succeed(); + } + ]); + + )"); +} + +class PendingApprovalTelemetryExtensionDiagnosticsApiV2BrowserTest + : public TelemetryExtensionDiagnosticsApiV2BrowserTest { + public: + PendingApprovalTelemetryExtensionDiagnosticsApiV2BrowserTest() { + feature_list_.InitAndEnableFeature( + extensions_features::kTelemetryExtensionPendingApprovalApi); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F( + PendingApprovalTelemetryExtensionDiagnosticsApiV2BrowserTest, + CreateNetworkBandwidthRoutineWithFeatureFlagSuccess) { + fake_service().SetOnCreateRoutineCalled(base::BindLambdaForTesting([this]() { + auto* control = fake_service().GetCreatedRoutineControlForRoutineType( + crosapi::TelemetryDiagnosticRoutineArgument::Tag::kNetworkBandwidth); + ASSERT_TRUE(control); + + auto network_bandwidth_detail = + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetail::New(); + network_bandwidth_detail->download_speed_kbps = 123.0; + network_bandwidth_detail->upload_speed_kbps = 456.0; + + auto finished_state = + crosapi::TelemetryDiagnosticRoutineStateFinished::New(); + finished_state->detail = + crosapi::TelemetryDiagnosticRoutineDetail::NewNetworkBandwidth( + std::move(network_bandwidth_detail)); + finished_state->has_passed = true; + + auto state = crosapi::TelemetryDiagnosticRoutineState::New(); + state->state_union = + crosapi::TelemetryDiagnosticRoutineStateUnion::NewFinished( + std::move(finished_state)); + + control->SetState(std::move(state)); + })); + + OpenAppUiAndMakeItSecure(); + + CreateExtensionAndRunServiceWorker(R"( + chrome.test.runTests([ + async function createNetworkBandwidthRoutine() { + let resolver; + // Set later once the routine was created. + var uuid = new Promise((resolve) => { + resolver = resolve; + }); + + + let onInitCalled = false; + chrome.os.diagnostics.onRoutineInitialized.addListener( + async (status) => { + chrome.test.assertEq(status.uuid, await uuid); + onInitCalled = true; + }); + + // Only resolve the test once we got the final event. + chrome.os.diagnostics.onRoutineFinished.addListener( + async (status) => { + chrome.test.assertEq(status, { + "detail": { + "networkBandwidth": { + "downloadSpeedKbps": 123.0, + "uploadSpeedKbps": 456.0 + } + }, + "hasPassed": true, + "uuid": await uuid + }); + chrome.test.assertTrue(onInitCalled); + chrome.test.succeed(); + }); + + const response = await chrome.os.diagnostics.createRoutine({ + networkBandwidth: {}, + }); + chrome.test.assertTrue(response !== undefined); + resolver(response.uuid); + } + ]); + )"); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.cc b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.cc index 58c9103e..23b91c2 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.cc
@@ -39,6 +39,29 @@ case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kFan: detail.fan = ConvertPtr(std::move(input->get_fan())); return detail; + case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kNetworkBandwidth: + detail.network_bandwidth = + ConvertPtr(std::move(input->get_network_bandwidth())); + return detail; + } +} + +std::optional<cx_diag::RoutineRunningInfoUnion> +ConvertRoutineRunningInfoUnionPtr( + crosapi::TelemetryDiagnosticRoutineRunningInfoPtr input) { + if (input.is_null()) { + return std::nullopt; + } + cx_diag::RoutineRunningInfoUnion info; + switch (input->which()) { + case crosapi::TelemetryDiagnosticRoutineRunningInfo::Tag:: + kUnrecognizedArgument: + LOG(WARNING) << "Got unknown routine running info"; + return std::nullopt; + case crosapi::TelemetryDiagnosticRoutineRunningInfo::Tag::kNetworkBandwidth: + info.network_bandwidth = + ConvertPtr(std::move(input->get_network_bandwidth())); + return info; } } @@ -61,9 +84,18 @@ cx_diag::RoutineRunningInfo result; result.uuid = uuid.AsLowercaseString(); result.percentage = percentage; + result.info = ConvertRoutineRunningInfoUnionPtr(std::move(input->info)); return result; } +cx_diag::NetworkBandwidthRoutineRunningInfo UncheckedConvertPtr( + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfoPtr input) { + cx_diag::NetworkBandwidthRoutineRunningInfo info; + info.type = Convert(input->type); + info.speed_kbps = input->speed_kbps; + return info; +} + cx_diag::RoutineWaitingInfo UncheckedConvertPtr( crosapi::TelemetryDiagnosticRoutineStateWaitingPtr input, base::Uuid uuid, @@ -162,6 +194,14 @@ return result; } +cx_diag::NetworkBandwidthRoutineFinishedDetail UncheckedConvertPtr( + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetailPtr input) { + cx_diag::NetworkBandwidthRoutineFinishedDetail result; + result.download_speed_kbps = input->download_speed_kbps; + result.upload_speed_kbps = input->upload_speed_kbps; + return result; +} + cx_diag::RoutineFinishedInfo UncheckedConvertPtr( crosapi::TelemetryDiagnosticRoutineStateFinishedPtr input, base::Uuid uuid, @@ -270,4 +310,21 @@ NOTREACHED_NORETURN(); } +cx_diag::NetworkBandwidthRoutineRunningType Convert( + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type + input) { + switch (input) { + case crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type:: + kUnmappedEnumField: + return cx_diag::NetworkBandwidthRoutineRunningType::kNone; + case crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type:: + kDownload: + return cx_diag::NetworkBandwidthRoutineRunningType::kDownload; + case crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type:: + kUpload: + return cx_diag::NetworkBandwidthRoutineRunningType::kUpload; + } + NOTREACHED_NORETURN(); +} + } // namespace chromeos::converters::routines
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.h b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.h index b06aa91..49b58634 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.h +++ b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.h
@@ -32,6 +32,10 @@ base::Uuid uuid, uint32_t percentage); +api::os_diagnostics::NetworkBandwidthRoutineRunningInfo UncheckedConvertPtr( + crosapi::mojom::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfoPtr + input); + api::os_diagnostics::RoutineWaitingInfo UncheckedConvertPtr( crosapi::mojom::TelemetryDiagnosticRoutineStateWaitingPtr input, base::Uuid uuid, @@ -67,6 +71,9 @@ api::os_diagnostics::FanRoutineFinishedDetail UncheckedConvertPtr( crosapi::mojom::TelemetryDiagnosticFanRoutineDetailPtr input); +api::os_diagnostics::NetworkBandwidthRoutineFinishedDetail UncheckedConvertPtr( + crosapi::mojom::TelemetryDiagnosticNetworkBandwidthRoutineDetailPtr input); + api::os_diagnostics::RoutineFinishedInfo UncheckedConvertPtr( crosapi::mojom::TelemetryDiagnosticRoutineStateFinishedPtr input, base::Uuid uuid, @@ -86,6 +93,10 @@ api::os_diagnostics::HardwarePresenceStatus Convert( crosapi::mojom::TelemetryDiagnosticHardwarePresenceStatus input); +api::os_diagnostics::NetworkBandwidthRoutineRunningType Convert( + crosapi::mojom::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type + input); + template <class InputT, class OutputT = decltype(Convert(std::declval<InputT>())), class = std::enable_if_t<std::is_enum_v<InputT> ||
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters_unittest.cc b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters_unittest.cc index ad89b18..685e123 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters_unittest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters_unittest.cc
@@ -44,6 +44,40 @@ ASSERT_TRUE(result.percentage.has_value()); EXPECT_EQ(static_cast<uint32_t>(*result.percentage), kPercentage); + + EXPECT_FALSE(result.info.has_value()); +} + +TEST(TelemetryExtensionDiagnosticRoutineConvertersTest, + NetworkBandwidthRoutineRunningInfo) { + const base::Uuid kUuid = base::Uuid::GenerateRandomV4(); + constexpr uint32_t kPercentage = 50; + + auto running_info = + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::New(); + running_info->type = crosapi:: + TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type::kDownload; + running_info->speed_kbps = 100.0; + + auto input = crosapi::TelemetryDiagnosticRoutineStateRunning::New(); + input->info = + crosapi::TelemetryDiagnosticRoutineRunningInfo::NewNetworkBandwidth( + std::move(running_info)); + + auto result = ConvertPtr(std::move(input), kUuid, kPercentage); + + ASSERT_TRUE(result.uuid.has_value()); + EXPECT_EQ(*result.uuid, kUuid.AsLowercaseString()); + + ASSERT_TRUE(result.percentage.has_value()); + EXPECT_EQ(static_cast<uint32_t>(*result.percentage), kPercentage); + + ASSERT_TRUE(result.info.has_value()); + ASSERT_TRUE(result.info->network_bandwidth.has_value()); + + EXPECT_EQ(result.info->network_bandwidth->type, + cx_diag::NetworkBandwidthRoutineRunningType::kDownload); + EXPECT_EQ(result.info->network_bandwidth->speed_kbps, 100.0); } TEST(TelemetryExtensionDiagnosticRoutineConvertersTest, RoutineWaitingInfo) { @@ -308,6 +342,36 @@ cx_diag::HardwarePresenceStatus::kMatched); } +TEST(TelemetryExtensionDiagnosticRoutineConvertersTest, + RoutineFinishedInfoWithNetworkBandwidthDetail) { + constexpr bool kHasPassed = true; + const base::Uuid kUuid = base::Uuid::GenerateRandomV4(); + + auto detail = + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetail::New(); + detail->download_speed_kbps = 123.0; + detail->upload_speed_kbps = 456.0; + + auto input = crosapi::TelemetryDiagnosticRoutineStateFinished::New(); + input->detail = + crosapi::TelemetryDiagnosticRoutineDetail::NewNetworkBandwidth( + std::move(detail)); + + auto result = ConvertPtr(std::move(input), kUuid, kHasPassed); + + ASSERT_TRUE(result.uuid.has_value()); + EXPECT_EQ(*result.uuid, kUuid.AsLowercaseString()); + + ASSERT_TRUE(result.has_passed.has_value()); + EXPECT_EQ(*result.has_passed, kHasPassed); + + ASSERT_TRUE(result.detail.has_value()); + ASSERT_TRUE(result.detail->network_bandwidth.has_value()); + + EXPECT_EQ(result.detail->network_bandwidth->download_speed_kbps, 123.0); + EXPECT_EQ(result.detail->network_bandwidth->upload_speed_kbps, 456.0); +} + TEST(TelemetryExtensionDiagnosticRoutineConvertersTest, ExceptionReason) { EXPECT_EQ( Convert(crosapi::TelemetryExtensionException::Reason::kUnmappedEnumField),
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation.cc b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation.cc index 6edac1cd..cc5f5941 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation.cc
@@ -80,6 +80,9 @@ cx_diag::OnFanRoutineFinished::kEventName, base::Value::List().Append(finished_info.ToValue()), browser_context); } + case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kNetworkBandwidth: + // No need to support legacy finished events for newer routines. + return nullptr; } NOTREACHED_NORETURN(); }
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation_browsertest.cc index 96574b0f..a92a5ec 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation_browsertest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_observation_browsertest.cc
@@ -185,6 +185,58 @@ } IN_PROC_BROWSER_TEST_F(TelemetryExtensionDiagnosticRoutineObserverBrowserTest, + CanObserveOnRoutineRunningWithNetworkBandwidthInfo) { + SetRoutineObservation(); + RegisterEventObserver( + api::os_diagnostics::OnRoutineRunning::kEventName, + base::BindLambdaForTesting([this] { + auto network_bandwidth_info = crosapi:: + TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::New(); + network_bandwidth_info->type = + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo:: + Type::kDownload; + network_bandwidth_info->speed_kbps = 100.0; + + auto running_state = + crosapi::TelemetryDiagnosticRoutineStateRunning::New(); + running_state->info = + crosapi::TelemetryDiagnosticRoutineRunningInfo::NewNetworkBandwidth( + std::move(network_bandwidth_info)); + + auto state = crosapi::TelemetryDiagnosticRoutineState::New(); + state->state_union = + crosapi::TelemetryDiagnosticRoutineStateUnion::NewRunning( + std::move(running_state)); + state->percentage = 50; + + remote_->OnRoutineStateChange(std::move(state)); + })); + + CreateExtensionAndRunServiceWorker( + base::StringPrintf(R"( + chrome.test.runTests([ + async function canObserveOnRoutineRunningWithNetworkBandwidthInfo() { + chrome.os.diagnostics.onRoutineRunning.addListener((event) => { + chrome.test.assertEq(event, { + info: { + "networkBandwidth": { + "speedKbps": 100.0, + "type": "download", + } + }, + percentage: 50, + uuid:"%s", + }); + + chrome.test.succeed(); + }); + } + ]); + )", + uuid_.AsLowercaseString().c_str())); +} + +IN_PROC_BROWSER_TEST_F(TelemetryExtensionDiagnosticRoutineObserverBrowserTest, CanObserveOnRoutineWaiting) { SetRoutineObservation(); RegisterEventObserver( @@ -609,4 +661,59 @@ EXPECT_EQ(info.uuid, uuid_); } +IN_PROC_BROWSER_TEST_F(TelemetryExtensionDiagnosticRoutineObserverBrowserTest, + CanObserveOnRoutineFinishedWithNetworkBandwidthDetail) { + SetRoutineObservation(); + RegisterEventObserver( + api::os_diagnostics::OnRoutineFinished::kEventName, + base::BindLambdaForTesting([this] { + auto network_bandwidth_detail = + crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetail::New(); + network_bandwidth_detail->download_speed_kbps = 123.0; + network_bandwidth_detail->upload_speed_kbps = 456.0; + + auto finished_state = + crosapi::TelemetryDiagnosticRoutineStateFinished::New(); + finished_state->detail = + crosapi::TelemetryDiagnosticRoutineDetail::NewNetworkBandwidth( + std::move(network_bandwidth_detail)); + finished_state->has_passed = true; + + auto state = crosapi::TelemetryDiagnosticRoutineState::New(); + state->state_union = + crosapi::TelemetryDiagnosticRoutineStateUnion::NewFinished( + std::move(finished_state)); + state->percentage = 100; + + remote_->OnRoutineStateChange(std::move(state)); + })); + + CreateExtensionAndRunServiceWorker( + base::StringPrintf(R"( + chrome.test.runTests([ + async function canObserveOnRoutineFinishedWithNetworkBandwidthDetail() { + chrome.os.diagnostics.onRoutineFinished.addListener((event) => { + chrome.test.assertEq(event, { + "detail": { + "networkBandwidth": { + "downloadSpeedKbps": 123.0, + "uploadSpeedKbps": 456.0 + } + }, + "hasPassed": true, + "uuid":"%s" + }); + + chrome.test.succeed(); + }); + } + ]); + )", + uuid_.AsLowercaseString().c_str())); + + auto info = WaitForFinishedReport(); + EXPECT_EQ(info.extension_id, extension_id()); + EXPECT_EQ(info.uuid, uuid_); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc index 3cb43e7..2a56e7f 100644 --- a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc +++ b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc
@@ -14,6 +14,7 @@ #include "base/functional/bind.h" #include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" +#include "base/strings/utf_string_conversions.h" #include "base/unguessable_token.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/chromeos/mahi/mahi_browser_client_impl.h" @@ -66,23 +67,31 @@ void MahiWebContentsManager::OnFocusedPageLoadComplete( content::WebContents* web_contents) { - // Creates a new focused web content state, and fires `OnFocusedPageChanged()` - // event immediately so that `MahiManager` knows the focused page has changed. - focused_web_content_state_ = WebContentState( - web_contents->GetLastCommittedURL(), web_contents->GetTitle()); - focused_web_content_state_.favicon = GetFavicon(web_contents); + // Page info may not be properly updated yet if the user forwards/backwards + // the tab through cache. Thus, if focused page's URL does not change, we + // don't create a new `focused_web_content_state_` here, and instead rely on + // the callback of `RequestAXTreeSnapshot` to update if needed. + if (web_contents->GetLastCommittedURL() != focused_web_content_state_.url) { + // Creates a new focused web content state, and fires + // `OnFocusedPageChanged()` + // event immediately so that `MahiManager` knows the focused page has + // changed. + focused_web_content_state_ = WebContentState( + web_contents->GetLastCommittedURL(), web_contents->GetTitle()); + focused_web_content_state_.favicon = GetFavicon(web_contents); - // If the page is in the skip list, sets its distillability to false and - // notifies `MahiManager` immediately without requesting the snapshot. - if (ShouldSkip(web_contents)) { - focused_web_content_state_.is_distillable.emplace(false); + // If the page is in the skip list, sets its distillability to false and + // notifies `MahiManager` immediately without requesting the snapshot. + if (ShouldSkip(web_contents)) { + focused_web_content_state_.is_distillable.emplace(false); + client_->OnFocusedPageChanged(focused_web_content_state_); + return; + } + + // Notifies `MahiManger` the focused page has changed. client_->OnFocusedPageChanged(focused_web_content_state_); - return; } - // Notifies `MahiManger` the focused page has changed. - client_->OnFocusedPageChanged(focused_web_content_state_); - // Requests the a11y tree snapshot. content::RenderFrameHost* render_frame_host = web_contents->GetPrimaryMainFrame(); @@ -93,7 +102,7 @@ web_contents->RequestAXTreeSnapshot( base::BindOnce(&MahiWebContentsManager::OnGetSnapshot, weak_pointer_factory_.GetWeakPtr(), - focused_web_content_state_.page_id), + focused_web_content_state_.page_id, web_contents), ui::kAXModeWebContentsOnly, /* max_nodes= */ 5000, /* timeout= */ {}); } @@ -154,9 +163,24 @@ void MahiWebContentsManager::OnGetSnapshot( const base::UnguessableToken& page_id, + content::WebContents* web_contents, const ui::AXTreeUpdate& snapshot) { // Updates states and checks the distillability of the snapshot. if (page_id == focused_web_content_state_.page_id) { + // If the acquired url does not match the one within the snapshot, updates + // `focused_web_content_state_` to ensure they match. + if (focused_web_content_state_.url != GURL(snapshot.tree_data.url)) { + focused_web_content_state_ = + WebContentState(GURL(snapshot.tree_data.url), + base::UTF8ToUTF16(snapshot.tree_data.title)); + // Attempts to update the favicon if the url of the focused web contents + // have updated. + if (web_contents && web_contents->GetLastCommittedURL() == + focused_web_content_state_.url) { + focused_web_content_state_.favicon = GetFavicon(web_contents); + } + } + focused_web_content_state_.snapshot = snapshot; content_extraction_delegate_->CheckDistillablity( focused_web_content_state_);
diff --git a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h index 6a82ce12..aaf7e0a 100644 --- a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h +++ b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h
@@ -85,6 +85,7 @@ virtual ~MahiWebContentsManager(); void OnGetSnapshot(const base::UnguessableToken& page_id, + content::WebContents* web_contents, const ui::AXTreeUpdate& snapshot); void OnFinishDistillableCheck(const base::UnguessableToken& page_id,
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_util.cc b/chrome/browser/extensions/api/autofill_private/autofill_util.cc index 23af950..00a3673 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_util.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_util.cc
@@ -260,12 +260,12 @@ api::autofill_private::AccountInfo api_account; api_account.email = account->email; api_account.is_sync_enabled_for_autofill_profiles = - personal_data.IsSyncFeatureEnabledForAutofill(); + personal_data.address_data_manager().IsSyncFeatureEnabledForAutofill(); api_account.is_eligible_for_address_account_storage = personal_data.address_data_manager().IsEligibleForAddressAccountStorage(); api_account.is_autofill_sync_toggle_enabled = - personal_data.IsUserSelectableTypeEnabled( - syncer::UserSelectableType::kAutofill); + personal_data.address_data_manager() + .IsAutofillUserSelectableTypeEnabled(); api_account.is_autofill_sync_toggle_available = personal_data.IsAutofillSyncToggleAvailable(); return std::move(api_account);
diff --git a/chrome/browser/lacros/browser_service_lacros.cc b/chrome/browser/lacros/browser_service_lacros.cc index f5291be..778bc28 100644 --- a/chrome/browser/lacros/browser_service_lacros.cc +++ b/chrome/browser/lacros/browser_service_lacros.cc
@@ -195,7 +195,7 @@ BrowserList::RemoveObserver(this); } -void BrowserServiceLacros::REMOVED_0(REMOVED_0Callback callback) { +void BrowserServiceLacros::REMOVED_0() { NOTIMPLEMENTED(); }
diff --git a/chrome/browser/lacros/browser_service_lacros.h b/chrome/browser/lacros/browser_service_lacros.h index bb3e7b8..6d3afb3 100644 --- a/chrome/browser/lacros/browser_service_lacros.h +++ b/chrome/browser/lacros/browser_service_lacros.h
@@ -31,7 +31,7 @@ ~BrowserServiceLacros() override; // crosapi::mojom::BrowserService: - void REMOVED_0(REMOVED_0Callback callback) override; + void REMOVED_0() override; void REMOVED_2(crosapi::mojom::BrowserInitParamsPtr) override; void REMOVED_7(bool should_trigger_session_restore, base::OnceClosure callback) override;
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc index 9116b96..60ec289 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h" +#include <string_view> #include <utility> #include "base/base64url.h" @@ -12,7 +13,6 @@ #include "base/json/values_util.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "chrome/browser/nearby_sharing/certificates/common.h" #include "chrome/browser/nearby_sharing/certificates/constants.h" #include "chrome/browser/nearby_sharing/common/nearby_share_switches.h" @@ -122,7 +122,7 @@ std::set<std::vector<uint8_t>> salts; for (size_t i = 0; i < str.size(); i += chars_per_salt) { std::vector<uint8_t> salt; - base::HexStringToBytes(base::StringPiece(&str[i], chars_per_salt), &salt); + base::HexStringToBytes(std::string_view(&str[i], chars_per_salt), &salt); salts.insert(std::move(salt)); } return salts;
diff --git a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc index eb85cc53..d4d51d0 100644 --- a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc +++ b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.h" #include <sstream> +#include <string_view> #include "base/functional/bind.h" #include "base/functional/callback.h" @@ -260,7 +261,7 @@ } } -void ReceiveMessagesExpress::OnDataReceived(base::StringPiece data, +void ReceiveMessagesExpress::OnDataReceived(std::string_view data, base::OnceClosure resume) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.h b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.h index 46aa76a..548ba79c 100644 --- a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.h +++ b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_NEARBY_SHARING_INSTANTMESSAGING_RECEIVE_MESSAGES_EXPRESS_H_ #include <cstdint> +#include <string_view> #include "base/functional/callback_forward.h" #include "base/memory/scoped_refptr.h" @@ -79,7 +80,7 @@ void OnFastPathReadyTimeout(); // network::SimpleURLLoaderStreamConsumer: - void OnDataReceived(base::StringPiece string_piece, + void OnDataReceived(std::string_view string_piece, base::OnceClosure resume) override; void OnComplete(bool success) override; void OnRetry(base::OnceClosure start_retry) override;
diff --git a/chrome/browser/nearby_sharing/instantmessaging/stream_parser.cc b/chrome/browser/nearby_sharing/instantmessaging/stream_parser.cc index e1ec7d70..b42af2ef 100644 --- a/chrome/browser/nearby_sharing/instantmessaging/stream_parser.cc +++ b/chrome/browser/nearby_sharing/instantmessaging/stream_parser.cc
@@ -4,8 +4,9 @@ #include "chrome/browser/nearby_sharing/instantmessaging/stream_parser.h" +#include <string_view> + #include "base/logging.h" -#include "base/strings/string_piece.h" #include "net/base/io_buffer.h" #include "third_party/protobuf/src/google/protobuf/io/coded_stream.h" #include "third_party/protobuf/src/google/protobuf/wire_format_lite.h" @@ -34,7 +35,7 @@ std::vector< chrome_browser_nearby_sharing_instantmessaging::ReceiveMessagesResponse> -StreamParser::Append(base::StringPiece data) { +StreamParser::Append(std::string_view data) { if (!unparsed_data_buffer_) { unparsed_data_buffer_ = base::MakeRefCounted<net::GrowableIOBuffer>(); unparsed_data_buffer_->SetCapacity(data.size() + kReadBufferSpareCapacity);
diff --git a/chrome/browser/nearby_sharing/instantmessaging/stream_parser.h b/chrome/browser/nearby_sharing/instantmessaging/stream_parser.h index 65baff67..b0327339 100644 --- a/chrome/browser/nearby_sharing/instantmessaging/stream_parser.h +++ b/chrome/browser/nearby_sharing/instantmessaging/stream_parser.h
@@ -6,9 +6,9 @@ #define CHROME_BROWSER_NEARBY_SHARING_INSTANTMESSAGING_STREAM_PARSER_H_ #include <string> +#include <string_view> #include "base/functional/callback.h" -#include "base/strings/string_piece.h" #include "chrome/browser/nearby_sharing/instantmessaging/proto/instantmessaging.pb.h" namespace google { @@ -39,7 +39,7 @@ // empty vector is returned. std::vector< chrome_browser_nearby_sharing_instantmessaging::ReceiveMessagesResponse> - Append(base::StringPiece data); + Append(std::string_view data); private: enum class StreamParsingResult {
diff --git a/chrome/browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc b/chrome/browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc index 8a6f1d4..851eeee4 100644 --- a/chrome/browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc +++ b/chrome/browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc
@@ -6,6 +6,7 @@ #include <algorithm> #include <string> +#include <string_view> #include <vector> #include "base/functional/bind.h" @@ -164,7 +165,7 @@ EXPECT_EQ(0u, responses.size()); char bytes[2] = {0x0f, 0x00}; - auto bytes_string = base::StringPiece(bytes); + auto bytes_string = std::string_view(bytes); EXPECT_EQ(1u, bytes_string.length()); responses = GetStreamParser().Append(bytes); EXPECT_EQ(0u, responses.size());
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc index 1f40ac6..459991c0f 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc
@@ -46,6 +46,9 @@ // Duration of message before timeout; 20 seconds. const int kMessageDismissDurationMs = 20000; +constexpr base::TimeDelta kUpdateGMSCoreMessageDisplayDelay = + base::Milliseconds(500); + // Log the outcome of the save/update password workflow. // It differentiates whether the the flow was accepted/cancelled immediately // or after calling the password edit dialog. @@ -106,17 +109,6 @@ } } -void MaybeNudgeToUpdateGmsCore(ManagePasswordsState& passwords_state) { - if (passwords_state.client() - ->GetPasswordFeatureManager() - ->ShouldUpdateGmsCore()) { - passwords_state.client()->ShowPasswordManagerErrorMessage( - password_manager::ErrorMessageFlowType::kSaveFlow, - password_manager::PasswordStoreBackendErrorType:: - kGMSCoreOutdatedSavingPossible); - } -} - } // namespace SaveUpdatePasswordMessageDelegate::SaveUpdatePasswordMessageDelegate() @@ -378,7 +370,12 @@ void SaveUpdatePasswordMessageDelegate::SavePassword() { if (!device_lock_bridge_->ShouldShowDeviceLockUi()) { passwords_state_.form_manager()->Save(); - MaybeNudgeToUpdateGmsCore(passwords_state_); + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &SaveUpdatePasswordMessageDelegate::MaybeNudgeToUpdateGmsCore, + weak_ptr_factory_.GetWeakPtr()), + kUpdateGMSCoreMessageDisplayDelay); return; } device_lock_bridge_->LaunchDeviceLockUiIfNeededBeforeRunningCallback( @@ -393,7 +390,12 @@ CHECK(device_lock_bridge_->RequiresDeviceLock()); if (is_device_lock_requirement_met) { passwords_state_.form_manager()->Save(); - MaybeNudgeToUpdateGmsCore(passwords_state_); + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &SaveUpdatePasswordMessageDelegate::MaybeNudgeToUpdateGmsCore, + weak_ptr_factory_.GetWeakPtr()), + kUpdateGMSCoreMessageDisplayDelay); TryToShowPasswordMigrationWarning(create_migration_warning_callback_, web_contents_); } @@ -646,3 +648,14 @@ } return ui_dismissal_reason; } + +void SaveUpdatePasswordMessageDelegate::MaybeNudgeToUpdateGmsCore() { + if (passwords_state_.client() + ->GetPasswordFeatureManager() + ->ShouldUpdateGmsCore()) { + passwords_state_.client()->ShowPasswordManagerErrorMessage( + password_manager::ErrorMessageFlowType::kSaveFlow, + password_manager::PasswordStoreBackendErrorType:: + kGMSCoreOutdatedSavingPossible); + } +}
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.h b/chrome/browser/password_manager/android/save_update_password_message_delegate.h index 7eb9534..bbf2ca8 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate.h +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.h
@@ -173,6 +173,8 @@ MessageDismissReasonToPasswordManagerUIDismissalReason( messages::DismissReason dismiss_reason); + void MaybeNudgeToUpdateGmsCore(); + PasswordEditDialogFactory password_edit_dialog_factory_; raw_ptr<content::WebContents> web_contents_ = nullptr;
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc index 9732aee..936316dc 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc
@@ -233,6 +233,8 @@ return delegate_.get(); } + void FastForward() { task_environment()->FastForwardBy(base::Seconds(1)); } + private: PasswordForm pending_credentials_; GURL password_form_url_; @@ -251,8 +253,9 @@ MockPasswordManagerClient password_manager_client_; }; -SaveUpdatePasswordMessageDelegateTest::SaveUpdatePasswordMessageDelegateTest() = - default; +SaveUpdatePasswordMessageDelegateTest::SaveUpdatePasswordMessageDelegateTest() + : ChromeRenderViewHostTestHarness( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} void SaveUpdatePasswordMessageDelegateTest::SetUp() { ChromeRenderViewHostTestHarness::SetUp(); @@ -643,6 +646,9 @@ EXPECT_CALL(*(GetClient()->GetPasswordFeatureManager()), ShouldUpdateGmsCore) .WillOnce(Return(true)); TriggerActionClick(); + + // Fast forward, since Update message is shown with a delay. + FastForward(); EXPECT_EQ(nullptr, GetMessageWrapper()); } @@ -668,6 +674,9 @@ EXPECT_CALL(*(GetClient()->GetPasswordFeatureManager()), ShouldUpdateGmsCore) .WillOnce(Return(false)); TriggerActionClick(); + + // Fast forward, since Update message is shown with a delay. + FastForward(); EXPECT_EQ(nullptr, GetMessageWrapper()); } @@ -765,6 +774,9 @@ EXPECT_CALL(*(GetClient()->GetPasswordFeatureManager()), ShouldUpdateGmsCore) .WillOnce(Return(true)); TriggerActionClick(); + + // Fast forward, since Update message is shown with a delay. + FastForward(); EXPECT_EQ(nullptr, GetMessageWrapper()); } @@ -795,6 +807,9 @@ EXPECT_CALL(*(GetClient()->GetPasswordFeatureManager()), ShouldUpdateGmsCore) .WillOnce(Return(false)); TriggerActionClick(); + + // Fast forward, since Update message is shown with a delay. + FastForward(); EXPECT_EQ(nullptr, GetMessageWrapper()); } @@ -879,6 +894,8 @@ /*password=*/kPassword); EXPECT_CALL(GetMigrationWarningCallback(), Run); TriggerDialogDismissedCallback(/*dialog_accepted=*/true); + // Fast forward, since Update message is shown with a delay. + FastForward(); } // Tests that the message to update GMSCore will not show when the user accepts @@ -914,6 +931,8 @@ /*password=*/kPassword); EXPECT_CALL(GetMigrationWarningCallback(), Run); TriggerDialogDismissedCallback(/*dialog_accepted=*/true); + // Fast forward, since Update message is shown with a delay. + FastForward(); } // Tests that the local password migration warning will show when the user
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index cbe9540..d196944 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -41,6 +41,7 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/translate/chrome_translate_client.h" +#include "chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h" #include "chrome/browser/ui/passwords/password_generation_popup_controller_impl.h" #include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h" #include "chrome/browser/ui/passwords/passwords_model_delegate.h" @@ -1084,6 +1085,32 @@ #endif } +#if !BUILDFLAG(IS_ANDROID) +std::unique_ptr< + password_manager::PasswordCrossDomainConfirmationPopupController> +ChromePasswordManagerClient::ShowCrossDomainConfirmationPopup( + const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) { + gfx::Rect client_area = web_contents()->GetContainerBounds(); + gfx::RectF element_bounds_in_screen_space = + element_bounds + client_area.OffsetFromOrigin(); + auto controller = + cross_domain_confirmation_popup_factory_for_testing_ + ? cross_domain_confirmation_popup_factory_for_testing_.Run() + : std::make_unique< + PasswordCrossDomainConfirmationPopupControllerImpl>( + web_contents()); + + controller->Show(element_bounds_in_screen_space, text_direction, domain, + password_origin, std::move(confirmation_callback)); + + return controller; +} +#endif // !BUILDFLAG(IS_ANDROID) + void ChromePasswordManagerClient::AutomaticGenerationAvailable( const autofill::password_generation::PasswordGenerationUIData& ui_data) { content::RenderFrameHost* rfh =
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h index d3cba9fa..26181013 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.h +++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -23,6 +24,7 @@ #include "components/password_manager/core/browser/http_auth_manager.h" #include "components/password_manager/core/browser/http_auth_manager_impl.h" #include "components/password_manager/core/browser/manage_passwords_referrer.h" +#include "components/password_manager/core/browser/password_cross_domain_confirmation_popup_controller.h" #include "components/password_manager/core/browser/password_feature_manager_impl.h" #include "components/password_manager/core/browser/password_form_manager_for_ui.h" #include "components/password_manager/core/browser/password_manager.h" @@ -284,6 +286,16 @@ #endif // BUILDFLAG(IS_ANDROID) version_info::Channel GetChannel() const override; void RefreshPasswordManagerSettingsIfNeeded() const override; +#if !BUILDFLAG(IS_ANDROID) + std::unique_ptr< + password_manager::PasswordCrossDomainConfirmationPopupController> + ShowCrossDomainConfirmationPopup( + const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) override; +#endif // !BUILDFLAG(IS_ANDROID) // autofill::mojom::PasswordGenerationDriver overrides. void AutomaticGenerationAvailable( @@ -327,6 +339,15 @@ } #endif +#if !BUILDFLAG(IS_ANDROID) + void set_cross_domain_confirmation_popup_factory_for_testing( + base::RepeatingCallback<std::unique_ptr< + password_manager::PasswordCrossDomainConfirmationPopupController>()> + factory) { + cross_domain_confirmation_popup_factory_for_testing_ = std::move(factory); + } +#endif // !BUILDFLAG(IS_ANDROID) + #if BUILDFLAG(IS_ANDROID) PasswordAccessoryController* GetOrCreatePasswordAccessory(); @@ -496,6 +517,14 @@ autofill::ScopedAutofillManagersObservation autofill_managers_observation_{ this}; +#if !BUILDFLAG(IS_ANDROID) + // The cross domain confirmation popup view factory, used for testing to mock + // some views specific initializations. + base::RepeatingCallback<std::unique_ptr< + password_manager::PasswordCrossDomainConfirmationPopupController>()> + cross_domain_confirmation_popup_factory_for_testing_; +#endif // !BUILDFLAG(IS_ANDROID) + WEB_CONTENTS_USER_DATA_KEY_DECL(); };
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc index 48f08782..02306ca 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -14,11 +14,13 @@ #include "base/command_line.h" #include "base/containers/span.h" #include "base/functional/bind.h" +#include "base/functional/callback_helpers.h" #include "base/ranges/algorithm.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "build/build_config.h" @@ -31,6 +33,7 @@ #include "chrome/browser/safe_browsing/user_interaction_observer.h" #include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/ui/autofill/chrome_autofill_client.h" +#include "chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" @@ -1624,3 +1627,52 @@ } #endif // BUILDFLAG(IS_ANDROID) + +#if !BUILDFLAG(IS_ANDROID) + +class MockPasswordCrossDomainConfirmationPopupController + : public password_manager::PasswordCrossDomainConfirmationPopupController { + public: + MOCK_METHOD(void, Hide, (autofill::PopupHidingReason), (override)); + MOCK_METHOD(void, + Show, + (const gfx::RectF&, + base::i18n::TextDirection, + const GURL&, + const std::u16string&, + base::OnceClosure), + (override)); +}; + +TEST_F(ChromePasswordManagerClientTest, ShowCrossDomainConfirmationPopup) { +// This simple method of the web contents repositioning doesn't work on Mac. +// The screen coordinates calculation testing is skipped on this platform, but +// the logic is completely platform independent and is being tested on others. +#if !BUILDFLAG(IS_MAC) + web_contents()->GetNativeView()->SetBounds(gfx::Rect(100, 100, 1000, 1000)); +#endif // !BUILDFLAG(IS_MAC) + + base::MockRepeatingCallback<std::unique_ptr< + password_manager::PasswordCrossDomainConfirmationPopupController>()> + popup_factory; + EXPECT_CALL(popup_factory, Run).WillOnce([&]() { + auto mock_controller = + std::make_unique<MockPasswordCrossDomainConfirmationPopupController>(); + EXPECT_CALL( + *mock_controller, + Show(gfx::RectF( + gfx::PointF(web_contents()->GetContainerBounds().origin()), + gfx::SizeF(100, 100)), + base::i18n::TextDirection::LEFT_TO_RIGHT, + GURL("https://google.com"), std::u16string(u"google.de"), _)); + return mock_controller; + }); + GetClient()->set_cross_domain_confirmation_popup_factory_for_testing( + popup_factory.Get()); + + GetClient()->ShowCrossDomainConfirmationPopup( + gfx::RectF(100, 100), base::i18n::TextDirection::LEFT_TO_RIGHT, + GURL("https://google.com"), u"google.de", base::DoNothing()); +} + +#endif // !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.cc b/chrome/browser/policy/cloud/user_policy_signin_service.cc index 324e2db..e43f8f6 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service.cc
@@ -167,6 +167,7 @@ if (identity_manager()) identity_manager()->RemoveObserver(this); UserPolicySigninServiceBase::Shutdown(); + profile_ = nullptr; } void UserPolicySigninService::ShutdownCloudPolicyManager() {
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc b/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc index 1580aed..3930eea 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc
@@ -9,6 +9,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/trace_event/base_tracing.h" #include "base/trace_event/common/trace_event_common.h" +#include "chrome/browser/after_startup_task_utils.h" #include "content/public/browser/browser_thread.h" #include "net/base/load_flags.h" #include "services/network/public/cpp/resource_request.h" @@ -84,6 +85,11 @@ TRACE_ID_LOCAL(this), TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); + // Avoid making network service to be more busy during the browser startup. + if (!AfterStartupTaskUtils::IsBrowserStartupComplete()) { + return; + } + url::Origin top_frame_origin = url::Origin::Create(top_frame_main_resource_url); MaybeAddPrewarmJob(top_frame_origin, top_frame_main_resource_url);
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/input_page.html b/chrome/browser/resources/ash/settings/os_languages_page/input_page.html index dd5ff02d..a44f7b6f 100644 --- a/chrome/browser/resources/ash/settings/os_languages_page/input_page.html +++ b/chrome/browser/resources/ash/settings/os_languages_page/input_page.html
@@ -129,15 +129,13 @@ } </style> -<template is="dom-if" if="[[shouldShowLanguagePacksNotice_]]"> - <div class="settings-box first"> - <localized-link id="languagePacksNotice" - class="cr-secondary-text" - localized-string="$i18n{languagePacksNotice}" - on-link-clicked="onLanguagePackNoticeLinkClick_"> - </localized-link> - </div> -</template> +<div class="settings-box first"> + <localized-link id="languagePacksNotice" + class="cr-secondary-text" + localized-string="$i18n{languagePacksNotice}" + on-link-clicked="onLanguagePackNoticeLinkClick_"> + </localized-link> +</div> <settings-toggle-button class="first" id="showImeMenu" pref="{{prefs.settings.language.ime_menu_activated}}"
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/input_page.ts b/chrome/browser/resources/ash/settings/os_languages_page/input_page.ts index 1846489..e4cf567 100644 --- a/chrome/browser/resources/ash/settings/os_languages_page/input_page.ts +++ b/chrome/browser/resources/ash/settings/os_languages_page/input_page.ts
@@ -97,13 +97,6 @@ }, }, - shouldShowLanguagePacksNotice_: { - type: Boolean, - value() { - return loadTimeData.getBoolean('languagePacksHandwritingEnabled'); - }, - }, - /** * Whether the shortcut reminder for the last used IME is currently * showing. @@ -180,7 +173,6 @@ // loadTimeData flags. private onDeviceGrammarCheckEnabled_: boolean; private languageSettingsJapaneseEnabled_: boolean; - private shouldShowLanguagePacksNotice_: boolean; private languagePacksInSettingsEnabled_ = loadTimeData.getBoolean('languagePacksInSettingsEnabled'); private readonly allowEmojiSuggestion_: boolean =
diff --git a/chrome/browser/resources/chromeos/app_install/app_install_dialog.html b/chrome/browser/resources/chromeos/app_install/app_install_dialog.html index 521286c..7954467a 100644 --- a/chrome/browser/resources/chromeos/app_install/app_install_dialog.html +++ b/chrome/browser/resources/chromeos/app_install/app_install_dialog.html
@@ -113,7 +113,7 @@ <h1 id="title">$i18n{installAppToDevice}</h1> <div id="content-card" style="display: none"> <div id="essential-details"> - <img id="app-icon" is="cr-auto-img" width="32" height="32" alt=""> + <img id="app-icon" is="cr-auto-img" width="32" height="32"> <div id="name-and-url"> <p id="name"></p> <p id="url">$i18n{appDetails}
diff --git a/chrome/browser/resources/chromeos/app_install/app_install_dialog.ts b/chrome/browser/resources/chromeos/app_install/app_install_dialog.ts index c0bd4321..e13e17f 100644 --- a/chrome/browser/resources/chromeos/app_install/app_install_dialog.ts +++ b/chrome/browser/resources/chromeos/app_install/app_install_dialog.ts
@@ -197,6 +197,10 @@ const iconElement = this.$<HTMLImageElement>('#app-icon'); assert(iconElement); iconElement.setAttribute('auto-src', dialogArgs.args.iconUrl.url); + iconElement.setAttribute( + 'alt', + loadTimeData.substituteString( + loadTimeData.getString('iconAlt'), dialogArgs.args.name)); if (dialogArgs.args.description) { this.$<HTMLDivElement>('#description').textContent =
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc index 3a616db..b0061560 100644 --- a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc +++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl.cc
@@ -150,7 +150,7 @@ switches::kEnableBoundSessionCredentialsExclusiveRegistrationPath.Get(); if (!exclusive_registration_path.empty() && !base::EqualsCaseInsensitiveASCII( - registration_params.RegistrationEndpoint().path_piece(), + registration_params.registration_endpoint().path_piece(), exclusive_registration_path)) { return; }
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc index 0213b7c..3e00150 100644 --- a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc +++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_refresh_service_impl_unittest.cc
@@ -821,7 +821,7 @@ CreateTestRegistrationFetcherParams(kSecondPath)); ASSERT_TRUE(registration_fetcher()); EXPECT_EQ( - registration_fetcher()->params().RegistrationEndpoint().path_piece(), + registration_fetcher()->params().registration_endpoint().path_piece(), kFirstPath); // Verify that a request can complete normally.
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_impl.cc b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_impl.cc index 432b594..6bffccb 100644 --- a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_impl.cc +++ b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_impl.cc
@@ -66,7 +66,7 @@ RegistrationCompleteCallback callback) { TRACE_EVENT("browser", "BoundSessionRegistrationFetcherImpl::Start", perfetto::Flow::FromPointer(this), "endpoint", - registration_params_.RegistrationEndpoint()); + registration_params_.registration_endpoint()); CHECK(!registration_duration_.has_value()); CHECK(!callback_); CHECK(!registration_token_helper_); @@ -75,8 +75,8 @@ // base::Unretained() is safe since `this` owns // `registration_token_helper_`. registration_token_helper_ = RegistrationTokenHelper::CreateForSessionBinding( - key_service_.get(), registration_params_.Challenge(), - registration_params_.RegistrationEndpoint(), + key_service_.get(), registration_params_.challenge(), + registration_params_.registration_endpoint(), base::BindOnce( &BoundSessionRegistrationFetcherImpl::OnRegistrationTokenCreated, base::Unretained(this), base::ElapsedTimer())); @@ -130,7 +130,7 @@ bound_session_credentials::BoundSessionParams params = std::move(params_or_error).value(); params.set_site( - net::SchemefulSite(registration_params_.RegistrationEndpoint()) + net::SchemefulSite(registration_params_.registration_endpoint()) .Serialize()); params.set_wrapped_key(wrapped_key_str_); *params.mutable_creation_time() = @@ -210,14 +210,14 @@ })"); auto request = std::make_unique<network::ResourceRequest>(); - request->url = registration_params_.RegistrationEndpoint(); + request->url = registration_params_.registration_endpoint(); request->method = "POST"; - request->site_for_cookies = - net::SiteForCookies::FromUrl(registration_params_.RegistrationEndpoint()); + request->site_for_cookies = net::SiteForCookies::FromUrl( + registration_params_.registration_endpoint()); request->trusted_params = network::ResourceRequest::TrustedParams(); request->trusted_params->isolation_info = net::IsolationInfo::CreateForInternalRequest( - url::Origin::Create(registration_params_.RegistrationEndpoint())); + url::Origin::Create(registration_params_.registration_endpoint())); std::string content_type = "application/jwt";
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.cc b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.cc index dad2a11..e5d5040e 100644 --- a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.cc +++ b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.cc
@@ -31,7 +31,7 @@ } // namespace BoundSessionRegistrationFetcherParam::BoundSessionRegistrationFetcherParam( - BoundSessionRegistrationFetcherParam&& other) = default; + BoundSessionRegistrationFetcherParam&& other) noexcept = default; BoundSessionRegistrationFetcherParam& BoundSessionRegistrationFetcherParam::operator=( @@ -48,6 +48,7 @@ supported_algos_(std::move(supported_algos)), challenge_(std::move(challenge)) {} +// static std::optional<BoundSessionRegistrationFetcherParam> BoundSessionRegistrationFetcherParam::MaybeCreateInstance( const GURL& request_url, @@ -113,6 +114,7 @@ } } +// static BoundSessionRegistrationFetcherParam BoundSessionRegistrationFetcherParam::CreateInstanceForTesting( GURL registration_endpoint, @@ -122,16 +124,3 @@ std::move(supported_algos), std::move(challenge)); } - -const GURL& BoundSessionRegistrationFetcherParam::RegistrationEndpoint() const { - return registration_endpoint_; -} - -base::span<const crypto::SignatureVerifier::SignatureAlgorithm> -BoundSessionRegistrationFetcherParam::SupportedAlgos() const { - return supported_algos_; -} - -const std::string& BoundSessionRegistrationFetcherParam::Challenge() const { - return challenge_; -}
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.h b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.h index 44744af..5ea6e24 100644 --- a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.h +++ b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.h
@@ -16,14 +16,14 @@ class BoundSessionRegistrationFetcherParam { public: BoundSessionRegistrationFetcherParam( - BoundSessionRegistrationFetcherParam&& other); + BoundSessionRegistrationFetcherParam&& other) noexcept; BoundSessionRegistrationFetcherParam& operator=( BoundSessionRegistrationFetcherParam&& other) noexcept; BoundSessionRegistrationFetcherParam( const BoundSessionRegistrationFetcherParam& other) = delete; BoundSessionRegistrationFetcherParam& operator=( - const BoundSessionRegistrationFetcherParam&) = delete; + const BoundSessionRegistrationFetcherParam& other) = delete; ~BoundSessionRegistrationFetcherParam(); // Will return a valid instance or return std::nullopt; @@ -38,10 +38,14 @@ supported_algos, std::string challenge); - const GURL& RegistrationEndpoint() const; + const GURL& registration_endpoint() const { return registration_endpoint_; } + base::span<const crypto::SignatureVerifier::SignatureAlgorithm> - SupportedAlgos() const; - const std::string& Challenge() const; + supported_algos() const { + return supported_algos_; + } + + const std::string& challenge() const { return challenge_; } private: BoundSessionRegistrationFetcherParam(
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param_unittest.cc b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param_unittest.cc index 3599f224..5f2a178 100644 --- a/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param_unittest.cc +++ b/chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/signin/bound_session_credentials/bound_session_registration_fetcher_param.h" + #include "base/strings/strcat.h" #include "base/test/bind.h" #include "base/test/task_environment.h" @@ -16,24 +17,14 @@ constexpr char kChallenge[] = "test_challenge"; } // namespace -class BoundSessionRegistrationFetcherParamTest : public testing::Test { - public: - BoundSessionRegistrationFetcherParamTest() = default; - BoundSessionRegistrationFetcherParamTest( - const BoundSessionRegistrationFetcherParamTest&) = delete; - BoundSessionRegistrationFetcherParamTest& operator=( - const BoundSessionRegistrationFetcherParamTest&) = delete; - ~BoundSessionRegistrationFetcherParamTest() override = default; -}; - -TEST_F(BoundSessionRegistrationFetcherParamTest, AllInvalid) { +TEST(BoundSessionRegistrationFetcherParamTest, AllInvalid) { std::vector<crypto::SignatureVerifier::SignatureAlgorithm> supported_algos; BoundSessionRegistrationFetcherParam params = BoundSessionRegistrationFetcherParam::CreateInstanceForTesting( GURL(), supported_algos, ""); } -TEST_F(BoundSessionRegistrationFetcherParamTest, AllValid) { +TEST(BoundSessionRegistrationFetcherParamTest, AllValid) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -46,16 +37,16 @@ registration_request, response_headers.get()); ASSERT_TRUE(maybe_params.has_value()); BoundSessionRegistrationFetcherParam params = std::move(maybe_params.value()); - ASSERT_EQ(params.RegistrationEndpoint(), + EXPECT_EQ(params.registration_endpoint(), GURL("https://www.google.com/startsession")); - ASSERT_EQ(params.SupportedAlgos()[0], + EXPECT_EQ(params.supported_algos()[0], crypto::SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256); - ASSERT_EQ(params.SupportedAlgos()[1], + EXPECT_EQ(params.supported_algos()[1], crypto::SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256); - ASSERT_EQ(params.Challenge(), kChallenge); + EXPECT_EQ(params.challenge(), kChallenge); } -TEST_F(BoundSessionRegistrationFetcherParamTest, AllValidFullUrl) { +TEST(BoundSessionRegistrationFetcherParamTest, AllValidFullUrl) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -68,16 +59,16 @@ registration_request, response_headers.get()); ASSERT_TRUE(maybe_params.has_value()); BoundSessionRegistrationFetcherParam params = std::move(maybe_params.value()); - ASSERT_EQ(params.RegistrationEndpoint(), + EXPECT_EQ(params.registration_endpoint(), GURL("https://accounts.google.com/startsession")); - ASSERT_EQ(params.SupportedAlgos()[0], + EXPECT_EQ(params.supported_algos()[0], crypto::SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256); - ASSERT_EQ(params.SupportedAlgos()[1], + EXPECT_EQ(params.supported_algos()[1], crypto::SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256); - ASSERT_EQ(params.Challenge(), kChallenge); + EXPECT_EQ(params.challenge(), kChallenge); } -TEST_F(BoundSessionRegistrationFetcherParamTest, AllValidFullDifferentUrl) { +TEST(BoundSessionRegistrationFetcherParamTest, AllValidFullDifferentUrl) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -88,10 +79,10 @@ std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); } -TEST_F(BoundSessionRegistrationFetcherParamTest, AllValidSwapAlgo) { +TEST(BoundSessionRegistrationFetcherParamTest, AllValidSwapAlgo) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -104,16 +95,16 @@ registration_request, response_headers.get()); ASSERT_TRUE(maybe_params.has_value()); BoundSessionRegistrationFetcherParam params = std::move(maybe_params.value()); - ASSERT_EQ(params.RegistrationEndpoint(), + EXPECT_EQ(params.registration_endpoint(), GURL("https://www.google.com/startsession")); - ASSERT_EQ(params.SupportedAlgos()[0], + EXPECT_EQ(params.supported_algos()[0], crypto::SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256); - ASSERT_EQ(params.SupportedAlgos()[1], + EXPECT_EQ(params.supported_algos()[1], crypto::SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256); - ASSERT_EQ(params.Challenge(), kChallenge); + EXPECT_EQ(params.challenge(), kChallenge); } -TEST_F(BoundSessionRegistrationFetcherParamTest, AllValidOneAlgo) { +TEST(BoundSessionRegistrationFetcherParamTest, AllValidOneAlgo) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -126,24 +117,24 @@ registration_request, response_headers.get()); ASSERT_TRUE(maybe_params.has_value()); BoundSessionRegistrationFetcherParam params = std::move(maybe_params.value()); - ASSERT_EQ(params.RegistrationEndpoint(), + EXPECT_EQ(params.registration_endpoint(), GURL("https://www.google.com/startsession")); - ASSERT_EQ(params.SupportedAlgos()[0], + EXPECT_EQ(params.supported_algos()[0], crypto::SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256); - ASSERT_EQ(params.Challenge(), kChallenge); + EXPECT_EQ(params.challenge(), kChallenge); } -TEST_F(BoundSessionRegistrationFetcherParamTest, MissingHeader) { +TEST(BoundSessionRegistrationFetcherParamTest, MissingHeader) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); // Note: not adding the right header, causing std::nullopt to be returned. std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); } -TEST_F(BoundSessionRegistrationFetcherParamTest, MissingUrl) { +TEST(BoundSessionRegistrationFetcherParamTest, MissingUrl) { GURL registration_request = GURL(); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -154,10 +145,10 @@ std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); } -TEST_F(BoundSessionRegistrationFetcherParamTest, MissingAlgo) { +TEST(BoundSessionRegistrationFetcherParamTest, MissingAlgo) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -167,10 +158,10 @@ std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); } -TEST_F(BoundSessionRegistrationFetcherParamTest, MissingRegistration) { +TEST(BoundSessionRegistrationFetcherParamTest, MissingRegistration) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -179,10 +170,10 @@ std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); } -TEST_F(BoundSessionRegistrationFetcherParamTest, MissingChallenge) { +TEST(BoundSessionRegistrationFetcherParamTest, MissingChallenge) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -191,10 +182,10 @@ std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); } -TEST_F(BoundSessionRegistrationFetcherParamTest, EmptyChallenge) { +TEST(BoundSessionRegistrationFetcherParamTest, EmptyChallenge) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -203,10 +194,10 @@ std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); } -TEST_F(BoundSessionRegistrationFetcherParamTest, ChallengeInvalidUtf8) { +TEST(BoundSessionRegistrationFetcherParamTest, ChallengeInvalidUtf8) { GURL registration_request = GURL("https://www.google.com/registration"); auto response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); response_headers->SetHeader( @@ -216,5 +207,5 @@ std::optional<BoundSessionRegistrationFetcherParam> maybe_params = BoundSessionRegistrationFetcherParam::MaybeCreateInstance( registration_request, response_headers.get()); - ASSERT_FALSE(maybe_params.has_value()); + EXPECT_FALSE(maybe_params.has_value()); }
diff --git a/chrome/browser/signin/signin_promo_unittest.cc b/chrome/browser/signin/signin_promo_unittest.cc index e11221c3..17e86c66 100644 --- a/chrome/browser/signin/signin_promo_unittest.cc +++ b/chrome/browser/signin/signin_promo_unittest.cc
@@ -6,7 +6,15 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" +#include "chrome/browser/signin/signin_promo_util.h" #include "chrome/common/webui_url_constants.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "components/signin/public/base/consent_level.h" +#include "components/signin/public/base/signin_switches.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/identity_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -47,7 +55,7 @@ "https://accounts.google.com/signin/chrome/sync?ssp=1&" "color_scheme=dark&flow=promo", GetChromeSyncURLForDice( - {.request_dark_scheme = true, .flow = signin::Flow::PROMO})); + {.request_dark_scheme = true, .flow = Flow::PROMO})); EXPECT_EQ( "https://accounts.google.com/signin/chrome/sync?ssp=1&" "email_hint=email%40gmail.com&continue=https%3A%2F%2Fcontinue_url%2F", @@ -56,7 +64,7 @@ EXPECT_EQ( "https://accounts.google.com/signin/chrome/" "sync?ssp=1&flow=embedded_promo", - GetChromeSyncURLForDice({.flow = signin::Flow::EMBEDDED_PROMO})); + GetChromeSyncURLForDice({.flow = Flow::EMBEDDED_PROMO})); EXPECT_EQ( "https://accounts.google.com/AddSession?" "Email=email%40gmail.com&continue=https%3A%2F%2Fcontinue_url%2F", @@ -64,4 +72,112 @@ GURL("https://continue_url/"))); } +class ShowPromoTest : public testing::Test { + public: + ShowPromoTest() { + profile_ = IdentityTestEnvironmentProfileAdaptor:: + CreateProfileForIdentityTestEnvironment(); + identity_test_env_adaptor_ = + std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get()); + } + + IdentityManager* identity_manager() { + return identity_test_env_adaptor_->identity_test_env()->identity_manager(); + } + + Profile* profile() { return profile_.get(); } + + private: + content::BrowserTaskEnvironment task_environment_; + std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> + identity_test_env_adaptor_; +}; + +// Tests for ShouldShowPromo. +#if !BUILDFLAG(IS_CHROMEOS_ASH) +TEST_F(ShowPromoTest, ShowPromoWithNoAccount) { + EXPECT_TRUE(ShouldShowPromo(*profile(), ConsentLevel::kSync)); +} + +TEST_F(ShowPromoTest, ShowPromoWithSignedInAccount) { + MakePrimaryAccountAvailable(identity_manager(), "test@email.com", + ConsentLevel::kSignin); + EXPECT_TRUE(ShouldShowPromo(*profile(), ConsentLevel::kSync)); +} + +TEST_F(ShowPromoTest, DoNotShowPromoWithSyncingAccount) { + MakePrimaryAccountAvailable(identity_manager(), "test@email.com", + ConsentLevel::kSync); + EXPECT_FALSE(ShouldShowPromo(*profile(), ConsentLevel::kSync)); +} +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) + +// Tests for ShouldShowSignInPromo. +TEST_F(ShowPromoTest, DoNotShowSignInPromoWithoutExplicitBrowserSignin) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + switches::kExplicitBrowserSigninUIOnDesktop); + + EXPECT_FALSE(ShouldShowSignInPromo(*profile(), + SignInAutofillBubblePromoType::Passwords)); +} + +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +class ShowSigninPromoTestExplicitBrowserSignin : public ShowPromoTest { + base::test::ScopedFeatureList feature_list{ + switches::kExplicitBrowserSigninUIOnDesktop}; +}; + +TEST_F(ShowSigninPromoTestExplicitBrowserSignin, ShowPromoWithNoAccount) { + EXPECT_TRUE(ShouldShowSignInPromo(*profile(), + SignInAutofillBubblePromoType::Payments)); +} + +TEST_F(ShowSigninPromoTestExplicitBrowserSignin, + ShowPromoWithWebSignedInAccount) { + MakeAccountAvailable(identity_manager(), "test@email.com"); + EXPECT_TRUE(ShouldShowSignInPromo(*profile(), + SignInAutofillBubblePromoType::Addresses)); +} + +TEST_F(ShowSigninPromoTestExplicitBrowserSignin, + ShowPromoWithSignInPausedAccount) { + AccountInfo info = MakePrimaryAccountAvailable( + identity_manager(), "test@email.com", ConsentLevel::kSignin); + UpdatePersistentErrorOfRefreshTokenForAccount( + identity_manager(), info.account_id, + GoogleServiceAuthError( + GoogleServiceAuthError::State::USER_NOT_SIGNED_UP)); + EXPECT_TRUE(ShouldShowSignInPromo(*profile(), + SignInAutofillBubblePromoType::Passwords)); +} + +TEST_F(ShowSigninPromoTestExplicitBrowserSignin, + DoNotShowPromoWithAlreadySignedInAccount) { + MakePrimaryAccountAvailable(identity_manager(), "test@email.com", + ConsentLevel::kSignin); + EXPECT_FALSE(ShouldShowSignInPromo(*profile(), + SignInAutofillBubblePromoType::Payments)); +} + +TEST_F(ShowSigninPromoTestExplicitBrowserSignin, + DoNotShowPromoWithAlreadySyncingAccount) { + MakePrimaryAccountAvailable(identity_manager(), "test@email.com", + ConsentLevel::kSync); + EXPECT_FALSE(ShouldShowSignInPromo(*profile(), + SignInAutofillBubblePromoType::Addresses)); +} + +TEST_F(ShowSigninPromoTestExplicitBrowserSignin, + DoNotShowPromoAfterFiveTimesShown) { + // TODO (crbug.com/319411728): Implement a counter and test it. +} + +TEST_F(ShowSigninPromoTestExplicitBrowserSignin, + DoNotShowPromoAfterTwoTimesDismissed) { + // TODO (crbug.com/319411728): Implement a counter and test it. +} +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) + } // namespace signin
diff --git a/chrome/browser/signin/signin_promo_util.cc b/chrome/browser/signin/signin_promo_util.cc index 98aac88..b84e0ee 100644 --- a/chrome/browser/signin/signin_promo_util.cc +++ b/chrome/browser/signin/signin_promo_util.cc
@@ -8,14 +8,16 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "components/prefs/pref_service.h" +#include "components/signin/public/base/consent_level.h" #include "components/signin/public/base/signin_pref_names.h" +#include "components/signin/public/base/signin_switches.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/primary_account_mutator.h" #include "net/base/network_change_notifier.h" namespace signin { -bool ShouldShowPromo(Profile* profile) { +bool ShouldShowPromo(Profile& profile, ConsentLevel promo_type) { #if BUILDFLAG(IS_CHROMEOS_ASH) // There's no need to show the sign in promo on cros since cros users are // already logged in. @@ -29,21 +31,41 @@ // Consider original profile even if an off-the-record profile was // passed to this method as sign-in state is only defined for the // primary profile. - Profile* original_profile = profile->GetOriginalProfile(); + Profile* original_profile = profile.GetOriginalProfile(); // Don't show for supervised child profiles. if (original_profile->IsChild()) return false; - // Don't show if sign-in is not allowed. + // Don't show if sign in is not allowed. if (!original_profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed)) return false; - // Display the signin promo if the user is not signed in. - signin::IdentityManager* identity_manager = + IdentityManager* identity_manager = IdentityManagerFactory::GetForProfile(original_profile); - return !identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync); + + // No promo if the user is already syncing. + if (identity_manager->HasPrimaryAccount(ConsentLevel::kSync)) { + return false; + } + + // Sync Promos are always shown when the user is not syncing. + if (promo_type == ConsentLevel::kSync) { + return true; + } + + // Signin promo is shown if the user is not signed in or needs to reauth. + return !identity_manager->HasPrimaryAccount(ConsentLevel::kSignin) || + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + identity_manager->GetPrimaryAccountId(ConsentLevel::kSignin)); #endif } +bool ShouldShowSignInPromo(Profile& profile, + SignInAutofillBubblePromoType signin_promo_type) { + return ShouldShowPromo(profile, ConsentLevel::kSignin) && + switches::IsExplicitBrowserSigninUIOnDesktopEnabled( + switches::ExplicitBrowserSigninPhase::kFull); +} + } // namespace signin
diff --git a/chrome/browser/signin/signin_promo_util.h b/chrome/browser/signin/signin_promo_util.h index c115c8b2..aef8dba4 100644 --- a/chrome/browser/signin/signin_promo_util.h +++ b/chrome/browser/signin/signin_promo_util.h
@@ -5,13 +5,24 @@ #ifndef CHROME_BROWSER_SIGNIN_SIGNIN_PROMO_UTIL_H_ #define CHROME_BROWSER_SIGNIN_SIGNIN_PROMO_UTIL_H_ +#include "components/signin/public/base/consent_level.h" + class Profile; namespace signin { -// Returns true if the sign in promo should be visible. +// Enumeration of sign in promo types for the autofill bubble. +enum class SignInAutofillBubblePromoType { Passwords, Addresses, Payments }; + +// Returns true if the sync/sign in promo should be visible. // |profile| is the profile of the tab the promo would be shown on. -bool ShouldShowPromo(Profile* profile); +// |promo_type| specifies whether the promo would be for sync or sign in. +bool ShouldShowPromo(Profile& profile, ConsentLevel promo_type); + +// Whether we should show the sign in promo after data of the type +// |signin_promo_type| was saved. +bool ShouldShowSignInPromo(Profile& profile, + SignInAutofillBubblePromoType signin_promo_type); } // namespace signin
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 0ad697d9..5a161e5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -745,6 +745,13 @@ deps += [ "//chrome/browser/vr:vr_base" ] } + if (is_win || is_linux || is_mac || is_chromeos) { + sources += [ + "passwords/password_cross_domain_confirmation_popup_controller_impl.cc", + "passwords/password_cross_domain_confirmation_popup_controller_impl.h", + ] + } + if (is_win || is_android || is_linux || is_chromeos) { sources += [ "webui/sandbox/sandbox_internals_ui.cc", @@ -754,8 +761,6 @@ if (is_win || is_linux || is_mac || is_chromeos_ash) { sources += [ - "passwords/password_cross_domain_confirmation_popup_controller.cc", - "passwords/password_cross_domain_confirmation_popup_controller.h", "passwords/password_cross_domain_confirmation_popup_view.h", "webui/connectors_internals/connectors_internals_page_handler.cc", "webui/connectors_internals/connectors_internals_page_handler.h",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 300f9d23..507c958 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2243,6 +2243,14 @@ <message name="IDS_SYNC_REVIEW_DATA" desc="Title for link to https://chrome.google.com/sync Dashboard to manage sync data."> Review your synced data </message> + <!-- TODO(b/326574743): Revisit string and mark it as translatable.--> + <message name="IDS_SIGNIN_REVIEW_DATA_TITLE" desc="Title for link to https://chrome.google.com/sync Dashboard to manage sync data." translateable="false"> + Data in your account + </message> + <!-- TODO(b/326574743): Revisit string and mark it as translatable.--> + <message name="IDS_SIGNIN_REVIEW_DATA_SUMMARY" desc="Summary for link to https://chrome.google.com/sync Dashboard to manage sync data." translateable="false"> + Review your account data + </message> <message name="IDS_SYNC_PASSPHRASE_TYPE_TITLE" desc="Title of sync passphrase type dialog. [CHAR_LIMIT=24]"> Encryption </message>
diff --git a/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc b/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc index 97e0c0d..2d1ca032 100644 --- a/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc +++ b/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc
@@ -23,6 +23,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" #include "chrome/browser/ash/crosapi/crosapi_ash.h" #include "chrome/browser/ash/crosapi/crosapi_manager.h" #include "chrome/browser/ash/file_manager/file_manager_test_util.h" @@ -34,16 +35,20 @@ #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h" #include "chrome/browser/chromeos/policy/dlp/test/dlp_content_manager_test_helper.h" #include "chrome/browser/chromeos/policy/dlp/test/mock_dlp_rules_manager.h" +#include "chrome/browser/download/download_prefs.h" #include "chrome/browser/enterprise/data_controls/dlp_reporting_manager.h" #include "chrome/browser/enterprise/data_controls/dlp_reporting_manager_test_helper.h" #include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/policy/policy_test_utils.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/enterprise/data_controls/dlp_policy_event.pb.h" +#include "components/policy/policy_constants.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "media/base/media_switches.h" @@ -180,12 +185,39 @@ } // namespace +class CaptureModeBrowserTest : public InProcessBrowserTest {}; + +IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, ContextMenuStaysOpen) { + // Right click the desktop to open a context menu. + aura::Window* browser_window = browser()->window()->GetNativeWindow(); + const gfx::Point point_on_desktop(1, 1); + ASSERT_FALSE(browser_window->bounds().Contains(point_on_desktop)); + + ui::test::EventGenerator event_generator(browser_window->GetRootWindow(), + point_on_desktop); + event_generator.ClickRightButton(); + + ash::ShellTestApi shell_test_api; + ASSERT_TRUE(shell_test_api.IsContextMenuShown()); + + ash::CaptureModeTestApi().StartForWindow(/*for_video=*/false); + EXPECT_TRUE(shell_test_api.IsContextMenuShown()); +} + +// A regression test for https://crbug.com/1350711 in which a session is started +// quickly after clicking the sign out button. +IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, + SimulateStartingSessionAfterSignOut) { + ash::Shell::Get()->session_controller()->RequestSignOut(); + ash::CaptureModeTestApi().StartForFullscreen(false); +} + // Testing class to test CrOS capture mode, which is a feature to take // screenshots and record video. -class CaptureModeBrowserTest : public InProcessBrowserTest { +class CaptureModeDlpBrowserTest : public CaptureModeBrowserTest { public: - CaptureModeBrowserTest() = default; - ~CaptureModeBrowserTest() override = default; + CaptureModeDlpBrowserTest() = default; + ~CaptureModeDlpBrowserTest() override = default; void SetUpOnMainThread() override { // Instantiate |DlpContentManagerTestHelper| after main thread has been @@ -231,25 +263,8 @@ std::vector<DlpPolicyEvent> events_; }; -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, ContextMenuStaysOpen) { - // Right click the desktop to open a context menu. - aura::Window* browser_window = browser()->window()->GetNativeWindow(); - const gfx::Point point_on_desktop(1, 1); - ASSERT_FALSE(browser_window->bounds().Contains(point_on_desktop)); - - ui::test::EventGenerator event_generator(browser_window->GetRootWindow(), - point_on_desktop); - event_generator.ClickRightButton(); - - ash::ShellTestApi shell_test_api; - ASSERT_TRUE(shell_test_api.IsContextMenuShown()); - - ash::CaptureModeTestApi().StartForWindow(/*for_video=*/false); - EXPECT_TRUE(shell_test_api.IsContextMenuShown()); -} - // Checks that video capture emits exactly one DLP reporting event. -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, DlpReportingVideoCapture) { +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpReportingVideoCapture) { // Set DLP restriction. auto* dlp_content_observer = policy::DlpContentObserver::Get(); ASSERT_TRUE(dlp_content_observer); @@ -300,7 +315,7 @@ } // Tests DLP reporting without opening the capture bar. -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpReportingDialogOnFullscreenScreenCaptureShortcut) { ASSERT_TRUE(browser()); // Set DLP restriction. @@ -329,7 +344,7 @@ kRuleName, kRuleId, policy::DlpRulesManager::Level::kReport))); } -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpWarningDialogOnVideoEndDismissed) { ASSERT_TRUE(browser()); StartVideoRecording(); @@ -365,7 +380,7 @@ policy::DlpRulesManager::Level::kWarn))); } -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpWarningDialogOnVideoEndAccepted) { ASSERT_TRUE(browser()); StartVideoRecording(); @@ -401,32 +416,25 @@ kRuleName, kRuleId))); } -// A regression test for https://crbug.com/1350711 in which a session is started -// quickly after clicking the sign out button. -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, - SimulateStartingSessionAfterSignOut) { - ash::Shell::Get()->session_controller()->RequestSignOut(); - ash::CaptureModeTestApi().StartForFullscreen(false); -} - // Parametrize capture mode browser tests to check both making screenshots and // video capture. This is particularly important for DLP which handles reporting // of user activity differently for screenshots and video capture. -class CaptureModeParamBrowserTest : public CaptureModeBrowserTest, - public ::testing::WithParamInterface<bool> { +class CaptureModeParamDlpBrowserTest + : public CaptureModeDlpBrowserTest, + public ::testing::WithParamInterface<bool> { public: - CaptureModeParamBrowserTest() : for_video_(GetParam()) {} - ~CaptureModeParamBrowserTest() override = default; + CaptureModeParamDlpBrowserTest() : for_video_(GetParam()) {} + ~CaptureModeParamDlpBrowserTest() override = default; protected: const bool for_video_; }; -INSTANTIATE_TEST_SUITE_P(CaptureModeParamBrowserTest, - CaptureModeParamBrowserTest, +INSTANTIATE_TEST_SUITE_P(CaptureModeParamDlpBrowserTest, + CaptureModeParamDlpBrowserTest, ::testing::Bool()); -IN_PROC_BROWSER_TEST_P(CaptureModeParamBrowserTest, +IN_PROC_BROWSER_TEST_P(CaptureModeParamDlpBrowserTest, DlpWarningDialogOnSessionInitDismissed) { ASSERT_TRUE(browser()); MarkActiveTabAsDlpWarnedForScreenCapture(browser()); @@ -453,7 +461,7 @@ kRuleName, kRuleId, policy::DlpRulesManager::Level::kWarn))); } -IN_PROC_BROWSER_TEST_P(CaptureModeParamBrowserTest, +IN_PROC_BROWSER_TEST_P(CaptureModeParamDlpBrowserTest, DlpWarningDialogOnSessionInitAccepted) { ASSERT_TRUE(browser()); MarkActiveTabAsDlpWarnedForScreenCapture(browser()); @@ -482,7 +490,7 @@ kRuleName, kRuleId, policy::DlpRulesManager::Level::kWarn))); } -IN_PROC_BROWSER_TEST_P(CaptureModeParamBrowserTest, +IN_PROC_BROWSER_TEST_P(CaptureModeParamDlpBrowserTest, DlpWarningDialogOnPerformingCaptureDismissed) { ASSERT_TRUE(browser()); // Start the session before a window becomes restricted. @@ -516,7 +524,7 @@ kRuleName, kRuleId, policy::DlpRulesManager::Level::kWarn))); } -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpWarningDialogOnPerformingScreenCaptureAccepted) { ASSERT_TRUE(browser()); // Start the session before a window becomes restricted. @@ -559,7 +567,7 @@ kRuleName, kRuleId))); } -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpWarningDialogOnPerformingVideoCaptureAccepted) { ASSERT_TRUE(browser()); SetupDlpReporting(); @@ -624,7 +632,7 @@ kRuleName, kRuleId))); } -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpWarningDialogOnCountdownEndDismissed) { ASSERT_TRUE(browser()); ash::CaptureModeTestApi test_api; @@ -660,7 +668,7 @@ kRuleName, kRuleId, policy::DlpRulesManager::Level::kWarn))); } -IN_PROC_BROWSER_TEST_F(CaptureModeBrowserTest, +IN_PROC_BROWSER_TEST_F(CaptureModeDlpBrowserTest, DlpWarningDialogOnCountdownEndAccepted) { ASSERT_TRUE(browser()); ash::CaptureModeTestApi test_api; @@ -709,7 +717,7 @@ } IN_PROC_BROWSER_TEST_F( - CaptureModeBrowserTest, + CaptureModeDlpBrowserTest, DlpWarningDialogOnCaptureScreenshotsOfAllDisplaysDismissed) { ASSERT_TRUE(browser()); MarkActiveTabAsDlpWarnedForScreenCapture(browser()); @@ -736,7 +744,7 @@ } IN_PROC_BROWSER_TEST_F( - CaptureModeBrowserTest, + CaptureModeDlpBrowserTest, DlpWarningDialogOnFullscreenScreenCaptureShortcutAccepted) { ASSERT_TRUE(browser()); MarkActiveTabAsDlpWarnedForScreenCapture(browser()); @@ -1034,3 +1042,83 @@ EXPECT_TRUE(!is_share_screen_icon_enabled_ || !vc_tray_screen_share_icon()->GetVisible()); } + +// Tests that the capture is saved to policy defined location if feature is +// enabled. Received a param on whether to test video or image capture and +// another param on whether the feature is enabled or not. +class CaptureModePolicyBrowserTest + : public testing::WithParamInterface<std::pair<bool, bool>>, + public policy::PolicyTest { + public: + CaptureModePolicyBrowserTest() + : for_video_(GetParam().first), skyvault_enabled_(GetParam().second) { + if (skyvault_enabled_) { + scoped_feature_list_.InitAndEnableFeature(features::kSkyVault); + } else { + scoped_feature_list_.InitAndDisableFeature(features::kSkyVault); + } + } + + protected: + bool for_video_, skyvault_enabled_; + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_P(CaptureModePolicyBrowserTest, + ScreenCaptureLocationPolicy) { + ASSERT_TRUE(browser()); + // Start the session before a window becomes restricted. + ash::CaptureModeTestApi test_api; + + test_api.StartForFullscreen(for_video_); + ASSERT_TRUE(test_api.IsSessionActive()); + { + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + policy::PolicyMap policies; + SetPolicy(&policies, policy::key::kScreenCaptureLocation, + base::Value(temp_dir.GetPath().value())); + UpdateProviderPolicy(policies); + + // Set up a waiter to wait for the file to be saved. + base::test::TestFuture<const base::FilePath&> path_future; + test_api.SetOnCaptureFileSavedCallback(path_future.GetCallback()); + + test_api.PerformCapture(); + + if (for_video_) { + // Explicitly waiting for video capture to start as it might + // asynchronously check custom destination folder. + if (!test_api.IsVideoRecordingInProgress()) { + base::RunLoop run_loop; + test_api.SetOnVideoRecordingStartedCallback(run_loop.QuitClosure()); + run_loop.Run(); + } + // Wait while the file location is checked. + test_api.FlushRecordingServiceForTesting(); + test_api.StopVideoRecording(); + } + + // If SkyVault enabled - the file is saved + // to the policy dir, otherwise to the default downloads folder. + const base::FilePath expected_location = + skyvault_enabled_ + ? temp_dir.GetPath() + : DownloadPrefs::FromBrowserContext(browser()->profile()) + ->GetDefaultDownloadDirectoryForProfile(); + // Wait for the file to be saved. + EXPECT_TRUE(expected_location.IsParent(path_future.Get())); + } +} + +INSTANTIATE_TEST_SUITE_P(, // Empty to simplify gtest output + CaptureModePolicyBrowserTest, + testing::ValuesIn({ + std::make_pair(true, true), + std::make_pair(true, false), + std::make_pair(false, true), + std::make_pair(false, false), + }));
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller.h b/chrome/browser/ui/autofill/autofill_popup_controller.h index 008cdad..ab0f4ec 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller.h +++ b/chrome/browser/ui/autofill/autofill_popup_controller.h
@@ -18,11 +18,29 @@ #include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/common/aliases.h" +namespace content { +class WebContents; +} // namespace content + namespace autofill { +struct PopupControllerCommon; + // This interface provides data to an AutofillPopupView. class AutofillPopupController : public AutofillPopupViewDelegate { public: + // Acts as a factory method to create a new `AutofillPopupController`, or + // reuse `previous` if the construction arguments are the same. `previous` may + // be invalidated by this call. The controller will listen for keyboard input + // routed to `web_contents` while the popup is showing, unless `web_contents` + // is null. + static base::WeakPtr<AutofillPopupController> GetOrCreate( + base::WeakPtr<AutofillPopupController> previous, + base::WeakPtr<AutofillPopupDelegate> delegate, + content::WebContents* web_contents, + PopupControllerCommon controller_common, + int32_t form_control_ax_id); + // Recalculates the height and width of the popup and triggers a redraw when // suggestions change. virtual void OnSuggestionsChanged() = 0;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc index f5aa886..9683bbe 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -110,7 +110,7 @@ #if !BUILDFLAG(IS_MAC) // static -WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetOrCreate( +WeakPtr<AutofillPopupController> AutofillPopupController::GetOrCreate( WeakPtr<AutofillPopupController> previous, WeakPtr<AutofillPopupDelegate> delegate, content::WebContents* web_contents, @@ -133,12 +133,12 @@ previous->Hide(PopupHidingReason::kViewDestroyed); } #if BUILDFLAG(IS_ANDROID) - AutofillPopupControllerImpl* controller = new AutofillPopupControllerImpl( + auto* controller = new AutofillPopupControllerImpl( delegate, web_contents, std::move(controller_common), form_control_ax_id, base::BindRepeating(&local_password_migration::ShowWarning), /*parent=*/std::nullopt); #else - AutofillPopupControllerImpl* controller = new AutofillPopupControllerImpl( + auto* controller = new AutofillPopupControllerImpl( delegate, web_contents, std::move(controller_common), form_control_ax_id, base::DoNothing(), /*parent=*/std::nullopt); #endif @@ -364,8 +364,12 @@ } // For tests, keep open when hiding is due to external stimuli. if (keep_popup_open_for_testing_ && - reason == PopupHidingReason::kWidgetChanged) { - return; // Don't close the popup because the browser window is resized. + (reason == PopupHidingReason::kWidgetChanged || + reason == PopupHidingReason::kEndEditing)) { + return; // Don't close the popup because the browser window is resized or + // because too many fields get focus one after each other (this can + // happen on Desktop, if multiple password forms are present, and + // they are all autofilled by default). } if (delegate_ && IsRootPopup()) {
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h index da60cca..01c77795 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -74,17 +74,6 @@ AutofillPopupControllerImpl& operator=(const AutofillPopupControllerImpl&) = delete; - // Creates a new `AutofillPopupControllerImpl`, or reuses `previous` if the - // construction arguments are the same. `previous` may be invalidated by this - // call. The controller will listen for keyboard input routed to - // `web_contents` while the popup is showing, unless `web_contents` is NULL. - static base::WeakPtr<AutofillPopupControllerImpl> GetOrCreate( - base::WeakPtr<AutofillPopupController> previous, - base::WeakPtr<AutofillPopupDelegate> delegate, - content::WebContents* web_contents, - PopupControllerCommon controller_common, - int32_t form_control_ax_id); - // Handles a key press event and returns whether the event should be swallowed // (meaning that no other handler, in not particular the default handler, can // process it). @@ -133,8 +122,6 @@ time_view_shown_ = NextIdleTimeTicks::CaptureNextIdleTimeTicks(); } - int GetLineCountForTesting() const { return GetLineCount(); } - protected: AutofillPopupControllerImpl( base::WeakPtr<AutofillPopupDelegate> delegate, @@ -176,6 +163,8 @@ virtual void HideViewAndDie(); private: + friend class AutofillPopupController; + // Clear the internal state of the controller. This is needed to ensure that // when the popup is reused it doesn't leak values between uses. void ClearState();
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm b/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm index 716c9fd8..0e70b2a 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl_mac.mm
@@ -17,7 +17,7 @@ namespace autofill { // static -WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetOrCreate( +WeakPtr<AutofillPopupController> AutofillPopupController::GetOrCreate( WeakPtr<AutofillPopupController> previous, WeakPtr<AutofillPopupDelegate> delegate, content::WebContents* web_contents, @@ -36,7 +36,7 @@ if (previous.get()) previous->Hide(PopupHidingReason::kViewDestroyed); - AutofillPopupControllerImpl* controller = new AutofillPopupControllerImplMac( + auto* controller = new AutofillPopupControllerImplMac( delegate, web_contents, std::move(controller_common), form_control_ax_id); return controller->GetWeakPtr(); }
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc index 0a327fc..44899f04 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc
@@ -4,56 +4,11 @@ #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" -#include <stddef.h> - -#include <memory> #include <optional> -#include <string> -#include <utility> -#include "base/memory/weak_ptr.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/gmock_callback_support.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/mock_callback.h" -#include "base/test/task_environment.h" -#include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/accessibility/accessibility_state_utils.h" -#include "chrome/browser/autofill/personal_data_manager_factory.h" -#include "chrome/browser/ui/autofill/autofill_popup_view.h" -#include "chrome/browser/ui/autofill/popup_controller_common.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "chrome/test/base/testing_profile.h" -#include "components/autofill/content/browser/content_autofill_driver.h" -#include "components/autofill/content/browser/content_autofill_driver_factory.h" -#include "components/autofill/content/browser/content_autofill_driver_factory_test_api.h" -#include "components/autofill/content/browser/test_autofill_client_injector.h" -#include "components/autofill/content/browser/test_autofill_driver_injector.h" -#include "components/autofill/content/browser/test_autofill_manager_injector.h" -#include "components/autofill/content/browser/test_content_autofill_client.h" -#include "components/autofill/core/browser/autofill_driver_router.h" -#include "components/autofill/core/browser/autofill_external_delegate.h" -#include "components/autofill/core/browser/autofill_manager.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/browser_autofill_manager_test_api.h" -#include "components/autofill/core/browser/test_personal_data_manager.h" -#include "components/autofill/core/browser/ui/autofill_popup_delegate.h" -#include "components/autofill/core/browser/ui/popup_hiding_reasons.h" -#include "components/autofill/core/browser/ui/popup_item_ids.h" -#include "components/autofill/core/browser/ui/suggestion.h" -#include "components/autofill/core/common/aliases.h" -#include "components/autofill/core/common/unique_ids.h" -#include "components/password_manager/core/common/password_manager_features.h" -#include "components/prefs/pref_service.h" -#include "components/strings/grit/components_strings.h" -#include "content/public/browser/render_widget_host_view.h" -#include "content/public/browser/video_picture_in_picture_window_controller.h" -#include "content/public/browser/weak_document_ptr.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/input/native_web_keyboard_event.h" -#include "content/public/test/navigation_simulator.h" +#include "chrome/browser/ui/autofill/autofill_popup_controller_test_base.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/ax_active_popup.h" @@ -63,41 +18,21 @@ #include "ui/accessibility/ax_tree_manager_map.h" #include "ui/accessibility/platform/ax_platform_node_base.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/events/event.h" -#include "ui/events/keycodes/dom/dom_code.h" -#include "ui/events/keycodes/dom/keycode_converter.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/text_utils.h" #if !BUILDFLAG(IS_CHROMEOS_ASH) #include "content/public/test/scoped_accessibility_mode_override.h" #endif // !BUILDFLAG(IS_CHROMEOS_ASH) -#if BUILDFLAG(IS_ANDROID) -#include "chrome/browser/autofill/mock_manual_filling_view.h" -#include "chrome/browser/keyboard_accessory/android/manual_filling_controller_impl.h" -#include "chrome/browser/keyboard_accessory/test_utils/android/mock_address_accessory_controller.h" -#include "chrome/browser/keyboard_accessory/test_utils/android/mock_credit_card_accessory_controller.h" -#include "chrome/browser/keyboard_accessory/test_utils/android/mock_password_accessory_controller.h" -#endif // BUILDFLAG(IS_ANDROID) - namespace autofill { + namespace { -using base::ASCIIToUTF16; -using base::WeakPtr; using ::testing::_; -using ::testing::AtLeast; -using ::testing::Eq; +using ::testing::AllOf; using ::testing::Field; -using ::testing::Invoke; using ::testing::Matcher; -using ::testing::Mock; using ::testing::NiceMock; -using ::testing::Optional; using ::testing::Return; -using ::testing::StrictMock; #if !BUILDFLAG(IS_ANDROID) Matcher<const AutofillPopupDelegate::SuggestionPosition&> @@ -109,1139 +44,9 @@ } #endif // !BUILDFLAG(IS_ANDROID) -class MockAutofillDriver : public ContentAutofillDriver { - public: - MockAutofillDriver(content::RenderFrameHost* rfh, - ContentAutofillDriverFactory* factory) - : ContentAutofillDriver(rfh, factory) {} - - MockAutofillDriver(MockAutofillDriver&) = delete; - MockAutofillDriver& operator=(MockAutofillDriver&) = delete; - - ~MockAutofillDriver() override = default; - MOCK_METHOD(ui::AXTreeID, GetAxTreeId, (), (const override)); -}; - -class MockAutofillExternalDelegate : public AutofillExternalDelegate { - public: - explicit MockAutofillExternalDelegate( - BrowserAutofillManager* autofill_manager) - : AutofillExternalDelegate(autofill_manager) {} - ~MockAutofillExternalDelegate() override = default; - - void DidSelectSuggestion(const Suggestion& suggestion) override {} - - MOCK_METHOD(void, ClearPreviewedForm, (), (override)); - MOCK_METHOD(void, OnPopupShown, (), (override)); - MOCK_METHOD(void, OnPopupHidden, (), (override)); - MOCK_METHOD(void, - DidAcceptSuggestion, - (const Suggestion&, - const AutofillPopupDelegate::SuggestionPosition&), - (override)); - MOCK_METHOD(void, - DidPerformButtonActionForSuggestion, - (const Suggestion&), - (override)); - MOCK_METHOD(bool, RemoveSuggestion, (const Suggestion&), (override)); -}; - -class MockAutofillPopupView : public AutofillPopupView { - public: - MockAutofillPopupView() = default; - MockAutofillPopupView(MockAutofillPopupView&) = delete; - MockAutofillPopupView& operator=(MockAutofillPopupView&) = delete; - ~MockAutofillPopupView() override = default; - - MOCK_METHOD(bool, Show, (AutoselectFirstSuggestion), (override)); - MOCK_METHOD(void, Hide, (), (override)); - MOCK_METHOD(bool, - HandleKeyPressEvent, - (const content::NativeWebKeyboardEvent&), - (override)); - MOCK_METHOD(void, OnSuggestionsChanged, (), (override)); - MOCK_METHOD(bool, OverlapsWithPictureInPictureWindow, (), (const override)); - MOCK_METHOD(std::optional<int32_t>, GetAxUniqueId, (), (override)); - MOCK_METHOD(void, AxAnnounce, (const std::u16string&), (override)); - MOCK_METHOD(base::WeakPtr<AutofillPopupView>, - CreateSubPopupView, - (base::WeakPtr<AutofillPopupController>), - (override)); - MOCK_METHOD(std::optional<AutofillClient::PopupScreenLocation>, - GetPopupScreenLocation, - (), - (const override)); - - base::WeakPtr<AutofillPopupView> GetWeakPtr() override { - return weak_ptr_factory_.GetWeakPtr(); - } - - private: - base::WeakPtrFactory<AutofillPopupView> weak_ptr_factory_{this}; -}; - -class TestAutofillPopupController : public AutofillPopupControllerImpl { - public: - TestAutofillPopupController( - base::WeakPtr<AutofillExternalDelegate> external_delegate, - content::WebContents* web_contents, - const gfx::RectF& element_bounds, - base::RepeatingCallback<void( - gfx::NativeWindow, - Profile*, - password_manager::metrics_util::PasswordMigrationWarningTriggers)> - show_pwd_migration_warning_callback, - std::optional<base::WeakPtr<ExpandablePopupParentControllerImpl>> parent = - std::nullopt) - : AutofillPopupControllerImpl( - external_delegate, - web_contents, - PopupControllerCommon(element_bounds, - base::i18n::UNKNOWN_DIRECTION, - nullptr), - /*form_control_ax_id=*/0, - std::move(show_pwd_migration_warning_callback), - parent) {} - ~TestAutofillPopupController() override = default; - - // Making protected functions public for testing - using AutofillPopupControllerImpl::AcceptSuggestion; - using AutofillPopupControllerImpl::element_bounds; - using AutofillPopupControllerImpl::FireControlsChangedEvent; - using AutofillPopupControllerImpl::GetLineCount; - using AutofillPopupControllerImpl::GetRootAXPlatformNodeForWebContents; - using AutofillPopupControllerImpl::GetSuggestionAt; - using AutofillPopupControllerImpl::GetSuggestionLabelsAt; - using AutofillPopupControllerImpl::GetSuggestionMainTextAt; - using AutofillPopupControllerImpl::GetWeakPtr; - using AutofillPopupControllerImpl::PerformButtonActionForSuggestion; - using AutofillPopupControllerImpl::RemoveSuggestion; - using AutofillPopupControllerImpl::SelectSuggestion; - MOCK_METHOD(void, Hide, (PopupHidingReason reason), (override)); - MOCK_METHOD(ui::AXPlatformNode*, - GetRootAXPlatformNodeForWebContents, - (), - (override)); - - void DoHide() { DoHide(PopupHidingReason::kTabGone); } - - void DoHide(PopupHidingReason reason) { - AutofillPopupControllerImpl::Hide(reason); - } -}; - -class BrowserAutofillManagerWithMockDelegate : public BrowserAutofillManager { - public: - explicit BrowserAutofillManagerWithMockDelegate(AutofillDriver* driver) - : BrowserAutofillManager(driver, "en-US") { - test_api(*this).SetExternalDelegate( - std::make_unique<NiceMock<MockAutofillExternalDelegate>>(this)); - } - - BrowserAutofillManagerWithMockDelegate( - BrowserAutofillManagerWithMockDelegate&) = delete; - BrowserAutofillManagerWithMockDelegate& operator=( - BrowserAutofillManagerWithMockDelegate&) = delete; - - ~BrowserAutofillManagerWithMockDelegate() override = default; - - MockAutofillExternalDelegate& external_delegate() { - return static_cast<MockAutofillExternalDelegate&>( - *test_api(*this).external_delegate()); - } -}; - -class TestContentAutofillClientWithMockController - : public TestContentAutofillClient { - public: - explicit TestContentAutofillClientWithMockController( - content::WebContents* web_contents) - : TestContentAutofillClient(web_contents) { - ON_CALL(popup_view(), CreateSubPopupView) - .WillByDefault(Return(sub_popup_view().GetWeakPtr())); - } - - ~TestContentAutofillClientWithMockController() override { DoHide(); } - - // Returns the current controller. Controllers are specific to the `manager`'s - // AutofillExternalDelegate. Therefore, when there are two consecutive - // `popup_controller(x)` and `popup_controller(y)`, the second call hides the - // old and creates new controller iff `x` and `y` are distinct. - TestAutofillPopupController& popup_controller( - BrowserAutofillManagerWithMockDelegate& manager) { - if (manager_of_last_controller_.get() != &manager) { - DoHide(); - CHECK(!popup_controller_); - } - if (!popup_controller_) { - popup_controller_ = (new NiceMock<TestAutofillPopupController>( - manager.external_delegate().GetWeakPtrForTest(), - &GetWebContents(), gfx::RectF(), - show_pwd_migration_warning_callback_.Get())) - ->GetWeakPtr(); - popup_controller_->SetViewForTesting(popup_view_->GetWeakPtr()); - manager_of_last_controller_ = manager.GetWeakPtr(); - ON_CALL(cast_popup_controller(), Hide) - .WillByDefault([this](PopupHidingReason reason) { DoHide(reason); }); - } - return cast_popup_controller(); - } - - MockAutofillPopupView& popup_view() { return *popup_view_; } - - MockAutofillPopupView& sub_popup_view() { return *sub_popup_view_; } - -#if BUILDFLAG(IS_ANDROID) - base::MockCallback<base::RepeatingCallback< - void(gfx::NativeWindow, - Profile*, - password_manager::metrics_util::PasswordMigrationWarningTriggers)>>& - show_pwd_migration_warning_callback() { - return show_pwd_migration_warning_callback_; - } -#endif // BUILDFLAG(IS_ANDROID) - - private: - void DoHide(PopupHidingReason reason) { - if (popup_controller_) { - cast_popup_controller().DoHide(reason); - } - } - - void DoHide() { - if (popup_controller_) { - cast_popup_controller().DoHide(); - } - } - - TestAutofillPopupController& cast_popup_controller() { - return static_cast<TestAutofillPopupController&>(*popup_controller_); - } - - base::WeakPtr<AutofillPopupControllerImpl> popup_controller_; - base::WeakPtr<AutofillManager> manager_of_last_controller_; - - std::unique_ptr<MockAutofillPopupView> popup_view_ = - std::make_unique<NiceMock<MockAutofillPopupView>>(); - std::unique_ptr<MockAutofillPopupView> sub_popup_view_ = - std::make_unique<NiceMock<MockAutofillPopupView>>(); - base::MockCallback<base::RepeatingCallback<void( - gfx::NativeWindow, - Profile*, - password_manager::metrics_util::PasswordMigrationWarningTriggers)>> - show_pwd_migration_warning_callback_; -}; - -content::RenderFrameHost* CreateAndNavigateChildFrame( - content::RenderFrameHost* parent, - const GURL& url, - std::string_view name) { - content::RenderFrameHost* rfh = - content::RenderFrameHostTester::For(parent)->AppendChild( - std::string(name)); - // ContentAutofillDriverFactory::DidFinishNavigation() creates a driver for - // subframes only if - // `NavigationHandle::HasSubframeNavigationEntryCommitted()` is true. This - // is not the case for the first navigation. (In non-unit-tests, the first - // navigation creates a driver in - // ContentAutofillDriverFactory::BindAutofillDriver().) Therefore, - // we simulate *two* navigations here, and explicitly set the transition - // type for the second navigation. - std::unique_ptr<content::NavigationSimulator> simulator; - // First navigation: `HasSubframeNavigationEntryCommitted() == false`. - // Must be a different URL from the second navigation. - GURL about_blank("about:blank"); - CHECK_NE(about_blank, url); - simulator = - content::NavigationSimulator::CreateRendererInitiated(about_blank, rfh); - simulator->Commit(); - rfh = simulator->GetFinalRenderFrameHost(); - // Second navigation: `HasSubframeNavigationEntryCommitted() == true`. - // Must set the transition type to ui::PAGE_TRANSITION_MANUAL_SUBFRAME. - simulator = content::NavigationSimulator::CreateRendererInitiated(url, rfh); - simulator->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME); - simulator->Commit(); - return simulator->GetFinalRenderFrameHost(); -} - -content::RenderFrameHost* NavigateAndCommitFrame(content::RenderFrameHost* rfh, - const GURL& url) { - std::unique_ptr<content::NavigationSimulator> simulator = - content::NavigationSimulator::CreateRendererInitiated(url, rfh); - simulator->Commit(); - return simulator->GetFinalRenderFrameHost(); -} - } // namespace -class AutofillPopupControllerImplTest : public ChromeRenderViewHostTestHarness { - public: - AutofillPopupControllerImplTest() - : ChromeRenderViewHostTestHarness( - base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} - ~AutofillPopupControllerImplTest() override = default; - - void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - PersonalDataManagerFactory::GetInstance()->SetTestingFactory( - profile(), base::BindRepeating([](content::BrowserContext* context) - -> std::unique_ptr<KeyedService> { - return std::make_unique<TestPersonalDataManager>(); - })); - NavigateAndCommit(GURL("https://foo.com/")); - FocusWebContentsOnMainFrame(); - ASSERT_TRUE(web_contents()->GetFocusedFrame()); - -#if BUILDFLAG(IS_ANDROID) - ManualFillingControllerImpl::CreateForWebContentsForTesting( - web_contents(), mock_pwd_controller_.AsWeakPtr(), - mock_address_controller_.AsWeakPtr(), mock_cc_controller_.AsWeakPtr(), - std::make_unique<NiceMock<MockManualFillingView>>()); -#endif // BUILDFLAG(IS_ANDROID) - } - - void TearDown() override { - // Wait for the pending deletion of the controllers. Otherwise, the - // controllers are destroyed after the WebContents, and each of them - // receives a final Hide() call for which we'd need to add explicit - // expectations. - task_environment()->RunUntilIdle(); - ChromeRenderViewHostTestHarness::TearDown(); - } - - content::RenderFrameHost* main_frame() { - return web_contents()->GetPrimaryMainFrame(); - } - - TestContentAutofillClientWithMockController& client() { - return *autofill_client_injector_[web_contents()]; - } - - MockAutofillDriver& driver(content::RenderFrameHost* rfh = nullptr) { - return *autofill_driver_injector_[rfh ? rfh : main_frame()]; - } - - BrowserAutofillManagerWithMockDelegate& manager( - content::RenderFrameHost* rfh = nullptr) { - return *autofill_manager_injector_[rfh ? rfh : main_frame()]; - } - - TestPersonalDataManager& personal_data() { - return static_cast<TestPersonalDataManager&>( - *PersonalDataManagerFactory::GetForProfile(profile())); - } - - // Shows empty suggestions with the popup_item_id ids passed as - // `popup_item_ids`. - void ShowSuggestions( - BrowserAutofillManagerWithMockDelegate& manager, - const std::vector<PopupItemId>& popup_item_ids, - AutofillSuggestionTriggerSource trigger_source = - AutofillSuggestionTriggerSource::kFormControlElementClicked) { - std::vector<Suggestion> suggestions; - suggestions.reserve(popup_item_ids.size()); - for (PopupItemId popup_item_id : popup_item_ids) { - suggestions.emplace_back(u"", popup_item_id); - } - ShowSuggestions(manager, std::move(suggestions), trigger_source); - } - - void ShowSuggestions( - BrowserAutofillManagerWithMockDelegate& manager, - std::vector<Suggestion> suggestions, - AutofillSuggestionTriggerSource trigger_source = - AutofillSuggestionTriggerSource::kFormControlElementClicked) { - FocusWebContentsOnFrame( - static_cast<ContentAutofillDriver&>(manager.driver()) - .render_frame_host()); - client().popup_controller(manager).Show(std::move(suggestions), - trigger_source, - AutoselectFirstSuggestion(false)); - } - - content::NativeWebKeyboardEvent CreateKeyPressEvent(int windows_key_code) { - content::NativeWebKeyboardEvent event( - blink::WebInputEvent::Type::kRawKeyDown, - blink::WebInputEvent::kNoModifiers, - blink::WebInputEvent::GetStaticTimeStampForTests()); - event.windows_key_code = windows_key_code; - return event; - } - - private: - test::AutofillUnitTestEnvironment autofill_test_environment_; - - TestAutofillClientInjector<TestContentAutofillClientWithMockController> - autofill_client_injector_; - TestAutofillDriverInjector<NiceMock<MockAutofillDriver>> - autofill_driver_injector_; - TestAutofillManagerInjector<BrowserAutofillManagerWithMockDelegate> - autofill_manager_injector_; - -#if BUILDFLAG(IS_ANDROID) - NiceMock<MockPasswordAccessoryController> mock_pwd_controller_; - NiceMock<MockAddressAccessoryController> mock_address_controller_; - NiceMock<MockCreditCardAccessoryController> mock_cc_controller_; -#endif // BUILDFLAG(IS_ANDROID) -}; - -TEST_F(AutofillPopupControllerImplTest, RemoveSuggestion) { - ShowSuggestions(manager(), - {PopupItemId::kAddressEntry, PopupItemId::kAddressEntry, - PopupItemId::kAutofillOptions}); - - // Generate a popup, so it can be hidden later. It doesn't matter what the - // external_delegate thinks is being shown in the process, since we are just - // testing the popup here. - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAddressEntry))) - .WillRepeatedly(Return(true)); - - // Remove the first entry. The popup should be redrawn since its size has - // changed. - EXPECT_CALL(client().popup_view(), OnSuggestionsChanged()); - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); - Mock::VerifyAndClearExpectations(&client().popup_view()); - - // Remove the next entry. The popup should then be hidden since there are - // no Autofill entries left. - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kNoSuggestions)); - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); -} - -// Regression test for (crbug.com/1513574): Showing an Autofill Compose -// suggestion twice does not crash. -TEST_F(AutofillPopupControllerImplTest, ShowTwice) { - ShowSuggestions(manager(), - {Suggestion(u"Help me write", PopupItemId::kCompose)}); - ShowSuggestions(manager(), - {Suggestion(u"Help me write", PopupItemId::kCompose)}); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAutocompleteSuggestion_AnnounceText) { - ShowSuggestions(manager(), - {Suggestion(u"main text", PopupItemId::kAutocompleteEntry)}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAutocompleteEntry))) - .WillOnce(Return(true)); - EXPECT_CALL(client().popup_view(), - AxAnnounce(Eq(u"Entry main text has been deleted"))); - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAutocompleteSuggestion_IgnoresClickOutsideCheck) { - ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry, - PopupItemId::kAutocompleteEntry}); - - // Generate a popup, so it can be hidden later. It doesn't matter what the - // external_delegate thinks is being shown in the process, since we are just - // testing the popup here. - test::GenerateTestAutofillPopup(&manager().external_delegate()); - - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAutocompleteEntry))) - .WillOnce(Return(true)); - // Remove the first entry. The popup should be redrawn since its size has - // changed. - EXPECT_CALL(client().popup_view(), OnSuggestionsChanged()); - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); - Mock::VerifyAndClearExpectations(&client().popup_view()); - - EXPECT_TRUE(client() - .popup_controller(manager()) - .ShouldIgnoreMouseObservedOutsideItemBoundsCheck()); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAutocompleteSuggestion_NoMetricsEmittedOnFail) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAutocompleteEntry))) - .WillOnce(Return(false)); - - EXPECT_FALSE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); - histogram_tester.ExpectUniqueSample( - "Autofill.Autocomplete.SingleEntryRemovalMethod", - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, - 0); - histogram_tester.ExpectUniqueSample( - "Autocomplete.Events2", - AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAutocompleteSuggestion_MetricsEmittedOnSuccess) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAutocompleteEntry))) - .WillOnce(Return(true)); - - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); - histogram_tester.ExpectUniqueSample( - "Autofill.Autocomplete.SingleEntryRemovalMethod", - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, - 1); - histogram_tester.ExpectUniqueSample( - "Autocomplete.Events2", - AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 1); - // Also no autofill metrics are emitted. - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); - histogram_tester.ExpectUniqueSample( - "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAddressSuggestion_ShiftDelete_NoMetricsEmittedOnFail) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAddressEntry))) - .WillOnce(Return(false)); - - EXPECT_FALSE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); - histogram_tester.ExpectUniqueSample( - "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAddressSuggestion_ShiftDelete_MetricsEmittedOnSuccess) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAddressEntry))) - .WillOnce(Return(true)); - - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 1); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 1); - // Also no autocomplete or keyboard accessory metrics are emitted. - histogram_tester.ExpectUniqueSample( - "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); - histogram_tester.ExpectUniqueSample( - "Autofill.Autocomplete.SingleEntryRemovalMethod", - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, - 0); - histogram_tester.ExpectUniqueSample( - "Autocomplete.Events2", - AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAddressSuggestion_KeyboardAccessory_NoMetricsEmittedOnFail) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAddressEntry))) - .WillOnce(Return(false)); - - EXPECT_FALSE(client().popup_controller(manager()).RemoveSuggestion( - 0, AutofillMetrics::SingleEntryRemovalMethod::kKeyboardAccessory)); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); - histogram_tester.ExpectUniqueSample( - "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveAddressSuggestion_KeyboardAccessory_MetricsEmittedOnSuccess) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kAddressEntry))) - .WillOnce(Return(true)); - - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, AutofillMetrics::SingleEntryRemovalMethod::kKeyboardAccessory)); - histogram_tester.ExpectUniqueSample( - "Autofill.ProfileDeleted.KeyboardAccessory", 1, 1); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 1); - // Also no autocomplete or shift+delete metrics are emitted. - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); - histogram_tester.ExpectUniqueSample( - "Autofill.Autocomplete.SingleEntryRemovalMethod", - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, - 0); - histogram_tester.ExpectUniqueSample( - "Autocomplete.Events2", - AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); -} - -TEST_F(AutofillPopupControllerImplTest, - RemoveCreditCardSuggestion_NoMetricsEmitted) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kCreditCardEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(manager().external_delegate(), - RemoveSuggestion(Field(&Suggestion::popup_item_id, - PopupItemId::kCreditCardEntry))) - .WillOnce(Return(true)); - - EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( - 0, - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); - histogram_tester.ExpectUniqueSample( - "Autofill.Autocomplete.SingleEntryRemovalMethod", - AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, - 0); - histogram_tester.ExpectUniqueSample( - "Autocomplete.Events2", - AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); - histogram_tester.ExpectUniqueSample( - "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); - histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); -} - -TEST_F(AutofillPopupControllerImplTest, - ManualFallBackTriggerSource_IgnoresClickOutsideCheck) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}, - AutofillSuggestionTriggerSource::kManualFallbackAddress); - - // Generate a popup, so it can be hidden later. It doesn't matter what the - // external_delegate thinks is being shown in the process, since we are just - // testing the popup here. - test::GenerateTestAutofillPopup(&manager().external_delegate()); - - EXPECT_TRUE(client() - .popup_controller(manager()) - .ShouldIgnoreMouseObservedOutsideItemBoundsCheck()); -} - -TEST_F(AutofillPopupControllerImplTest, UpdateDataListValues) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - std::vector<SelectOption> options = { - {.value = u"data list value 1", .content = u"data list label 1"}}; - client().popup_controller(manager()).UpdateDataListValues(options); - - ASSERT_EQ(3, client().popup_controller(manager()).GetLineCount()); - - Suggestion result0 = client().popup_controller(manager()).GetSuggestionAt(0); - EXPECT_EQ(options[0].value, result0.main_text.value); - EXPECT_EQ(options[0].value, - client().popup_controller(manager()).GetSuggestionMainTextAt(0)); - ASSERT_EQ(1u, result0.labels.size()); - ASSERT_EQ(1u, result0.labels[0].size()); - EXPECT_EQ(options[0].content, result0.labels[0][0].value); - EXPECT_EQ(std::u16string(), result0.additional_label); - EXPECT_EQ(options[0].content, client() - .popup_controller(manager()) - .GetSuggestionLabelsAt(0)[0][0] - .value); - EXPECT_EQ(PopupItemId::kDatalistEntry, result0.popup_item_id); - - Suggestion result1 = client().popup_controller(manager()).GetSuggestionAt(1); - EXPECT_EQ(std::u16string(), result1.main_text.value); - EXPECT_TRUE(result1.labels.empty()); - EXPECT_EQ(std::u16string(), result1.additional_label); - EXPECT_EQ(PopupItemId::kSeparator, result1.popup_item_id); - - Suggestion result2 = client().popup_controller(manager()).GetSuggestionAt(2); - EXPECT_EQ(std::u16string(), result2.main_text.value); - EXPECT_TRUE(result2.labels.empty()); - EXPECT_EQ(std::u16string(), result2.additional_label); - EXPECT_EQ(PopupItemId::kAddressEntry, result2.popup_item_id); - - // Add two data list entries (which should replace the current one). - options.push_back( - {.value = u"data list value 1", .content = u"data list label 1"}); - client().popup_controller(manager()).UpdateDataListValues(options); - ASSERT_EQ(4, client().popup_controller(manager()).GetLineCount()); - - // Original one first, followed by new one, then separator. - EXPECT_EQ( - options[0].value, - client().popup_controller(manager()).GetSuggestionAt(0).main_text.value); - EXPECT_EQ(options[0].value, - client().popup_controller(manager()).GetSuggestionMainTextAt(0)); - ASSERT_EQ( - 1u, - client().popup_controller(manager()).GetSuggestionAt(0).labels.size()); - ASSERT_EQ( - 1u, - client().popup_controller(manager()).GetSuggestionAt(0).labels[0].size()); - EXPECT_EQ(options[0].content, client() - .popup_controller(manager()) - .GetSuggestionAt(0) - .labels[0][0] - .value); - EXPECT_EQ( - std::u16string(), - client().popup_controller(manager()).GetSuggestionAt(0).additional_label); - EXPECT_EQ( - options[1].value, - client().popup_controller(manager()).GetSuggestionAt(1).main_text.value); - EXPECT_EQ(options[1].value, - client().popup_controller(manager()).GetSuggestionMainTextAt(1)); - ASSERT_EQ( - 1u, - client().popup_controller(manager()).GetSuggestionAt(1).labels.size()); - ASSERT_EQ( - 1u, - client().popup_controller(manager()).GetSuggestionAt(1).labels[0].size()); - EXPECT_EQ(options[1].content, client() - .popup_controller(manager()) - .GetSuggestionAt(1) - .labels[0][0] - .value); - EXPECT_EQ( - std::u16string(), - client().popup_controller(manager()).GetSuggestionAt(1).additional_label); - EXPECT_EQ( - PopupItemId::kSeparator, - client().popup_controller(manager()).GetSuggestionAt(2).popup_item_id); - - // Clear all data list values. - options.clear(); - client().popup_controller(manager()).UpdateDataListValues(options); - - ASSERT_EQ(1, client().popup_controller(manager()).GetLineCount()); - EXPECT_EQ( - PopupItemId::kAddressEntry, - client().popup_controller(manager()).GetSuggestionAt(0).popup_item_id); -} - -TEST_F(AutofillPopupControllerImplTest, PopupsWithOnlyDataLists) { - // Create the popup with a single datalist element. - ShowSuggestions(manager(), {PopupItemId::kDatalistEntry}); - - // Replace the datalist element with a new one. - std::vector<SelectOption> options = { - {.value = u"data list value 1", .content = u"data list label 1"}}; - client().popup_controller(manager()).UpdateDataListValues(options); - - ASSERT_EQ(1, client().popup_controller(manager()).GetLineCount()); - EXPECT_EQ( - options[0].value, - client().popup_controller(manager()).GetSuggestionAt(0).main_text.value); - ASSERT_EQ( - 1u, - client().popup_controller(manager()).GetSuggestionAt(0).labels.size()); - ASSERT_EQ( - 1u, - client().popup_controller(manager()).GetSuggestionAt(0).labels[0].size()); - EXPECT_EQ(options[0].content, client() - .popup_controller(manager()) - .GetSuggestionAt(0) - .labels[0][0] - .value); - EXPECT_EQ( - std::u16string(), - client().popup_controller(manager()).GetSuggestionAt(0).additional_label); - EXPECT_EQ( - PopupItemId::kDatalistEntry, - client().popup_controller(manager()).GetSuggestionAt(0).popup_item_id); - - // Clear datalist values and check that the popup becomes hidden. - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kNoSuggestions)); - options.clear(); - client().popup_controller(manager()).UpdateDataListValues(options); -} - -TEST_F(AutofillPopupControllerImplTest, GetOrCreate) { - auto create_controller = [&](gfx::RectF bounds) { - return AutofillPopupControllerImpl::GetOrCreate( - client().popup_controller(manager()).GetWeakPtr(), - manager().external_delegate().GetWeakPtrForTest(), nullptr, - PopupControllerCommon(std::move(bounds), base::i18n::UNKNOWN_DIRECTION, - nullptr), - /*form_control_ax_id=*/0); - }; - WeakPtr<AutofillPopupControllerImpl> controller = - create_controller(gfx::RectF()); - EXPECT_TRUE(controller); - - controller->Hide(PopupHidingReason::kViewDestroyed); - EXPECT_FALSE(controller); - - controller = create_controller(gfx::RectF()); - EXPECT_TRUE(controller); - - WeakPtr<AutofillPopupControllerImpl> controller2 = - create_controller(gfx::RectF()); - EXPECT_EQ(controller.get(), controller2.get()); - - controller->Hide(PopupHidingReason::kViewDestroyed); - EXPECT_FALSE(controller); - EXPECT_FALSE(controller2); - - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kViewDestroyed)); - gfx::RectF bounds(0.f, 0.f, 1.f, 2.f); - base::WeakPtr<AutofillPopupControllerImpl> controller3 = - create_controller(bounds); - EXPECT_EQ(&client().popup_controller(manager()), controller3.get()); - EXPECT_EQ(bounds, static_cast<AutofillPopupController*>(controller3.get()) - ->element_bounds()); - controller3->Hide(PopupHidingReason::kViewDestroyed); - - client().popup_controller(manager()).DoHide(); - - const base::WeakPtr<AutofillPopupControllerImpl> controller4 = - create_controller(bounds); - EXPECT_EQ(&client().popup_controller(manager()), controller4.get()); - EXPECT_EQ(bounds, - static_cast<const AutofillPopupController*>(controller4.get()) - ->element_bounds()); - - client().popup_controller(manager()).DoHide(); -} - -TEST_F(AutofillPopupControllerImplTest, ProperlyResetController) { - ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry, - PopupItemId::kAutocompleteEntry}); - - // Now show a new popup with the same controller, but with fewer items. - WeakPtr<AutofillPopupControllerImpl> controller = - AutofillPopupControllerImpl::GetOrCreate( - client().popup_controller(manager()).GetWeakPtr(), - manager().external_delegate().GetWeakPtrForTest(), nullptr, - PopupControllerCommon(gfx::RectF(), base::i18n::UNKNOWN_DIRECTION, - nullptr), - /*form_control_ax_id=*/0); - EXPECT_EQ(0, controller->GetLineCountForTesting()); -} - -TEST_F(AutofillPopupControllerImplTest, UnselectingClearsPreview) { - EXPECT_CALL(manager().external_delegate(), ClearPreviewedForm()); - client().popup_controller(manager()).UnselectSuggestion(); -} - -TEST_F(AutofillPopupControllerImplTest, HidingClearsPreview) { - EXPECT_CALL(manager().external_delegate(), ClearPreviewedForm()); - EXPECT_CALL(manager().external_delegate(), OnPopupHidden()); - client().popup_controller(manager()).DoHide(); -} - -TEST_F(AutofillPopupControllerImplTest, DontHideWhenWaitingForData) { - EXPECT_CALL(client().popup_view(), Hide).Times(0); - client().popup_controller(manager()).PinView(); - - // Hide() will not work for stale data or when focusing native UI. - client().popup_controller(manager()).DoHide(PopupHidingReason::kStaleData); - client().popup_controller(manager()).DoHide(PopupHidingReason::kEndEditing); - - // Check the expectations now since TearDown will perform a successful hide. - Mock::VerifyAndClearExpectations(&manager().external_delegate()); - Mock::VerifyAndClearExpectations(&client().popup_view()); -} - -TEST_F(AutofillPopupControllerImplTest, ShouldReportHidingPopupReason) { - base::HistogramTester histogram_tester; - client().popup_controller(manager()).DoHide(PopupHidingReason::kTabGone); - histogram_tester.ExpectTotalCount("Autofill.PopupHidingReason", 1); - histogram_tester.ExpectBucketCount("Autofill.PopupHidingReason", - /*kTabGone=*/8, 1); -} - -// This is a regression test for crbug.com/521133 to ensure that we don't crash -// when suggestions updates race with user selections. -TEST_F(AutofillPopupControllerImplTest, SelectInvalidSuggestion) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); - - // The following should not crash: - client().popup_controller(manager()).AcceptSuggestion( - /*index=*/1); // Out of bounds! -} - -TEST_F(AutofillPopupControllerImplTest, AcceptSuggestionRespectsTimeout) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - - // Calls before the threshold are ignored. - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); - client().popup_controller(manager()).AcceptSuggestion(0); - task_environment()->FastForwardBy(base::Milliseconds(100)); - client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); - - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion); - task_environment()->FastForwardBy(base::Milliseconds(400)); - client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); - - histogram_tester.ExpectTotalCount( - "Autofill.Popup.AcceptanceDelayThresholdNotMet", 2); -} - -TEST_F(AutofillPopupControllerImplTest, - AcceptSuggestionTimeoutIsUpdatedOnPopupMove) { - base::HistogramTester histogram_tester; - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - - // Calls before the threshold are ignored. - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); - client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); - task_environment()->FastForwardBy(base::Milliseconds(100)); - client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); - - histogram_tester.ExpectTotalCount( - "Autofill.Popup.AcceptanceDelayThresholdNotMet", 2); - task_environment()->FastForwardBy(base::Milliseconds(400)); - // Show the suggestions again (simulating, e.g., a click somewhere slightly - // different). - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); - client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); - histogram_tester.ExpectTotalCount( - "Autofill.Popup.AcceptanceDelayThresholdNotMet", 3); - - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion); - // After waiting, suggestions are accepted again. - task_environment()->FastForwardBy(base::Milliseconds(500)); - client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); - histogram_tester.ExpectTotalCount( - "Autofill.Popup.AcceptanceDelayThresholdNotMet", 3); -} - -// Tests that when a picture-in-picture window is initialized, there is a call -// to the popup view to check if the autofill popup bounds overlap with the -// picture-in-picture window. -TEST_F(AutofillPopupControllerImplTest, - CheckBoundsOverlapWithPictureInPicture) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - PictureInPictureWindowManager* picture_in_picture_window_manager = - PictureInPictureWindowManager::GetInstance(); - EXPECT_CALL(client().popup_view(), OverlapsWithPictureInPictureWindow); - picture_in_picture_window_manager->NotifyObserversOnEnterPictureInPicture(); -} - -TEST_F(AutofillPopupControllerImplTest, - GetRemovalConfirmationText_UnrelatedPopupItemId) { - std::u16string title; - std::u16string body; - ShowSuggestions( - manager(), - {Suggestion(u"Entry", PopupItemId::kAddressFieldByFieldFilling)}); - - EXPECT_FALSE(client().popup_controller(manager()).GetRemovalConfirmationText( - 0, &title, &body)); -} - -TEST_F(AutofillPopupControllerImplTest, - GetRemovalConfirmationText_InvalidUniqueId) { - std::u16string title; - std::u16string body; - ShowSuggestions(manager(), {test::CreateAutofillSuggestion( - PopupItemId::kAddressFieldByFieldFilling, - u"Entry", Suggestion::Guid("1111"))}); - - EXPECT_FALSE(client().popup_controller(manager()).GetRemovalConfirmationText( - 0, &title, &body)); -} - -TEST_F(AutofillPopupControllerImplTest, - GetRemovalConfirmationText_Autocomplete) { - std::u16string title; - std::u16string body; - ShowSuggestions(manager(), {Suggestion(u"Autocomplete entry", - PopupItemId::kAutocompleteEntry)}); - - EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( - 0, &title, &body)); - EXPECT_EQ(title, u"Autocomplete entry"); - EXPECT_EQ(body, - l10n_util::GetStringUTF16( - IDS_AUTOFILL_DELETE_AUTOCOMPLETE_SUGGESTION_CONFIRMATION_BODY)); -} - -TEST_F(AutofillPopupControllerImplTest, - GetRemovalConfirmationText_LocalCreditCard) { - CreditCard local_card = test::GetCreditCard(); - personal_data().AddCreditCard(local_card); - - std::u16string title; - std::u16string body; - ShowSuggestions(manager(), - {test::CreateAutofillSuggestion( - PopupItemId::kCreditCardEntry, u"Local credit card", - Suggestion::Guid(local_card.guid()))}); - - EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( - 0, &title, &body)); - EXPECT_EQ(title, local_card.CardNameAndLastFourDigits()); - EXPECT_EQ(body, - l10n_util::GetStringUTF16( - IDS_AUTOFILL_DELETE_CREDIT_CARD_SUGGESTION_CONFIRMATION_BODY)); -} - -TEST_F(AutofillPopupControllerImplTest, - GetRemovalConfirmationText_ServerCreditCard) { - CreditCard server_card = test::GetMaskedServerCard(); - personal_data().AddServerCreditCard(server_card); - - std::u16string title; - std::u16string body; - ShowSuggestions(manager(), - {test::CreateAutofillSuggestion( - PopupItemId::kCreditCardEntry, u"Server credit card", - Suggestion::Guid(server_card.guid()))}); - - EXPECT_FALSE(client().popup_controller(manager()).GetRemovalConfirmationText( - 0, &title, &body)); -} - -TEST_F(AutofillPopupControllerImplTest, - GetRemovalConfirmationText_CompleteAutofillProfile) { - AutofillProfile complete_profile = test::GetFullProfile(); - personal_data().AddProfile(complete_profile); - - std::u16string title; - std::u16string body; - ShowSuggestions(manager(), - {test::CreateAutofillSuggestion( - PopupItemId::kAddressEntry, u"Complete autofill profile", - Suggestion::Guid(complete_profile.guid()))}); - - EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( - 0, &title, &body)); - EXPECT_EQ(title, complete_profile.GetRawInfo(ADDRESS_HOME_CITY)); - EXPECT_EQ(body, - l10n_util::GetStringUTF16( - IDS_AUTOFILL_DELETE_PROFILE_SUGGESTION_CONFIRMATION_BODY)); -} - -TEST_F(AutofillPopupControllerImplTest, - GetRemovalConfirmationText_AutofillProfile_EmptyCity) { - AutofillProfile profile = test::GetFullProfile(); - profile.ClearFields({ADDRESS_HOME_CITY}); - personal_data().AddProfile(profile); - - std::u16string title; - std::u16string body; - ShowSuggestions(manager(), {test::CreateAutofillSuggestion( - PopupItemId::kAddressEntry, - u"Autofill profile without city", - Suggestion::Guid(profile.guid()))}); - - EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( - 0, &title, &body)); - EXPECT_EQ(title, u"Autofill profile without city"); - EXPECT_EQ(body, - l10n_util::GetStringUTF16( - IDS_AUTOFILL_DELETE_PROFILE_SUGGESTION_CONFIRMATION_BODY)); -} - -#if BUILDFLAG(IS_ANDROID) -TEST_F(AutofillPopupControllerImplTest, - AcceptPwdSuggestionInvokesWarningAndroid) { - base::test::ScopedFeatureList scoped_feature_list( - password_manager::features:: - kUnifiedPasswordManagerLocalPasswordsMigrationWarning); - ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); - - // Calls are accepted immediately. - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); - EXPECT_CALL(client().show_pwd_migration_warning_callback(), - Run(_, _, - password_manager::metrics_util:: - PasswordMigrationWarningTriggers::kKeyboardAcessoryBar)); - task_environment()->FastForwardBy(base::Milliseconds(500)); - client().popup_controller(manager()).AcceptSuggestion(0); -} - -TEST_F(AutofillPopupControllerImplTest, - AcceptUsernameSuggestionInvokesWarningAndroid) { - base::test::ScopedFeatureList scoped_feature_list( - password_manager::features:: - kUnifiedPasswordManagerLocalPasswordsMigrationWarning); - ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); - - // Calls are accepted immediately. - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); - EXPECT_CALL(client().show_pwd_migration_warning_callback(), Run); - task_environment()->FastForwardBy(base::Milliseconds(500)); - client().popup_controller(manager()).AcceptSuggestion(0); -} - -TEST_F(AutofillPopupControllerImplTest, - AcceptPwdSuggestionNoWarningIfDisabledAndroid) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - password_manager::features:: - kUnifiedPasswordManagerLocalPasswordsMigrationWarning); - ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); - - // Calls are accepted immediately. - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); - EXPECT_CALL(client().show_pwd_migration_warning_callback(), Run).Times(0); - task_environment()->FastForwardBy(base::Milliseconds(500)); - client().popup_controller(manager()).AcceptSuggestion(0); -} - -TEST_F(AutofillPopupControllerImplTest, AcceptAddressNoPwdWarningAndroid) { - base::test::ScopedFeatureList scoped_feature_list( - password_manager::features:: - kUnifiedPasswordManagerLocalPasswordsMigrationWarning); - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - - // Calls are accepted immediately. - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); - EXPECT_CALL(client().show_pwd_migration_warning_callback(), Run).Times(0); - task_environment()->FastForwardBy(base::Milliseconds(500)); - client().popup_controller(manager()).AcceptSuggestion(0); -} - -// When a suggestion is accepted, the popup is hidden inside -// `delegate->DidAcceptSuggestion()`. On Android, some code is still being -// executed after hiding. This test makes sure no use-after-free, null pointer -// dereferencing or other memory violations occur. -TEST_F(AutofillPopupControllerImplTest, AcceptSuggestionIsMemorySafe) { - ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); - task_environment()->FastForwardBy(base::Milliseconds(500)); - - EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion) - .WillOnce([this]() { - client().popup_controller(manager()).Hide( - PopupHidingReason::kAcceptSuggestion); - }); - client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); -} - -#endif // BUILDFLAG(IS_ANDROID) +using AutofillPopupControllerImplTest = AutofillPopupControllerTestBase<>; #if !BUILDFLAG(IS_ANDROID) TEST_F(AutofillPopupControllerImplTest, SubPopupIsCreatedWithViewFromParent) { @@ -1312,41 +117,47 @@ } #endif // !BUILDFLAG(IS_ANDROID) -// Tests that the popup controller queries the view for its screen location. -TEST_F(AutofillPopupControllerImplTest, GetPopupScreenLocationCallsView) { - ShowSuggestions(manager(), {PopupItemId::kCompose}); - - using PopupScreenLocation = AutofillClient::PopupScreenLocation; - constexpr gfx::Rect kSampleRect = gfx::Rect(123, 234); - EXPECT_CALL(client().popup_view(), GetPopupScreenLocation) - .WillOnce(Return(PopupScreenLocation{.bounds = kSampleRect})); - EXPECT_THAT(client().popup_controller(manager()).GetPopupScreenLocation(), - Optional(Field(&PopupScreenLocation::bounds, kSampleRect))); -} - -// Tests that a change to a text field hides a popup with a Compose suggestion. -TEST_F(AutofillPopupControllerImplTest, HidesOnFieldChangeForComposeEntries) { - ShowSuggestions(manager(), {PopupItemId::kCompose}); - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kFieldValueChanged)); - manager().NotifyObservers( - &AutofillManager::Observer::OnBeforeTextFieldDidChange, FormGlobalId(), - FieldGlobalId()); -} - -// Tests that a change to a text field does not hide a popup with an -// Autocomplete suggestion. TEST_F(AutofillPopupControllerImplTest, - DoeNotHideOnFieldChangeForNonComposeEntries) { - ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry}); - EXPECT_CALL(client().popup_controller(manager()), Hide).Times(0); - manager().NotifyObservers( - &AutofillManager::Observer::OnBeforeTextFieldDidChange, FormGlobalId(), - FieldGlobalId()); - Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); + ManualFallBackTriggerSource_IgnoresClickOutsideCheck) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}, + AutofillSuggestionTriggerSource::kManualFallbackAddress); + + // Generate a popup, so it can be hidden later. It doesn't matter what the + // external_delegate thinks is being shown in the process, since we are just + // testing the popup here. + test::GenerateTestAutofillPopup(&manager().external_delegate()); + + EXPECT_TRUE(client() + .popup_controller(manager()) + .ShouldIgnoreMouseObservedOutsideItemBoundsCheck()); } #if !BUILDFLAG(IS_CHROMEOS_ASH) +namespace { + +class MockAutofillDriver : public ContentAutofillDriver { + public: + using ContentAutofillDriver::ContentAutofillDriver; + + MockAutofillDriver(MockAutofillDriver&) = delete; + MockAutofillDriver& operator=(MockAutofillDriver&) = delete; + + ~MockAutofillDriver() override = default; + MOCK_METHOD(ui::AXTreeID, GetAxTreeId, (), (const override)); +}; + +class AutofillPopupControllerForPopupAxTest + : public AutofillPopupControllerForPopupTest { + public: + using AutofillPopupControllerForPopupTest:: + AutofillPopupControllerForPopupTest; + + MOCK_METHOD(ui::AXPlatformNode*, + GetRootAXPlatformNodeForWebContents, + (), + (override)); +}; + class MockAxTreeManager : public ui::AXTreeManager { public: MockAxTreeManager() = default; @@ -1396,8 +207,14 @@ MOCK_METHOD(ui::AXPlatformNodeDelegate*, GetDelegate, (), (const override)); }; +} // namespace + +using AutofillPopupControllerImplTestAccessibilityBase = + AutofillPopupControllerTestBase< + NiceMock<AutofillPopupControllerForPopupAxTest>, + NiceMock<MockAutofillDriver>>; class AutofillPopupControllerImplTestAccessibility - : public AutofillPopupControllerImplTest { + : public AutofillPopupControllerImplTestAccessibilityBase { public: static constexpr int kAxUniqueId = 123; @@ -1410,7 +227,7 @@ ~AutofillPopupControllerImplTestAccessibility() override = default; void SetUp() override { - AutofillPopupControllerImplTest::SetUp(); + AutofillPopupControllerImplTestAccessibilityBase::SetUp(); ON_CALL(driver(), GetAxTreeId()).WillByDefault(Return(test_tree_id_)); ON_CALL(client().popup_controller(manager()), @@ -1429,7 +246,7 @@ // `kScreenReader` causes mocked functions to get called with // `mock_ax_platform_node_delegate` after it has been destroyed. accessibility_mode_override_.ResetMode(); - AutofillPopupControllerImplTest::TearDown(); + AutofillPopupControllerImplTestAccessibilityBase::TearDown(); } protected: @@ -1473,7 +290,7 @@ TEST_F(AutofillPopupControllerImplTestAccessibility, FireControlsChangedEventNoPopupAxUniqueId) { EXPECT_CALL(client().popup_view(), GetAxUniqueId) - .WillOnce(testing::Return(std::nullopt)); + .WillOnce(Return(std::nullopt)); ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); // Manually fire the event for popup show since setting the test view results @@ -1483,179 +300,4 @@ } #endif -class AutofillPopupControllerImplTestHidingLogic - : public AutofillPopupControllerImplTest { - public: - void SetUp() override { - AutofillPopupControllerImplTest::SetUp(); -#if !BUILDFLAG(IS_ANDROID) -#endif // BUILDFLAG(IS_ANDROID) - sub_frame_ = CreateAndNavigateChildFrame( - main_frame(), GURL("https://bar.com"), "sub_frame") - ->GetWeakDocumentPtr(); - } - - void TearDown() override { - AutofillPopupControllerImplTest::TearDown(); - } - - BrowserAutofillManagerWithMockDelegate& sub_manager() { - return manager(sub_frame()); - } - - content::RenderFrameHost* sub_frame() { - return sub_frame_.AsRenderFrameHostIfValid(); - } - - private: - content::WeakDocumentPtr sub_frame_; -}; - -// Tests that if the popup is shown in the *main frame*, destruction of the -// *sub frame* does not hide the popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - KeepOpenInMainFrameOnSubFrameDestruction) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(client().popup_controller(manager()), Hide).Times(0); - content::RenderFrameHostTester::For(sub_frame())->Detach(); - // Verify and clear before TearDown() closes the popup. - Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); -} - -// Tests that if the popup is shown in the *main frame*, a navigation in the -// *sub frame* does not hide the popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - KeepOpenInMainFrameOnSubFrameNavigation) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(client().popup_controller(manager()), Hide).Times(0); - NavigateAndCommitFrame(sub_frame(), GURL("https://bar.com/")); - // Verify and clear before TearDown() closes the popup. - Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); -} - -// Tests that if the popup is shown, destruction of the WebContents hides the -// popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, HideOnWebContentsDestroyed) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kRendererEvent)); - DeleteContents(); -} - -// Tests that if the popup is shown in the *main frame*, destruction of the -// *main frame* hides the popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - HideInMainFrameOnDestruction) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kRendererEvent)); -} - -// Tests that if the popup is shown in the *sub frame*, destruction of the -// *sub frame* hides the popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - HideInSubFrameOnDestruction) { - ShowSuggestions(sub_manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&sub_manager().external_delegate()); - EXPECT_CALL(client().popup_controller(sub_manager()), - Hide(PopupHidingReason::kRendererEvent)); - content::RenderFrameHostTester::For(sub_frame())->Detach(); - // Verify and clear before TearDown() closes the popup. - Mock::VerifyAndClearExpectations(&client().popup_controller(sub_manager())); -} - -// Tests that if the popup is shown in the *main frame*, a navigation in the -// *main frame* hides the popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - HideInMainFrameOnMainFrameNavigation) { - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kNavigation)); - NavigateAndCommitFrame(main_frame(), GURL("https://bar.com/")); - // Verify and clear before TearDown() closes the popup. - Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); -} - -// Tests that if the popup is shown in the *sub frame*, a navigation in the -// *sub frame* hides the popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - HideInSubFrameOnSubFrameNavigation) { - ShowSuggestions(sub_manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&sub_manager().external_delegate()); - if (sub_frame()->ShouldChangeRenderFrameHostOnSameSiteNavigation()) { - // If the RenderFrameHost changes, a RenderFrameDeleted will fire first. - EXPECT_CALL(client().popup_controller(sub_manager()), - Hide(PopupHidingReason::kRendererEvent)); - } else { - EXPECT_CALL(client().popup_controller(sub_manager()), - Hide(PopupHidingReason::kNavigation)); - } - NavigateAndCommitFrame(sub_frame(), GURL("https://bar.com/")); - // Verify and clear before TearDown() closes the popup. - Mock::VerifyAndClearExpectations(&client().popup_controller(sub_manager())); -} - -// Tests that if the popup is shown in the *sub frame*, a navigation in the -// *main frame* hides the popup. -// -// TODO(crbug.com/1519872): This test only makes little sense: with BFcache, the -// navigation doesn't destroy the `sub_frame()` and thus we wouldn't hide the -// popup. What hides the popup in reality is -// AutofillExternalDelegate::DidEndTextFieldEditing(). -TEST_F(AutofillPopupControllerImplTestHidingLogic, - HideInSubFrameOnMainFrameNavigation) { - ShowSuggestions(sub_manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&sub_manager().external_delegate()); - EXPECT_CALL(client().popup_controller(sub_manager()), - Hide(PopupHidingReason::kRendererEvent)); - NavigateAndCommitFrame(main_frame(), GURL("https://bar.com/")); -} - -// Tests that Compose saved state notification popup gets hidden after 2 -// seconds, but not after 1 second. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - TimedHideComposeSavedStateNotification) { - ShowSuggestions(manager(), {PopupItemId::kComposeSavedStateNotification}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - ::testing::MockFunction<void()> check; - { - ::testing::InSequence s; - EXPECT_CALL(check, Call); - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kFadeTimerExpired)); - } - task_environment()->FastForwardBy(base::Seconds(1)); - check.Call(); - task_environment()->FastForwardBy(base::Seconds(1)); - Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); -} - -#if !BUILDFLAG(IS_ANDROID) -// Tests that if the popup is shown in the *main frame*, changing the zoom hides -// the popup. -TEST_F(AutofillPopupControllerImplTestHidingLogic, - HideInMainFrameOnZoomChange) { - zoom::ZoomController::CreateForWebContents(web_contents()); - ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); - test::GenerateTestAutofillPopup(&manager().external_delegate()); - // Triggered by OnZoomChanged(). - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kContentAreaMoved)); - // Override the default ON_CALL behavior to do nothing to avoid destroying the - // hide helper. We want to test ZoomObserver events explicitly. - EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kWidgetChanged)) - .WillOnce(Return()); - auto* zoom_controller = zoom::ZoomController::FromWebContents(web_contents()); - zoom_controller->SetZoomLevel(zoom_controller->GetZoomLevel() + 1.0); - // Verify and clear before TearDown() closes the popup. - Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); -} -#endif // BUILDFLAG(IS_ANDROID) - } // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_test_base.cc b/chrome/browser/ui/autofill/autofill_popup_controller_test_base.cc new file mode 100644 index 0000000..8ce9d3b --- /dev/null +++ b/chrome/browser/ui/autofill/autofill_popup_controller_test_base.cc
@@ -0,0 +1,43 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/autofill/autofill_popup_controller_test_base.h" + +#include <memory> +#include <optional> +#include <utility> + +namespace autofill { + +AutofillExternalDelegateForPopupTest::AutofillExternalDelegateForPopupTest( + BrowserAutofillManager* autofill_manager) + : AutofillExternalDelegate(autofill_manager) {} + +AutofillExternalDelegateForPopupTest::~AutofillExternalDelegateForPopupTest() = + default; + +AutofillPopupControllerForPopupTest::AutofillPopupControllerForPopupTest( + base::WeakPtr<AutofillExternalDelegate> external_delegate, + content::WebContents* web_contents, + const gfx::RectF& element_bounds, + base::RepeatingCallback< + void(gfx::NativeWindow, + Profile*, + password_manager::metrics_util::PasswordMigrationWarningTriggers)> + show_pwd_migration_warning_callback, + std::optional<base::WeakPtr<ExpandablePopupParentControllerImpl>> parent) + : AutofillPopupControllerImpl( + external_delegate, + web_contents, + PopupControllerCommon(element_bounds, + base::i18n::UNKNOWN_DIRECTION, + nullptr), + /*form_control_ax_id=*/0, + std::move(show_pwd_migration_warning_callback), + parent) {} + +AutofillPopupControllerForPopupTest::~AutofillPopupControllerForPopupTest() = + default; + +} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_test_base.h b/chrome/browser/ui/autofill/autofill_popup_controller_test_base.h new file mode 100644 index 0000000..90969935 --- /dev/null +++ b/chrome/browser/ui/autofill/autofill_popup_controller_test_base.h
@@ -0,0 +1,371 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_TEST_BASE_H_ +#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_TEST_BASE_H_ + +#include <concepts> +#include <memory> +#include <optional> +#include <utility> + +#include "base/functional/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/test/mock_callback.h" +#include "chrome/browser/autofill/personal_data_manager_factory.h" +#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" +#include "chrome/browser/ui/autofill/autofill_popup_view.h" +#include "chrome/browser/ui/autofill/mock_autofill_popup_view.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/content/browser/test_autofill_client_injector.h" +#include "components/autofill/content/browser/test_autofill_driver_injector.h" +#include "components/autofill/content/browser/test_autofill_manager_injector.h" +#include "components/autofill/content/browser/test_content_autofill_client.h" +#include "components/autofill/core/browser/autofill_external_delegate.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/ui/autofill_popup_delegate.h" +#include "components/autofill/core/common/autofill_test_utils.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if BUILDFLAG(IS_ANDROID) +#include "chrome/browser/autofill/mock_manual_filling_view.h" +#include "chrome/browser/keyboard_accessory/android/manual_filling_controller_impl.h" +#include "chrome/browser/keyboard_accessory/test_utils/android/mock_address_accessory_controller.h" +#include "chrome/browser/keyboard_accessory/test_utils/android/mock_credit_card_accessory_controller.h" +#include "chrome/browser/keyboard_accessory/test_utils/android/mock_password_accessory_controller.h" +#endif // BUILDFLAG(IS_ANDROID) + +namespace autofill { + +class AutofillPopupControllerForPopupTest; + +namespace internal { + +// Satisfied if `D` is derived from either `B` or a mock wrapper around `B`. +template <typename D, typename B> +concept DerivedFromClassOrMock = + std::derived_from<D, B> || std::derived_from<D, ::testing::NaggyMock<B>> || + std::derived_from<D, ::testing::NiceMock<B>> || + std::derived_from<D, ::testing::StrictMock<B>>; + +template <typename Controller, typename Driver> +concept ControllerAndDriver = + DerivedFromClassOrMock<Controller, AutofillPopupControllerForPopupTest> && + DerivedFromClassOrMock<Driver, ContentAutofillDriver>; + +} // namespace internal + +// This text fixture is intended for unit tests of the Autofill popup +// controller, which controls the Autofill popup on Desktop and the Keyboard +// Accessory on Clank. It has two template parameters that allow customizing the +// test fixture's behavior: +// - The class of the `AutofillPopupController` to test. The use of this +// parameter is to be able to test different implementations of the +// `AutofillPopupController` interface. +// - The class of the `AutofillDriver` to inject, used, e.g., in a11y-specific +// tests. +// +// The main reason for the complexity of the test fixture is that there is +// little value in testing an `AutofillPopupController` just by itself: Most of +// its behavior depends on interactions with the `WebContents`, the +// `AutofillClient`, or the `AutofillPopupView`. This test fixture sets these up +// in a way that allows for controller testing. +// +// Once setup, the test fixture should allow writing popup controller unit tests +// that closely mirror the production setup. Example: +// +// using SampleTest = AutofillPopupControllerTestBase<>; +// +// TEST_F(SampleTest, AcceptSuggestionWorksAfter500Ms) { +// ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); +// EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion); +// task_environment()->FastForwardBy(base::Milliseconds(500)); +// client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); +// } +template <typename Controller = + ::testing::NiceMock<AutofillPopupControllerForPopupTest>, + typename Driver = ContentAutofillDriver> + requires(internal::ControllerAndDriver<Controller, Driver>) +class AutofillPopupControllerTestBase : public ChromeRenderViewHostTestHarness { + public: + AutofillPopupControllerTestBase() + : ChromeRenderViewHostTestHarness( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + ~AutofillPopupControllerTestBase() override = default; + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + PersonalDataManagerFactory::GetInstance()->SetTestingFactory( + profile(), base::BindRepeating([](content::BrowserContext* context) + -> std::unique_ptr<KeyedService> { + return std::make_unique<TestPersonalDataManager>(); + })); + NavigateAndCommit(GURL("https://foo.com/")); + FocusWebContentsOnMainFrame(); + ASSERT_TRUE(web_contents()->GetFocusedFrame()); + +#if BUILDFLAG(IS_ANDROID) + ManualFillingControllerImpl::CreateForWebContentsForTesting( + web_contents(), mock_pwd_controller_.AsWeakPtr(), + mock_address_controller_.AsWeakPtr(), mock_cc_controller_.AsWeakPtr(), + std::make_unique<::testing::NiceMock<MockManualFillingView>>()); +#endif // BUILDFLAG(IS_ANDROID) + } + + void TearDown() override { + // Wait for the pending deletion of the controllers. Otherwise, the + // controllers are destroyed after the WebContents, and each of them + // receives a final Hide() call for which we'd need to add explicit + // expectations. + task_environment()->RunUntilIdle(); + ChromeRenderViewHostTestHarness::TearDown(); + } + + class TestManager; + class TestClient; + + content::RenderFrameHost* main_frame() { + return web_contents()->GetPrimaryMainFrame(); + } + + TestClient& client() { return *autofill_client_injector_[web_contents()]; } + + Driver& driver(content::RenderFrameHost* rfh = nullptr) { + return *autofill_driver_injector_[rfh ? rfh : main_frame()]; + } + + TestManager& manager(content::RenderFrameHost* rfh = nullptr) { + return *autofill_manager_injector_[rfh ? rfh : main_frame()]; + } + + TestPersonalDataManager& personal_data() { + return static_cast<TestPersonalDataManager&>( + *PersonalDataManagerFactory::GetForProfile(profile())); + } + + // Shows empty suggestions with the popup_item_id ids passed as + // `popup_item_ids`. + void ShowSuggestions( + TestManager& manager, + const std::vector<PopupItemId>& popup_item_ids, + AutofillSuggestionTriggerSource trigger_source = + AutofillSuggestionTriggerSource::kFormControlElementClicked) { + std::vector<Suggestion> suggestions; + suggestions.reserve(popup_item_ids.size()); + for (PopupItemId popup_item_id : popup_item_ids) { + suggestions.emplace_back(u"", popup_item_id); + } + ShowSuggestions(manager, std::move(suggestions), trigger_source); + } + + void ShowSuggestions( + TestManager& manager, + std::vector<Suggestion> suggestions, + AutofillSuggestionTriggerSource trigger_source = + AutofillSuggestionTriggerSource::kFormControlElementClicked) { + FocusWebContentsOnFrame( + static_cast<ContentAutofillDriver&>(manager.driver()) + .render_frame_host()); + client().popup_controller(manager).Show(std::move(suggestions), + trigger_source, + AutoselectFirstSuggestion(false)); + } + + content::NativeWebKeyboardEvent CreateKeyPressEvent(int windows_key_code) { + content::NativeWebKeyboardEvent event( + blink::WebInputEvent::Type::kRawKeyDown, + blink::WebInputEvent::kNoModifiers, + blink::WebInputEvent::GetStaticTimeStampForTests()); + event.windows_key_code = windows_key_code; + return event; + } + + private: + ::autofill::test::AutofillUnitTestEnvironment autofill_test_environment_; + + TestAutofillClientInjector<TestClient> autofill_client_injector_; + TestAutofillDriverInjector<Driver> autofill_driver_injector_; + TestAutofillManagerInjector<TestManager> autofill_manager_injector_; + +#if BUILDFLAG(IS_ANDROID) + ::testing::NiceMock<MockPasswordAccessoryController> mock_pwd_controller_; + ::testing::NiceMock<MockAddressAccessoryController> mock_address_controller_; + ::testing::NiceMock<MockCreditCardAccessoryController> mock_cc_controller_; +#endif // BUILDFLAG(IS_ANDROID) +}; + +// Below are test versions of `AutofillClient`, `BrowserAutofillManager`, +// `AutofillExternalDelegate` and `AutofillPopupController` that are used in the +// fixture above. + +class AutofillExternalDelegateForPopupTest : public AutofillExternalDelegate { + public: + explicit AutofillExternalDelegateForPopupTest( + BrowserAutofillManager* autofill_manager); + ~AutofillExternalDelegateForPopupTest() override; + + void DidSelectSuggestion(const Suggestion& suggestion) override {} + + MOCK_METHOD(void, ClearPreviewedForm, (), (override)); + MOCK_METHOD(void, OnPopupShown, (), (override)); + MOCK_METHOD(void, OnPopupHidden, (), (override)); + MOCK_METHOD(void, + DidAcceptSuggestion, + (const Suggestion&, + const AutofillPopupDelegate::SuggestionPosition&), + (override)); + MOCK_METHOD(void, + DidPerformButtonActionForSuggestion, + (const Suggestion&), + (override)); + MOCK_METHOD(bool, RemoveSuggestion, (const Suggestion&), (override)); +}; + +// A `BrowserAutofillManager` with a modified `AutofillExternalDelegate` that +// allows verifying interactions with the popup. +template <typename Controller, typename Driver> + requires(internal::ControllerAndDriver<Controller, Driver>) +class AutofillPopupControllerTestBase<Controller, Driver>::TestManager + : public BrowserAutofillManager { + public: + explicit TestManager(AutofillDriver* driver) + : BrowserAutofillManager(driver, "en-US") { + test_api(*this).SetExternalDelegate( + std::make_unique< + ::testing::NiceMock<AutofillExternalDelegateForPopupTest>>(this)); + } + TestManager(TestManager&) = delete; + TestManager& operator=(TestManager&) = delete; + ~TestManager() override = default; + + AutofillExternalDelegateForPopupTest& external_delegate() { + return static_cast<AutofillExternalDelegateForPopupTest&>( + *test_api(*this).external_delegate()); + } +}; + +// A modified `TestContentAutofillClient` that simulates the production behavior +// of the controller lifetime. +template <typename Controller, typename Driver> + requires(internal::ControllerAndDriver<Controller, Driver>) +class AutofillPopupControllerTestBase<Controller, Driver>::TestClient + : public TestContentAutofillClient { + public: + explicit TestClient(content::WebContents* web_contents) + : TestContentAutofillClient(web_contents) { + ON_CALL(popup_view(), CreateSubPopupView) + .WillByDefault(::testing::Return(sub_popup_view().GetWeakPtr())); + } + + ~TestClient() override { DoHide(); } + + // Returns the current controller. Controllers are specific to the `manager`'s + // AutofillExternalDelegate. Therefore, when there are two consecutive + // `popup_controller(x)` and `popup_controller(y)`, the second call hides the + // old and creates new controller iff `x` and `y` are distinct. + Controller& popup_controller(TestManager& manager) { + if (manager_of_last_controller_.get() != &manager) { + DoHide(); + CHECK(!popup_controller_); + } + if (!popup_controller_) { + popup_controller_ = + (new Controller(manager.external_delegate().GetWeakPtrForTest(), + &GetWebContents(), gfx::RectF(), + show_pwd_migration_warning_callback_.Get())) + ->GetWeakPtr(); + cast_popup_controller().SetViewForTesting(popup_view_->GetWeakPtr()); + manager_of_last_controller_ = manager.GetWeakPtr(); + ON_CALL(cast_popup_controller(), Hide) + .WillByDefault([this](PopupHidingReason reason) { DoHide(reason); }); + } + return cast_popup_controller(); + } + + MockAutofillPopupView& popup_view() { return *popup_view_; } + + MockAutofillPopupView& sub_popup_view() { return *sub_popup_view_; } + +#if BUILDFLAG(IS_ANDROID) + base::MockCallback<base::RepeatingCallback< + void(gfx::NativeWindow, + Profile*, + password_manager::metrics_util::PasswordMigrationWarningTriggers)>>& + show_pwd_migration_warning_callback() { + return show_pwd_migration_warning_callback_; + } +#endif // BUILDFLAG(IS_ANDROID) + + private: + void DoHide(PopupHidingReason reason) { + if (popup_controller_) { + cast_popup_controller().DoHide(reason); + } + } + + void DoHide() { + if (popup_controller_) { + cast_popup_controller().DoHide(); + } + } + + Controller& cast_popup_controller() { + return static_cast<Controller&>(*popup_controller_); + } + + base::WeakPtr<AutofillPopupController> popup_controller_; + base::WeakPtr<AutofillManager> manager_of_last_controller_; + + std::unique_ptr<MockAutofillPopupView> popup_view_ = + std::make_unique<::testing::NiceMock<MockAutofillPopupView>>(); + std::unique_ptr<MockAutofillPopupView> sub_popup_view_ = + std::make_unique<::testing::NiceMock<MockAutofillPopupView>>(); + base::MockCallback<base::RepeatingCallback<void( + gfx::NativeWindow, + Profile*, + password_manager::metrics_util::PasswordMigrationWarningTriggers)>> + show_pwd_migration_warning_callback_; +}; + +class AutofillPopupControllerForPopupTest : public AutofillPopupControllerImpl { + public: + AutofillPopupControllerForPopupTest( + base::WeakPtr<AutofillExternalDelegate> external_delegate, + content::WebContents* web_contents, + const gfx::RectF& element_bounds, + base::RepeatingCallback<void( + gfx::NativeWindow, + Profile*, + password_manager::metrics_util::PasswordMigrationWarningTriggers)> + show_pwd_migration_warning_callback, + std::optional<base::WeakPtr<ExpandablePopupParentControllerImpl>> parent = + std::nullopt); + ~AutofillPopupControllerForPopupTest() override; + + // Making protected functions public for testing + using AutofillPopupControllerImpl::AcceptSuggestion; + using AutofillPopupControllerImpl::element_bounds; + using AutofillPopupControllerImpl::FireControlsChangedEvent; + using AutofillPopupControllerImpl::GetLineCount; + using AutofillPopupControllerImpl::GetSuggestionAt; + using AutofillPopupControllerImpl::GetSuggestionLabelsAt; + using AutofillPopupControllerImpl::GetSuggestionMainTextAt; + using AutofillPopupControllerImpl::GetWeakPtr; + using AutofillPopupControllerImpl::PerformButtonActionForSuggestion; + using AutofillPopupControllerImpl::RemoveSuggestion; + using AutofillPopupControllerImpl::SelectSuggestion; + MOCK_METHOD(void, Hide, (PopupHidingReason reason), (override)); + + void DoHide(PopupHidingReason reason = PopupHidingReason::kTabGone) { + AutofillPopupControllerImpl::Hide(reason); + } +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_TEST_BASE_H_
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc new file mode 100644 index 0000000..6dcca3a8 --- /dev/null +++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -0,0 +1,1059 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> + +#include <memory> +#include <optional> +#include <string> +#include <utility> + +#include "base/memory/weak_ptr.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/gmock_callback_support.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/mock_callback.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "build/build_config.h" +#include "chrome/browser/accessibility/accessibility_state_utils.h" +#include "chrome/browser/autofill/personal_data_manager_factory.h" +#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" +#include "chrome/browser/ui/autofill/autofill_popup_controller_test_base.h" +#include "chrome/browser/ui/autofill/autofill_popup_view.h" +#include "chrome/browser/ui/autofill/popup_controller_common.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "chrome/test/base/testing_profile.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/content/browser/content_autofill_driver_factory.h" +#include "components/autofill/content/browser/content_autofill_driver_factory_test_api.h" +#include "components/autofill/content/browser/test_autofill_client_injector.h" +#include "components/autofill/content/browser/test_autofill_driver_injector.h" +#include "components/autofill/content/browser/test_autofill_manager_injector.h" +#include "components/autofill/content/browser/test_content_autofill_client.h" +#include "components/autofill/core/browser/autofill_driver_router.h" +#include "components/autofill/core/browser/autofill_external_delegate.h" +#include "components/autofill/core/browser/autofill_manager.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/browser_autofill_manager_test_api.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/autofill/core/browser/ui/autofill_popup_delegate.h" +#include "components/autofill/core/browser/ui/popup_hiding_reasons.h" +#include "components/autofill/core/browser/ui/popup_item_ids.h" +#include "components/autofill/core/browser/ui/suggestion.h" +#include "components/autofill/core/common/aliases.h" +#include "components/autofill/core/common/unique_ids.h" +#include "components/password_manager/core/common/password_manager_features.h" +#include "components/prefs/pref_service.h" +#include "components/strings/grit/components_strings.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/video_picture_in_picture_window_controller.h" +#include "content/public/browser/weak_document_ptr.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/input/native_web_keyboard_event.h" +#include "content/public/test/navigation_simulator.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/text_utils.h" + +namespace autofill { +namespace { + +using base::ASCIIToUTF16; +using base::WeakPtr; +using ::testing::_; +using ::testing::AtLeast; +using ::testing::Eq; +using ::testing::Field; +using ::testing::Invoke; +using ::testing::Mock; +using ::testing::Optional; +using ::testing::Return; + +content::RenderFrameHost* CreateAndNavigateChildFrame( + content::RenderFrameHost* parent, + const GURL& url, + std::string_view name) { + content::RenderFrameHost* rfh = + content::RenderFrameHostTester::For(parent)->AppendChild( + std::string(name)); + // ContentAutofillDriverFactory::DidFinishNavigation() creates a driver for + // subframes only if + // `NavigationHandle::HasSubframeNavigationEntryCommitted()` is true. This + // is not the case for the first navigation. (In non-unit-tests, the first + // navigation creates a driver in + // ContentAutofillDriverFactory::BindAutofillDriver().) Therefore, + // we simulate *two* navigations here, and explicitly set the transition + // type for the second navigation. + std::unique_ptr<content::NavigationSimulator> simulator; + // First navigation: `HasSubframeNavigationEntryCommitted() == false`. + // Must be a different URL from the second navigation. + GURL about_blank("about:blank"); + CHECK_NE(about_blank, url); + simulator = + content::NavigationSimulator::CreateRendererInitiated(about_blank, rfh); + simulator->Commit(); + rfh = simulator->GetFinalRenderFrameHost(); + // Second navigation: `HasSubframeNavigationEntryCommitted() == true`. + // Must set the transition type to ui::PAGE_TRANSITION_MANUAL_SUBFRAME. + simulator = content::NavigationSimulator::CreateRendererInitiated(url, rfh); + simulator->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME); + simulator->Commit(); + return simulator->GetFinalRenderFrameHost(); +} + +content::RenderFrameHost* NavigateAndCommitFrame(content::RenderFrameHost* rfh, + const GURL& url) { + std::unique_ptr<content::NavigationSimulator> simulator = + content::NavigationSimulator::CreateRendererInitiated(url, rfh); + simulator->Commit(); + return simulator->GetFinalRenderFrameHost(); +} + +} // namespace + +using AutofillPopupControllerTest = AutofillPopupControllerTestBase<>; + +TEST_F(AutofillPopupControllerTest, RemoveSuggestion) { + ShowSuggestions(manager(), + {PopupItemId::kAddressEntry, PopupItemId::kAddressEntry, + PopupItemId::kAutofillOptions}); + + // Generate a popup, so it can be hidden later. It doesn't matter what the + // external_delegate thinks is being shown in the process, since we are just + // testing the popup here. + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAddressEntry))) + .WillRepeatedly(Return(true)); + + // Remove the first entry. The popup should be redrawn since its size has + // changed. + EXPECT_CALL(client().popup_view(), OnSuggestionsChanged()); + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); + Mock::VerifyAndClearExpectations(&client().popup_view()); + + // Remove the next entry. The popup should then be hidden since there are + // no Autofill entries left. + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kNoSuggestions)); + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); +} + +// Regression test for (crbug.com/1513574): Showing an Autofill Compose +// suggestion twice does not crash. +TEST_F(AutofillPopupControllerTest, ShowTwice) { + ShowSuggestions(manager(), + {Suggestion(u"Help me write", PopupItemId::kCompose)}); + ShowSuggestions(manager(), + {Suggestion(u"Help me write", PopupItemId::kCompose)}); +} + +TEST_F(AutofillPopupControllerTest, RemoveAutocompleteSuggestion_AnnounceText) { + ShowSuggestions(manager(), + {Suggestion(u"main text", PopupItemId::kAutocompleteEntry)}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAutocompleteEntry))) + .WillOnce(Return(true)); + EXPECT_CALL(client().popup_view(), + AxAnnounce(Eq(u"Entry main text has been deleted"))); + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); +} + +TEST_F(AutofillPopupControllerTest, + RemoveAutocompleteSuggestion_IgnoresClickOutsideCheck) { + ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry, + PopupItemId::kAutocompleteEntry}); + + // Generate a popup, so it can be hidden later. It doesn't matter what the + // external_delegate thinks is being shown in the process, since we are just + // testing the popup here. + test::GenerateTestAutofillPopup(&manager().external_delegate()); + + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAutocompleteEntry))) + .WillOnce(Return(true)); + // Remove the first entry. The popup should be redrawn since its size has + // changed. + EXPECT_CALL(client().popup_view(), OnSuggestionsChanged()); + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); + Mock::VerifyAndClearExpectations(&client().popup_view()); + + EXPECT_TRUE(client() + .popup_controller(manager()) + .ShouldIgnoreMouseObservedOutsideItemBoundsCheck()); +} + +TEST_F(AutofillPopupControllerTest, + RemoveAutocompleteSuggestion_NoMetricsEmittedOnFail) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAutocompleteEntry))) + .WillOnce(Return(false)); + + EXPECT_FALSE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); + histogram_tester.ExpectUniqueSample( + "Autofill.Autocomplete.SingleEntryRemovalMethod", + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, + 0); + histogram_tester.ExpectUniqueSample( + "Autocomplete.Events2", + AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); +} + +TEST_F(AutofillPopupControllerTest, + RemoveAutocompleteSuggestion_MetricsEmittedOnSuccess) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAutocompleteEntry))) + .WillOnce(Return(true)); + + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); + histogram_tester.ExpectUniqueSample( + "Autofill.Autocomplete.SingleEntryRemovalMethod", + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, + 1); + histogram_tester.ExpectUniqueSample( + "Autocomplete.Events2", + AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 1); + // Also no autofill metrics are emitted. + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); + histogram_tester.ExpectUniqueSample( + "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); +} + +TEST_F(AutofillPopupControllerTest, + RemoveAddressSuggestion_ShiftDelete_NoMetricsEmittedOnFail) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAddressEntry))) + .WillOnce(Return(false)); + + EXPECT_FALSE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); + histogram_tester.ExpectUniqueSample( + "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); +} + +TEST_F(AutofillPopupControllerTest, + RemoveAddressSuggestion_ShiftDelete_MetricsEmittedOnSuccess) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAddressEntry))) + .WillOnce(Return(true)); + + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 1); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 1); + // Also no autocomplete or keyboard accessory metrics are emitted. + histogram_tester.ExpectUniqueSample( + "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); + histogram_tester.ExpectUniqueSample( + "Autofill.Autocomplete.SingleEntryRemovalMethod", + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, + 0); + histogram_tester.ExpectUniqueSample( + "Autocomplete.Events2", + AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); +} + +TEST_F(AutofillPopupControllerTest, + RemoveAddressSuggestion_KeyboardAccessory_NoMetricsEmittedOnFail) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAddressEntry))) + .WillOnce(Return(false)); + + EXPECT_FALSE(client().popup_controller(manager()).RemoveSuggestion( + 0, AutofillMetrics::SingleEntryRemovalMethod::kKeyboardAccessory)); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); + histogram_tester.ExpectUniqueSample( + "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); +} + +TEST_F(AutofillPopupControllerTest, + RemoveAddressSuggestion_KeyboardAccessory_MetricsEmittedOnSuccess) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kAddressEntry))) + .WillOnce(Return(true)); + + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, AutofillMetrics::SingleEntryRemovalMethod::kKeyboardAccessory)); + histogram_tester.ExpectUniqueSample( + "Autofill.ProfileDeleted.KeyboardAccessory", 1, 1); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 1); + // Also no autocomplete or shift+delete metrics are emitted. + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); + histogram_tester.ExpectUniqueSample( + "Autofill.Autocomplete.SingleEntryRemovalMethod", + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, + 0); + histogram_tester.ExpectUniqueSample( + "Autocomplete.Events2", + AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); +} + +TEST_F(AutofillPopupControllerTest, + RemoveCreditCardSuggestion_NoMetricsEmitted) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kCreditCardEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(manager().external_delegate(), + RemoveSuggestion(Field(&Suggestion::popup_item_id, + PopupItemId::kCreditCardEntry))) + .WillOnce(Return(true)); + + EXPECT_TRUE(client().popup_controller(manager()).RemoveSuggestion( + 0, + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed)); + histogram_tester.ExpectUniqueSample( + "Autofill.Autocomplete.SingleEntryRemovalMethod", + AutofillMetrics::SingleEntryRemovalMethod::kKeyboardShiftDeletePressed, + 0); + histogram_tester.ExpectUniqueSample( + "Autocomplete.Events2", + AutofillMetrics::AutocompleteEvent::AUTOCOMPLETE_SUGGESTION_DELETED, 0); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Popup", 1, 0); + histogram_tester.ExpectUniqueSample( + "Autofill.ProfileDeleted.KeyboardAccessory", 1, 0); + histogram_tester.ExpectUniqueSample("Autofill.ProfileDeleted.Any", 1, 0); +} + +TEST_F(AutofillPopupControllerTest, UpdateDataListValues) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + std::vector<SelectOption> options = { + {.value = u"data list value 1", .content = u"data list label 1"}}; + client().popup_controller(manager()).UpdateDataListValues(options); + + ASSERT_EQ(3, client().popup_controller(manager()).GetLineCount()); + + Suggestion result0 = client().popup_controller(manager()).GetSuggestionAt(0); + EXPECT_EQ(options[0].value, result0.main_text.value); + EXPECT_EQ(options[0].value, + client().popup_controller(manager()).GetSuggestionMainTextAt(0)); + ASSERT_EQ(1u, result0.labels.size()); + ASSERT_EQ(1u, result0.labels[0].size()); + EXPECT_EQ(options[0].content, result0.labels[0][0].value); + EXPECT_EQ(std::u16string(), result0.additional_label); + EXPECT_EQ(options[0].content, client() + .popup_controller(manager()) + .GetSuggestionLabelsAt(0)[0][0] + .value); + EXPECT_EQ(PopupItemId::kDatalistEntry, result0.popup_item_id); + + Suggestion result1 = client().popup_controller(manager()).GetSuggestionAt(1); + EXPECT_EQ(std::u16string(), result1.main_text.value); + EXPECT_TRUE(result1.labels.empty()); + EXPECT_EQ(std::u16string(), result1.additional_label); + EXPECT_EQ(PopupItemId::kSeparator, result1.popup_item_id); + + Suggestion result2 = client().popup_controller(manager()).GetSuggestionAt(2); + EXPECT_EQ(std::u16string(), result2.main_text.value); + EXPECT_TRUE(result2.labels.empty()); + EXPECT_EQ(std::u16string(), result2.additional_label); + EXPECT_EQ(PopupItemId::kAddressEntry, result2.popup_item_id); + + // Add two data list entries (which should replace the current one). + options.push_back( + {.value = u"data list value 1", .content = u"data list label 1"}); + client().popup_controller(manager()).UpdateDataListValues(options); + ASSERT_EQ(4, client().popup_controller(manager()).GetLineCount()); + + // Original one first, followed by new one, then separator. + EXPECT_EQ( + options[0].value, + client().popup_controller(manager()).GetSuggestionAt(0).main_text.value); + EXPECT_EQ(options[0].value, + client().popup_controller(manager()).GetSuggestionMainTextAt(0)); + ASSERT_EQ( + 1u, + client().popup_controller(manager()).GetSuggestionAt(0).labels.size()); + ASSERT_EQ( + 1u, + client().popup_controller(manager()).GetSuggestionAt(0).labels[0].size()); + EXPECT_EQ(options[0].content, client() + .popup_controller(manager()) + .GetSuggestionAt(0) + .labels[0][0] + .value); + EXPECT_EQ( + std::u16string(), + client().popup_controller(manager()).GetSuggestionAt(0).additional_label); + EXPECT_EQ( + options[1].value, + client().popup_controller(manager()).GetSuggestionAt(1).main_text.value); + EXPECT_EQ(options[1].value, + client().popup_controller(manager()).GetSuggestionMainTextAt(1)); + ASSERT_EQ( + 1u, + client().popup_controller(manager()).GetSuggestionAt(1).labels.size()); + ASSERT_EQ( + 1u, + client().popup_controller(manager()).GetSuggestionAt(1).labels[0].size()); + EXPECT_EQ(options[1].content, client() + .popup_controller(manager()) + .GetSuggestionAt(1) + .labels[0][0] + .value); + EXPECT_EQ( + std::u16string(), + client().popup_controller(manager()).GetSuggestionAt(1).additional_label); + EXPECT_EQ( + PopupItemId::kSeparator, + client().popup_controller(manager()).GetSuggestionAt(2).popup_item_id); + + // Clear all data list values. + options.clear(); + client().popup_controller(manager()).UpdateDataListValues(options); + + ASSERT_EQ(1, client().popup_controller(manager()).GetLineCount()); + EXPECT_EQ( + PopupItemId::kAddressEntry, + client().popup_controller(manager()).GetSuggestionAt(0).popup_item_id); +} + +TEST_F(AutofillPopupControllerTest, PopupsWithOnlyDataLists) { + // Create the popup with a single datalist element. + ShowSuggestions(manager(), {PopupItemId::kDatalistEntry}); + + // Replace the datalist element with a new one. + std::vector<SelectOption> options = { + {.value = u"data list value 1", .content = u"data list label 1"}}; + client().popup_controller(manager()).UpdateDataListValues(options); + + ASSERT_EQ(1, client().popup_controller(manager()).GetLineCount()); + EXPECT_EQ( + options[0].value, + client().popup_controller(manager()).GetSuggestionAt(0).main_text.value); + ASSERT_EQ( + 1u, + client().popup_controller(manager()).GetSuggestionAt(0).labels.size()); + ASSERT_EQ( + 1u, + client().popup_controller(manager()).GetSuggestionAt(0).labels[0].size()); + EXPECT_EQ(options[0].content, client() + .popup_controller(manager()) + .GetSuggestionAt(0) + .labels[0][0] + .value); + EXPECT_EQ( + std::u16string(), + client().popup_controller(manager()).GetSuggestionAt(0).additional_label); + EXPECT_EQ( + PopupItemId::kDatalistEntry, + client().popup_controller(manager()).GetSuggestionAt(0).popup_item_id); + + // Clear datalist values and check that the popup becomes hidden. + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kNoSuggestions)); + options.clear(); + client().popup_controller(manager()).UpdateDataListValues(options); +} + +TEST_F(AutofillPopupControllerTest, GetOrCreate) { + auto create_controller = [&](gfx::RectF bounds) { + return AutofillPopupController::GetOrCreate( + client().popup_controller(manager()).GetWeakPtr(), + manager().external_delegate().GetWeakPtrForTest(), nullptr, + PopupControllerCommon(std::move(bounds), base::i18n::UNKNOWN_DIRECTION, + nullptr), + /*form_control_ax_id=*/0); + }; + WeakPtr<AutofillPopupController> controller = create_controller(gfx::RectF()); + EXPECT_TRUE(controller); + + controller->Hide(PopupHidingReason::kViewDestroyed); + EXPECT_FALSE(controller); + + controller = create_controller(gfx::RectF()); + EXPECT_TRUE(controller); + + WeakPtr<AutofillPopupController> controller2 = + create_controller(gfx::RectF()); + EXPECT_EQ(controller.get(), controller2.get()); + + controller->Hide(PopupHidingReason::kViewDestroyed); + EXPECT_FALSE(controller); + EXPECT_FALSE(controller2); + + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kViewDestroyed)); + gfx::RectF bounds(0.f, 0.f, 1.f, 2.f); + base::WeakPtr<AutofillPopupController> controller3 = + create_controller(bounds); + EXPECT_EQ(&client().popup_controller(manager()), controller3.get()); + EXPECT_EQ(bounds, static_cast<AutofillPopupController*>(controller3.get()) + ->element_bounds()); + controller3->Hide(PopupHidingReason::kViewDestroyed); + + client().popup_controller(manager()).DoHide(); + + const base::WeakPtr<AutofillPopupController> controller4 = + create_controller(bounds); + EXPECT_EQ(&client().popup_controller(manager()), controller4.get()); + EXPECT_EQ(bounds, + static_cast<const AutofillPopupController*>(controller4.get()) + ->element_bounds()); + + client().popup_controller(manager()).DoHide(); +} + +TEST_F(AutofillPopupControllerTest, ProperlyResetController) { + ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry, + PopupItemId::kAutocompleteEntry}); + + // Now show a new popup with the same controller, but with fewer items. + WeakPtr<AutofillPopupController> controller = + AutofillPopupController::GetOrCreate( + client().popup_controller(manager()).GetWeakPtr(), + manager().external_delegate().GetWeakPtrForTest(), nullptr, + PopupControllerCommon(gfx::RectF(), base::i18n::UNKNOWN_DIRECTION, + nullptr), + /*form_control_ax_id=*/0); + EXPECT_EQ(0, controller->GetLineCount()); +} + +TEST_F(AutofillPopupControllerTest, UnselectingClearsPreview) { + EXPECT_CALL(manager().external_delegate(), ClearPreviewedForm()); + client().popup_controller(manager()).UnselectSuggestion(); +} + +TEST_F(AutofillPopupControllerTest, HidingClearsPreview) { + EXPECT_CALL(manager().external_delegate(), ClearPreviewedForm()); + EXPECT_CALL(manager().external_delegate(), OnPopupHidden()); + client().popup_controller(manager()).DoHide(); +} + +TEST_F(AutofillPopupControllerTest, DontHideWhenWaitingForData) { + EXPECT_CALL(client().popup_view(), Hide).Times(0); + client().popup_controller(manager()).PinView(); + + // Hide() will not work for stale data or when focusing native UI. + client().popup_controller(manager()).DoHide(PopupHidingReason::kStaleData); + client().popup_controller(manager()).DoHide(PopupHidingReason::kEndEditing); + + // Check the expectations now since TearDown will perform a successful hide. + Mock::VerifyAndClearExpectations(&manager().external_delegate()); + Mock::VerifyAndClearExpectations(&client().popup_view()); +} + +TEST_F(AutofillPopupControllerTest, ShouldReportHidingPopupReason) { + base::HistogramTester histogram_tester; + client().popup_controller(manager()).DoHide(PopupHidingReason::kTabGone); + histogram_tester.ExpectTotalCount("Autofill.PopupHidingReason", 1); + histogram_tester.ExpectBucketCount("Autofill.PopupHidingReason", + PopupHidingReason::kTabGone, 1); +} + +// This is a regression test for crbug.com/521133 to ensure that we don't crash +// when suggestions updates race with user selections. +TEST_F(AutofillPopupControllerTest, SelectInvalidSuggestion) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); + + // The following should not crash: + client().popup_controller(manager()).AcceptSuggestion( + /*index=*/1); // Out of bounds! +} + +TEST_F(AutofillPopupControllerTest, AcceptSuggestionRespectsTimeout) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + + // Calls before the threshold are ignored. + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); + client().popup_controller(manager()).AcceptSuggestion(0); + task_environment()->FastForwardBy(base::Milliseconds(100)); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); + + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion); + task_environment()->FastForwardBy(base::Milliseconds(400)); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); + + histogram_tester.ExpectTotalCount( + "Autofill.Popup.AcceptanceDelayThresholdNotMet", 2); +} + +TEST_F(AutofillPopupControllerTest, + AcceptSuggestionTimeoutIsUpdatedOnPopupMove) { + base::HistogramTester histogram_tester; + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + + // Calls before the threshold are ignored. + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); + task_environment()->FastForwardBy(base::Milliseconds(100)); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); + + histogram_tester.ExpectTotalCount( + "Autofill.Popup.AcceptanceDelayThresholdNotMet", 2); + task_environment()->FastForwardBy(base::Milliseconds(400)); + // Show the suggestions again (simulating, e.g., a click somewhere slightly + // different). + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(0); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); + histogram_tester.ExpectTotalCount( + "Autofill.Popup.AcceptanceDelayThresholdNotMet", 3); + + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion); + // After waiting, suggestions are accepted again. + task_environment()->FastForwardBy(base::Milliseconds(500)); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); + histogram_tester.ExpectTotalCount( + "Autofill.Popup.AcceptanceDelayThresholdNotMet", 3); +} + +// Tests that when a picture-in-picture window is initialized, there is a call +// to the popup view to check if the autofill popup bounds overlap with the +// picture-in-picture window. +TEST_F(AutofillPopupControllerTest, CheckBoundsOverlapWithPictureInPicture) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + PictureInPictureWindowManager* picture_in_picture_window_manager = + PictureInPictureWindowManager::GetInstance(); + EXPECT_CALL(client().popup_view(), OverlapsWithPictureInPictureWindow); + picture_in_picture_window_manager->NotifyObserversOnEnterPictureInPicture(); +} + +TEST_F(AutofillPopupControllerTest, + GetRemovalConfirmationText_UnrelatedPopupItemId) { + std::u16string title; + std::u16string body; + ShowSuggestions( + manager(), + {Suggestion(u"Entry", PopupItemId::kAddressFieldByFieldFilling)}); + + EXPECT_FALSE(client().popup_controller(manager()).GetRemovalConfirmationText( + 0, &title, &body)); +} + +TEST_F(AutofillPopupControllerTest, + GetRemovalConfirmationText_InvalidUniqueId) { + std::u16string title; + std::u16string body; + ShowSuggestions(manager(), {test::CreateAutofillSuggestion( + PopupItemId::kAddressFieldByFieldFilling, + u"Entry", Suggestion::Guid("1111"))}); + + EXPECT_FALSE(client().popup_controller(manager()).GetRemovalConfirmationText( + 0, &title, &body)); +} + +TEST_F(AutofillPopupControllerTest, GetRemovalConfirmationText_Autocomplete) { + std::u16string title; + std::u16string body; + ShowSuggestions(manager(), {Suggestion(u"Autocomplete entry", + PopupItemId::kAutocompleteEntry)}); + + EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( + 0, &title, &body)); + EXPECT_EQ(title, u"Autocomplete entry"); + EXPECT_EQ(body, + l10n_util::GetStringUTF16( + IDS_AUTOFILL_DELETE_AUTOCOMPLETE_SUGGESTION_CONFIRMATION_BODY)); +} + +TEST_F(AutofillPopupControllerTest, + GetRemovalConfirmationText_LocalCreditCard) { + CreditCard local_card = test::GetCreditCard(); + personal_data().AddCreditCard(local_card); + + std::u16string title; + std::u16string body; + ShowSuggestions(manager(), + {test::CreateAutofillSuggestion( + PopupItemId::kCreditCardEntry, u"Local credit card", + Suggestion::Guid(local_card.guid()))}); + + EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( + 0, &title, &body)); + EXPECT_EQ(title, local_card.CardNameAndLastFourDigits()); + EXPECT_EQ(body, + l10n_util::GetStringUTF16( + IDS_AUTOFILL_DELETE_CREDIT_CARD_SUGGESTION_CONFIRMATION_BODY)); +} + +TEST_F(AutofillPopupControllerTest, + GetRemovalConfirmationText_ServerCreditCard) { + CreditCard server_card = test::GetMaskedServerCard(); + personal_data().AddServerCreditCard(server_card); + + std::u16string title; + std::u16string body; + ShowSuggestions(manager(), + {test::CreateAutofillSuggestion( + PopupItemId::kCreditCardEntry, u"Server credit card", + Suggestion::Guid(server_card.guid()))}); + + EXPECT_FALSE(client().popup_controller(manager()).GetRemovalConfirmationText( + 0, &title, &body)); +} + +TEST_F(AutofillPopupControllerTest, + GetRemovalConfirmationText_CompleteAutofillProfile) { + AutofillProfile complete_profile = test::GetFullProfile(); + personal_data().AddProfile(complete_profile); + + std::u16string title; + std::u16string body; + ShowSuggestions(manager(), + {test::CreateAutofillSuggestion( + PopupItemId::kAddressEntry, u"Complete autofill profile", + Suggestion::Guid(complete_profile.guid()))}); + + EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( + 0, &title, &body)); + EXPECT_EQ(title, complete_profile.GetRawInfo(ADDRESS_HOME_CITY)); + EXPECT_EQ(body, + l10n_util::GetStringUTF16( + IDS_AUTOFILL_DELETE_PROFILE_SUGGESTION_CONFIRMATION_BODY)); +} + +TEST_F(AutofillPopupControllerTest, + GetRemovalConfirmationText_AutofillProfile_EmptyCity) { + AutofillProfile profile = test::GetFullProfile(); + profile.ClearFields({ADDRESS_HOME_CITY}); + personal_data().AddProfile(profile); + + std::u16string title; + std::u16string body; + ShowSuggestions(manager(), {test::CreateAutofillSuggestion( + PopupItemId::kAddressEntry, + u"Autofill profile without city", + Suggestion::Guid(profile.guid()))}); + + EXPECT_TRUE(client().popup_controller(manager()).GetRemovalConfirmationText( + 0, &title, &body)); + EXPECT_EQ(title, u"Autofill profile without city"); + EXPECT_EQ(body, + l10n_util::GetStringUTF16( + IDS_AUTOFILL_DELETE_PROFILE_SUGGESTION_CONFIRMATION_BODY)); +} + +#if BUILDFLAG(IS_ANDROID) +TEST_F(AutofillPopupControllerTest, AcceptPwdSuggestionInvokesWarningAndroid) { + base::test::ScopedFeatureList scoped_feature_list( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsMigrationWarning); + ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); + + // Calls are accepted immediately. + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); + EXPECT_CALL(client().show_pwd_migration_warning_callback(), + Run(_, _, + password_manager::metrics_util:: + PasswordMigrationWarningTriggers::kKeyboardAcessoryBar)); + task_environment()->FastForwardBy(base::Milliseconds(500)); + client().popup_controller(manager()).AcceptSuggestion(0); +} + +TEST_F(AutofillPopupControllerTest, + AcceptUsernameSuggestionInvokesWarningAndroid) { + base::test::ScopedFeatureList scoped_feature_list( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsMigrationWarning); + ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); + + // Calls are accepted immediately. + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); + EXPECT_CALL(client().show_pwd_migration_warning_callback(), Run); + task_environment()->FastForwardBy(base::Milliseconds(500)); + client().popup_controller(manager()).AcceptSuggestion(0); +} + +TEST_F(AutofillPopupControllerTest, + AcceptPwdSuggestionNoWarningIfDisabledAndroid) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsMigrationWarning); + ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); + + // Calls are accepted immediately. + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); + EXPECT_CALL(client().show_pwd_migration_warning_callback(), Run).Times(0); + task_environment()->FastForwardBy(base::Milliseconds(500)); + client().popup_controller(manager()).AcceptSuggestion(0); +} + +TEST_F(AutofillPopupControllerTest, AcceptAddressNoPwdWarningAndroid) { + base::test::ScopedFeatureList scoped_feature_list( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsMigrationWarning); + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + + // Calls are accepted immediately. + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion).Times(1); + EXPECT_CALL(client().show_pwd_migration_warning_callback(), Run).Times(0); + task_environment()->FastForwardBy(base::Milliseconds(500)); + client().popup_controller(manager()).AcceptSuggestion(0); +} + +// When a suggestion is accepted, the popup is hidden inside +// `delegate->DidAcceptSuggestion()`. On Android, some code is still being +// executed after hiding. This test makes sure no use-after-free, null pointer +// dereferencing or other memory violations occur. +TEST_F(AutofillPopupControllerTest, AcceptSuggestionIsMemorySafe) { + ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); + task_environment()->FastForwardBy(base::Milliseconds(500)); + + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion) + .WillOnce([this]() { + client().popup_controller(manager()).Hide( + PopupHidingReason::kAcceptSuggestion); + }); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0); +} + +#endif // BUILDFLAG(IS_ANDROID) + +// Tests that the popup controller queries the view for its screen location. +TEST_F(AutofillPopupControllerTest, GetPopupScreenLocationCallsView) { + ShowSuggestions(manager(), {PopupItemId::kCompose}); + + using PopupScreenLocation = AutofillClient::PopupScreenLocation; + constexpr gfx::Rect kSampleRect = gfx::Rect(123, 234); + EXPECT_CALL(client().popup_view(), GetPopupScreenLocation) + .WillOnce(Return(PopupScreenLocation{.bounds = kSampleRect})); + EXPECT_THAT(client().popup_controller(manager()).GetPopupScreenLocation(), + Optional(Field(&PopupScreenLocation::bounds, kSampleRect))); +} + +// Tests that a change to a text field hides a popup with a Compose suggestion. +TEST_F(AutofillPopupControllerTest, HidesOnFieldChangeForComposeEntries) { + ShowSuggestions(manager(), {PopupItemId::kCompose}); + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kFieldValueChanged)); + manager().NotifyObservers( + &AutofillManager::Observer::OnBeforeTextFieldDidChange, FormGlobalId(), + FieldGlobalId()); +} + +// Tests that a change to a text field does not hide a popup with an +// Autocomplete suggestion. +TEST_F(AutofillPopupControllerTest, + DoeNotHideOnFieldChangeForNonComposeEntries) { + ShowSuggestions(manager(), {PopupItemId::kAutocompleteEntry}); + EXPECT_CALL(client().popup_controller(manager()), Hide).Times(0); + manager().NotifyObservers( + &AutofillManager::Observer::OnBeforeTextFieldDidChange, FormGlobalId(), + FieldGlobalId()); + Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); +} + +class AutofillPopupControllerTestHidingLogic + : public AutofillPopupControllerTest { + public: + void SetUp() override { + AutofillPopupControllerTest::SetUp(); + sub_frame_ = CreateAndNavigateChildFrame( + main_frame(), GURL("https://bar.com"), "sub_frame") + ->GetWeakDocumentPtr(); + } + + TestManager& sub_manager() { return manager(sub_frame()); } + + content::RenderFrameHost* sub_frame() { + return sub_frame_.AsRenderFrameHostIfValid(); + } + + private: + content::WeakDocumentPtr sub_frame_; +}; + +// Tests that if the popup is shown in the *main frame*, destruction of the +// *sub frame* does not hide the popup. +TEST_F(AutofillPopupControllerTestHidingLogic, + KeepOpenInMainFrameOnSubFrameDestruction) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(client().popup_controller(manager()), Hide).Times(0); + content::RenderFrameHostTester::For(sub_frame())->Detach(); + // Verify and clear before TearDown() closes the popup. + Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); +} + +// Tests that if the popup is shown in the *main frame*, a navigation in the +// *sub frame* does not hide the popup. +TEST_F(AutofillPopupControllerTestHidingLogic, + KeepOpenInMainFrameOnSubFrameNavigation) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(client().popup_controller(manager()), Hide).Times(0); + NavigateAndCommitFrame(sub_frame(), GURL("https://bar.com/")); + // Verify and clear before TearDown() closes the popup. + Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); +} + +// Tests that if the popup is shown, destruction of the WebContents hides the +// popup. +TEST_F(AutofillPopupControllerTestHidingLogic, HideOnWebContentsDestroyed) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kRendererEvent)); + DeleteContents(); +} + +// Tests that if the popup is shown in the *main frame*, destruction of the +// *main frame* hides the popup. +TEST_F(AutofillPopupControllerTestHidingLogic, HideInMainFrameOnDestruction) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kRendererEvent)); +} + +// Tests that if the popup is shown in the *sub frame*, destruction of the +// *sub frame* hides the popup. +TEST_F(AutofillPopupControllerTestHidingLogic, HideInSubFrameOnDestruction) { + ShowSuggestions(sub_manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&sub_manager().external_delegate()); + EXPECT_CALL(client().popup_controller(sub_manager()), + Hide(PopupHidingReason::kRendererEvent)); + content::RenderFrameHostTester::For(sub_frame())->Detach(); + // Verify and clear before TearDown() closes the popup. + Mock::VerifyAndClearExpectations(&client().popup_controller(sub_manager())); +} + +// Tests that if the popup is shown in the *main frame*, a navigation in the +// *main frame* hides the popup. +TEST_F(AutofillPopupControllerTestHidingLogic, + HideInMainFrameOnMainFrameNavigation) { + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kNavigation)); + NavigateAndCommitFrame(main_frame(), GURL("https://bar.com/")); + // Verify and clear before TearDown() closes the popup. + Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); +} + +// Tests that if the popup is shown in the *sub frame*, a navigation in the +// *sub frame* hides the popup. +TEST_F(AutofillPopupControllerTestHidingLogic, + HideInSubFrameOnSubFrameNavigation) { + ShowSuggestions(sub_manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&sub_manager().external_delegate()); + if (sub_frame()->ShouldChangeRenderFrameHostOnSameSiteNavigation()) { + // If the RenderFrameHost changes, a RenderFrameDeleted will fire first. + EXPECT_CALL(client().popup_controller(sub_manager()), + Hide(PopupHidingReason::kRendererEvent)); + } else { + EXPECT_CALL(client().popup_controller(sub_manager()), + Hide(PopupHidingReason::kNavigation)); + } + NavigateAndCommitFrame(sub_frame(), GURL("https://bar.com/")); + // Verify and clear before TearDown() closes the popup. + Mock::VerifyAndClearExpectations(&client().popup_controller(sub_manager())); +} + +// Tests that if the popup is shown in the *sub frame*, a navigation in the +// *main frame* hides the popup. +// +// TODO(crbug.com/1519872): This test only makes little sense: with BFcache, the +// navigation doesn't destroy the `sub_frame()` and thus we wouldn't hide the +// popup. What hides the popup in reality is +// AutofillExternalDelegate::DidEndTextFieldEditing(). +TEST_F(AutofillPopupControllerTestHidingLogic, + HideInSubFrameOnMainFrameNavigation) { + ShowSuggestions(sub_manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&sub_manager().external_delegate()); + EXPECT_CALL(client().popup_controller(sub_manager()), + Hide(PopupHidingReason::kRendererEvent)); + NavigateAndCommitFrame(main_frame(), GURL("https://bar.com/")); +} + +// Tests that Compose saved state notification popup gets hidden after 2 +// seconds, but not after 1 second. +TEST_F(AutofillPopupControllerTestHidingLogic, + TimedHideComposeSavedStateNotification) { + ShowSuggestions(manager(), {PopupItemId::kComposeSavedStateNotification}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + ::testing::MockFunction<void()> check; + { + ::testing::InSequence s; + EXPECT_CALL(check, Call); + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kFadeTimerExpired)); + } + task_environment()->FastForwardBy(base::Seconds(1)); + check.Call(); + task_environment()->FastForwardBy(base::Seconds(1)); + Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); +} + +#if !BUILDFLAG(IS_ANDROID) +// Tests that if the popup is shown in the *main frame*, changing the zoom hides +// the popup. +TEST_F(AutofillPopupControllerTestHidingLogic, HideInMainFrameOnZoomChange) { + zoom::ZoomController::CreateForWebContents(web_contents()); + ShowSuggestions(manager(), {PopupItemId::kAddressEntry}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + // Triggered by OnZoomChanged(). + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kContentAreaMoved)); + // Override the default ON_CALL behavior to do nothing to avoid destroying the + // hide helper. We want to test ZoomObserver events explicitly. + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kWidgetChanged)) + .WillOnce(Return()); + auto* zoom_controller = zoom::ZoomController::FromWebContents(web_contents()); + zoom_controller->SetZoomLevel(zoom_controller->GetZoomLevel() + 1.0); + // Verify and clear before TearDown() closes the popup. + Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); +} +#endif // BUILDFLAG(IS_ANDROID) + +} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.cc b/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.cc index 90437f0..6a2dbb7 100644 --- a/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.cc +++ b/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.cc
@@ -68,6 +68,11 @@ state_->access_point_ = access_point; state_->time_limit_ = time_limit; state_->initialization_time_ = base::Time::Now(); + state_->is_initialized_ = true; +} + +bool AutofillSigninPromoTabHelper::IsInitializedForTesting() const { + return state_->is_initialized_; } void AutofillSigninPromoTabHelper::OnPrimaryAccountChanged(
diff --git a/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.h b/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.h index 860134c..3938d16 100644 --- a/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.h +++ b/chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.h
@@ -41,6 +41,9 @@ signin_metrics::AccessPoint access_point, base::TimeDelta time_limit = base::Minutes(50)); + // Returns true if the helper has been initialized for testing. + bool IsInitializedForTesting() const; + // Overrides signin::IdentityManager::Observer functions. void OnPrimaryAccountChanged( const signin::PrimaryAccountChangeEvent& event_details) override; @@ -67,6 +70,7 @@ signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN; base::Time initialization_time_; base::TimeDelta time_limit_; + bool is_initialized_ = false; }; std::unique_ptr<ResetableState> state_;
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 0d9b7b85..9db2de3 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -927,7 +927,7 @@ open_args.element_bounds + client_area.OffsetFromOrigin(); // Deletes or reuses the old `popup_controller_`. - popup_controller_ = AutofillPopupControllerImpl::GetOrCreate( + popup_controller_ = AutofillPopupController::GetOrCreate( popup_controller_, delegate, web_contents(), PopupControllerCommon(element_bounds_in_screen_space, open_args.text_direction, @@ -946,8 +946,10 @@ autofill_field_promo_controller_manual_fallback_->Hide(); } - // When testing, try to keep popup open when the reason to hide is from an - // external browser frame resize that is extraneous to our testing goals. + // When testing, try to keep popup open when the reason to hide is one of: + // - An external browser frame resize that is extraneous to our testing goals. + // - Too many fields get focus one after another (for example, multiple + // password fields being autofilled by default on Desktop). if (keep_popup_open_for_testing_ && popup_controller_.get()) { popup_controller_->KeepPopupOpenForTesting(); }
diff --git a/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc b/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc index cd7d48e..6ba54a3 100644 --- a/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/delete_address_profile_dialog_controller_impl.cc
@@ -80,7 +80,7 @@ PersonalDataManager* pdm = PersonalDataManagerFactory::GetForBrowserContext( web_contents_->GetBrowserContext()); return l10n_util::GetStringUTF16( - pdm->IsSyncFeatureEnabledForAutofill() + pdm->address_data_manager().IsSyncFeatureEnabledForAutofill() ? IDS_AUTOFILL_DELETE_SYNC_ADDRESS_SOURCE_NOTICE : IDS_AUTOFILL_DELETE_LOCAL_ADDRESS_SOURCE_NOTICE); }
diff --git a/chrome/browser/ui/autofill/mock_autofill_popup_view.cc b/chrome/browser/ui/autofill/mock_autofill_popup_view.cc new file mode 100644 index 0000000..8a9a153 --- /dev/null +++ b/chrome/browser/ui/autofill/mock_autofill_popup_view.cc
@@ -0,0 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/autofill/mock_autofill_popup_view.h" + +namespace autofill { + +MockAutofillPopupView::MockAutofillPopupView() = default; + +MockAutofillPopupView::~MockAutofillPopupView() = default; + +} // namespace autofill
diff --git a/chrome/browser/ui/autofill/mock_autofill_popup_view.h b/chrome/browser/ui/autofill/mock_autofill_popup_view.h new file mode 100644 index 0000000..8cdaedb --- /dev/null +++ b/chrome/browser/ui/autofill/mock_autofill_popup_view.h
@@ -0,0 +1,55 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_MOCK_AUTOFILL_POPUP_VIEW_H_ +#define CHROME_BROWSER_UI_AUTOFILL_MOCK_AUTOFILL_POPUP_VIEW_H_ + +#include <optional> +#include <string> +#include <vector> + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/autofill/autofill_popup_view.h" +#include "components/autofill/core/browser/autofill_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace autofill { + +class MockAutofillPopupView : public AutofillPopupView { + public: + MockAutofillPopupView(); + MockAutofillPopupView(MockAutofillPopupView&) = delete; + MockAutofillPopupView& operator=(MockAutofillPopupView&) = delete; + ~MockAutofillPopupView() override; + + MOCK_METHOD(bool, Show, (AutoselectFirstSuggestion), (override)); + MOCK_METHOD(void, Hide, (), (override)); + MOCK_METHOD(bool, + HandleKeyPressEvent, + (const content::NativeWebKeyboardEvent&), + (override)); + MOCK_METHOD(void, OnSuggestionsChanged, (), (override)); + MOCK_METHOD(bool, OverlapsWithPictureInPictureWindow, (), (const override)); + MOCK_METHOD(std::optional<int32_t>, GetAxUniqueId, (), (override)); + MOCK_METHOD(void, AxAnnounce, (const std::u16string&), (override)); + MOCK_METHOD(base::WeakPtr<AutofillPopupView>, + CreateSubPopupView, + (base::WeakPtr<AutofillPopupController>), + (override)); + MOCK_METHOD(std::optional<AutofillClient::PopupScreenLocation>, + GetPopupScreenLocation, + (), + (const override)); + + base::WeakPtr<AutofillPopupView> GetWeakPtr() override { + return weak_ptr_factory_.GetWeakPtr(); + } + + private: + base::WeakPtrFactory<AutofillPopupView> weak_ptr_factory_{this}; +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_MOCK_AUTOFILL_POPUP_VIEW_H_
diff --git a/chrome/browser/ui/autofill/save_address_bubble_controller.cc b/chrome/browser/ui/autofill/save_address_bubble_controller.cc index 54e12b3..6bbf3b2 100644 --- a/chrome/browser/ui/autofill/save_address_bubble_controller.cc +++ b/chrome/browser/ui/autofill/save_address_bubble_controller.cc
@@ -154,9 +154,10 @@ GetPrimaryAccountInfoFromBrowserContext( web_contents()->GetBrowserContext()); - int string_id = pdm->IsSyncFeatureEnabledForAutofill() - ? IDS_AUTOFILL_SYNCABLE_PROFILE_MIGRATION_PROMPT_NOTICE - : IDS_AUTOFILL_LOCAL_PROFILE_MIGRATION_PROMPT_NOTICE; + int string_id = + pdm->address_data_manager().IsSyncFeatureEnabledForAutofill() + ? IDS_AUTOFILL_SYNCABLE_PROFILE_MIGRATION_PROMPT_NOTICE + : IDS_AUTOFILL_LOCAL_PROFILE_MIGRATION_PROMPT_NOTICE; return l10n_util::GetStringFUTF16(string_id, base::UTF8ToUTF16(account->email));
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.cc b/chrome/browser/ui/passwords/manage_passwords_test.cc index 6641defb..2ea6aaa8 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.cc +++ b/chrome/browser/ui/passwords/manage_passwords_test.cc
@@ -23,6 +23,8 @@ #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" +#include "components/password_manager/core/browser/form_saver.h" +#include "components/password_manager/core/browser/form_saver_impl.h" #include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_form_manager.h" @@ -246,6 +248,14 @@ } } +void ManagePasswordsTest::SetupSaveToAccountStore() { + ON_CALL(*client_.GetPasswordFeatureManager(), IsOptedInForAccountStorage()) + .WillByDefault(testing::Return(true)); + ON_CALL(*client_.GetPasswordFeatureManager(), GetDefaultPasswordStore()) + .WillByDefault(testing::Return( + password_manager::PasswordForm::Store::kAccountStore)); +} + std::unique_ptr<base::HistogramSamples> ManagePasswordsTest::GetSamples( const char* histogram) { // Ensure that everything has been properly recorded before pulling samples. @@ -258,7 +268,9 @@ browser()->tab_strip_model()->GetActiveWebContents()); } -std::unique_ptr<PasswordFormManager> ManagePasswordsTest::CreateFormManager() { +std::unique_ptr<PasswordFormManager> ManagePasswordsTest::CreateFormManager( + password_manager::PasswordStoreInterface* profile_store, + password_manager::PasswordStoreInterface* account_store) { autofill::FormData observed_form; observed_form.url = password_form_.url; autofill::FormFieldData field; @@ -267,12 +279,21 @@ field.form_control_type = autofill::FormControlType::kInputPassword; observed_form.fields.push_back(field); + std::unique_ptr<password_manager::FormSaver> form_saver; + if (profile_store) { + form_saver = + std::make_unique<password_manager::FormSaverImpl>(profile_store); + } else { + form_saver = std::make_unique<password_manager::StubFormSaver>(); + } + auto form_manager = std::make_unique<PasswordFormManager>( &client_, driver_.AsWeakPtr(), observed_form, &fetcher_, std::make_unique<password_manager::PasswordSaveManagerImpl>( - /*profile_form_saver=*/std::make_unique< - password_manager::StubFormSaver>(), - /*account_form_saver=*/nullptr), + /*profile_form_saver=*/std::move(form_saver), + /*account_form_saver=*/account_store + ? std::make_unique<password_manager::FormSaverImpl>(account_store) + : nullptr), /*metrics_recorder=*/nullptr); insecure_credential_ = password_form_;
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.h b/chrome/browser/ui/passwords/manage_passwords_test.h index cc1b1c60..3afe28a 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.h +++ b/chrome/browser/ui/passwords/manage_passwords_test.h
@@ -75,6 +75,9 @@ // Put the controller, icon, and bubble into a moving-password state. void SetupMovingPasswords(); + // Put the client into a state which induces password save to account store. + void SetupSaveToAccountStore(); + // Always configures a signed-in user, and when |is_enabled| is true, it also // configures the Sync service to sync passwords. |is_account_storage_enabled| // enables account storage for the user. @@ -88,9 +91,16 @@ // Get the UI controller for the current WebContents. ManagePasswordsUIController* GetController(); - private: - std::unique_ptr<password_manager::PasswordFormManager> CreateFormManager(); + protected: + // Creates a form manager using the given password password stores. + // If |profile_store| is nullptr, password_manager::StubFormSaver is used for + // the profile store. If |account_store| is nullptr, a nullptr + // password_manager::FormSaver is used for the account store. + std::unique_ptr<password_manager::PasswordFormManager> CreateFormManager( + password_manager::PasswordStoreInterface* profile_store = nullptr, + password_manager::PasswordStoreInterface* account_store = nullptr); + private: password_manager::PasswordForm password_form_; password_manager::PasswordForm insecure_credential_; base::HistogramTester histogram_tester_;
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index 9ed7998..8d0310be 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/password_manager/profile_password_store_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/signin/signin_promo_util.h" #include "chrome/browser/signin/signin_ui_util.h" #include "chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.h" #include "chrome/browser/ui/browser_command_controller.h" @@ -764,6 +765,8 @@ ->NotifyEvent("passwords_account_storage_used"); } + // TODO(crbug/333709971): Decide whether the post save compromised bubble or + // the sign in promo bubble should be shown. post_save_compromised_helper_ = std::make_unique<password_manager::PostSaveCompromisedHelper>( passwords_data_.form_manager()->GetInsecureCredentials(), username); @@ -780,7 +783,11 @@ // The icon is to be updated after the bubble (either "Save password" or "Sign // in to Chrome") is closed. bubble_status_ = BubbleStatus::SHOWN_PENDING_ICON_UPDATE; - if (Browser* browser = chrome::FindBrowserWithTab(web_contents())) { + Browser* browser = chrome::FindBrowserWithTab(web_contents()); + // Do not trigger the IPH if the sign in promo will be shown. + if (browser && !signin::ShouldShowSignInPromo( + *browser->profile(), + signin::SignInAutofillBubblePromoType::Passwords)) { if (browser->window()->MaybeShowFeaturePromo( feature_engagement:: kIPHPasswordsManagementBubbleAfterSaveFeature)) {
diff --git a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller.cc b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller.cc deleted file mode 100644 index 7a3f6bfe..0000000 --- a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller.cc +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller.h" - -#include "base/functional/bind.h" -#include "chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_view.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" - -PasswordCrossDomainConfirmationPopupController:: - PasswordCrossDomainConfirmationPopupController( - content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) {} - -PasswordCrossDomainConfirmationPopupController:: - ~PasswordCrossDomainConfirmationPopupController() { - HideImpl(); -} - -void PasswordCrossDomainConfirmationPopupController::Show( - const gfx::RectF& element_bounds, - base::i18n::TextDirection text_direction, - const GURL& domain, - const std::u16string& password_origin, - base::OnceClosure confirmation_callback) { - if (!web_contents()) { - return; - } - - HideImpl(); - - element_bounds_ = element_bounds; - text_direction_ = text_direction; - confirmation_callback_ = std::move(confirmation_callback); - - view_ = PasswordCrossDomainConfirmationPopupView::Show( - weak_ptr_factory_.GetWeakPtr(), domain, password_origin, - base::BindOnce(&PasswordCrossDomainConfirmationPopupController::OnConfirm, - weak_ptr_factory_.GetWeakPtr()), - base::BindOnce(&PasswordCrossDomainConfirmationPopupController::OnCancel, - weak_ptr_factory_.GetWeakPtr())); - - content::RenderFrameHost* rfh = web_contents()->GetFocusedFrame(); - popup_hide_helper_.emplace( - web_contents(), rfh->GetGlobalId(), - autofill::AutofillPopupHideHelper::HidingParams{}, - /*hiding_callback=*/ - base::BindRepeating(&PasswordCrossDomainConfirmationPopupController::Hide, - base::Unretained(this)), - /*pip_detection_callback=*/ - base::BindRepeating(&PasswordCrossDomainConfirmationPopupController:: - OverlapsWithPictureInPictureWindow, - base::Unretained(this))); -} - -void PasswordCrossDomainConfirmationPopupController::Hide( - autofill::PopupHidingReason) { - HideImpl(); -} - -void PasswordCrossDomainConfirmationPopupController::ViewDestroyed() { - HideImpl(); -} - -gfx::NativeView PasswordCrossDomainConfirmationPopupController::container_view() - const { - return web_contents() ? web_contents()->GetContentNativeView() - : gfx::NativeView(); -} - -content::WebContents* -PasswordCrossDomainConfirmationPopupController::GetWebContents() const { - return web_contents(); -} - -const gfx::RectF& -PasswordCrossDomainConfirmationPopupController::element_bounds() const { - return element_bounds_; -} - -base::i18n::TextDirection -PasswordCrossDomainConfirmationPopupController::GetElementTextDirection() - const { - return text_direction_; -} - -void PasswordCrossDomainConfirmationPopupController::HideImpl() { - if (view_) { - view_->Hide(); - } - popup_hide_helper_.reset(); -} - -bool PasswordCrossDomainConfirmationPopupController:: - OverlapsWithPictureInPictureWindow() const { - return view_ && view_->OverlapsWithPictureInPictureWindow(); -} - -void PasswordCrossDomainConfirmationPopupController::OnConfirm() { - HideImpl(); - - std::move(confirmation_callback_).Run(); -} - -void PasswordCrossDomainConfirmationPopupController::OnCancel() { - HideImpl(); -}
diff --git a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller.h b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller.h deleted file mode 100644 index ebe5ada..0000000 --- a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_PASSWORDS_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_H_ -#define CHROME_BROWSER_UI_PASSWORDS_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_H_ - -#include "base/functional/callback_forward.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/ui/autofill/autofill_popup_hide_helper.h" -#include "chrome/browser/ui/autofill/autofill_popup_view_delegate.h" -#include "content/public/browser/web_contents_observer.h" -#include "ui/gfx/geometry/rect_f.h" -#include "url/gurl.h" - -class PasswordCrossDomainConfirmationPopupView; - -// The controller of the cross domain usage confirmation popup. It provides API -// to Show/Hide the popup and get the user's decision (via a callback). -class PasswordCrossDomainConfirmationPopupController - : public autofill::AutofillPopupViewDelegate, - public content::WebContentsObserver { - public: - explicit PasswordCrossDomainConfirmationPopupController( - content::WebContents* web_contents); - PasswordCrossDomainConfirmationPopupController( - const PasswordCrossDomainConfirmationPopupController&) = delete; - PasswordCrossDomainConfirmationPopupController& operator=( - const PasswordCrossDomainConfirmationPopupController&) = delete; - ~PasswordCrossDomainConfirmationPopupController() override; - - // autofill::AutofillPopupViewDelegate: - void Hide(autofill::PopupHidingReason reason) override; - void ViewDestroyed() override; - gfx::NativeView container_view() const override; - content::WebContents* GetWebContents() const override; - const gfx::RectF& element_bounds() const override; - base::i18n::TextDirection GetElementTextDirection() const override; - - // Creates and shows a popup pointing to `element_bounds` and presenting - // a message regarding cross domain password usage. `domain` is the domain - // of the current web site the popup is triggered on. `password_origin` is - // the name of the place where the password was originally created, it can - // be the domain of the web site or the name of the Android application. - // `confirmation_callback` is called if the user confirms the action, if - // the user cancels it, the popup is silently hidden. - // If the popup is already shown, it gets hidden and a new one shows up. - void Show(const gfx::RectF& element_bounds, - base::i18n::TextDirection text_direction, - const GURL& domain, - const std::u16string& password_origin, - base::OnceClosure confirmation_callback); - - private: - void HideImpl(); - bool OverlapsWithPictureInPictureWindow() const; - - // Handles the confirmation response from the view. - void OnConfirm(); - - // Handles the cancel response from the view. - void OnCancel(); - - gfx::RectF element_bounds_; - base::i18n::TextDirection text_direction_; - base::OnceClosure confirmation_callback_; - - base::WeakPtr<PasswordCrossDomainConfirmationPopupView> view_; - - std::optional<autofill::AutofillPopupHideHelper> popup_hide_helper_; - - base::WeakPtrFactory<PasswordCrossDomainConfirmationPopupController> - weak_ptr_factory_{this}; -}; - -#endif // CHROME_BROWSER_UI_PASSWORDS_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_H_
diff --git a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.cc b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.cc new file mode 100644 index 0000000..3b7f390 --- /dev/null +++ b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.cc
@@ -0,0 +1,112 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h" + +#include "base/functional/bind.h" +#include "chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_view.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" + +PasswordCrossDomainConfirmationPopupControllerImpl:: + PasswordCrossDomainConfirmationPopupControllerImpl( + content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) {} + +PasswordCrossDomainConfirmationPopupControllerImpl:: + ~PasswordCrossDomainConfirmationPopupControllerImpl() { + HideImpl(); +} + +void PasswordCrossDomainConfirmationPopupControllerImpl::Show( + const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) { + if (!web_contents()) { + return; + } + + HideImpl(); + + element_bounds_ = element_bounds; + text_direction_ = text_direction; + confirmation_callback_ = std::move(confirmation_callback); + + view_ = PasswordCrossDomainConfirmationPopupView::Show( + weak_ptr_factory_.GetWeakPtr(), domain, password_origin, + base::BindOnce( + &PasswordCrossDomainConfirmationPopupControllerImpl::OnConfirm, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce( + &PasswordCrossDomainConfirmationPopupControllerImpl::OnCancel, + weak_ptr_factory_.GetWeakPtr())); + + content::RenderFrameHost* rfh = web_contents()->GetFocusedFrame(); + popup_hide_helper_.emplace( + web_contents(), rfh->GetGlobalId(), + autofill::AutofillPopupHideHelper::HidingParams{}, + /*hiding_callback=*/ + base::BindRepeating( + &PasswordCrossDomainConfirmationPopupControllerImpl::Hide, + base::Unretained(this)), + /*pip_detection_callback=*/ + base::BindRepeating(&PasswordCrossDomainConfirmationPopupControllerImpl:: + OverlapsWithPictureInPictureWindow, + base::Unretained(this))); +} + +void PasswordCrossDomainConfirmationPopupControllerImpl::Hide( + autofill::PopupHidingReason) { + HideImpl(); +} + +void PasswordCrossDomainConfirmationPopupControllerImpl::ViewDestroyed() { + HideImpl(); +} + +gfx::NativeView +PasswordCrossDomainConfirmationPopupControllerImpl::container_view() const { + return web_contents() ? web_contents()->GetContentNativeView() + : gfx::NativeView(); +} + +content::WebContents* +PasswordCrossDomainConfirmationPopupControllerImpl::GetWebContents() const { + return web_contents(); +} + +const gfx::RectF& +PasswordCrossDomainConfirmationPopupControllerImpl::element_bounds() const { + return element_bounds_; +} + +base::i18n::TextDirection +PasswordCrossDomainConfirmationPopupControllerImpl::GetElementTextDirection() + const { + return text_direction_; +} + +void PasswordCrossDomainConfirmationPopupControllerImpl::HideImpl() { + if (view_) { + view_->Hide(); + } + popup_hide_helper_.reset(); +} + +bool PasswordCrossDomainConfirmationPopupControllerImpl:: + OverlapsWithPictureInPictureWindow() const { + return view_ && view_->OverlapsWithPictureInPictureWindow(); +} + +void PasswordCrossDomainConfirmationPopupControllerImpl::OnConfirm() { + HideImpl(); + + std::move(confirmation_callback_).Run(); +} + +void PasswordCrossDomainConfirmationPopupControllerImpl::OnCancel() { + HideImpl(); +}
diff --git a/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h new file mode 100644 index 0000000..d7c8dcd --- /dev/null +++ b/chrome/browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl.h
@@ -0,0 +1,70 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_PASSWORDS_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_UI_PASSWORDS_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_IMPL_H_ + +#include "base/functional/callback_forward.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/autofill/autofill_popup_hide_helper.h" +#include "chrome/browser/ui/autofill/autofill_popup_view_delegate.h" +#include "components/password_manager/core/browser/password_cross_domain_confirmation_popup_controller.h" +#include "content/public/browser/web_contents_observer.h" +#include "ui/gfx/geometry/rect_f.h" +#include "url/gurl.h" + +class PasswordCrossDomainConfirmationPopupView; + +// Implementation of the cross domain usage confirmation popup controller. +class PasswordCrossDomainConfirmationPopupControllerImpl + : public password_manager::PasswordCrossDomainConfirmationPopupController, + public autofill::AutofillPopupViewDelegate, + public content::WebContentsObserver { + public: + explicit PasswordCrossDomainConfirmationPopupControllerImpl( + content::WebContents* web_contents); + PasswordCrossDomainConfirmationPopupControllerImpl( + const PasswordCrossDomainConfirmationPopupControllerImpl&) = delete; + PasswordCrossDomainConfirmationPopupControllerImpl& operator=( + const PasswordCrossDomainConfirmationPopupControllerImpl&) = delete; + ~PasswordCrossDomainConfirmationPopupControllerImpl() override; + + // autofill::AutofillPopupViewDelegate: + void Hide(autofill::PopupHidingReason reason) override; + void ViewDestroyed() override; + gfx::NativeView container_view() const override; + content::WebContents* GetWebContents() const override; + const gfx::RectF& element_bounds() const override; + base::i18n::TextDirection GetElementTextDirection() const override; + + // PasswordCrossDomainConfirmationPopupController: + void Show(const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) override; + + private: + void HideImpl(); + bool OverlapsWithPictureInPictureWindow() const; + + // Handles the confirmation response from the view. + void OnConfirm(); + + // Handles the cancel response from the view. + void OnCancel(); + + gfx::RectF element_bounds_; + base::i18n::TextDirection text_direction_; + base::OnceClosure confirmation_callback_; + + base::WeakPtr<PasswordCrossDomainConfirmationPopupView> view_; + + std::optional<autofill::AutofillPopupHideHelper> popup_hide_helper_; + + base::WeakPtrFactory<PasswordCrossDomainConfirmationPopupControllerImpl> + weak_ptr_factory_{this}; +}; + +#endif // CHROME_BROWSER_UI_PASSWORDS_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/sync/sync_promo_ui.cc b/chrome/browser/ui/sync/sync_promo_ui.cc index e481b42e..df5da2ce 100644 --- a/chrome/browser/ui/sync/sync_promo_ui.cc +++ b/chrome/browser/ui/sync/sync_promo_ui.cc
@@ -7,11 +7,12 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/signin_promo_util.h" #include "chrome/browser/sync/sync_service_factory.h" +#include "components/signin/public/base/consent_level.h" #include "components/sync/service/sync_prefs.h" bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) { // Don't show sync promo if the sign in promo should not be shown. - if (!signin::ShouldShowPromo(profile)) { + if (!signin::ShouldShowPromo(*profile, signin::ConsentLevel::kSync)) { return false; }
diff --git a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc index 54373aa..f1a13a6 100644 --- a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc +++ b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.cc
@@ -36,7 +36,7 @@ namespace { using TabRole = ::TabSharingInfoBarDelegate::TabRole; -constexpr int kCscPermissionButtonIconHeight = 16; +constexpr int kCapturedSurfaceControlIndicatorButtonIconHeight = 16; } // namespace class TabSharingInfoBarDelegate::TabSharingInfoBarDelegateButton { @@ -165,12 +165,12 @@ const bool focus_target_is_capturer_; }; -class TabSharingInfoBarDelegate::CscPermissionButton +class TabSharingInfoBarDelegate::CscIndicatorButton : public TabSharingInfoBarDelegate::TabSharingInfoBarDelegateButton { public: - explicit CscPermissionButton(content::WebContents* web_contents) + explicit CscIndicatorButton(content::WebContents* web_contents) : web_contents_(web_contents ? web_contents->GetWeakPtr() : nullptr) {} - ~CscPermissionButton() override = default; + ~CscIndicatorButton() override = default; void Click(infobars::InfoBar* infobar) override { if (!web_contents_) { @@ -187,9 +187,9 @@ bool IsEnabled() const override { return true; } ui::ImageModel GetImage() const override { - return ui::ImageModel::FromVectorIcon(vector_icons::kTouchpadMouseIcon, - ui::kColorSysPrimary, - kCscPermissionButtonIconHeight); + return ui::ImageModel::FromVectorIcon( + vector_icons::kTouchpadMouseIcon, ui::kColorSysPrimary, + kCapturedSurfaceControlIndicatorButtonIconHeight); } private: @@ -322,8 +322,7 @@ if (role_ == TabRole::kCapturingTab && captured_surface_control_active && base::FeatureList::IsEnabled( features::kCapturedSurfaceControlStickyPermissions)) { - csc_permission_button_ = - std::make_unique<CscPermissionButton>(web_contents); + csc_indicator_button_ = std::make_unique<CscIndicatorButton>(web_contents); } } @@ -379,9 +378,9 @@ DCHECK(quick_nav_button_); return quick_nav_button_->GetLabel(); - case kCscPermission: - DCHECK(csc_permission_button_); - return csc_permission_button_->GetLabel(); + case kCapturedSurfaceControlIndicator: + DCHECK(csc_indicator_button_); + return csc_indicator_button_->GetLabel(); } NOTREACHED_NORETURN(); } @@ -405,9 +404,9 @@ DCHECK(quick_nav_button_); return quick_nav_button_->GetImage(); - case kCscPermission: - DCHECK(csc_permission_button_); - return csc_permission_button_->GetImage(); + case kCapturedSurfaceControlIndicator: + DCHECK(csc_indicator_button_); + return csc_indicator_button_->GetImage(); } NOTREACHED_NORETURN(); } @@ -428,9 +427,9 @@ DCHECK(quick_nav_button_); return quick_nav_button_->IsEnabled(); - case kCscPermission: - DCHECK(csc_permission_button_); - return csc_permission_button_->IsEnabled(); + case kCapturedSurfaceControlIndicator: + DCHECK(csc_indicator_button_); + return csc_indicator_button_->IsEnabled(); } NOTREACHED_NORETURN(); } @@ -452,9 +451,9 @@ DCHECK(quick_nav_button_); return quick_nav_button_->GetTooltip(); - case kCscPermission: - DCHECK(csc_permission_button_); - return csc_permission_button_->GetTooltip(); + case kCapturedSurfaceControlIndicator: + DCHECK(csc_indicator_button_); + return csc_indicator_button_->GetTooltip(); } NOTREACHED_NORETURN(); } @@ -462,7 +461,7 @@ int TabSharingInfoBarDelegate::GetButtons() const { return kStop | (share_this_tab_instead_button_ ? kShareThisTabInstead : 0) | (quick_nav_button_ ? kQuickNav : 0) | - (csc_permission_button_ ? kCscPermission : 0); + (csc_indicator_button_ ? kCapturedSurfaceControlIndicator : 0); } void TabSharingInfoBarDelegate::Stop() { @@ -481,8 +480,8 @@ void TabSharingInfoBarDelegate:: OnCapturedSurfaceControlActivityIndicatorPressed() { - DCHECK(csc_permission_button_); - csc_permission_button_->Click(infobar()); + DCHECK(csc_indicator_button_); + csc_indicator_button_->Click(infobar()); } bool TabSharingInfoBarDelegate::IsCloseable() const {
diff --git a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h index dcfc899..4358010 100644 --- a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h +++ b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate.h
@@ -53,8 +53,7 @@ kStop = 1 << 0, kShareThisTabInstead = 1 << 1, kQuickNav = 1 << 2, - // TODO(crbug.com/1466247): Rename to kCapturedSurfaceControlIndicator. - kCscPermission = 1 << 3, + kCapturedSurfaceControlIndicator = 1 << 3, }; enum class ButtonState { @@ -82,7 +81,7 @@ class TabSharingInfoBarDelegateButton; class ShareTabInsteadButton; class SwitchToTabButton; - class CscPermissionButton; + class CscIndicatorButton; // Creates a tab sharing infobar, which has 1-2 buttons. // @@ -163,9 +162,7 @@ std::unique_ptr<ShareTabInsteadButton> share_this_tab_instead_button_; std::unique_ptr<SwitchToTabButton> quick_nav_button_; - // TODO(crbug.com/324468211): Rename both class and member to remove the word - // "permission". - std::unique_ptr<CscPermissionButton> csc_permission_button_; + std::unique_ptr<CscIndicatorButton> csc_indicator_button_; }; std::unique_ptr<infobars::InfoBar> CreateTabSharingInfoBar(
diff --git a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate_unittest.cc b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate_unittest.cc index 0f3c8b5..229dc958 100644 --- a/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate_unittest.cc +++ b/chrome/browser/ui/tab_sharing/tab_sharing_infobar_delegate_unittest.cc
@@ -192,11 +192,11 @@ IDS_TAB_SHARING_INFOBAR_SHARING_ANOTHER_UNTITLED_TAB_LABEL, kAppName)); - const int expected_buttons = TabSharingInfoBarDelegate::kStop | - TabSharingInfoBarDelegate::kQuickNav | - (captured_surface_control_active_ - ? TabSharingInfoBarDelegate::kCscPermission - : 0); + const int expected_buttons = + TabSharingInfoBarDelegate::kStop | TabSharingInfoBarDelegate::kQuickNav | + (captured_surface_control_active_ + ? TabSharingInfoBarDelegate::kCapturedSurfaceControlIndicator + : 0); EXPECT_EQ(delegate->GetButtons(), expected_buttons); EXPECT_EQ(delegate->GetButtonLabel(TabSharingInfoBarDelegate::kStop), l10n_util::GetStringUTF16(IDS_TAB_SHARING_INFOBAR_STOP_BUTTON)); @@ -208,7 +208,8 @@ if (captured_surface_control_active_) { EXPECT_EQ( - delegate->GetButtonLabel(TabSharingInfoBarDelegate::kCscPermission), + delegate->GetButtonLabel( + TabSharingInfoBarDelegate::kCapturedSurfaceControlIndicator), l10n_util::GetStringUTF16( IDS_TAB_SHARING_INFOBAR_CAPTURED_SURFACE_CONTROL_PERMISSION_BUTTON)); }
diff --git a/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.cc b/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.cc index d48410f..fedd043 100644 --- a/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.cc +++ b/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.cc
@@ -42,6 +42,8 @@ namespace { constexpr char kWidgetName[] = "EditorMenuPromoCardViewWidget"; +constexpr char16_t kCardShownAnnouncement[] = + u"Help Me Write, press tab to focus the Help Me Write card."; constexpr int kPromoCardIconSizeDip = 20; @@ -160,6 +162,14 @@ return true; } +void EditorMenuPromoCardView::OnWidgetVisibilityChanged(views::Widget* widget, + bool visible) { + if (visible && !queued_announcement_) { + GetViewAccessibility().AnnounceAlert(kCardShownAnnouncement); + queued_announcement_ = true; + } +} + void EditorMenuPromoCardView::UpdateBounds( const gfx::Rect& anchor_view_bounds) { GetWidget()->SetBounds(GetEditorMenuBounds(anchor_view_bounds, this));
diff --git a/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.h b/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.h index 3ad8e58..e633e15 100644 --- a/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.h +++ b/chrome/browser/ui/views/editor_menu/editor_menu_promo_card_view.h
@@ -51,6 +51,7 @@ void OnWidgetDestroying(views::Widget* widget) override; void OnWidgetActivationChanged(views::Widget* widget, bool active) override; bool AcceleratorPressed(const ui::Accelerator& accelerator) override; + void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override; void UpdateBounds(const gfx::Rect& anchor_view_bounds); @@ -74,6 +75,8 @@ raw_ptr<views::MdTextButton> dismiss_button_ = nullptr; raw_ptr<views::MdTextButton> try_it_button_ = nullptr; + bool queued_announcement_ = false; + base::ScopedObservation<views::Widget, views::WidgetObserver> widget_observation_{this};
diff --git a/chrome/browser/ui/views/editor_menu/editor_menu_view.cc b/chrome/browser/ui/views/editor_menu/editor_menu_view.cc index 868c887..2e085a95 100644 --- a/chrome/browser/ui/views/editor_menu/editor_menu_view.cc +++ b/chrome/browser/ui/views/editor_menu/editor_menu_view.cc
@@ -51,6 +51,8 @@ namespace { constexpr char kWidgetName[] = "EditorMenuViewWidget"; +constexpr char16_t kCardShownAnnouncement[] = + u"Help Me Write, press tab to focus the Help Me Write card."; constexpr gfx::Insets kTitleContainerInsets = gfx::Insets::TLBR(12, 16, 12, 14); @@ -159,6 +161,11 @@ bool visible) { CHECK(delegate_); delegate_->OnEditorMenuVisibilityChanged(visible); + + if (visible && !queued_announcement_) { + GetViewAccessibility().AnnounceAlert(kCardShownAnnouncement); + queued_announcement_ = true; + } } void EditorMenuView::UpdateBounds(const gfx::Rect& anchor_view_bounds) {
diff --git a/chrome/browser/ui/views/editor_menu/editor_menu_view.h b/chrome/browser/ui/views/editor_menu/editor_menu_view.h index 5012a51..1f132547 100644 --- a/chrome/browser/ui/views/editor_menu/editor_menu_view.h +++ b/chrome/browser/ui/views/editor_menu/editor_menu_view.h
@@ -92,6 +92,8 @@ raw_ptr<EditorMenuTextfieldView> textfield_ = nullptr; + bool queued_announcement_ = false; + base::WeakPtrFactory<EditorMenuView> weak_factory_{this}; };
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.cc b/chrome/browser/ui/views/passwords/password_save_update_view.cc index 90120f5..2fb969c 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_view.cc +++ b/chrome/browser/ui/views/passwords/password_save_update_view.cc
@@ -11,6 +11,7 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/signin_promo_util.h" #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/hats/hats_service.h" #include "chrome/browser/ui/hats/hats_service_factory.h" @@ -21,12 +22,14 @@ #include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/passwords/credentials_item_view.h" #include "chrome/browser/ui/views/passwords/views_utils.h" +#include "chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.h" #include "chrome/browser/ui/views/user_education/browser_feature_promo_controller.h" #include "chrome/grit/branded_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/tracker.h" +#include "components/signin/public/base/signin_buildflags.h" #include "components/user_education/common/feature_promo_specification.h" #include "components/user_education/common/help_bubble_params.h" #include "content/public/browser/storage_partition.h" @@ -44,6 +47,7 @@ #include "ui/views/interaction/element_tracker_views.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/layout/flex_layout.h" +#include "ui/views/view_class_properties.h" // TODO(crbug.com/1077706): come up with a more general solution for this. // This layout auto-resizes the host view to always adapt to changes in the size @@ -189,8 +193,12 @@ (dialog->controller_.*func)(); }; - SetAcceptCallback(base::BindOnce(button_clicked, base::Unretained(this), - &Controller::OnSaveClicked)); + SetAcceptCallbackWithClose( + base::BindRepeating(button_clicked, base::Unretained(this), + &Controller::OnSaveClicked) + .Then(base::BindRepeating( + &PasswordSaveUpdateView::CloseOrReplaceWithPromo, + base::Unretained(this)))); SetCancelCallback(base::BindOnce( button_clicked, base::Unretained(this), is_update_bubble_ ? &Controller::OnNoThanksClicked @@ -224,6 +232,48 @@ return &controller_; } +bool PasswordSaveUpdateView::CloseOrReplaceWithPromo() { +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + // Close the bubble if the sign in promo should not be shown. + if (!signin::ShouldShowSignInPromo( + *controller_.GetProfile(), + signin::SignInAutofillBubblePromoType::Passwords)) { + return true; + } + + // Remove current elements. + animating_layout_for_iph_observation_.Reset(); + animating_layout_for_username_dropdown_observation_.reset(); + username_dropdown_ = nullptr; + password_dropdown_ = nullptr; + destination_dropdown_ = nullptr; + accessibility_alert_ = nullptr; + RemoveAllChildViews(); + SetLayoutManager(std::make_unique<views::FillLayout>()); + SetShowIcon(false); + SetButtons(ui::DIALOG_BUTTON_NONE); + GetBubbleFrameView()->SetFootnoteView(nullptr); + + // TODO(crbug/319411476): Should be changed to the correct string, moved + // inside the AutofillBubbleSignInPromoView and depending on autofill type. + SetTitle(IDS_PASSWORD_GENERATION_HELP_TEXT_TRUSTED_ADVICE); + + // Show the sign in promo. + auto sign_in_promo = std::make_unique<AutofillBubbleSignInPromoView>( + controller_.GetWebContents(), + signin::SignInAutofillBubblePromoType::Passwords); + AddChildView(std::move(sign_in_promo)); + SizeToContents(); + + GetBubbleFrameView()->SetProperty(views::kElementIdentifierKey, + kPasswordBubble); + + return false; +#else + return true; +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) +} + void PasswordSaveUpdateView::DestinationChanged() { bool is_account_store_selected = destination_dropdown_->GetSelectedIndex() == 0u; @@ -520,3 +570,5 @@ }, base::Unretained(this), std::move(pin))); } + +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(PasswordSaveUpdateView, kPasswordBubble);
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.h b/chrome/browser/ui/views/passwords/password_save_update_view.h index 73e08ba..447e9627 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_view.h +++ b/chrome/browser/ui/views/passwords/password_save_update_view.h
@@ -30,6 +30,8 @@ public views::WidgetObserver, public views::AnimatingLayoutManager::Observer { public: + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kPasswordBubble); + PasswordSaveUpdateView(content::WebContents* web_contents, views::View* anchor_view, DisplayReason reason); @@ -61,6 +63,12 @@ PasswordBubbleControllerBase* GetController() override; const PasswordBubbleControllerBase* GetController() const override; + // If the sign in promo should be shown, it will remove the current contents + // of the bubble and replace them with the sign in promo. Returns true if the + // bubble is not replaced with the promo, and therefore closed. Returns false + // if it is replaced, which will cause the bubble to stay open. + bool CloseOrReplaceWithPromo(); + // PasswordBubbleViewBase: views::View* GetInitiallyFocusedView() override; bool IsDialogButtonEnabled(ui::DialogButton button) const override;
diff --git a/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_interactive_uitest.cc b/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_interactive_uitest.cc new file mode 100644 index 0000000..fd3ded1 --- /dev/null +++ b/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_interactive_uitest.cc
@@ -0,0 +1,310 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/password_manager/password_manager_test_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/chrome_signin_client_test_util.h" +#include "chrome/browser/signin/dice_tab_helper.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/ui/autofill/autofill_signin_promo_tab_helper.h" +#include "chrome/browser/ui/passwords/manage_passwords_test.h" +#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" +#include "chrome/browser/ui/views/passwords/password_bubble_view_base.h" +#include "chrome/browser/ui/views/passwords/password_save_update_view.h" +#include "chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.h" +#include "chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.h" +#include "chrome/test/base/interactive_test_utils.h" +#include "chrome/test/base/profile_waiter.h" +#include "components/password_manager/core/browser/password_form.h" +#include "components/password_manager/core/browser/password_manager_test_utils.h" +#include "components/password_manager/core/browser/password_store/test_password_store.h" +#include "components/signin/public/base/consent_level.h" +#include "components/signin/public/base/signin_pref_names.h" +#include "components/signin/public/base/signin_switches.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/identity_test_utils.h" +#include "components/sync/base/features.h" +#include "content/public/test/browser_test.h" + +namespace { +constexpr char kButton[] = "SignInButton"; +} // namespace + +MATCHER_P(FormMatches, form, "") { + return form.signon_realm == arg.signon_realm && form.url == arg.url && + form.action == arg.action && + form.username_element == arg.username_element && + form.password_element == arg.password_element; +} + +class AutofillBubbleSignInPromoInteractiveUITest : public ManagePasswordsTest { + public: + void SetUpInProcessBrowserTestFixture() override { + ManagePasswordsTest::SetUpInProcessBrowserTestFixture(); + url_loader_factory_helper_.SetUp(); + create_services_subscription_ = + BrowserContextDependencyManager::GetInstance() + ->RegisterCreateServicesCallbackForTesting(base::BindRepeating( + &AutofillBubbleSignInPromoInteractiveUITest:: + OnWillCreateBrowserContextServices, + base::Unretained(this))); + } + + void OnWillCreateBrowserContextServices(content::BrowserContext* context) { + // Create password stores. + local_password_store_ = CreateAndUseTestPasswordStore(context); + account_password_store_ = CreateAndUseTestAccountPasswordStore(context); + } + + // Trigger the password save by simulating an "Accept" in the password bubble, + // and wait for it to appear in the store. If |store| is kAccountStore, it + // will wait for a password to appear in the account store, if not, in the + // profile store. + void SavePassword(password_manager::PasswordForm::Store store); + + // Perform a sign in with the password bubble access point and wait for an + // event in the account store. + void SignIn(); + + // Returns true if the current tab's URL is a sign in URL. + bool IsSignInURL(); + + // Returns true if there is a primary account without a refresh token in + // persistent error state. + bool IsSignedIn(); + + network::TestURLLoaderFactory* test_url_loader_factory() { + return url_loader_factory_helper_.test_url_loader_factory(); + } + + signin::IdentityManager* identity_manager() { + return IdentityManagerFactory::GetForProfile(browser()->profile()); + } + + protected: + base::test::ScopedFeatureList scoped_feature_list_{ + switches::kExplicitBrowserSigninUIOnDesktop}; + + ChromeSigninClientWithURLLoaderHelper url_loader_factory_helper_; + base::CallbackListSubscription create_services_subscription_; + scoped_refptr<password_manager::TestPasswordStore> local_password_store_; + scoped_refptr<password_manager::TestPasswordStore> account_password_store_; +}; + +void AutofillBubbleSignInPromoInteractiveUITest::SavePassword( + password_manager::PasswordForm::Store store) { + auto store_waiter = + store == password_manager::PasswordForm::Store::kAccountStore + ? password_manager::PasswordStoreWaiter(account_password_store_.get()) + : password_manager::PasswordStoreWaiter(local_password_store_.get()); + + PasswordBubbleViewBase* bubble = + PasswordBubbleViewBase::manage_password_bubble(); + bubble->AcceptDialog(); + + store_waiter.WaitOrReturn(); +} + +void AutofillBubbleSignInPromoInteractiveUITest::SignIn() { + signin::MakeAccountAvailable( + identity_manager(), + signin::AccountAvailabilityOptionsBuilder(test_url_loader_factory()) + .WithCookie() + .AsPrimary(signin::ConsentLevel::kSignin) + .WithAccessPoint( + signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE) + .Build("test@email.com")); +} + +bool AutofillBubbleSignInPromoInteractiveUITest::IsSignInURL() { + DiceTabHelper* tab_helper = DiceTabHelper::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents()); + return tab_helper->IsChromeSigninPage(); +} + +bool AutofillBubbleSignInPromoInteractiveUITest::IsSignedIn() { + return identity_manager()->HasPrimaryAccountWithRefreshToken( + signin::ConsentLevel::kSignin) && + !identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState( + identity_manager()->GetPrimaryAccountId( + signin::ConsentLevel::kSignin)); +} + +IN_PROC_BROWSER_TEST_F(AutofillBubbleSignInPromoInteractiveUITest, + SignInPromoNoAccountPresent) { + // Set up password and password stores. + GetController()->OnPasswordSubmitted(CreateFormManager( + local_password_store_.get(), account_password_store_.get())); + + // Save the password and check that it was properly saved to profile store. + SavePassword(password_manager::PasswordForm::Store::kProfileStore); + EXPECT_EQ(1u, local_password_store_->stored_passwords().size()); + EXPECT_EQ(0u, account_password_store_->stored_passwords().size()); + + // Wait for the bubble to be replaced with the sign in promo and click the + // sign in button. + RunTestSequence( + WaitForShow(BubbleSignInPromoSignInButtonView::kPromoSignInButton), + EnsurePresent(PasswordSaveUpdateView::kPasswordBubble), + SetOnIncompatibleAction( + OnIncompatibleAction::kIgnoreAndContinue, + "Screenshot can only run in pixel_tests on Windows."), + Screenshot(PasswordSaveUpdateView::kPasswordBubble, std::string(), + "5231400"), + NameChildViewByType<views::MdTextButton>( + BubbleSignInPromoSignInButtonView::kPromoSignInButton, kButton), + PressButton(kButton).SetMustRemainVisible(false), + EnsureNotPresent(PasswordSaveUpdateView::kPasswordBubble)); + + // Check that clicking the sign in button navigated to a sign in page. + EXPECT_TRUE(IsSignInURL()); + + // Check that there is a helper attached to the sign in tab, because the + // password still needs to be moved. + EXPECT_TRUE(autofill::AutofillSigninPromoTabHelper::GetForWebContents( + *browser()->tab_strip_model()->GetActiveWebContents()) + ->IsInitializedForTesting()); + + // Simulate a sign in event with the correct access point, which will move the + // password. Wait for the password to show up in account store. + auto account_store_waiter = + password_manager::PasswordStoreWaiter(account_password_store_.get()); + SignIn(); + account_store_waiter.WaitOrReturn(); + + // Check that the sign in was successful. + EXPECT_TRUE(IsSignedIn()); + + // Check that password was moved to account store. + EXPECT_EQ(0u, local_password_store_->stored_passwords().size()); + EXPECT_EQ(1u, account_password_store_->stored_passwords().size()); + + auto found = account_password_store_->stored_passwords().find( + test_form()->signon_realm); + EXPECT_NE(account_password_store_->stored_passwords().end(), found); + EXPECT_THAT(found->second, testing::ElementsAre(FormMatches(*test_form()))); +} + +IN_PROC_BROWSER_TEST_F(AutofillBubbleSignInPromoInteractiveUITest, + SignInPromoWithWebSignedInAccount) { + // Sign in with an account, but only on the web. The primary account is not + // set. + signin::MakeAccountAvailable( + identity_manager(), + signin::AccountAvailabilityOptionsBuilder(test_url_loader_factory()) + .WithCookie() + .WithAccessPoint(signin_metrics::AccessPoint::ACCESS_POINT_WEB_SIGNIN) + .Build("test@email.com")); + + // Set up password and password stores. + GetController()->OnPasswordSubmitted(CreateFormManager( + local_password_store_.get(), account_password_store_.get())); + + // Save the password and check that it was properly saved to profile store. + SavePassword(password_manager::PasswordForm::Store::kProfileStore); + EXPECT_EQ(1u, local_password_store_->stored_passwords().size()); + EXPECT_EQ(0u, account_password_store_->stored_passwords().size()); + + // Wait for the bubble to be replaced with the sign in promo and click the + // sign in button. This should directly sign the user in and move the + // password. + auto account_store_waiter = + password_manager::PasswordStoreWaiter(account_password_store_.get()); + RunTestSequence( + WaitForShow(BubbleSignInPromoSignInButtonView::kPromoSignInButton), + EnsurePresent(PasswordSaveUpdateView::kPasswordBubble), + SetOnIncompatibleAction( + OnIncompatibleAction::kIgnoreAndContinue, + "Screenshot can only run in pixel_tests on Windows."), + Screenshot(PasswordSaveUpdateView::kPasswordBubble, std::string(), + "5231400"), + NameChildViewByType<views::MdTextButton>( + BubbleSignInPromoSignInButtonView::kPromoSignInButton, kButton), + PressButton(kButton).SetMustRemainVisible(false), + EnsureNotPresent(PasswordSaveUpdateView::kPasswordBubble)); + account_store_waiter.WaitOrReturn(); + + // Check that there is no helper attached to the sign in tab, because the + // password was already moved. + EXPECT_FALSE(autofill::AutofillSigninPromoTabHelper::GetForWebContents( + *browser()->tab_strip_model()->GetActiveWebContents()) + ->IsInitializedForTesting()); + + // Check that the sign in was successful. + EXPECT_TRUE(IsSignedIn()); + + // Check that password was moved to account store. + EXPECT_EQ(0u, local_password_store_->stored_passwords().size()); + EXPECT_EQ(1u, account_password_store_->stored_passwords().size()); + + auto found = account_password_store_->stored_passwords().find( + test_form()->signon_realm); + EXPECT_NE(account_password_store_->stored_passwords().end(), found); + EXPECT_THAT(found->second, testing::ElementsAre(FormMatches(*test_form()))); +} + +IN_PROC_BROWSER_TEST_F(AutofillBubbleSignInPromoInteractiveUITest, + SignInPromoWithAccountSignInPaused) { + // Sign in with an account, and put its refresh token into an error + // state. This simulates the "sign in paused" state. + AccountInfo info = signin::MakePrimaryAccountAvailable( + identity_manager(), "test@email.com", signin::ConsentLevel::kSignin); + signin::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_manager(), info.account_id, + GoogleServiceAuthError( + GoogleServiceAuthError::State::USER_NOT_SIGNED_UP)); + + // Set up password and password stores. + GetController()->OnPasswordSubmitted(CreateFormManager( + local_password_store_.get(), account_password_store_.get())); + + // Simulate the use of account store. + SetupSaveToAccountStore(); + + // Save the password and check that it was properly saved to account store. + SavePassword(password_manager::PasswordForm::Store::kAccountStore); + EXPECT_EQ(0u, local_password_store_->stored_passwords().size()); + EXPECT_EQ(1u, account_password_store_->stored_passwords().size()); + + // Wait for the bubble to be replaced with the sign in promo and click + // the sign in button. + RunTestSequence( + WaitForShow(BubbleSignInPromoSignInButtonView::kPromoSignInButton), + EnsurePresent(PasswordSaveUpdateView::kPasswordBubble), + SetOnIncompatibleAction( + OnIncompatibleAction::kIgnoreAndContinue, + "Screenshot can only run in pixel_tests on Windows."), + Screenshot(PasswordSaveUpdateView::kPasswordBubble, std::string(), + "5231400"), + NameChildViewByType<views::MdTextButton>( + BubbleSignInPromoSignInButtonView::kPromoSignInButton, kButton), + PressButton(kButton).SetMustRemainVisible(false), + EnsureNotPresent(PasswordSaveUpdateView::kPasswordBubble)); + + // Check that clicking the sign in button navigated to a sign in page. + EXPECT_TRUE(IsSignInURL()); + + // Check that there is no helper attached to the sign in tab, because the + // password does not need to be moved. + EXPECT_FALSE(autofill::AutofillSigninPromoTabHelper::GetForWebContents( + *browser()->tab_strip_model()->GetActiveWebContents()) + ->IsInitializedForTesting()); + + // Set a new refresh token for the primary account, which verifies the + // user's identity and signs them back in. The password will stay in the + // account store. + signin::SetRefreshTokenForPrimaryAccount(identity_manager()); + + // Check that the sign in was successful. + EXPECT_TRUE(IsSignedIn()); + + // Check that password is still account store. + EXPECT_EQ(0u, local_password_store_->stored_passwords().size()); + EXPECT_EQ(1u, account_password_store_->stored_passwords().size()); + + auto found = account_password_store_->stored_passwords().find( + test_form()->signon_realm); + EXPECT_NE(account_password_store_->stored_passwords().end(), found); + EXPECT_THAT(found->second, testing::ElementsAre(FormMatches(*test_form()))); +}
diff --git a/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.cc b/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.cc index b7f7c67b..d148565f 100644 --- a/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.cc +++ b/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.cc
@@ -58,7 +58,7 @@ AutofillBubbleSignInPromoView::AutofillBubbleSignInPromoView( content::WebContents* web_contents, - PromoType promo_type) + signin::SignInAutofillBubblePromoType promo_type) // TODO(crbug.com/319411728): Make this dependant on type (for now only // password). : controller_(PasswordsModelDelegateFromWebContents(web_contents)), @@ -75,9 +75,9 @@ int message_resource_id = 0; switch (promo_type_) { // TODO(crbug.com/319411728): Add the correct strings per type. - case PromoType::Payments: - case PromoType::Address: - case PromoType::Password: + case signin::SignInAutofillBubblePromoType::Payments: + case signin::SignInAutofillBubblePromoType::Addresses: + case signin::SignInAutofillBubblePromoType::Passwords: message_resource_id = IDS_PASSWORD_MANAGER_DICE_PROMO_SIGNIN_MESSAGE; } AddChildView(new BubbleSignInPromoView(
diff --git a/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.h b/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.h index e2849a4..23ea590e 100644 --- a/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.h +++ b/chrome/browser/ui/views/promos/autofill_bubble_signin_promo_view.h
@@ -6,6 +6,8 @@ #define CHROME_BROWSER_UI_VIEWS_PROMOS_AUTOFILL_BUBBLE_SIGNIN_PROMO_VIEW_H_ #include <memory> + +#include "chrome/browser/signin/signin_promo_util.h" #include "chrome/browser/ui/autofill/autofill_bubble_signin_promo_controller.h" #include "chrome/browser/ui/signin/bubble_signin_promo_delegate.h" #include "ui/views/controls/button/button.h" @@ -27,10 +29,9 @@ METADATA_HEADER(AutofillBubbleSignInPromoView, views::View) public: - enum class PromoType { Password, Address, Payments }; - - explicit AutofillBubbleSignInPromoView(content::WebContents* web_contents, - PromoType promo_type); + explicit AutofillBubbleSignInPromoView( + content::WebContents* web_contents, + signin::SignInAutofillBubblePromoType promo_type); AutofillBubbleSignInPromoView(const AutofillBubbleSignInPromoView&) = delete; AutofillBubbleSignInPromoView& operator=( const AutofillBubbleSignInPromoView&) = delete; @@ -42,7 +43,7 @@ class DiceSigninPromoDelegate; autofill::AutofillBubbleSignInPromoController controller_; - const PromoType promo_type_; + const signin::SignInAutofillBubblePromoType promo_type_; std::unique_ptr<DiceSigninPromoDelegate> dice_sign_in_promo_delegate_; };
diff --git a/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.cc b/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.cc index aad7125..135e8d21 100644 --- a/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.cc +++ b/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.cc
@@ -20,7 +20,7 @@ #include "ui/base/ui_base_types.h" #include "ui/gfx/canvas.h" #include "ui/views/border.h" -#include "ui/views/controls/button/md_text_button.h" +#include "ui/views/interaction/element_tracker_views.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/flex_layout.h" @@ -38,6 +38,8 @@ l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON)) .SetStyle(button_style)) .BuildChildren(); + + SetProperty(views::kElementIdentifierKey, kPromoSignInButton); } BubbleSignInPromoSignInButtonView::BubbleSignInPromoSignInButtonView( @@ -82,10 +84,15 @@ IDS_PROFILES_DICE_SIGNIN_BUTTON)) .SetStyle(ui::ButtonStyle::kProminent)) .BuildChildren(); + + SetProperty(views::kElementIdentifierKey, kPromoSignInButton); } BubbleSignInPromoSignInButtonView:: ~BubbleSignInPromoSignInButtonView() = default; +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(BubbleSignInPromoSignInButtonView, + kPromoSignInButton); + BEGIN_METADATA(BubbleSignInPromoSignInButtonView) END_METADATA
diff --git a/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.h b/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.h index 710ec5d..127e1e9 100644 --- a/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.h +++ b/chrome/browser/ui/views/promos/bubble_signin_promo_signin_button_view.h
@@ -10,8 +10,10 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/ui/views/controls/hover_button.h" #include "components/signin/public/identity_manager/account_info.h" +#include "ui/base/interaction/element_tracker.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/controls/button/label_button.h" +#include "ui/views/controls/button/md_text_button.h" #include "ui/views/metadata/view_factory.h" #include "ui/views/view.h" @@ -22,6 +24,8 @@ METADATA_HEADER(BubbleSignInPromoSignInButtonView, views::View) public: + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kPromoSignInButton); + // Create a non-personalized sign-in button with |button_style|. // |callback| is called every time the user interacts with this button. explicit BubbleSignInPromoSignInButtonView(
diff --git a/chrome/browser/ui/views/promos/bubble_signin_promo_view.cc b/chrome/browser/ui/views/promos/bubble_signin_promo_view.cc index 6cde544..b596e421 100644 --- a/chrome/browser/ui/views/promos/bubble_signin_promo_view.cc +++ b/chrome/browser/ui/views/promos/bubble_signin_promo_view.cc
@@ -26,6 +26,7 @@ #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/flex_layout.h" +#include "ui/views/widget/widget.h" BubbleSignInPromoView::BubbleSignInPromoView( Profile* profile, @@ -133,6 +134,7 @@ void BubbleSignInPromoView::SignIn() { std::optional<AccountInfo> account = signin_button_view_->account(); delegate_->OnSignIn(account.value_or(AccountInfo())); + GetWidget()->Close(); } BEGIN_METADATA(BubbleSignInPromoView)
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc index be7e066e..19b2260 100644 --- a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc +++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.cc
@@ -26,7 +26,8 @@ #include "ui/views/view_class_properties.h" namespace { -constexpr auto kCscPermissionButtonInsets = gfx::Insets::VH(4, 8); +constexpr auto kCapturedSurfaceControlIndicatorButtonInsets = + gfx::Insets::VH(4, 8); } TabSharingInfoBar::TabSharingInfoBar( @@ -42,7 +43,7 @@ int button_context = views::style::CONTEXT_BUTTON_MD) { const bool use_text_color_for_icon = - type != TabSharingInfoBarDelegate::kCscPermission; + type != TabSharingInfoBarDelegate::kCapturedSurfaceControlIndicator; auto* button = AddChildView(std::make_unique<views::MdTextButton>( base::BindRepeating(click_function, base::Unretained(this)), delegate_ptr->GetButtonLabel(type), button_context, @@ -81,16 +82,17 @@ &TabSharingInfoBar::QuickNavButtonPressed); } - if (buttons & TabSharingInfoBarDelegate::kCscPermission) { - csc_permission_button_ = create_button( - TabSharingInfoBarDelegate::kCscPermission, + if (buttons & TabSharingInfoBarDelegate::kCapturedSurfaceControlIndicator) { + csc_indicator_button_ = create_button( + TabSharingInfoBarDelegate::kCapturedSurfaceControlIndicator, &TabSharingInfoBar::OnCapturedSurfaceControlActivityIndicatorPressed, CONTEXT_OMNIBOX_PRIMARY); - csc_permission_button_->SetStyle(ui::ButtonStyle::kDefault); - csc_permission_button_->SetCornerRadius( + csc_indicator_button_->SetStyle(ui::ButtonStyle::kDefault); + csc_indicator_button_->SetCornerRadius( GetLayoutConstant(TOOLBAR_CORNER_RADIUS)); - csc_permission_button_->SetCustomPadding(kCscPermissionButtonInsets); - csc_permission_button_->SetTextColorId( + csc_indicator_button_->SetCustomPadding( + kCapturedSurfaceControlIndicatorButtonInsets); + csc_indicator_button_->SetTextColorId( views::Button::ButtonState::STATE_NORMAL, ui::kColorSysOnSurface); } @@ -116,8 +118,8 @@ quick_nav_button_->SizeToPreferredSize(); } - if (csc_permission_button_) { - csc_permission_button_->SizeToPreferredSize(); + if (csc_indicator_button_) { + csc_indicator_button_->SizeToPreferredSize(); } int x = GetStartX(); @@ -148,8 +150,8 @@ if (quick_nav_button_) { order_of_buttons.push_back(quick_nav_button_); } - if (csc_permission_button_) { - order_of_buttons.push_back(csc_permission_button_); + if (csc_indicator_button_) { + order_of_buttons.push_back(csc_indicator_button_); } if (!views::PlatformStyle::kIsOkButtonLeading) { @@ -213,7 +215,7 @@ const int button_count = (stop_button_ ? 1 : 0) + (share_this_tab_instead_button_ ? 1 : 0) + - (quick_nav_button_ ? 1 : 0) + (csc_permission_button_ ? 1 : 0); + (quick_nav_button_ ? 1 : 0) + (csc_indicator_button_ ? 1 : 0); int width = (label_->GetText().empty() || button_count == 0) ? 0 : label_spacing; @@ -225,7 +227,7 @@ ? share_this_tab_instead_button_->width() : 0; width += quick_nav_button_ ? quick_nav_button_->width() : 0; - width += csc_permission_button_ ? csc_permission_button_->width() : 0; + width += csc_indicator_button_ ? csc_indicator_button_->width() : 0; return width + ((width && !link_->GetText().empty()) ? label_spacing : 0); }
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h index ccde616..c7066e5 100644 --- a/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h +++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_infobar.h
@@ -55,7 +55,7 @@ raw_ptr<views::MdTextButton> stop_button_ = nullptr; raw_ptr<views::MdTextButton> share_this_tab_instead_button_ = nullptr; raw_ptr<views::MdTextButton> quick_nav_button_ = nullptr; - raw_ptr<views::MdTextButton> csc_permission_button_ = nullptr; + raw_ptr<views::MdTextButton> csc_indicator_button_ = nullptr; raw_ptr<views::Link> link_ = nullptr; };
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc index bf3f7324..d4e6cbc 100644 --- a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc +++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc
@@ -124,24 +124,24 @@ ->GetButtonImage(TabSharingInfoBarDelegate::InfoBarButton::kQuickNav); } -// TODO(crbug.com/1466247): Rename to "...Indicator". -bool HasCscPermissionButton(Browser* browser, int tab) { +bool HasCscIndicatorButton(Browser* browser, int tab) { return GetDelegate(browser, tab)->GetButtons() & - TabSharingInfoBarDelegate::InfoBarButton::kCscPermission; + TabSharingInfoBarDelegate::InfoBarButton:: + kCapturedSurfaceControlIndicator; } -std::u16string GetCscPermissionButtonLabel(Browser* browser, int tab) { - DCHECK(HasCscPermissionButton(browser, tab)); // Test error otherwise. +std::u16string GetCscIndicatorButtonLabel(Browser* browser, int tab) { + DCHECK(HasCscIndicatorButton(browser, tab)); // Test error otherwise. return GetDelegate(browser, tab) - ->GetButtonLabel( - TabSharingInfoBarDelegate::InfoBarButton::kCscPermission); + ->GetButtonLabel(TabSharingInfoBarDelegate::InfoBarButton:: + kCapturedSurfaceControlIndicator); } -ui::ImageModel GetCscPermissionButtonImage(Browser* browser, int tab) { - DCHECK(HasCscPermissionButton(browser, tab)); // Test error otherwise. +ui::ImageModel GetCscIndicatorButtonImage(Browser* browser, int tab) { + DCHECK(HasCscIndicatorButton(browser, tab)); // Test error otherwise. return GetDelegate(browser, tab) - ->GetButtonImage( - TabSharingInfoBarDelegate::InfoBarButton::kCscPermission); + ->GetButtonImage(TabSharingInfoBarDelegate::InfoBarButton:: + kCapturedSurfaceControlIndicator); } std::u16string GetExpectedSwitchToMessage(Browser* browser, int tab) { @@ -317,7 +317,7 @@ if (i == capturing_tab && i == captured_tab) { // Self-capture. EXPECT_FALSE(HasShareThisTabInsteadButton(browser, i)); - EXPECT_FALSE(HasCscPermissionButton(browser, i)); + EXPECT_FALSE(HasCscIndicatorButton(browser, i)); } else if (i == capturing_tab) { // Capturing-tab's infobar. ASSERT_TRUE(HasQuickNavButton(browser, i)); @@ -325,14 +325,14 @@ GetExpectedSwitchToMessage(browser, captured_tab)); EXPECT_EQ(GetQuickNavButtonImage(browser, i), GetFaviconAssociatedWith(browser, captured_tab)); - EXPECT_EQ(HasCscPermissionButton(browser, i), + EXPECT_EQ(HasCscIndicatorButton(browser, i), has_captured_surface_control_indicator); - if (HasCscPermissionButton(browser, i)) { + if (HasCscIndicatorButton(browser, i)) { EXPECT_EQ( - GetCscPermissionButtonLabel(browser, i), + GetCscIndicatorButtonLabel(browser, i), l10n_util::GetStringUTF16( IDS_TAB_SHARING_INFOBAR_CAPTURED_SURFACE_CONTROL_PERMISSION_BUTTON)); - EXPECT_EQ(GetCscPermissionButtonImage(browser, i), + EXPECT_EQ(GetCscIndicatorButtonImage(browser, i), ui::ImageModel::FromVectorIcon( vector_icons::kTouchpadMouseIcon, ui::kColorSysPrimary, /*icon_size=*/16)); @@ -344,7 +344,7 @@ GetExpectedSwitchToMessage(browser, capturing_tab)); EXPECT_EQ(GetQuickNavButtonImage(browser, i), GetFaviconAssociatedWith(browser, capturing_tab)); - EXPECT_FALSE(HasCscPermissionButton(browser, i)); + EXPECT_FALSE(HasCscIndicatorButton(browser, i)); } else if (infobar_manager->infobars().size() > 0) { // Any other infobar. ASSERT_TRUE(HasShareThisTabInsteadButton(browser, i)); @@ -355,7 +355,7 @@ EXPECT_EQ(ShareThisTabInsteadButtonIsEnabled(browser, i), i != tab_with_disabled_button) << "Tab: " << i; - EXPECT_FALSE(HasCscPermissionButton(browser, i)); + EXPECT_FALSE(HasCscIndicatorButton(browser, i)); } } }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 67f4cb23..aeaf2c77 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -1879,16 +1879,35 @@ void TabDragController::AttachTabsToNewBrowserOnDrop() { DCHECK(!attached_context_hidden_); + // TODO(crbug.com/40238145): `CreateBrowserForDrag()` does almost the same as + // this method. Factor out the common parts into a separate method. + + // Find if there's a controlling app, and thus we should open an app window. + Browser* from_browser = BrowserView::GetBrowserViewForNativeWindow( + GetAttachedBrowserWidget()->GetNativeWindow()) + ->browser(); + const std::optional<webapps::AppId> controlling_app = + GetControllingAppForDrag(from_browser); + const bool open_as_web_app = controlling_app.has_value(); + + Browser::CreateParams create_params = + open_as_web_app + ? Browser::CreateParams::CreateForApp( + web_app::GenerateApplicationNameFromAppId( + controlling_app.value()), + /* trusted_source=*/true, gfx::Rect(), from_browser->profile(), + /* user_gesture=*/true) + : from_browser->create_params(); + views::Widget* widget = attached_context_->GetWidget(); gfx::Rect window_bounds(widget->GetRestoredBounds()); window_bounds.set_origin(GetWindowCreatePoint(last_point_in_screen_)); - Browser::CreateParams create_params = - BrowserView::GetBrowserViewForNativeWindow( - GetAttachedBrowserWidget()->GetNativeWindow()) - ->browser() - ->create_params(); - create_params.initial_bounds = window_bounds; + // Web app windows have their own initial size independent of the source + // browser window. + if (!open_as_web_app) { + create_params.initial_bounds = window_bounds; + } // Don't copy the initial workspace since the *current* workspace might be // different and copying the workspace will move the tab to the initial one. @@ -1900,9 +1919,12 @@ create_params.user_title = std::string(); Browser* browser = Browser::Create(create_params); - // If the window is created maximized then the bounds we supplied are ignored. - // We need to reset them again so they are honored. - browser->window()->SetBounds(window_bounds); + + if (!open_as_web_app) { + // If the window is created maximized then the bounds we supplied are + // ignored. We need to reset them again so they are honored. + browser->window()->SetBounds(window_bounds); + } auto* new_context = BrowserView::GetBrowserViewForBrowser(browser) ->tabstrip() @@ -2415,6 +2437,9 @@ const gfx::Point& point_in_screen, gfx::Vector2d* drag_offset, std::vector<gfx::Rect>* drag_bounds) { + // TODO(crbug.com/40238145): `AttachTabsToNewBrowserOnDrop()` does almost the + // same as this method. Factor out the common parts into a separate method. + source->GetWidget() ->GetCompositor() ->RequestSuccessfulPresentationTimeForNextFrame(base::BindOnce( @@ -2446,10 +2471,7 @@ controlling_app.value()), /* trusted_source=*/true, gfx::Rect(), from_browser->profile(), /* user_gesture=*/true) - : BrowserView::GetBrowserViewForNativeWindow( - GetAttachedBrowserWidget()->GetNativeWindow()) - ->browser() - ->create_params(); + : from_browser->create_params(); // Web app windows have their own initial size independent of the source // browser window.
diff --git a/chrome/browser/ui/webui/ash/app_install/app_install_ui.cc b/chrome/browser/ui/webui/ash/app_install/app_install_ui.cc index 511a95c..3da9a76 100644 --- a/chrome/browser/ui/webui/ash/app_install/app_install_ui.cc +++ b/chrome/browser/ui/webui/ash/app_install/app_install_ui.cc
@@ -46,6 +46,7 @@ {"noAppDataDescription", IDS_APP_INSTALL_DIALOG_NO_APP_DATA_DESCRIPTION}, {"tryAgain", IDS_APP_INSTALL_DIALOG_TRY_AGAIN_BUTTON_LABEL}, {"failedInstall", IDS_APP_INSTALL_DIALOG_FAILED_INSTALL_TITLE}, + {"iconAlt", IDS_APP_INSTALL_DIALOG_APP_ICON_ALT}, }; source->AddLocalizedStrings(kStrings);
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc b/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc index 57cb8b98..2701baa 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc
@@ -574,12 +574,6 @@ } else { LOG(ERROR) << "Unexpected alternate URL - Drive editing unavailable: " << hosted_url.host(); - // TODO(b/323452926): Remove DumpWithoutCrashing() once sure the - // introduction of kFileNotAnOfficeFile fixed the only cause of - // kUnexpectedAlternateUrlHost. - SCOPED_CRASH_KEY_STRING64("OfficeUpload", "UnexpectedHost", - hosted_url.host()); - base::debug::DumpWithoutCrashing(); OnEndCopy(OfficeFilesUploadResult::kUnexpectedAlternateUrlHost); } } else {
diff --git a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc b/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc index 8bf9ff6..dde36e8 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc
@@ -480,9 +480,6 @@ "onDeviceGrammarCheckEnabled", base::FeatureList::IsEnabled(features::kOnDeviceGrammarCheck)); - // TODO: b/332967598 - Remove obsolete pre-LanguagePacks code in Settings. - html_source->AddBoolean("languagePacksHandwritingEnabled", true); - html_source->AddBoolean( "systemJapanesePhysicalTyping", base::FeatureList::IsEnabled(features::kSystemJapanesePhysicalTyping));
diff --git a/chrome/browser/ui/webui/cr_components/most_visited/most_visited_handler.cc b/chrome/browser/ui/webui/cr_components/most_visited/most_visited_handler.cc index cb991ce..6f4219b 100644 --- a/chrome/browser/ui/webui/cr_components/most_visited/most_visited_handler.cc +++ b/chrome/browser/ui/webui/cr_components/most_visited/most_visited_handler.cc
@@ -210,14 +210,36 @@ void MostVisitedHandler::PrerenderMostVisitedTile( most_visited::mojom::MostVisitedTilePtr tile, bool is_hover_trigger) { - if (base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2)) { - PrerenderManager::CreateForWebContents(web_contents_); - auto* prerender_manager = PrerenderManager::FromWebContents(web_contents_); - prerender_handle_ = prerender_manager->StartPrerenderNewTabPage( - tile->url, is_hover_trigger - ? chrome_preloading_predictor::kMouseHoverOnNewTabPage - : chrome_preloading_predictor::kPointerDownOnNewTabPage); + if (!base::FeatureList::IsEnabled( + features::kNewTabPageTriggerForPrerender2)) { + page_handler_.ReportBadMessage( + "PrerenderMostVisitedTile is only expected to be called " + "when kNewTabPageTriggerForPrerender2 is true."); + return; } + + if (is_hover_trigger && + !features::kPrerenderNewTabPageOnMouseHoverTrigger.Get()) { + page_handler_.ReportBadMessage( + "PrerenderMostVisitedTile by hovering is only expected to be called " + "when kPrerenderNewTabPageOnMouseHoverTrigger is true."); + return; + } + + if (!is_hover_trigger && + !features::kPrerenderNewTabPageOnMousePressedTrigger.Get()) { + page_handler_.ReportBadMessage( + "PrerenderMostVisitedTile by pressing is only expected to be called " + "when kPrerenderNewTabPageOnMousePressedTrigger is true."); + return; + } + PrerenderManager::CreateForWebContents(web_contents_); + auto* prerender_manager = PrerenderManager::FromWebContents(web_contents_); + + prerender_handle_ = prerender_manager->StartPrerenderNewTabPage( + tile->url, is_hover_trigger + ? chrome_preloading_predictor::kMouseHoverOnNewTabPage + : chrome_preloading_predictor::kPointerDownOnNewTabPage); } void MostVisitedHandler::PreconnectMostVisitedTile( @@ -240,11 +262,17 @@ } void MostVisitedHandler::CancelPrerender() { - if (base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2)) { - auto* prerender_manager = PrerenderManager::FromWebContents(web_contents_); - prerender_manager->StopPrerenderNewTabPage(prerender_handle_); - prerender_handle_ = nullptr; + if (!base::FeatureList::IsEnabled( + features::kNewTabPageTriggerForPrerender2)) { + page_handler_.ReportBadMessage( + "CancelPrerender is only expected to be called " + "when kNewTabPageTriggerForPrerender2 is true."); + return; } + + auto* prerender_manager = PrerenderManager::FromWebContents(web_contents_); + prerender_manager->StopPrerenderNewTabPage(prerender_handle_); + prerender_handle_ = nullptr; } void MostVisitedHandler::OnURLsAvailable(
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index 184294d..aba0818 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -209,15 +209,20 @@ base::FeatureList::IsEnabled( ntp_features::kNtpHandleMostVisitedNavigationExplicitly)); - source->AddBoolean( - "prerenderEnabled", - base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2)); source->AddInteger( "prerenderStartTimeThreshold", features::kNewTabPagePrerenderStartDelayOnMouseHoverByMiliSeconds.Get()); source->AddInteger( "preconnectStartTimeThreshold", features::kNewTabPagePreconnectStartDelayOnMouseHoverByMiliSeconds.Get()); + source->AddBoolean( + "prerenderOnPressEnabled", + base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2) && + features::kPrerenderNewTabPageOnMousePressedTrigger.Get()); + source->AddBoolean( + "prerenderOnHoverEnabled", + base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2) && + features::kPrerenderNewTabPageOnMouseHoverTrigger.Get()); source->AddBoolean( "oneGoogleBarEnabled",
diff --git a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc index 78def7b..0dd899ee 100644 --- a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc
@@ -102,15 +102,20 @@ base::FeatureList::IsEnabled( ntp_features::kNtpHandleMostVisitedNavigationExplicitly)); - source->AddBoolean( - "prerenderEnabled", - base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2)); source->AddInteger( "prerenderStartTimeThreshold", features::kNewTabPagePrerenderStartDelayOnMouseHoverByMiliSeconds.Get()); source->AddInteger( "preconnectStartTimeThreshold", features::kNewTabPagePreconnectStartDelayOnMouseHoverByMiliSeconds.Get()); + source->AddBoolean( + "prerenderOnPressEnabled", + base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2) && + features::kPrerenderNewTabPageOnMousePressedTrigger.Get()); + source->AddBoolean( + "prerenderOnHoverEnabled", + base::FeatureList::IsEnabled(features::kNewTabPageTriggerForPrerender2) && + features::kPrerenderNewTabPageOnMouseHoverTrigger.Get()); // Needed by <cr-most-visited> but not used in // chrome://new-tab-page-third-party/.
diff --git a/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc b/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc index 12875b0..c598ed6 100644 --- a/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc +++ b/chrome/browser/webauthn/chrome_webauthn_autofill_interactive_uitest.cc
@@ -495,6 +495,11 @@ ASSERT_TRUE(message_queue.WaitForMessage(&result)); EXPECT_EQ(result, "\"webauthn: OK\""); + // Tapping a GPM passkey will not automatically hide the popup + // because the enclave might still be loading. Manually hide the + // popup so that the autofill client can be destroyed, avoiding + // a DCHECK on test tear down. + autofill_client->HideAutofillPopup(autofill::PopupHidingReason::kTabGone); // The tracker outlives the test. Clean up the device_info to avoid flakiness. tracker->Remove(&device_info); } @@ -573,6 +578,11 @@ ASSERT_TRUE(message_queue.WaitForMessage(&result)); EXPECT_EQ(result, "\"webauthn: OK\""); + // Tapping a GPM passkey will not automatically hide the popup + // because the enclave might still be loading. Manually hide the + // popup so that the autofill client can be destroyed, avoiding + // a DCHECK on test tear down. + autofill_client->HideAutofillPopup(autofill::PopupHidingReason::kTabGone); // The tracker outlives the test. Clean up the device_info to avoid flakiness. tracker->Remove(&device_info); }
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index f680c1a..33b8b21 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1712793593-cae4312ebe70db70f6fca21a4ec89014b47d3a0e-25ba3307b92317024b267f58a62418fb6ca41e8a.profdata +chrome-android32-main-1712815180-314d5587d1fc94c56c5e984b44aa07e9ac33f88c-8feabe72a1885ec60963e9baa5f1eabb967e9e0a.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 4d18475..a3ca9578 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1712779168-f3aed91a650e73b32c48eb6fe5f7d160154ef49f-70851099c78cdb9e06f8342fa6cf601d695d013d.profdata +chrome-android64-main-1712807836-8484cbd6b3d4debb46ae14fc9dd17efc63331ad7-0d379889bb749cb52bdb96a980d32cb4d4191e0f.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 9319e183..6063a7b 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1712793593-0ba967a28b8dcac8770bbabddb038eac1cac9eca-25ba3307b92317024b267f58a62418fb6ca41e8a.profdata +chrome-linux-main-1712815180-fffbbf7d74598dc14032933eca0e3369cfd33bce-8feabe72a1885ec60963e9baa5f1eabb967e9e0a.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index e2d3b74..07c0410 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1712807836-f6aa73235f0783aa3cf386b9fd46ade573c05dac-0d379889bb749cb52bdb96a980d32cb4d4191e0f.profdata +chrome-mac-arm-main-1712829497-104978b514c7a5706388bf8c6cfc48aff306784d-dc61398475d19cc11c474daccfa5d29e3b54c300.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index eec67a37..964d1ba6 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1712793593-3f36a4e2a9c0646e8878aec063cc3aa5c3ff9fbf-25ba3307b92317024b267f58a62418fb6ca41e8a.profdata +chrome-win-arm64-main-1712815180-a3d29fb05007016d06e9760c9e7f7d1cce74cc05-8feabe72a1885ec60963e9baa5f1eabb967e9e0a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index abe942e..f110feb 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1712793593-2b0a15c5023bd513fd76d858c4221945c4696080-25ba3307b92317024b267f58a62418fb6ca41e8a.profdata +chrome-win32-main-1712815180-3f61f648bdce6773948ec882ba987cb044f287f7-8feabe72a1885ec60963e9baa5f1eabb967e9e0a.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 4bf9e79..f46bbc6a 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1712782756-7d62838f9169aa3b8e50f4ed0eccbf8c67d51dd1-953fc520cbcd7ba90b383a4e0e8c11ebc9d399b1.profdata +chrome-win64-main-1712815180-5159e4b56178f1dd6f40aed6c4927b6838cf62d1-8feabe72a1885ec60963e9baa5f1eabb967e9e0a.profdata
diff --git a/chrome/common/chromeos/extensions/api/diagnostics.idl b/chrome/common/chromeos/extensions/api/diagnostics.idl index f39ae776..13203cb5 100644 --- a/chrome/common/chromeos/extensions/api/diagnostics.idl +++ b/chrome/common/chromeos/extensions/api/diagnostics.idl
@@ -178,9 +178,27 @@ DOMString? uuid; }; + enum NetworkBandwidthRoutineRunningType { + download, + upload + }; + + dictionary NetworkBandwidthRoutineRunningInfo { + // The type of test that routine is running. + NetworkBandwidthRoutineRunningType type; + // The current network speed in Kbps. + double speedKbps; + }; + + // This is a union type. Exactly one field should be set. + dictionary RoutineRunningInfoUnion { + NetworkBandwidthRoutineRunningInfo? networkBandwidth; + }; + dictionary RoutineRunningInfo { DOMString? uuid; long? percentage; + RoutineRunningInfoUnion? info; }; enum RoutineWaitingReason { @@ -363,17 +381,29 @@ dictionary CreateFanRoutineArguments { }; + dictionary CreateNetworkBandwidthRoutineArguments { + }; + + dictionary NetworkBandwidthRoutineFinishedDetail { + // Average download speed in Kbit/s. + double downloadSpeedKbps; + // Average upload speed in Kbit/s. + double uploadSpeedKbps; + }; + // This is a union type. Exactly one field should be set. dictionary CreateRoutineArgumentsUnion { CreateMemoryRoutineArguments? memory; CreateVolumeButtonRoutineArguments? volumeButton; CreateFanRoutineArguments? fan; + CreateNetworkBandwidthRoutineArguments? networkBandwidth; }; // This is a union type. Exactly one field should be set. dictionary RoutineFinishedDetailUnion { MemoryRoutineFinishedDetail? memory; FanRoutineFinishedDetail? fan; + NetworkBandwidthRoutineFinishedDetail? networkBandwidth; }; dictionary RoutineFinishedInfo {
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index afb83e27..5186d02 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -651,7 +651,8 @@ "7FE4A999359A456C4B0FB7B7AD85CEA29CA50519", // Login screen APIs test extension "3F5995FE79A861F019C6F093BEF98D73FA9D3A5F", // Login screen APIs in-session test extension // Only has access to login.exitCurrentSession - "8ECFC754A70BE499325FA4BB705E62EFEEC1BC80" // b/314208017 + "8ECFC754A70BE499325FA4BB705E62EFEEC1BC80", // b/314208017 + "ECD28F2B60BDB3B4E566D6C60BD88BE0774044C1" // b/314208017 ] }], "loginScreenStorage": {
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index 52b0fa44..150fe60 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json
@@ -528,6 +528,14 @@ "3F5995FE79A861F019C6F093BEF98D73FA9D3A5F", // Login screen APIs in-session test extension "8ECFC754A70BE499325FA4BB705E62EFEEC1BC80" // b/314208017 ] + }, { + "channel": "stable", + "extension_types": ["platform_app"], + "location": "policy", + "platforms": ["chromeos", "lacros"], + "allowlist": [ + "ECD28F2B60BDB3B4E566D6C60BD88BE0774044C1" // b/314208017 + ] }], "loginScreenStorage": [{ "channel": "stable",
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc index 51979716..7082a04d3 100644 --- a/chrome/renderer/autofill/form_autofill_browsertest.cc +++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -1193,7 +1193,7 @@ expected.value = ASCIIToUTF16(placeholder_lastname); } else { expected.label.clear(); - expected.value.clear(); + expected.value = u""; } expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); @@ -1209,7 +1209,7 @@ expected.value = ASCIIToUTF16(placeholder_email); } else { expected.label.clear(); - expected.value.clear(); + expected.value = u""; } expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); @@ -1880,12 +1880,12 @@ expected.id_attribute = u"firstname"; expected.name = expected.id_attribute; - expected.value.clear(); + expected.value = u""; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.id_attribute = u"lastname"; expected.name = expected.id_attribute; - expected.value.clear(); + expected.value = u""; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.id_attribute = u"noAC"; @@ -1906,7 +1906,7 @@ expected.max_length = 0; expected.id_attribute = u"month"; expected.name = expected.id_attribute; - expected.value.clear(); + expected.value = u""; expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); @@ -1920,7 +1920,7 @@ expected.id_attribute = u"textarea"; expected.max_length = FormFieldData::kDefaultMaxLength; expected.name = expected.id_attribute; - expected.value.clear(); + expected.value = u""; expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[6]); @@ -2096,14 +2096,14 @@ expected.id_attribute = u"firstname"; expected.name = expected.id_attribute; - expected.value.clear(); + expected.value = u""; expected.form_control_type = FormControlType::kInputText; expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.id_attribute = u"lastname"; expected.name = expected.id_attribute; - expected.value.clear(); + expected.value = u""; expected.form_control_type = FormControlType::kInputText; expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); @@ -2378,7 +2378,7 @@ expected.id_attribute = u"element"; expected.name = expected.id_attribute; - expected.value.clear(); + expected.value = u""; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result1); FormFieldData result2; @@ -2528,7 +2528,7 @@ FormFieldData result3; WebFormControlElementToFormField(WebFormElement(), element, nullptr, {ExtractOption::kOptions}, &result3); - expected.value.clear(); + expected.value = u""; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result3); ASSERT_EQ(2U, result3.options.size());
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_gatt_server.cc b/chrome/services/sharing/nearby/platform/ble_v2_gatt_server.cc index 66d7044..593d164 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_gatt_server.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_gatt_server.cc
@@ -202,12 +202,9 @@ } void BleV2GattServer::Stop() { - VLOG(1) << __func__; - - // Clearing the `uuid_to_gatt_service_map_` destroys all `GattService`s owned - // by `BleV2GattServer`, which also includes destroying their underlying - // `GattService` Mojo remotes. - uuid_to_gatt_service_map_.clear(); + // TODO(b/311430390): Implement to call on the Mojo remote to stop the GATT + // server. + NOTIMPLEMENTED(); } BleV2GattServer::GattService::GattService() = default;
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc b/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc index fbba36e5..d313535 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_gatt_server_unittest.cc
@@ -261,27 +261,4 @@ read_result->get_error_code()); } -TEST_F(BleV2GattServerTest, Stop) { - auto fake_gatt_service = std::make_unique<bluetooth::FakeGattService>(); - fake_gatt_service->SetCreateCharacteristicResult(/*success=*/true); - - base::RunLoop run_loop; - bool fake_gatt_service_destroyed = false; - fake_gatt_service->SetOnDestroyedCallback(base::BindLambdaForTesting([&]() { - fake_gatt_service_destroyed = true; - run_loop.Quit(); - })); - - fake_adapter_->SetCreateLocalGattServiceResult( - /*gatt_service=*/std::move(fake_gatt_service)); - CallCreateCharacteristic( - /*characteristic_uuid=*/kCharacteristicUuid1, - /*expected_success=*/true); - - // Expect the underlying objects to have been destroyed. - ble_v2_gatt_server_->Stop(); - run_loop.Run(); - EXPECT_TRUE(fake_gatt_service_destroyed); -} - } // namespace nearby::chrome
diff --git a/chrome/services/sharing/nearby/test_support/fake_gatt_service.cc b/chrome/services/sharing/nearby/test_support/fake_gatt_service.cc index 1f6f9e8..a06aa86 100644 --- a/chrome/services/sharing/nearby/test_support/fake_gatt_service.cc +++ b/chrome/services/sharing/nearby/test_support/fake_gatt_service.cc
@@ -14,11 +14,7 @@ FakeGattService::FakeGattService() = default; -FakeGattService::~FakeGattService() { - if (on_destroyed_callback_) { - std::move(on_destroyed_callback_).Run(); - } -} +FakeGattService::~FakeGattService() = default; void FakeGattService::CreateCharacteristic( const device::BluetoothUUID& characteristic_uuid,
diff --git a/chrome/services/sharing/nearby/test_support/fake_gatt_service.h b/chrome/services/sharing/nearby/test_support/fake_gatt_service.h index 8587d91..1820338 100644 --- a/chrome/services/sharing/nearby/test_support/fake_gatt_service.h +++ b/chrome/services/sharing/nearby/test_support/fake_gatt_service.h
@@ -37,10 +37,6 @@ void SetCreateCharacteristicResult(bool success); int GetNumCharacteristicUuids() { return characteristic_uuids_.size(); } - void SetOnDestroyedCallback(base::OnceClosure callback) { - on_destroyed_callback_ = std::move(callback); - } - private: void OnLocalCharacteristicReadResponse( ValueCallback callback, @@ -49,7 +45,6 @@ std::vector<device::BluetoothUUID> characteristic_uuids_; mojo::Remote<mojom::GattServiceObserver> observer_remote_; bool set_create_characteristic_result_ = false; - base::OnceClosure on_destroyed_callback_; mojo::Receiver<mojom::GattService> gatt_server_{this}; };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index d22b695..ececc04 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6460,6 +6460,7 @@ "../browser/trusted_vault/trusted_vault_encryption_keys_tab_helper_unittest.cc", "../browser/ui/autofill/autofill_client_provider_unittest.cc", "../browser/ui/autofill/autofill_popup_controller_impl_unittest.cc", + "../browser/ui/autofill/autofill_popup_controller_unittest.cc", "../browser/ui/autofill/chrome_autofill_client_unittest.cc", "../browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl_unittest.cc", "../browser/ui/autofill/payments/chrome_payments_autofill_client_unittest.cc", @@ -10325,7 +10326,13 @@ static_library("test_support_unit") { testonly = true - sources = [ "base/run_all_unittests.cc" ] + sources = [ + "../browser/ui/autofill/autofill_popup_controller_test_base.cc", + "../browser/ui/autofill/autofill_popup_controller_test_base.h", + "../browser/ui/autofill/mock_autofill_popup_view.cc", + "../browser/ui/autofill/mock_autofill_popup_view.h", + "base/run_all_unittests.cc", + ] public_deps = [ ":test_support", @@ -10336,10 +10343,13 @@ "//chrome/common", "//mojo/core/test:test_support", ] - deps = [] + deps = [ + "//chrome/browser/autofill", + "//components/autofill/content/browser:test_support", + ] if (is_win) { - deps = [ "//chrome/install_static/test:test_support" ] + deps += [ "//chrome/install_static/test:test_support" ] } if (is_chromeos_ash) { @@ -10362,6 +10372,10 @@ deps += [ "//chromeos/lacros:test_support" ] } + if (is_android) { + deps += [ "//chrome/browser/keyboard_accessory/test_utils/android" ] + } + if (enable_bound_session_credentials) { sources += [ "../browser/signin/bound_session_credentials/fake_bound_session_cookie_refresh_service.cc", @@ -10892,6 +10906,10 @@ ] } + if (enable_dice_support) { + sources += [ "../browser/ui/views/promos/autofill_bubble_signin_promo_interactive_uitest.cc" ] + } + configs += [ "//build/config:precompiled_headers" ] if ((is_linux || is_chromeos) && !is_component_build) { configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py index 0517afc..e5ef4ddc 100644 --- a/chrome/test/chromedriver/client/chromedriver.py +++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -599,6 +599,12 @@ def FullScreenWindow(self): return self.ExecuteCommand(Command.FULLSCREEN_WINDOW) + def SetDevicePosture(self, posture): + return self.ExecuteCommand(Command.SET_DEVICE_POSTURE, {'posture': posture}) + + def ClearDevicePosture(self): + return self.ExecuteCommand(Command.CLEAR_DEVICE_POSTURE) + def TakeScreenshot(self): return self.ExecuteCommand(Command.SCREENSHOT)
diff --git a/chrome/test/chromedriver/client/command_executor.py b/chrome/test/chromedriver/client/command_executor.py index 6ed6cf1..12f75abe 100644 --- a/chrome/test/chromedriver/client/command_executor.py +++ b/chrome/test/chromedriver/client/command_executor.py
@@ -118,6 +118,10 @@ _Method.POST, '/session/:sessionId/window/minimize') FULLSCREEN_WINDOW = ( _Method.POST, '/session/:sessionId/window/fullscreen') + SET_DEVICE_POSTURE = ( + _Method.POST, '/session/:sessionId/deviceposture') + CLEAR_DEVICE_POSTURE = ( + _Method.DELETE, '/session/:sessionId/deviceposture') CLOSE = (_Method.DELETE, '/session/:sessionId/window') DRAG_ELEMENT = (_Method.POST, '/session/:sessionId/element/:id/drag') GET_ELEMENT_VALUE_OF_CSS_PROPERTY = (
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc index e436d70..89c0303 100644 --- a/chrome/test/chromedriver/server/http_handler.cc +++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -1041,6 +1041,17 @@ WrapToCommand("SetPermission", base::BindRepeating(&ExecuteSetPermission))), + // Extensions for Device Posture API: + // https://w3c.github.io/device-posture/#automation + CommandMapping( + kPost, "session/:sessionId/deviceposture", + WrapToCommand("SetDevicePosture", + base::BindRepeating(&ExecuteSetDevicePosture))), + CommandMapping( + kDelete, "session/:sessionId/deviceposture", + WrapToCommand("ClearDevicePosture", + base::BindRepeating(&ExecuteClearDevicePosture))), + // // Non-standard extension commands //
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 507e779e..1a3cbb4 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -4859,6 +4859,60 @@ "This sensor type is not being overridden with a virtual sensor", self._driver.UpdateVirtualSensor, 'ambient-light', {'illuminance': 42}) + def testSetDevicePosture(self): + self._driver.Load( + self.GetHttpsUrlForFile('/chromedriver/device_posture_test.html')) + self._driver.ExecuteScript('addDevicePostureEventListener()') + original_posture = self._driver.ExecuteScript( + 'return navigator.devicePosture.type') + posture = 'folded' if original_posture == 'continuous' else 'continuous' + self._driver.SetDevicePosture(posture) + self.assertTrue( + self.WaitForCondition(lambda: self._driver.ExecuteScript( + 'return postures.length === 1'))) + self.assertNotEqual(original_posture, + self._driver.ExecuteScript('return postures.at(-1)')) + self._driver.SetDevicePosture(original_posture) + self.assertTrue( + self.WaitForCondition(lambda: self._driver.ExecuteScript( + 'return postures.length === 2'))) + self.assertEqual(original_posture, + self._driver.ExecuteScript('return postures.at(-1)')) + + def testSetDevicePostureInvalidArgument(self): + self.assertRaisesRegex( + chromedriver.InvalidArgument, + "Invalid posture type", + self._driver.SetDevicePosture, 'invalid-posture') + + def testClearDevicePosture(self): + self._driver.Load( + self.GetHttpsUrlForFile('/chromedriver/device_posture_test.html')) + self._driver.ExecuteScript('addDevicePostureEventListener()') + original_posture = self._driver.ExecuteScript( + 'return navigator.devicePosture.type') + posture = 'folded' if original_posture == 'continuous' else 'continuous' + self._driver.SetDevicePosture(posture) + self.assertTrue( + self.WaitForCondition(lambda: self._driver.ExecuteScript( + 'return postures.length === 1'))) + self.assertNotEqual(original_posture, + self._driver.ExecuteScript('return postures.at(-1)')) + self._driver.ClearDevicePosture() + self.assertTrue( + self.WaitForCondition(lambda: self._driver.ExecuteScript( + 'return postures.length === 2'))) + self.assertEqual(original_posture, + self._driver.ExecuteScript('return postures.at(-1)')) + + def testClearDevicePostureWithoutSetDevicePosture(self): + self._driver.Load( + self.GetHttpsUrlForFile('/chromedriver/device_posture_test.html')) + self._driver.ExecuteScript('addDevicePostureEventListener()') + self._driver.ClearDevicePosture() + self.assertFalse( + self.WaitForCondition(lambda: self._driver.ExecuteScript( + 'return postures.length === 1'))) # Tests in the following class are expected to be moved to ChromeDriverTest # class when we no longer support the legacy mode.
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc index 4ad21999..4f5502b 100644 --- a/chrome/test/chromedriver/window_commands.cc +++ b/chrome/test/chromedriver/window_commands.cc
@@ -2897,3 +2897,26 @@ auto dict = std::make_unique<base::Value::Dict>(descriptor->Clone()); return session->chrome->SetPermission(std::move(dict), valid_state, web_view); } + +Status ExecuteSetDevicePosture(Session* session, + WebView* web_view, + const base::Value::Dict& params, + std::unique_ptr<base::Value>* value, + Timeout* timeout) { + const std::string* posture = params.FindString("posture"); + if (!posture) { + return Status(kInvalidArgument, "'posture' must be a string"); + } + base::Value::Dict args; + args.Set("posture", base::Value::Dict().Set("type", *posture)); + return web_view->SendCommand("Emulation.setDevicePostureOverride", args); +} + +Status ExecuteClearDevicePosture(Session* session, + WebView* web_view, + const base::Value::Dict& params, + std::unique_ptr<base::Value>* value, + Timeout* timeout) { + return web_view->SendCommand("Emulation.clearDevicePostureOverride", + base::Value::Dict()); +}
diff --git a/chrome/test/chromedriver/window_commands.h b/chrome/test/chromedriver/window_commands.h index 908a39f..b615321d 100644 --- a/chrome/test/chromedriver/window_commands.h +++ b/chrome/test/chromedriver/window_commands.h
@@ -415,6 +415,18 @@ std::unique_ptr<base::Value>* value, Timeout* timeout); +Status ExecuteSetDevicePosture(Session* session, + WebView* web_view, + const base::Value::Dict& params, + std::unique_ptr<base::Value>* value, + Timeout* timeout); + +Status ExecuteClearDevicePosture(Session* session, + WebView* web_view, + const base::Value::Dict& params, + std::unique_ptr<base::Value>* value, + Timeout* timeout); + // Sets the sink to be used when the web page invokes Presentation or Remote // Playback API. Uses the "sinkName" value in |params|. Status ExecuteSetSinkToUse(Session* session,
diff --git a/chrome/test/data/chromedriver/device_posture_test.html b/chrome/test/data/chromedriver/device_posture_test.html new file mode 100644 index 0000000..ba0e586 --- /dev/null +++ b/chrome/test/data/chromedriver/device_posture_test.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script> +const postures = []; + +function addDevicePostureEventListener() { + navigator.devicePosture.addEventListener("change", () => { + postures.push(navigator.devicePosture.type); + }); +} +</script>
diff --git a/chrome/test/data/webui/cr_components/cr_components_browsertest.cc b/chrome/test/data/webui/cr_components/cr_components_browsertest.cc index 03fe133..edf15de 100644 --- a/chrome/test/data/webui/cr_components/cr_components_browsertest.cc +++ b/chrome/test/data/webui/cr_components/cr_components_browsertest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/browser_features.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/web_ui_mocha_browser_test.h" #include "components/history_clusters/core/features.h" @@ -172,11 +173,6 @@ RunTest("cr_components/most_visited_test.js", "runMochaSuite('Theming');"); } -IN_PROC_BROWSER_TEST_F(CrComponentsMostVisitedTest, Prerendering) { - RunTest("cr_components/most_visited_test.js", - "runMochaSuite('Prerendering');"); -} - typedef WebUIMochaBrowserTest CrComponentsThemeColorPickerTest; IN_PROC_BROWSER_TEST_F(CrComponentsThemeColorPickerTest, ThemeColor) { set_test_loader_host(chrome::kChromeUICustomizeChromeSidePanelHost); @@ -201,3 +197,24 @@ RunTest("cr_components/theme_color_picker/theme_hue_slider_dialog_test.js", "mocha.run()"); } + +class CrComponentsPrerenderTest : public CrComponentsMostVisitedTest { + protected: + CrComponentsPrerenderTest() { + const std::map<std::string, std::string> params = { + {"prerender_start_delay_on_mouse_hover_ms", "0"}, + {"preconnect_start_delay_on_mouse_hover_ms", "0"}, + {"prerender_new_tab_page_on_mouse_pressed_trigger", "true"}, + {"prerender_new_tab_page_on_mouse_hover_trigger", "true"}}; + scoped_feature_list_.InitAndEnableFeatureWithParameters( + features::kNewTabPageTriggerForPrerender2, params); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(CrComponentsPrerenderTest, Prerendering) { + RunTest("cr_components/most_visited_test.js", + "runMochaSuite('Prerendering');"); +}
diff --git a/chrome/test/data/webui/cr_components/most_visited_test.ts b/chrome/test/data/webui/cr_components/most_visited_test.ts index d1eba7d..dbeec2d4 100644 --- a/chrome/test/data/webui/cr_components/most_visited_test.ts +++ b/chrome/test/data/webui/cr_components/most_visited_test.ts
@@ -1254,35 +1254,12 @@ }); suite('Prerendering', () => { - suiteSetup(() => { - loadTimeData.overrideValues({ - prerenderEnabled: true, - preconnectStartTimeThreshold: 0, - prerenderStartTimeThreshold: 0, - }); - }); + suiteSetup(() => {}); setup(() => { setUpTest(/*singleRow=*/ false, /*reflowOnOverflow=*/ false); }); - test('preconnect', async () => { - // Arrange. - await addTiles(1); - - // Act. - const tileLink = queryTiles()[0]!.querySelector('a')!; - // Prevent triggering a navigation, which would break the test. - tileLink.href = '#'; - // Simulate a mousedown event. - const mouseEvent = document.createEvent('MouseEvents'); - mouseEvent.initEvent('mouseenter', true, true); - tileLink.dispatchEvent(mouseEvent); - - // Make sure preconnect has been triggered. - await handler.whenCalled('preconnectMostVisitedTile'); - }); - test('onMouseHover Trigger', async () => { // Arrange. await addTiles(1); @@ -1296,7 +1273,8 @@ mouseEvent.initEvent('mouseenter', true, true); tileLink.dispatchEvent(mouseEvent); - // Make sure Prerendering has been triggered. + // Make sure both preconnect and prerender have been triggered. + await handler.whenCalled('preconnectMostVisitedTile'); await handler.whenCalled('prerenderMostVisitedTile'); });
diff --git a/chrome/test/data/webui/settings/chromeos/os_languages_page/input_page_test.ts b/chrome/test/data/webui/settings/chromeos/os_languages_page/input_page_test.ts index 73356d6..59ebd79 100644 --- a/chrome/test/data/webui/settings/chromeos/os_languages_page/input_page_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_languages_page/input_page_test.ts
@@ -122,21 +122,12 @@ }); suite('language pack notice', () => { - test('is shown when needed', async () => { - loadTimeData.overrideValues({languagePacksHandwritingEnabled: true}); + test('is shown', async () => { await createInputPage(); assertTrue(isVisible( inputPage.shadowRoot!.querySelector('#languagePacksNotice'))); }); - - test('is hidden when needed', async () => { - loadTimeData.overrideValues({languagePacksHandwritingEnabled: false}); - await createInputPage(); - - assertFalse(isVisible( - inputPage.shadowRoot!.querySelector('#languagePacksNotice'))); - }); }); suite('input method list', () => { @@ -639,10 +630,6 @@ }); test('when clicking on "learn more" about language packs', async () => { - inputPage.set('shouldShowLanguagePacksNotice_', true); - loadTimeData.overrideValues({languagePacksHandwritingEnabled: true}); - flush(); - const languagePacksNotice = inputPage.shadowRoot!.querySelector('#languagePacksNotice'); assertTrue(!!languagePacksNotice);
diff --git a/chrome/test/fuzzing/renderer_fuzzing/BUILD.gn b/chrome/test/fuzzing/renderer_fuzzing/BUILD.gn index df0e18fe..f6decf8 100644 --- a/chrome/test/fuzzing/renderer_fuzzing/BUILD.gn +++ b/chrome/test/fuzzing/renderer_fuzzing/BUILD.gn
@@ -4,7 +4,8 @@ import("//chrome/test/fuzzing/in_process_fuzzer.gni") import("//chrome/test/fuzzing/renderer_fuzzing/in_process_renderer_fuzzing.gni") -import("//chrome/test/fuzzing/renderer_fuzzing/mojom_interfaces.gni") +import( + "//chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/mojom_interfaces.gni") group("test") { testonly = true @@ -18,25 +19,54 @@ "//base", "//chrome/test:test_support", "//chrome/test/fuzzing:in_process_fuzzer_runner", + "//chrome/test/fuzzing:in_process_proto_fuzzer_runner", "//testing/libfuzzer:renderer_fuzzing", ] } } if (!is_android) { + action("renderer_in_process_mojolpm_fuzzer_generator") { + testonly = true + script = "//chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/generate_testcase.py" + args = [ + "-n", + "renderer_in_process_mojolpm_fuzzer", + "-d", + rebase_path("${target_gen_dir}/", root_gen_dir), + "-o", + rebase_path("${target_gen_dir}/testcase.h", root_build_dir), + "-c", + ] + foreach(interface, blink_browser_exposed_interfaces) { + args += [ interface[1] ] + } + args += [ "-p" ] + foreach(interface, process_browser_exposed_interfaces) { + args += [ interface[1] ] + } + outputs = [ "${target_gen_dir}/testcase.h" ] + } in_process_renderer_mojolpm_generated_fuzzer( "renderer_in_process_mojolpm_fuzzer") { sources = [ "renderer_in_process_mojolpm_fuzzer.cc" ] interfaces = blink_browser_exposed_interfaces + interfaces += process_browser_exposed_interfaces deps = [ + ":renderer_in_process_mojolpm_fuzzer_generator", "//chrome/test:test_support", "//chrome/test/fuzzing:in_process_proto_fuzzer_runner", + "//components/metrics/public/mojom:single_sample_metrics_mojo_bindings_mojolpm", + "//content/common:mojo_bindings_mojolpm", "//content/test/fuzzer:mojolpm_fuzzer_support", + "//media/mojo/mojom:mojom_mojolpm", + "//services/resource_coordinator/public/mojom:mojom_mojolpm", "//testing/libfuzzer:renderer_fuzzing", "//testing/libfuzzer/proto:url_proto_converter", "//third_party/blink/public/common:storage_key_proto_converter", + "//third_party/blink/public/mojom:embedded_frame_sink_mojo_bindings_mojolpm", "//third_party/blink/public/mojom:mojom_core_mojolpm", "//third_party/blink/public/mojom:mojom_modules_mojolpm", "//third_party/blink/public/mojom:mojom_platform_mojolpm", @@ -44,6 +74,11 @@ ] proto_deps = [ + "//components/metrics/public/mojom:single_sample_metrics_mojo_bindings_mojolpm", + "//content/common:mojo_bindings_mojolpm", + "//media/mojo/mojom:mojom_mojolpm", + "//services/resource_coordinator/public/mojom:mojom_mojolpm", + "//third_party/blink/public/mojom:embedded_frame_sink_mojo_bindings_mojolpm", "//third_party/blink/public/mojom:mojom_core_mojolpm", "//third_party/blink/public/mojom:mojom_modules_mojolpm", "//third_party/blink/public/mojom:mojom_platform_mojolpm",
diff --git a/chrome/test/fuzzing/renderer_fuzzing/in_process_renderer_fuzzing.h b/chrome/test/fuzzing/renderer_fuzzing/in_process_renderer_fuzzing.h index 2054bf0..f46b82c 100644 --- a/chrome/test/fuzzing/renderer_fuzzing/in_process_renderer_fuzzing.h +++ b/chrome/test/fuzzing/renderer_fuzzing/in_process_renderer_fuzzing.h
@@ -8,6 +8,7 @@ #include "base/base64.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/fuzzing/in_process_fuzzer.h" +#include "chrome/test/fuzzing/in_process_proto_fuzzer.h" #include "content/public/test/browser_test_utils.h" #include "testing/libfuzzer/renderer_fuzzing/renderer_fuzzing.h"
diff --git a/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/generate_testcase.py b/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/generate_testcase.py new file mode 100755 index 0000000..873aea3 --- /dev/null +++ b/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/generate_testcase.py
@@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""MojoLPM Testcase Generator + +This script must be used with MojoLPMGenerator and a RendererFuzzer. It +generates code to handle interface creation requested by MojoLPM by using the +interface brokers provided by the internal RendererFuzzer mechanism. + +This script uses the jinja2 and the `testcase.h.tmpl` template to generate C++ +code. A class named `RendererTestcase` will be created. +""" + +from __future__ import annotations + +import abc +import argparse +import dataclasses +import os +import pathlib +import re +import sys + +import typing +import enum + +# Copied from //mojo/public/tools/mojom/mojom/fileutil.py. +def AddLocalRepoThirdPartyDirToModulePath(): + """Helper function to find the top-level directory of this script's repository + assuming the script falls somewhere within a 'chrome' directory, and insert + the top-level 'third_party' directory early in the module search path. Used to + ensure that third-party dependencies provided within the repository itself + (e.g. Chromium sources include snapshots of jinja2 and ply) are preferred over + locally installed system library packages.""" + def _GetDirAbove(dirname: str): + """Returns the directory "above" this file containing |dirname| (which must + also be "above" this file).""" + path = os.path.abspath(__file__) + while True: + path, tail = os.path.split(path) + if not tail: + return None + if tail == dirname: + return path + + toplevel_dir = _GetDirAbove('chrome') + if toplevel_dir: + sys.path.insert(1, os.path.join(toplevel_dir, 'third_party')) + +# This is needed in order to be able to import jinja2. +AddLocalRepoThirdPartyDirToModulePath() + +import jinja2 + +def split_interface_name(interface: str): + """Helper that splits a qualified mojo interface name into a dictionary + containing the key 'name' that contains the name of the interface, and the + key 'namespace' that contains its mojo namespace. + + Args: + interface (str): the qualified interface name + + Returns: + a dict containing the actual interface name and its namespace. + """ + return { + "name": interface.split(".")[-1], + "namespace": "::".join(interface.split(".")[:-1]), + } + +def snake_to_camel_case(snake_str: str) -> str: + """Snake case to camel case conversion. + + Args: + snake_str: the snake case identifier to convert. + + Returns: + `snake_str` converted to a camel case identifier. + """ + return "".join(x.capitalize() for x in snake_str.lower().split("_")) + +def main(): + parser = argparse.ArgumentParser( + description='Generate an IPC fuzzer based on MojoLPM Generator.') + parser.add_argument( + '-c', + '--context', + default=[], + nargs='+', + required=True, + help="Context bound interfaces to fuzz.") + parser.add_argument( + '-p', + '--process', + default=[], + nargs='+', + required=True, + help="Process bound interfaces to fuzz.") + parser.add_argument( + '-d', + '--fuzzer_dir', + required=True, + help="The directory in which the MojoLPMGenerator fuzzer is generated.") + parser.add_argument( + '-n', + '--name', + required=True, + help="""The name of the MojoLPMGenerator fuzzing target. + This will used to deduce the name of the generated MojoLPM testcase.""") + parser.add_argument( + '-o', + '--output', + required=True, + help="Output file name.") + + args = parser.parse_args() + template_dir = os.path.dirname(os.path.abspath(__file__)) + environment = jinja2.Environment(loader=jinja2.FileSystemLoader( + template_dir)) + template = environment.get_template('testcase.h.tmpl') + fuzzer_path = os.path.join(args.fuzzer_dir, args.name) + fuzzer_name = snake_to_camel_case(args.name) + mojolpm_classname = f"mojolpmgenerator::{fuzzer_name}Testcase" + context = { + "filename": args.output, + "mojolpm_generator_filepath": f"{fuzzer_path}.h", + "mojolpm_generator_classname": mojolpm_classname, + "process_interfaces": [split_interface_name(p) for p in args.process], + "context_interfaces": [split_interface_name(c) for c in args.context], + } + with pathlib.Path(args.output).open(mode="w") as f: + f.write(template.render(context)) + +if __name__ == "__main__": + main()
diff --git a/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/mojom_interfaces.gni b/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/mojom_interfaces.gni new file mode 100644 index 0000000..debb352 --- /dev/null +++ b/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/mojom_interfaces.gni
@@ -0,0 +1,490 @@ +# Context exposed interfaces +# As for now, those are the blink interfaces exposed via Document/Frames +# defined at https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_interface_binders.cc;l=740;bpv=1;bpt=1 +# At some point, this will be automatically generated based on what's contained +# in this function. This only demonstrates how this could be done. +blink_browser_exposed_interfaces = [ + [ + "//third_party/blink/public/mojom/interest_group/ad_auction_service.mojom", + "blink.mojom.AdAuctionService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/preloading/anchor_element_interaction_host.mojom", + "blink.mojom.AnchorElementInteractionHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/loader/navigation_predictor.mojom", + "blink.mojom.AnchorElementMetricsHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/webaudio/audio_context_manager.mojom", + "blink.mojom.AudioContextManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/webauthn/authenticator.mojom", + "blink.mojom.Authenticator", + "Remote", + ], + [ + "//third_party/blink/public/mojom/background_fetch/background_fetch.mojom", + "blink.mojom.BackgroundFetchService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/blob/blob_url_store.mojom", + "blink.mojom.BlobURLStore", + "Remote", + ], + [ + "//third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom", + "blink.mojom.BrowsingTopicsDocumentService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/buckets/bucket_manager_host.mojom", + "blink.mojom.BucketManagerHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/cache_storage/cache_storage.mojom", + "blink.mojom.CacheStorage", + "Remote", + ], + [ + "//third_party/blink/public/mojom/clipboard/clipboard.mojom", + "blink.mojom.ClipboardHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/loader/code_cache.mojom", + "blink.mojom.CodeCacheHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/choosers/color_chooser.mojom", + "blink.mojom.ColorChooserFactory", + "Remote", + ], + [ + "//third_party/blink/public/mojom/contacts/contacts_manager.mojom", + "blink.mojom.ContactsManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/content_index/content_index.mojom", + "blink.mojom.ContentIndexService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/loader/content_security_notifier.mojom", + "blink.mojom.ContentSecurityNotifier", + "Remote", + ], + [ + "//third_party/blink/public/mojom/cookie_store/cookie_store.mojom", + "blink.mojom.CookieStore", + "Remote", + ], + [ + "//third_party/blink/public/mojom/credentialmanagement/credential_manager.mojom", + "blink.mojom.CredentialManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom", + "blink.mojom.DedicatedWorkerHostFactory", + "Remote", + ], + [ + "//third_party/blink/public/mojom/device/device.mojom", + "blink.mojom.DeviceAPIService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/device_posture/device_posture_provider.mojom", + "blink.mojom.DevicePostureProvider", + "Remote", + ], + [ + "//third_party/blink/public/mojom/webid/digital_identity_request.mojom", + "blink.mojom.DigitalIdentityRequest", + "Remote", + ], + [ + "//third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom", + "blink.mojom.DirectSocketsService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/choosers/color_chooser.mojom", + "blink.mojom.EyeDropperChooser", + "Remote", + ], + [ + "//third_party/blink/public/mojom/feature_observer/feature_observer.mojom", + "blink.mojom.FeatureObserver", + "Remote", + ], + [ + "//third_party/blink/public/mojom/webid/federated_auth_request.mojom", + "blink.mojom.FederatedAuthRequest", + "Remote", + ], + [ + "//third_party/blink/public/mojom/choosers/file_chooser.mojom", + "blink.mojom.FileChooser", + "Remote", + ], + [ + "//third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom", + "blink.mojom.FileSystemAccessManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/filesystem/file_system.mojom", + "blink.mojom.FileSystemManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/file/file_utilities.mojom", + "blink.mojom.FileUtilitiesHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/font_access/font_access.mojom", + "blink.mojom.FontAccessManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/geolocation/geolocation_service.mojom", + "blink.mojom.GeolocationService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/hid/hid.mojom", + "blink.mojom.HidService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/indexeddb/indexeddb.mojom", + "blink.mojom.IDBFactory", + "Remote", + ], + [ + "//third_party/blink/public/mojom/idle/idle_manager.mojom", + "blink.mojom.IdleManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/installedapp/installed_app_provider.mojom", + "blink.mojom.InstalledAppProvider", + "Remote", + ], + [ + "//third_party/blink/public/mojom/keyboard_lock/keyboard_lock.mojom", + "blink.mojom.KeyboardLockService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom", + "blink.mojom.LCPCriticalPathPredictorHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/locks/lock_manager.mojom", + "blink.mojom.LockManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/device/device.mojom", + "blink.mojom.ManagedConfigurationService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/mediastream/media_devices.mojom", + "blink.mojom.MediaDevicesDispatcherHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/mediasession/media_session.mojom", + "blink.mojom.MediaSessionService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/mediastream/media_stream.mojom", + "blink.mojom.MediaStreamDispatcherHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/model_execution/model_manager.mojom", + "blink.mojom.ModelManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/frame/frame.mojom", + "blink.mojom.NonAssociatedLocalFrameHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/prerender/prerender.mojom", + "blink.mojom.NoStatePrefetchProcessor", + "Remote", + ], + [ + "//third_party/blink/public/mojom/notifications/notification_service.mojom", + "blink.mojom.NotificationService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/background_sync/background_sync.mojom", + "blink.mojom.OneShotBackgroundSyncService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/origin_trial_state/origin_trial_state_host.mojom", + "blink.mojom.OriginTrialStateHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom", + "blink.mojom.PeerConnectionTrackerHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/background_sync/background_sync.mojom", + "blink.mojom.PeriodicBackgroundSyncService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/permissions/permission.mojom", + "blink.mojom.PermissionService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom", + "blink.mojom.PictureInPictureService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/presentation/presentation.mojom", + "blink.mojom.PresentationService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/push_messaging/push_messaging.mojom", + "blink.mojom.PushMessaging", + "Remote", + ], + [ + "//third_party/blink/public/mojom/quota/quota_manager_host.mojom", + "blink.mojom.QuotaManagerHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/render_accessibility.mojom", + "blink.mojom.RenderAccessibilityHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom", + "blink.mojom.RendererAudioInputStreamFactory", + "Remote", + ], + [ + "//third_party/blink/public/mojom/media/renderer_audio_output_stream_factory.mojom", + "blink.mojom.RendererAudioOutputStreamFactory", + "Remote", + ], + [ + "//third_party/blink/public/mojom/reporting/reporting.mojom", + "blink.mojom.ReportingServiceProxy", + "Remote", + ], + [ + "//third_party/blink/public/mojom/serial/serial.mojom", + "blink.mojom.SerialService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/worker/shared_worker_connector.mojom", + "blink.mojom.SharedWorkerConnector", + "Remote", + ], + [ + "//third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom", + "blink.mojom.SpeculationHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/speech/speech_recognizer.mojom", + "blink.mojom.SpeechRecognizer", + "Remote", + ], + [ + "//third_party/blink/public/mojom/speech/speech_synthesis.mojom", + "blink.mojom.SpeechSynthesis", + "Remote", + ], + [ + "//third_party/blink/public/mojom/storage_access/storage_access_handle.mojom", + "blink.mojom.StorageAccessHandle", + "Remote", + ], + [ + "//third_party/blink/public/mojom/input/input_host.mojom", + "blink.mojom.TextSuggestionHost", + "Remote", + ], + [ + "//third_party/blink/public/mojom/wake_lock/wake_lock.mojom", + "blink.mojom.WakeLockService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom", + "blink.mojom.WebBluetoothService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/sms/webotp_service.mojom", + "blink.mojom.WebOTPService", + "Remote", + ], + [ + "//third_party/blink/public/mojom/sensor/web_sensor_provider.mojom", + "blink.mojom.WebSensorProvider", + "Remote", + ], + [ + "//third_party/blink/public/mojom/websockets/websocket_connector.mojom", + "blink.mojom.WebSocketConnector", + "Remote", + ], + [ + "//third_party/blink/public/mojom/webtransport/web_transport_connector.mojom", + "blink.mojom.WebTransportConnector", + "Remote", + ], + [ + "//third_party/blink/public/mojom/usb/web_usb_service.mojom", + "blink.mojom.WebUsbService", + "Remote", + ], +] + +process_browser_exposed_interfaces = [ + [ + "//third_party/blink/public/mojom/blob/blob_registry.mojom", + "blink.mojom.BlobRegistry", + "Remote", + ], + [ + "//content/common/render_message_filter.mojom", + "content.mojom.RenderMessageFilter", + "Remote", + ], + [ + "//services/device/public/mojom/time_zone_monitor.mojom", + "device.mojom.TimeZoneMonitor", + "Remote", + ], + [ + "//services/device/public/mojom/power_monitor.mojom", + "device.mojom.PowerMonitor", + "Remote", + ], + [ + "//services/device/public/mojom/screen_orientation.mojom", + "device.mojom.ScreenOrientationListener", + "Remote", + ], + [ + "//third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom", + "blink.mojom.EmbeddedFrameSinkProvider", + "Remote", + ], + [ + "//services/viz/public/mojom/compositing/compositing_mode_watcher.mojom", + "viz.mojom.CompositingModeReporter", + "Remote", + ], + [ + "//third_party/blink/public/mojom/dom_storage/dom_storage.mojom", + "blink.mojom.DomStorageProvider", + "Remote", + ], + [ + "//third_party/blink/public/mojom/webdatabase/web_database.mojom", + "blink.mojom.WebDatabaseHost", + "Remote", + ], + [ + "//services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom", + "memory_instrumentation.mojom.CoordinatorConnector", + "Remote", + ], + [ + "//third_party/blink/public/mojom/mime/mime_registry.mojom", + "blink.mojom.MimeRegistry", + "Remote", + ], + [ + "//third_party/blink/public/mojom/hyphenation/hyphenation.mojom", + "blink.mojom.Hyphenation", + "Remote", + ], + [ + "//third_party/blink/public/mojom/font_unique_name_lookup/font_unique_name_lookup.mojom", + "blink.mojom.FontUniqueNameLookup", + "Remote", + ], + [ + "//services/viz/public/mojom/gpu.mojom", + "viz.mojom.Gpu", + "Remote", + ], + [ + "//third_party/blink/public/mojom/gpu/gpu.mojom", + "blink.mojom.GpuDataManager", + "Remote", + ], + [ + "//third_party/blink/public/mojom/mediastream/media_stream.mojom", + "blink.mojom.MediaStreamTrackMetricsHost", + "Remote", + ], + [ + "//components/metrics/public/mojom/single_sample_metrics.mojom", + "metrics.mojom.SingleSampleMetricsProvider", + "Remote", + ], + [ + "//content/common/media/media_log_records.mojom", + "content.mojom.MediaInternalLogRecords", + "Remote", + ], + [ + "//content/common/field_trial_recorder.mojom", + "content.mojom.FieldTrialRecorder", + "Remote", + ], + [ + "//media/mojo/mojom/interface_factory.mojom", + "media.mojom.InterfaceFactory", + "Remote", + ], + [ + "//media/mojo/mojom/video_encoder_metrics_provider.mojom", + "media.mojom.VideoEncoderMetricsProvider", + "Remote", + ], + [ + "//third_party/blink/public/mojom/mediastream/aec_dump.mojom", + "blink.mojom.AecDumpManager", + "Remote", + ], +]
diff --git a/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/testcase.h.tmpl b/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/testcase.h.tmpl new file mode 100644 index 0000000..e1514e86 --- /dev/null +++ b/chrome/test/fuzzing/renderer_fuzzing/ipc_fuzzing/testcase.h.tmpl
@@ -0,0 +1,173 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +{%- set header_guard = "%s_"|format( + filename|upper|replace("/","_")|replace(".","_")| + replace("-", "_")) %} + +#ifndef {{header_guard}} +#define {{header_guard}} + +#include "{{mojolpm_generator_filepath}}" + +#include "base/functional/bind.h" +#include "mojo/public/tools/fuzzers/mojolpm.h" + +class RendererTestcase + : public {{mojolpm_generator_classname}} { + public: + explicit RendererTestcase( + std::unique_ptr<ProtoTestcase> testcase, + const blink::BrowserInterfaceBrokerProxy* context_interface_broker_proxy, + blink::ThreadSafeBrowserInterfaceBrokerProxy* + process_interface_broker_proxy); + ~RendererTestcase() override; + + scoped_refptr<base::SequencedTaskRunner> GetFuzzerTaskRunner() override; + void SetUp(base::OnceClosure done_closure) override; + void TearDown(base::OnceClosure done_closure) override; +{% for interface in context_interfaces %} + void HandleNew{{interface.name}}Action( + uint32_t id, + base::OnceClosure done_closure) override; +{% endfor %} + +{% for interface in process_interfaces %} + void HandleNew{{interface.name}}Action( + uint32_t id, + base::OnceClosure done_closure) override; +{% endfor %} + + private: + void SetUpOnFuzzerThread(base::OnceClosure done_closure); + void TearDownOnFuzzerThread(base::OnceClosure done_closure); + + template <typename T> + void NewProcessInterface(uint32_t id, base::OnceClosure done_closure); + template <typename T> + void NewContextInterface(uint32_t id, base::OnceClosure done_closure); + + // This is different to the "normal" MojoLPM testcase model, since we need + // to also own the lifetime of the protobuf object, when it's normally owned + // by libfuzzer. + std::unique_ptr<ProtoTestcase> proto_testcase_ptr_; + + // Bindings + raw_ptr<const blink::BrowserInterfaceBrokerProxy> + context_interface_broker_proxy_; + raw_ptr<blink::ThreadSafeBrowserInterfaceBrokerProxy> + process_interface_broker_proxy_; + + SEQUENCE_CHECKER(sequence_checker_); +}; + +namespace { + +scoped_refptr<base::SequencedTaskRunner> GetFuzzerTaskRunnerImpl() { + // XXX: This should be main thread? IO thread? Probably doesn't + // actually matter. + static scoped_refptr<base::SequencedTaskRunner> fuzzer_task_runner = + base::SequencedTaskRunner::GetCurrentDefault(); + return fuzzer_task_runner; +} + +} // anonymous namespace + +{% for interface in context_interfaces %} +void RendererTestcase::HandleNew{{interface.name}}Action( + uint32_t id, + base::OnceClosure done_closure) { + NewContextInterface<{{interface.namespace}}::{{interface.name}}>(id, std::move(done_closure)); +} +{% endfor %} + +{% for interface in process_interfaces %} +void RendererTestcase::HandleNew{{interface.name}}Action( + uint32_t id, + base::OnceClosure done_closure) { + NewProcessInterface<{{interface.namespace}}::{{interface.name}}>(id, std::move(done_closure)); +} +{% endfor %} + + +scoped_refptr<base::SequencedTaskRunner> +RendererTestcase::GetFuzzerTaskRunner() { + return GetFuzzerTaskRunnerImpl(); +} + +RendererTestcase::RendererTestcase( + std::unique_ptr<ProtoTestcase> testcase, + const blink::BrowserInterfaceBrokerProxy* context_interface_broker_proxy, + blink::ThreadSafeBrowserInterfaceBrokerProxy* + process_interface_broker_proxy) + : {{mojolpm_generator_classname}}(*testcase.get()), + proto_testcase_ptr_(std::move(testcase)), + context_interface_broker_proxy_(context_interface_broker_proxy), + process_interface_broker_proxy_(process_interface_broker_proxy) { + // RendererTestcase is created on the main thread, but the actions that + // we want to validate the sequencing of take place on the fuzzer sequence. + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +RendererTestcase::~RendererTestcase() {} + +void RendererTestcase::SetUp(base::OnceClosure done_closure) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + GetFuzzerTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&RendererTestcase::SetUpOnFuzzerThread, + base::Unretained(this), std::move(done_closure))); +} + +void RendererTestcase::TearDown(base::OnceClosure done_closure) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + GetFuzzerTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&RendererTestcase::TearDownOnFuzzerThread, + base::Unretained(this), std::move(done_closure))); +} + +void RendererTestcase::SetUpOnFuzzerThread(base::OnceClosure done_closure) { + mojolpm::GetContext()->StartTestcase(); + + std::move(done_closure).Run(); +} + +void RendererTestcase::TearDownOnFuzzerThread(base::OnceClosure done_closure) { + mojolpm::GetContext()->EndTestcase(); + + std::move(done_closure).Run(); +} + +template <typename T> +void RendererTestcase::NewProcessInterface(uint32_t id, + base::OnceClosure done_closure) { + mojo::Remote<T> remote; + mojo::GenericPendingReceiver receiver = remote.BindNewPipeAndPassReceiver(); + + process_interface_broker_proxy_->GetInterface(std::move(receiver)); + CHECK(remote.is_bound() && remote.is_connected()); + + mojolpm::GetContext()->AddInstance(id, std::move(remote)); + + std::move(done_closure).Run(); +} + +template <typename T> +void RendererTestcase::NewContextInterface(uint32_t id, + base::OnceClosure done_closure) { + mojo::Remote<T> remote; + mojo::GenericPendingReceiver receiver = remote.BindNewPipeAndPassReceiver(); + + context_interface_broker_proxy_->GetInterface(std::move(receiver)); + CHECK(remote.is_bound() && remote.is_connected()); + + mojolpm::GetContext()->AddInstance(id, std::move(remote)); + + std::move(done_closure).Run(); +} + +#endif // {{header_guard}}
diff --git a/chrome/test/fuzzing/renderer_fuzzing/mojom_interfaces.gni b/chrome/test/fuzzing/renderer_fuzzing/mojom_interfaces.gni deleted file mode 100644 index 0111067..0000000 --- a/chrome/test/fuzzing/renderer_fuzzing/mojom_interfaces.gni +++ /dev/null
@@ -1,382 +0,0 @@ -# Context exposed interfaces -# As for now, those are the blink interfaces exposed via Document/Frames -# defined at https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_interface_binders.cc;l=740;bpv=1;bpt=1 -# At some point, this will be automatically generated based on what's contained -# in this function. This only demonstrates how this could be done. -blink_browser_exposed_interfaces = [ - [ - "//third_party/blink/public/mojom/blob/blob_registry.mojom", - "BlobRegistry", - "Remote", - ], - [ - "//third_party/blink/public/mojom/interest_group/ad_auction_service.mojom", - "AdAuctionService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/preloading/anchor_element_interaction_host.mojom", - "AnchorElementInteractionHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/loader/navigation_predictor.mojom", - "AnchorElementMetricsHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/webaudio/audio_context_manager.mojom", - "AudioContextManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/webauthn/authenticator.mojom", - "Authenticator", - "Remote", - ], - [ - "//third_party/blink/public/mojom/background_fetch/background_fetch.mojom", - "BackgroundFetchService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/blob/blob_url_store.mojom", - "BlobURLStore", - "Remote", - ], - [ - "//third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom", - "BrowsingTopicsDocumentService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/buckets/bucket_manager_host.mojom", - "BucketManagerHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/cache_storage/cache_storage.mojom", - "CacheStorage", - "Remote", - ], - [ - "//third_party/blink/public/mojom/clipboard/clipboard.mojom", - "ClipboardHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/loader/code_cache.mojom", - "CodeCacheHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/choosers/color_chooser.mojom", - "ColorChooserFactory", - "Remote", - ], - [ - "//third_party/blink/public/mojom/contacts/contacts_manager.mojom", - "ContactsManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/content_index/content_index.mojom", - "ContentIndexService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/loader/content_security_notifier.mojom", - "ContentSecurityNotifier", - "Remote", - ], - [ - "//third_party/blink/public/mojom/cookie_store/cookie_store.mojom", - "CookieStore", - "Remote", - ], - [ - "//third_party/blink/public/mojom/credentialmanagement/credential_manager.mojom", - "CredentialManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom", - "DedicatedWorkerHostFactory", - "Remote", - ], - [ - "//third_party/blink/public/mojom/device/device.mojom", - "DeviceAPIService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/device_posture/device_posture_provider.mojom", - "DevicePostureProvider", - "Remote", - ], - [ - "//third_party/blink/public/mojom/webid/digital_identity_request.mojom", - "DigitalIdentityRequest", - "Remote", - ], - [ - "//third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom", - "DirectSocketsService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/choosers/color_chooser.mojom", - "EyeDropperChooser", - "Remote", - ], - [ - "//third_party/blink/public/mojom/feature_observer/feature_observer.mojom", - "FeatureObserver", - "Remote", - ], - [ - "//third_party/blink/public/mojom/webid/federated_auth_request.mojom", - "FederatedAuthRequest", - "Remote", - ], - [ - "//third_party/blink/public/mojom/choosers/file_chooser.mojom", - "FileChooser", - "Remote", - ], - [ - "//third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom", - "FileSystemAccessManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/filesystem/file_system.mojom", - "FileSystemManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/file/file_utilities.mojom", - "FileUtilitiesHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/font_access/font_access.mojom", - "FontAccessManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/geolocation/geolocation_service.mojom", - "GeolocationService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/hid/hid.mojom", - "HidService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/indexeddb/indexeddb.mojom", - "IDBFactory", - "Remote", - ], - [ - "//third_party/blink/public/mojom/idle/idle_manager.mojom", - "IdleManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/installedapp/installed_app_provider.mojom", - "InstalledAppProvider", - "Remote", - ], - [ - "//third_party/blink/public/mojom/keyboard_lock/keyboard_lock.mojom", - "KeyboardLockService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom", - "LCPCriticalPathPredictorHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/locks/lock_manager.mojom", - "LockManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/device/device.mojom", - "ManagedConfigurationService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/mediastream/media_devices.mojom", - "MediaDevicesDispatcherHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/mediasession/media_session.mojom", - "MediaSessionService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/mediastream/media_stream.mojom", - "MediaStreamDispatcherHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/model_execution/model_manager.mojom", - "ModelManager", - "Remote", - ], - [ - "//third_party/blink/public/mojom/frame/frame.mojom", - "NonAssociatedLocalFrameHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/prerender/prerender.mojom", - "NoStatePrefetchProcessor", - "Remote", - ], - [ - "//third_party/blink/public/mojom/notifications/notification_service.mojom", - "NotificationService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/background_sync/background_sync.mojom", - "OneShotBackgroundSyncService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/origin_trial_state/origin_trial_state_host.mojom", - "OriginTrialStateHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom", - "PeerConnectionTrackerHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/background_sync/background_sync.mojom", - "PeriodicBackgroundSyncService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/permissions/permission.mojom", - "PermissionService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom", - "PictureInPictureService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/presentation/presentation.mojom", - "PresentationService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/push_messaging/push_messaging.mojom", - "PushMessaging", - "Remote", - ], - [ - "//third_party/blink/public/mojom/quota/quota_manager_host.mojom", - "QuotaManagerHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/render_accessibility.mojom", - "RenderAccessibilityHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom", - "RendererAudioInputStreamFactory", - "Remote", - ], - [ - "//third_party/blink/public/mojom/media/renderer_audio_output_stream_factory.mojom", - "RendererAudioOutputStreamFactory", - "Remote", - ], - [ - "//third_party/blink/public/mojom/reporting/reporting.mojom", - "ReportingServiceProxy", - "Remote", - ], - [ - "//third_party/blink/public/mojom/serial/serial.mojom", - "SerialService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/worker/shared_worker_connector.mojom", - "SharedWorkerConnector", - "Remote", - ], - [ - "//third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom", - "SpeculationHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/speech/speech_recognizer.mojom", - "SpeechRecognizer", - "Remote", - ], - [ - "//third_party/blink/public/mojom/speech/speech_synthesis.mojom", - "SpeechSynthesis", - "Remote", - ], - [ - "//third_party/blink/public/mojom/storage_access/storage_access_handle.mojom", - "StorageAccessHandle", - "Remote", - ], - [ - "//third_party/blink/public/mojom/input/input_host.mojom", - "TextSuggestionHost", - "Remote", - ], - [ - "//third_party/blink/public/mojom/wake_lock/wake_lock.mojom", - "WakeLockService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom", - "WebBluetoothService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/sms/webotp_service.mojom", - "WebOTPService", - "Remote", - ], - [ - "//third_party/blink/public/mojom/sensor/web_sensor_provider.mojom", - "WebSensorProvider", - "Remote", - ], - [ - "//third_party/blink/public/mojom/websockets/websocket_connector.mojom", - "WebSocketConnector", - "Remote", - ], - [ - "//third_party/blink/public/mojom/webtransport/web_transport_connector.mojom", - "WebTransportConnector", - "Remote", - ], - [ - "//third_party/blink/public/mojom/usb/web_usb_service.mojom", - "WebUsbService", - "Remote", - ], -]
diff --git a/chrome/test/fuzzing/renderer_fuzzing/renderer_in_process_mojolpm_fuzzer.cc b/chrome/test/fuzzing/renderer_fuzzing/renderer_in_process_mojolpm_fuzzer.cc index cb24c92..8b8ef0c 100644 --- a/chrome/test/fuzzing/renderer_fuzzing/renderer_in_process_mojolpm_fuzzer.cc +++ b/chrome/test/fuzzing/renderer_fuzzing/renderer_in_process_mojolpm_fuzzer.cc
@@ -2,886 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/test/fuzzing/renderer_fuzzing/renderer_in_process_mojolpm_fuzzer.h" - -#include "base/base64.h" #include "base/functional/bind.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/escape.h" -#include "base/test/bind.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/test/base/ui_test_utils.h" -#include "chrome/test/fuzzing/in_process_proto_fuzzer.h" #include "chrome/test/fuzzing/renderer_fuzzing/in_process_renderer_fuzzing.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/test/browser_test_utils.h" -#include "mojo/public/tools/fuzzers/mojolpm.h" -#include "testing/libfuzzer/proto/lpm_interface.h" +#include "chrome/test/fuzzing/renderer_fuzzing/testcase.h" #include "testing/libfuzzer/renderer_fuzzing/renderer_fuzzing.h" -#include "third_party/blink/public/mojom/blob/blob_registry.mojom-mojolpm.h" -#include "third_party/blink/public/web/web_testing_support.h" - -// This class fuzzes mojo interfaces exposed by the browser process to the -// renderer process using MojoLPM. -// It runs in the renderer process, and is fed testcases by the fuzzer -// running in the browser process. -// It currently uses MojoLPMGenerator in order to remove all the unnecessary -// boilerplate implied by using MojoLPM. -class RendererTestcase - : public mojolpmgenerator::RendererInProcessMojolpmFuzzerTestcase { - public: - explicit RendererTestcase( - std::unique_ptr<ProtoTestcase> testcase, - const blink::BrowserInterfaceBrokerProxy* context_interface_broker_proxy, - blink::ThreadSafeBrowserInterfaceBrokerProxy* - process_interface_broker_proxy); - ~RendererTestcase() override; - - scoped_refptr<base::SequencedTaskRunner> GetFuzzerTaskRunner() override; - void SetUp(base::OnceClosure done_closure) override; - void TearDown(base::OnceClosure done_closure) override; - void HandleNewBlobRegistryAction(uint32_t id, - base::OnceClosure done_closure) override; - // At some point, this will be automatically generated. As for now, we want - // to try fuzzing a larger part of the IPC surface. - void HandleNewAdAuctionServiceAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewAnchorElementInteractionHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewAnchorElementMetricsHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewAudioContextManagerAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewAuthenticatorAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewBackgroundFetchServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewBlobURLStoreAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewBrowsingTopicsDocumentServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewBucketManagerHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewCacheStorageAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewClipboardHostAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewCodeCacheHostAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewColorChooserFactoryAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewContactsManagerAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewContentIndexServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewContentSecurityNotifierAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewCookieStoreAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewCredentialManagerAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewDedicatedWorkerHostFactoryAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewDeviceAPIServiceAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewDevicePostureProviderAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewDigitalIdentityRequestAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewDirectSocketsServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewEyeDropperChooserAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewFeatureObserverAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewFederatedAuthRequestAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewFileChooserAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewFileSystemAccessManagerAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewFileSystemManagerAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewFileUtilitiesHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewFontAccessManagerAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewGeolocationServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewHidServiceAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewIDBFactoryAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewIdleManagerAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewInstalledAppProviderAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewKeyboardLockServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewLCPCriticalPathPredictorHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewLockManagerAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewManagedConfigurationServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewMediaDevicesDispatcherHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewMediaSessionServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewMediaStreamDispatcherHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewModelManagerAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewNonAssociatedLocalFrameHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewNoStatePrefetchProcessorAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewNotificationServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewOneShotBackgroundSyncServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewOriginTrialStateHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewPeerConnectionTrackerHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewPeriodicBackgroundSyncServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewPermissionServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewPictureInPictureServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewPresentationServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewPushMessagingAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewQuotaManagerHostAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewRenderAccessibilityHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewRendererAudioInputStreamFactoryAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewRendererAudioOutputStreamFactoryAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewReportingServiceProxyAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewSerialServiceAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewSharedWorkerConnectorAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewSpeculationHostAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewSpeechRecognizerAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewSpeechSynthesisAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewStorageAccessHandleAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewTextSuggestionHostAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewWakeLockServiceAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewWebBluetoothServiceAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewWebOTPServiceAction(uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewWebSensorProviderAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewWebSocketConnectorAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewWebTransportConnectorAction( - uint32_t id, - base::OnceClosure done_closure) override; - void HandleNewWebUsbServiceAction(uint32_t id, - base::OnceClosure done_closure) override; - - private: - void SetUpOnFuzzerThread(base::OnceClosure done_closure); - void TearDownOnFuzzerThread(base::OnceClosure done_closure); - - template <typename T> - void NewProcessInterface(uint32_t id, base::OnceClosure done_closure); - template <typename T> - void NewContextInterface(uint32_t id, base::OnceClosure done_closure); - - // This is different to the "normal" MojoLPM testcase model, since we need - // to also own the lifetime of the protobuf object, when it's normally owned - // by libfuzzer. - std::unique_ptr<ProtoTestcase> proto_testcase_ptr_; - - // Bindings - [[maybe_unused]] raw_ptr<const blink::BrowserInterfaceBrokerProxy> - context_interface_broker_proxy_; - [[maybe_unused]] raw_ptr<blink::ThreadSafeBrowserInterfaceBrokerProxy> - process_interface_broker_proxy_; - - SEQUENCE_CHECKER(sequence_checker_); -}; - -namespace { - -scoped_refptr<base::SequencedTaskRunner> GetFuzzerTaskRunnerImpl() { - // XXX: This should be main thread? IO thread? Probably doesn't - // actually matter. - static scoped_refptr<base::SequencedTaskRunner> fuzzer_task_runner = - base::SequencedTaskRunner::GetCurrentDefault(); - return fuzzer_task_runner; -} - -} // anonymous namespace - -void RendererTestcase::HandleNewBlobRegistryAction( - uint32_t id, - base::OnceClosure done_closure) { - NewProcessInterface<::blink::mojom::BlobRegistry>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewAdAuctionServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::AdAuctionService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewAnchorElementInteractionHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::AnchorElementInteractionHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewAnchorElementMetricsHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::AnchorElementMetricsHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewAudioContextManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::AudioContextManager>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewAuthenticatorAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::Authenticator>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewBackgroundFetchServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::BackgroundFetchService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewBlobURLStoreAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::BlobURLStore>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewBrowsingTopicsDocumentServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::BrowsingTopicsDocumentService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewBucketManagerHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::BucketManagerHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewCacheStorageAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::CacheStorage>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewClipboardHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ClipboardHost>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewCodeCacheHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::CodeCacheHost>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewColorChooserFactoryAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ColorChooserFactory>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewContactsManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ContactsManager>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewContentIndexServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ContentIndexService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewContentSecurityNotifierAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ContentSecurityNotifier>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewCookieStoreAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::CookieStore>(id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewCredentialManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::CredentialManager>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewDedicatedWorkerHostFactoryAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::DedicatedWorkerHostFactory>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewDeviceAPIServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::DeviceAPIService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewDevicePostureProviderAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::DevicePostureProvider>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewDigitalIdentityRequestAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::DigitalIdentityRequest>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewDirectSocketsServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::DirectSocketsService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewEyeDropperChooserAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::EyeDropperChooser>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewFeatureObserverAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::FeatureObserver>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewFederatedAuthRequestAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::FederatedAuthRequest>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewFileChooserAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::FileChooser>(id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewFileSystemAccessManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::FileSystemAccessManager>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewFileSystemManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::FileSystemManager>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewFileUtilitiesHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::FileUtilitiesHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewFontAccessManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::FontAccessManager>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewGeolocationServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::GeolocationService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewHidServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::HidService>(id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewIDBFactoryAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::IDBFactory>(id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewIdleManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::IdleManager>(id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewInstalledAppProviderAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::InstalledAppProvider>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewKeyboardLockServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::KeyboardLockService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewLockManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::LockManager>(id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewLCPCriticalPathPredictorHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::LCPCriticalPathPredictorHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewManagedConfigurationServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ManagedConfigurationService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewMediaDevicesDispatcherHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::MediaDevicesDispatcherHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewMediaSessionServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::MediaSessionService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewMediaStreamDispatcherHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::MediaStreamDispatcherHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewModelManagerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ModelManager>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewNonAssociatedLocalFrameHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::NonAssociatedLocalFrameHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewNoStatePrefetchProcessorAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::NoStatePrefetchProcessor>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewNotificationServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::NotificationService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewOneShotBackgroundSyncServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::OneShotBackgroundSyncService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewOriginTrialStateHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::OriginTrialStateHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewPeerConnectionTrackerHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::PeerConnectionTrackerHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewPeriodicBackgroundSyncServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::PeriodicBackgroundSyncService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewPermissionServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::PermissionService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewPictureInPictureServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::PictureInPictureService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewPresentationServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::PresentationService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewPushMessagingAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::PushMessaging>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewQuotaManagerHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::QuotaManagerHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewRenderAccessibilityHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::RenderAccessibilityHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewRendererAudioInputStreamFactoryAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::RendererAudioInputStreamFactory>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewRendererAudioOutputStreamFactoryAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::RendererAudioOutputStreamFactory>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewReportingServiceProxyAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::ReportingServiceProxy>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewSerialServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::SerialService>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewSharedWorkerConnectorAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::SharedWorkerConnector>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewSpeculationHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::SpeculationHost>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewSpeechRecognizerAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::SpeechRecognizer>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewSpeechSynthesisAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::SpeechSynthesis>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewStorageAccessHandleAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::StorageAccessHandle>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewTextSuggestionHostAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::TextSuggestionHost>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewWakeLockServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::WakeLockService>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewWebBluetoothServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::WebBluetoothService>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewWebOTPServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::WebOTPService>(id, - std::move(done_closure)); -} - -void RendererTestcase::HandleNewWebSensorProviderAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::WebSensorProvider>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewWebSocketConnectorAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::WebSocketConnector>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewWebTransportConnectorAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::WebTransportConnector>( - id, std::move(done_closure)); -} - -void RendererTestcase::HandleNewWebUsbServiceAction( - uint32_t id, - base::OnceClosure done_closure) { - NewContextInterface<::blink::mojom::WebUsbService>(id, - std::move(done_closure)); -} - -scoped_refptr<base::SequencedTaskRunner> -RendererTestcase::GetFuzzerTaskRunner() { - return GetFuzzerTaskRunnerImpl(); -} - -RendererTestcase::RendererTestcase( - std::unique_ptr<ProtoTestcase> testcase, - const blink::BrowserInterfaceBrokerProxy* context_interface_broker_proxy, - blink::ThreadSafeBrowserInterfaceBrokerProxy* - process_interface_broker_proxy) - : mojolpmgenerator::RendererInProcessMojolpmFuzzerTestcase(*testcase.get()), - proto_testcase_ptr_(std::move(testcase)), - context_interface_broker_proxy_(context_interface_broker_proxy), - process_interface_broker_proxy_(process_interface_broker_proxy) { - // RendererTestcase is created on the main thread, but the actions that - // we want to validate the sequencing of take place on the fuzzer sequence. - DETACH_FROM_SEQUENCE(sequence_checker_); -} - -RendererTestcase::~RendererTestcase() {} - -void RendererTestcase::SetUp(base::OnceClosure done_closure) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - GetFuzzerTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&RendererTestcase::SetUpOnFuzzerThread, - base::Unretained(this), std::move(done_closure))); -} - -void RendererTestcase::TearDown(base::OnceClosure done_closure) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - GetFuzzerTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&RendererTestcase::TearDownOnFuzzerThread, - base::Unretained(this), std::move(done_closure))); -} - -void RendererTestcase::SetUpOnFuzzerThread(base::OnceClosure done_closure) { - mojolpm::GetContext()->StartTestcase(); - - std::move(done_closure).Run(); -} - -void RendererTestcase::TearDownOnFuzzerThread(base::OnceClosure done_closure) { - mojolpm::GetContext()->EndTestcase(); - - std::move(done_closure).Run(); -} - -template <typename T> -void RendererTestcase::NewProcessInterface(uint32_t id, - base::OnceClosure done_closure) { - mojo::Remote<T> remote; - mojo::GenericPendingReceiver receiver = remote.BindNewPipeAndPassReceiver(); - - process_interface_broker_proxy_->GetInterface(std::move(receiver)); - CHECK(remote.is_bound() && remote.is_connected()); - - mojolpm::GetContext()->AddInstance(id, std::move(remote)); - - std::move(done_closure).Run(); -} - -template <typename T> -void RendererTestcase::NewContextInterface(uint32_t id, - base::OnceClosure done_closure) { - mojo::Remote<T> remote; - mojo::GenericPendingReceiver receiver = remote.BindNewPipeAndPassReceiver(); - - context_interface_broker_proxy_->GetInterface(std::move(receiver)); - CHECK(remote.is_bound() && remote.is_connected()); - - mojolpm::GetContext()->AddInstance(id, std::move(remote)); - - std::move(done_closure).Run(); -} // `RendererFuzzingAdapter` will be allocated by the internal renderer fuzzing // mechanism. It is statically allocated, and will remain alive until the // fuzzing process shuts down. -// Unfortunately, we cannot merge this class with `RendererTestcase`, because -// the latter needs to have a different lifetime. Indeed, it needs to be -// recreated for every fuzzing iteration, so that MojoLPM remains deterministic -// across runs for a given testcase. +// This interacts with the generated RendererTestcase MojoLPM fuzzer. class RendererFuzzingAdapter : public RendererFuzzerBase { public: using FuzzCase = RendererTestcase::ProtoTestcase; @@ -899,11 +28,11 @@ std::move(proto_testcase_ptr), context_interface_broker_proxy, process_interface_broker_proxy); - GetFuzzerTaskRunnerImpl()->PostTask( + ptr->GetFuzzerTaskRunner()->PostTask( FROM_HERE, base::BindOnce( &mojolpm::RunTestcase<RendererTestcase>, - base::Unretained(ptr.get()), GetFuzzerTaskRunnerImpl(), + base::Unretained(ptr.get()), ptr->GetFuzzerTaskRunner(), std::move(done_closure) .Then(base::OnceClosure( base::DoNothingWithBoundArgs(std::move(ptr))))));
diff --git a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_routines.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_routines.mojom index 6ffd0e0..67ee9c4 100644 --- a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_routines.mojom +++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_routines.mojom
@@ -330,7 +330,7 @@ mojo_base.mojom.TimeDelta? exec_duration@0; }; -// This routine checks the network bandwidth and report the speed info. +// This routine checks the network bandwidth and reports the speed info. // // NextMinVersion: 1, NextIndex: 0 [Stable] @@ -450,7 +450,7 @@ }; Type type@0; - // The current network speed in Kbps. + // The current network speed in kbit/s. double speed_kbps@1; }; @@ -947,8 +947,8 @@ // NextMinVersion: 1, NextIndex: 2 [Stable] struct NetworkBandwidthRoutineDetail { - // Average download speed in Kbit/s. + // Average download speed in kbit/s. double download_speed_kbps@0; - // Average upload speed in Kbit/s. + // Average upload speed in kbit/s. double upload_speed_kbps@1; };
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index bfc5c7f..fbd5a6e 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -1807,7 +1807,7 @@ RenamedFrom="crosapi.mojom.LacrosChromeService"] interface BrowserService { // Removed method. No longer used. - REMOVED_0@0() => (pending_receiver<Crosapi> receiver); + REMOVED_0@0(); REMOVED_2@2(BrowserInitParams params); // Opens a new window in the browser with the profile that matches
diff --git a/chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom b/chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom index 3d2dfee..9892cba 100644 --- a/chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom +++ b/chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom
@@ -128,9 +128,15 @@ TelemetryDiagnosticLedColor color@1; }; +// This routine checks the network bandwidth and reports the speed info. +// +// NextMinVersion: 1, NextIndex: 0 +[Stable] +struct TelemetryDiagnosticNetworkBandwidthRoutineArgument {}; + // Argument types for the possible routines the routine control API can create. // -// NextMinVersion: 5, NextIndex: 5 +// NextMinVersion: 6, NextIndex: 6 [Stable, Extensible] union TelemetryDiagnosticRoutineArgument { // Default field is required by extensible unions for backward compatibility. @@ -144,6 +150,9 @@ [MinVersion=3] TelemetryDiagnosticFanRoutineArgument fan@3; // Arguments to create a LED lit up routine. [MinVersion=4] TelemetryDiagnosticLedLitUpRoutineArgument led_lit_up@4; + // Arguments to create a network bandwidth routine. + [MinVersion=5] + TelemetryDiagnosticNetworkBandwidthRoutineArgument network_bandwidth@5; }; // Routine has been initialized but not yet started. @@ -152,11 +161,48 @@ [Stable] struct TelemetryDiagnosticRoutineStateInitialized {}; +// Running info regarding network bandwidth routine. +// +// NextMinVersion: 1, NextIndex: 2 +[Stable] +struct TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo { + // The type of test that routine is running. + // + // NextMinVersion: 1, NextIndex: 3 + [Stable, Extensible] + enum Type { + [Default] kUnmappedEnumField = 0, + // Routine is running download test. + kDownload = 1, + // Routine is running upload test. + kUpload = 2, + }; + Type type@0; + + // The current network speed in kbit/s. + double speed_kbps@1; +}; + +// Routine running info. Note that not every routine provides info during the +// running state. +// +// NextMinVersion: 1, NextIndex: 2 +[Stable] +union TelemetryDiagnosticRoutineRunningInfo { + // Default field is required by extensible unions for backward compatibility. + // Any unrecognized Mojo field will deserialize to this field. Don't use this. + [Default] bool unrecognizedArgument @0; + // Running info of network bandwidth routine. + TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo network_bandwidth@1; +}; + // Routine is currently running. // -// NextMinVersion: 1, NextIndex: 0 +// NextMinVersion: 2, NextIndex: 1 [Stable] -struct TelemetryDiagnosticRoutineStateRunning {}; +struct TelemetryDiagnosticRoutineStateRunning { + [MinVersion=1] TelemetryDiagnosticRoutineRunningInfo? info@0; +}; // Details to reply to a routine requesting to check the LED lit up state. // @@ -378,9 +424,20 @@ TelemetryDiagnosticHardwarePresenceStatus fan_count_status@2; }; +// Details regarding network bandwidth routine. +// +// NextMinVersion: 1, NextIndex: 2 +[Stable] +struct TelemetryDiagnosticNetworkBandwidthRoutineDetail { + // Average download speed in kbit/s. + double download_speed_kbps@0; + // Average upload speed in kbit/s. + double upload_speed_kbps@1; +}; + // Details about a finished routine. // -// NextMinVersion: 4, NextIndex: 4 +// NextMinVersion: 5, NextIndex: 5 [Stable, Extensible] union TelemetryDiagnosticRoutineDetail { // Default field is required by extensible unions for backward compatibility. @@ -392,6 +449,9 @@ [MinVersion=2] TelemetryDiagnosticVolumeButtonRoutineDetail volume_button@2; // Details of a completed fan routine. [MinVersion=3] TelemetryDiagnosticFanRoutineDetail fan@3; + // Details of a completed network bandwidth routine. + [MinVersion=4] + TelemetryDiagnosticNetworkBandwidthRoutineDetail network_bandwidth@4; }; // Information about a finished routine.
diff --git a/clank b/clank index 682118a..2d1d020 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 682118afe56ac594ac2a4343274a9bed1dac8710 +Subproject commit 2d1d020843dabd7ef41ae7a261f81b381281dbf4
diff --git a/components/autofill/content/renderer/autofill_agent_browsertest.cc b/components/autofill/content/renderer/autofill_agent_browsertest.cc index a1c49bc..d021f3b 100644 --- a/components/autofill/content/renderer/autofill_agent_browsertest.cc +++ b/components/autofill/content/renderer/autofill_agent_browsertest.cc
@@ -663,7 +663,7 @@ ASSERT_FALSE(field.IsNull()); std::u16string prior_value = form.fields[0].value; - form.fields[0].value += u"AUTOFILLED"; + form.fields[0].value = form.fields[0].value + u"AUTOFILLED"; form.fields[0].is_autofilled = true; ASSERT_EQ(field.GetAutofillState(), blink::WebAutofillState::kNotFilled);
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 2bf5c73..194c70f4 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -360,6 +360,8 @@ "metrics/payments/wallet_usage_data_metrics.h", "metrics/placeholder_metrics.cc", "metrics/placeholder_metrics.h", + "metrics/profile_deduplication_metrics.cc", + "metrics/profile_deduplication_metrics.h", "metrics/profile_import_metrics.cc", "metrics/profile_import_metrics.h", "metrics/profile_token_quality_metrics.cc",
diff --git a/components/autofill/core/browser/address_data_manager.cc b/components/autofill/core/browser/address_data_manager.cc index 9f5d3da..492a1d20 100644 --- a/components/autofill/core/browser/address_data_manager.cc +++ b/components/autofill/core/browser/address_data_manager.cc
@@ -13,6 +13,7 @@ #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/geo/country_data.h" +#include "components/autofill/core/browser/metrics/profile_deduplication_metrics.h" #include "components/autofill/core/browser/metrics/profile_token_quality_metrics.h" #include "components/autofill/core/browser/metrics/stored_profile_metrics.h" #include "components/autofill/core/browser/webdata/addresses/contact_info_precondition_checker.h" @@ -530,6 +531,20 @@ return prefs::IsAutofillProfileEnabled(pref_service_); } +bool AddressDataManager::IsSyncFeatureEnabledForAutofill() const { + // TODO(crbug.com/40066949): Remove this method in favor of + // `IsUserSelectableTypeEnabled` once ConsentLevel::kSync and + // SyncService::IsSyncFeatureEnabled() are deleted from the codebase. + return sync_service_ != nullptr && sync_service_->IsSyncFeatureEnabled() && + IsAutofillUserSelectableTypeEnabled(); +} + +bool AddressDataManager::IsAutofillUserSelectableTypeEnabled() const { + return sync_service_ != nullptr && + sync_service_->GetUserSettings()->GetSelectedTypes().Has( + syncer::UserSelectableType::kAutofill); +} + void AddressDataManager::SetAutofillSelectableTypeEnabled(bool enabled) { if (sync_service_ != nullptr) { sync_service_->GetUserSettings()->SetSelectedType( @@ -730,6 +745,10 @@ const std::vector<AutofillProfile*> profiles = GetProfiles(); autofill_metrics::LogStoredProfileMetrics(profiles); autofill_metrics::LogStoredProfileTokenQualityMetrics(profiles); + if (base::FeatureList::IsEnabled( + features::kAutofillLogDeduplicationMetrics)) { + autofill_metrics::LogDeduplicationStartupMetrics(profiles, app_locale_); + } autofill_metrics::LogLocalProfileSupersetMetrics(std::move(profiles), app_locale_); }
diff --git a/components/autofill/core/browser/address_data_manager.h b/components/autofill/core/browser/address_data_manager.h index 94cddd8a..aabdc3471 100644 --- a/components/autofill/core/browser/address_data_manager.h +++ b/components/autofill/core/browser/address_data_manager.h
@@ -227,6 +227,15 @@ // Returns the value of the AutofillProfileEnabled pref. virtual bool IsAutofillProfileEnabled() const; + // Returns true if Sync-the-feature is enabled and + // UserSelectableType::kAutofill is among the user's selected data types. + // TODO(crbug.com/40066949): Remove this method once ConsentLevel::kSync and + // SyncService::IsSyncFeatureEnabled() are deleted from the codebase. + bool IsSyncFeatureEnabledForAutofill() const; + + // Returns true if `syncer::UserSelectableType::kAutofill` is enabled. + bool IsAutofillUserSelectableTypeEnabled() const; + // Sets the Sync UserSelectableType::kAutofill toggle value. // TODO(crbug.com/1502843): Used for the toggle on the Autofill Settings page // only. It controls syncing of autofill data stored in user accounts for
diff --git a/components/autofill/core/browser/form_forest.cc b/components/autofill/core/browser/form_forest.cc index 6ee2d671..ed88395d 100644 --- a/components/autofill/core/browser/form_forest.cc +++ b/components/autofill/core/browser/form_forest.cc
@@ -601,7 +601,7 @@ renderer_form->fields.push_back(browser_field); if (!IsSafeToFill(renderer_form->fields.back())) { - renderer_form->fields.back().value.clear(); + renderer_form->fields.back().value = u""; } else { result.safe_fields.insert(browser_field.global_id()); }
diff --git a/components/autofill/core/browser/form_forest_unittest.cc b/components/autofill/core/browser/form_forest_unittest.cc index bd15709d..96542bf9 100644 --- a/components/autofill/core/browser/form_forest_unittest.cc +++ b/components/autofill/core/browser/form_forest_unittest.cc
@@ -1544,10 +1544,10 @@ WithValues(GetMockedForm("child2"), Profile(2))}; // Clear sensitive fields: the credit card number (field index 2) and CVC // (field index 5) in the two main-origin forms. - expectation[0].fields[2].value.clear(); - expectation[0].fields[5].value.clear(); - expectation[1].fields[2].value.clear(); - expectation[1].fields[5].value.clear(); + expectation[0].fields[2].value = u""; + expectation[0].fields[5].value = u""; + expectation[1].fields[2].value = u""; + expectation[1].fields[5].value = u""; EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kIframeUrl), FieldTypeMap("main")), UnorderedArrayEquals(expectation));
diff --git a/components/autofill/core/browser/metrics/profile_deduplication_metrics.cc b/components/autofill/core/browser/metrics/profile_deduplication_metrics.cc new file mode 100644 index 0000000..aa154b8 --- /dev/null +++ b/components/autofill/core/browser/metrics/profile_deduplication_metrics.cc
@@ -0,0 +1,54 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/metrics/profile_deduplication_metrics.h" + +#include <algorithm> +#include <string> +#include <vector> + +#include "base/functional/bind.h" +#include "base/task/thread_pool.h" +#include "components/autofill/core/browser/address_data_cleaner.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/field_types.h" + +namespace autofill::autofill_metrics { + +namespace { + +void LogDeduplicationStartupMetricsForProfile( + const AutofillProfile& profile, + std::vector<FieldTypeSet> min_incompatible_sets) { + // TODO(b/325452461): Implement metrics. +} + +} // namespace + +void LogDeduplicationStartupMetrics( + const std::vector<AutofillProfile*>& profiles, + const std::string& app_locale) { + auto log_metrics = [](std::vector<AutofillProfile> profiles, + const std::string& app_locale) { + AutofillProfileComparator comparator(app_locale); + for (AutofillProfile& profile : profiles) { + LogDeduplicationStartupMetricsForProfile( + profile, AddressDataCleaner::CalculateMinimalIncompatibleTypeSets( + profile, profiles, comparator)); + } + }; + // Since computing the metrics is quadratic in `profiles.size()`, it is done + // on a background thread. Create a copy of the `profiles`, to avoid passing + // pointers between threads. + std::vector<AutofillProfile> profiles_copy; + for (const AutofillProfile* profile : profiles) { + profiles_copy.push_back(*profile); + } + base::ThreadPool::PostTask( + FROM_HERE, + base::BindOnce(log_metrics, std::move(profiles_copy), app_locale)); +} + +} // namespace autofill::autofill_metrics
diff --git a/components/autofill/core/browser/metrics/profile_deduplication_metrics.h b/components/autofill/core/browser/metrics/profile_deduplication_metrics.h new file mode 100644 index 0000000..e606861 --- /dev/null +++ b/components/autofill/core/browser/metrics/profile_deduplication_metrics.h
@@ -0,0 +1,23 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_PROFILE_DEDUPLICATION_METRICS_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_PROFILE_DEDUPLICATION_METRICS_H_ + +#include <string> +#include <vector> + +#include "components/autofill/core/browser/data_model/autofill_profile.h" + +namespace autofill::autofill_metrics { + +// Logs various metrics around quasi duplicates (= profiles that are duplicates +// except for a small number of types). +void LogDeduplicationStartupMetrics( + const std::vector<AutofillProfile*>& profiles, + const std::string& app_locale); + +} // namespace autofill::autofill_metrics + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_PROFILE_DEDUPLICATION_METRICS_H_
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 3076efd8..f526526 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -444,20 +444,6 @@ return experiment_country_code_; } -bool PersonalDataManager::IsSyncFeatureEnabledForAutofill() const { - // TODO(crbug.com/40066949): Remove this method in favor of - // `IsUserSelectableTypeEnabled` once ConsentLevel::kSync and - // SyncService::IsSyncFeatureEnabled() are deleted from the codebase. - return sync_service_ != nullptr && sync_service_->IsSyncFeatureEnabled() && - IsUserSelectableTypeEnabled(syncer::UserSelectableType::kAutofill); -} - -bool PersonalDataManager::IsUserSelectableTypeEnabled( - syncer::UserSelectableType type) const { - return sync_service_ != nullptr && - sync_service_->GetUserSettings()->GetSelectedTypes().Has(type); -} - void PersonalDataManager::SetPaymentMethodsMandatoryReauthEnabled( bool enabled) { payments_data_manager_->SetPaymentMethodsMandatoryReauthEnabled(enabled);
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index dc1efc0..72fa955 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -413,15 +413,6 @@ // database by adding, updating and removing credit cards. void SetCreditCards(std::vector<CreditCard>* credit_cards); - // Returns true if Sync-the-feature is enabled and - // UserSelectableType::kAutofill is among the user's selected data types. - // TODO(crbug.com/40066949): Remove this method once ConsentLevel::kSync and - // SyncService::IsSyncFeatureEnabled() are deleted from the codebase. - bool IsSyncFeatureEnabledForAutofill() const; - - // Returns true if the user's selectable `type` is enabled. - bool IsUserSelectableTypeEnabled(syncer::UserSelectableType type) const; - // TODO(b/322170538): Deprecated. Use the functions in // `payments_data_manager()` instead. Some callers on iOS still rely on this. void SetPaymentMethodsMandatoryReauthEnabled(bool enabled);
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 7db12ea..f4028d6 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -678,6 +678,13 @@ kAutofillEnableCacheForRegexMatchingCacheSizeParam{ &kAutofillEnableCacheForRegexMatching, "cache_size", 300}; +// When enabled, various deduplication related metrics are logged on startup +// and on import. +// TODO(b/325452461): Remove once rolled out. +BASE_FEATURE(kAutofillLogDeduplicationMetrics, + "AutofillLogDeduplicationMetrics", + base::FEATURE_DISABLED_BY_DEFAULT); + #if BUILDFLAG(IS_ANDROID) // Controls the whether the Chrome may provide a virtual view structure for // Android Autofill.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 66ac142..27eb8bc 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -220,6 +220,8 @@ COMPONENT_EXPORT(AUTOFILL) extern const base::FeatureParam<int> kAutofillEnableCacheForRegexMatchingCacheSizeParam; +COMPONENT_EXPORT(AUTOFILL) +BASE_DECLARE_FEATURE(kAutofillLogDeduplicationMetrics); #if BUILDFLAG(IS_ANDROID) COMPONENT_EXPORT(AUTOFILL)
diff --git a/components/autofill/core/common/autofill_test_utils.cc b/components/autofill/core/common/autofill_test_utils.cc index 7bf087e..facfe8d 100644 --- a/components/autofill/core/common/autofill_test_utils.cc +++ b/components/autofill/core/common/autofill_test_utils.cc
@@ -106,7 +106,7 @@ FormData WithoutValues(FormData form) { for (FormFieldData& field : form.fields) { - field.value.clear(); + field.value = u""; } return form; }
diff --git a/components/autofill/core/common/form_field_data.cc b/components/autofill/core/common/form_field_data.cc index aaa8ff4f..41fb278 100644 --- a/components/autofill/core/common/form_field_data.cc +++ b/components/autofill/core/common/form_field_data.cc
@@ -94,14 +94,16 @@ bool DeserializeSection1(base::PickleIterator* iter, FormFieldData* field_data) { std::string form_control_type; + std::u16string value; bool success = iter->ReadString16(&field_data->label) && iter->ReadString16(&field_data->name) && - iter->ReadString16(&field_data->value) && + iter->ReadString16(&value) && iter->ReadString(&form_control_type) && iter->ReadString(&field_data->autocomplete_attribute) && iter->ReadUInt64(&field_data->max_length) && iter->ReadBool(&field_data->is_autofilled); if (success) { + field_data->value = std::move(value); // Form control types are serialized as strings for legacy reasons. // TODO(crbug.com/1353392,crbug.com/1482526): Why does the Password Manager // (de)serialize form control types? Remove it or migrate it to the enum
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 4c3156f..5358defd 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
@@ -175,8 +175,11 @@ return false; if (!data.ReadNameAttribute(&out->name_attribute)) return false; - if (!data.ReadValue(&out->value)) + std::u16string value; + if (!data.ReadValue(&value)) { return false; + } + out->value = std::move(value); if (!data.ReadSelectedText(&out->selected_text)) { return false; }
diff --git a/components/gwp_asan/client/sampling_helpers.cc b/components/gwp_asan/client/sampling_helpers.cc index 84afb30..3c19e55d 100644 --- a/components/gwp_asan/client/sampling_helpers.cc +++ b/components/gwp_asan/client/sampling_helpers.cc
@@ -67,6 +67,9 @@ return base::DoNothing(); } + // N.B. we call `FactoryGet()` here to avoid doing it inside the + // callback body, which could result in re-entrancy issues. + // See https://crbug.com/331729344 for details. const std::string histogram_name = base::StrCat({"Security.GwpAsan.AllocatorOom.", allocator_name, ".", process_str.value()});
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc index e8de949..ab9f085 100644 --- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc +++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -293,9 +293,6 @@ WebFeature::kTopicsAPI_BrowsingTopics_Method, WebFeature::kHTMLFencedFrameElement, WebFeature::kAuthorizationCrossOrigin, - WebFeature::kServiceWorkerBypassFetchHandlerForMainResource, - WebFeature:: - kServiceWorkerBypassFetchHandlerForMainResourceByOriginTrial, WebFeature::kCascadedCSSZoomNotEqualToOne, WebFeature::kV8Window_QueryLocalFonts_Method, WebFeature::kHiddenUntilFoundAttribute,
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index dfa79bcb..91723f6 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -81,6 +81,7 @@ "password_check_referrer_android.h", "password_counter.cc", "password_counter.h", + "password_cross_domain_confirmation_popup_controller.h", "password_feature_manager.h", "password_feature_manager_impl.cc", "password_feature_manager_impl.h",
diff --git a/components/password_manager/core/browser/features/password_features.cc b/components/password_manager/core/browser/features/password_features.cc index 9b6466c..0a07525 100644 --- a/components/password_manager/core/browser/features/password_features.cc +++ b/components/password_manager/core/browser/features/password_features.cc
@@ -168,10 +168,6 @@ "UsernameFirstFlowFallbackCrowdsourcing", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kUsernameFirstFlowHonorAutocomplete, - "UsernameFirstFlowHonorAutocomplete", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kUsernameFirstFlowStoreSeveralValues, "UsernameFirstFlowStoreSeveralValues", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/password_manager/core/browser/features/password_features.h b/components/password_manager/core/browser/features/password_features.h index 3c44058c..696ce75 100644 --- a/components/password_manager/core/browser/features/password_features.h +++ b/components/password_manager/core/browser/features/password_features.h
@@ -154,10 +154,6 @@ // we don't need additional signals. BASE_DECLARE_FEATURE(kUsernameFirstFlowFallbackCrowdsourcing); -// Enables suggesting username in the save/update prompt in the case of -// autocomplete="username". -BASE_DECLARE_FEATURE(kUsernameFirstFlowHonorAutocomplete); - // Enables storing more possible username values in the LRU cache. Part of the // `kUsernameFirstFlowWithIntermediateValues` feature. BASE_DECLARE_FEATURE(kUsernameFirstFlowStoreSeveralValues);
diff --git a/components/password_manager/core/browser/form_saver_impl.cc b/components/password_manager/core/browser/form_saver_impl.cc index 5b3e96f..732712b 100644 --- a/components/password_manager/core/browser/form_saver_impl.cc +++ b/components/password_manager/core/browser/form_saver_impl.cc
@@ -30,7 +30,7 @@ form->main_frame_origin = url::Origin(); for (FormFieldData& field : form->fields) { field.label.clear(); - field.value.clear(); + field.value = u""; field.autocomplete_attribute.clear(); field.options.clear(); field.placeholder.clear();
diff --git a/components/password_manager/core/browser/password_cross_domain_confirmation_popup_controller.h b/components/password_manager/core/browser/password_cross_domain_confirmation_popup_controller.h new file mode 100644 index 0000000..ca0d22b --- /dev/null +++ b/components/password_manager/core/browser/password_cross_domain_confirmation_popup_controller.h
@@ -0,0 +1,40 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_H_ + +#include "base/functional/callback_forward.h" +#include "base/i18n/rtl.h" +#include "components/autofill/core/browser/ui/popup_hiding_reasons.h" +#include "ui/gfx/geometry/rect_f.h" +#include "url/gurl.h" + +namespace password_manager { + +// The controller of the cross domain usage confirmation popup. It provides API +// to Show/Hide the popup and get the user's decision (via a callback). +class PasswordCrossDomainConfirmationPopupController { + public: + virtual ~PasswordCrossDomainConfirmationPopupController() = default; + + virtual void Hide(autofill::PopupHidingReason reason) = 0; + + // Creates and shows a popup pointing to `element_bounds` and presenting + // a message regarding cross domain password usage. `domain` is the domain + // of the current web site the popup is triggered on. `password_domain` is + // the domain of the web site the password was originally stored on. + // `confirmation_callback` is called if the user confirms the action, if + // the user cancels it, the popup is silently hidden. + // If the popup is already shown, it gets hidden and a new one shows up. + virtual void Show(const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) = 0; +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_CROSS_DOMAIN_CONFIRMATION_POPUP_CONTROLLER_H_
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 415c2e81..9601cb5e 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -186,9 +186,7 @@ PasswordFormHadMatchingUsername(true)}; } if (candidate_username.autocomplete_attribute_has_username && - !candidate_username.HasServerPrediction() && - base::FeatureList::IsEnabled( - password_manager::features::kUsernameFirstFlowHonorAutocomplete)) { + !candidate_username.HasServerPrediction()) { return {UsernameFoundOutsideOfFormType::kUsernameAutocomplete, PasswordFormHadMatchingUsername(false)}; }
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 22664e7..2400510a 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -2006,7 +2006,8 @@ CreateFormManager(observed_form_); form_manager_->PresaveGeneratedPassword(submitted_form.form_data, submitted_form.password_value); - form_data.fields[kPasswordFieldIndex].value += u"1"; + form_data.fields[kPasswordFieldIndex].value = + form_data.fields[kPasswordFieldIndex].value + u"1"; submitted_form.password_value = form_data.fields[kPasswordFieldIndex].value; form_manager_->PresaveGeneratedPassword(submitted_form.form_data, submitted_form.password_value); @@ -2021,7 +2022,8 @@ CreateFormManager(observed_form_); form_manager_->PresaveGeneratedPassword(submitted_form.form_data, submitted_form.password_value); - form_data.fields[kPasswordFieldIndex].value += u"2"; + form_data.fields[kPasswordFieldIndex].value = + form_data.fields[kPasswordFieldIndex].value + u"2"; submitted_form.password_value = form_data.fields[kPasswordFieldIndex].value; form_manager_->PresaveGeneratedPassword(submitted_form.form_data, submitted_form.password_value); @@ -3596,9 +3598,6 @@ // Tests that boolean representing autocomplete = "username" is taken into // consideration when offering username in prompt in username first flow. TEST_P(PasswordFormManagerTest, PossibleUsernameFromAutocomplete) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kUsernameFirstFlowHonorAutocomplete); // A single password form is loaded on the page. FormData submitted_form = observed_form_only_password_fields_;
diff --git a/components/password_manager/core/browser/password_manager_client.h b/components/password_manager/core/browser/password_manager_client.h index ce3cb5f..eb6e84b 100644 --- a/components/password_manager/core/browser/password_manager_client.h +++ b/components/password_manager/core/browser/password_manager_client.h
@@ -29,6 +29,14 @@ #include "components/sync/service/sync_service.h" #include "net/cert/cert_status_flags.h" +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || \ + BUILDFLAG(IS_CHROMEOS) +#include "base/i18n/rtl.h" +#include "components/password_manager/core/browser/password_cross_domain_confirmation_popup_controller.h" +#include "ui/gfx/geometry/rect_f.h" +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || + // BUILDFLAG(IS_CHROMEOS) + class PrefService; namespace affiliations { @@ -494,6 +502,18 @@ // Refreshes password manager settings stored in prefs. virtual void RefreshPasswordManagerSettingsIfNeeded() const; + +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || \ + BUILDFLAG(IS_CHROMEOS) + // Creates and show the cross domain confirmation popup. + virtual std::unique_ptr<PasswordCrossDomainConfirmationPopupController> + ShowCrossDomainConfirmationPopup(const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) = 0; +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || + // BUILDFLAG(IS_CHROMEOS) }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index af5a431d..5b10439 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -317,7 +317,7 @@ form->main_frame_origin = url::Origin(); for (FormFieldData& field : form->fields) { field.label.clear(); - field.value.clear(); + field.value = u""; field.autocomplete_attribute.clear(); field.options.clear(); field.placeholder.clear(); @@ -1340,7 +1340,7 @@ // The user deletes the password, no manuall fallback should be shown. PasswordForm empty_password_form(form); empty_password_form.password_value.clear(); - empty_password_form.form_data.fields[1].value.clear(); + empty_password_form.form_data.fields[1].value = u""; EXPECT_CALL(client_, ShowManualFallbackForSaving).Times(0); EXPECT_CALL(client_, HideManualFallbackForSaving); manager()->OnInformAboutUserInput(&driver_, empty_password_form.form_data); @@ -2886,7 +2886,7 @@ PasswordForm form(MakeFormWithOnlyNewPasswordField()); form.username_element.clear(); form.username_value.clear(); - form.form_data.fields[0].value.clear(); + form.form_data.fields[0].value = u""; std::vector<FormData> observed = {form.form_data}; // Emulate page load. @@ -2899,7 +2899,7 @@ OnPasswordFormSubmitted(form.form_data); // JavaScript cleared field values. - observed[0].fields[1].value.clear(); + observed[0].fields[1].value = u""; // Check success of the submission. std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; @@ -2919,7 +2919,7 @@ std::vector<FormData> observed; FormData form_data(MakeSimpleGAIAFormData()); // Simulate that no username is found. - form_data.fields[0].value.clear(); + form_data.fields[0].value = u""; observed.push_back(form_data); manager()->OnPasswordFormsRendered(&driver_, observed); @@ -4655,8 +4655,7 @@ feature_list.InitWithFeatures( /*enabled_features=*/ {password_manager::features::kUsernameFirstFlowStoreSeveralValues, - password_manager::features::kUsernameFirstFlowWithIntermediateValues, - password_manager::features::kUsernameFirstFlowHonorAutocomplete}, + password_manager::features::kUsernameFirstFlowWithIntermediateValues}, /*disabled_features_*/ {}); // Simulate the user typed a previously not saved username in the username // form. @@ -5282,9 +5281,9 @@ manager()->OnInformAboutUserInput(&driver_, form_data); - form_data.fields[0].value.clear(); + form_data.fields[0].value = u""; if (new_password_field_was_cleared) - form_data.fields[1].value.clear(); + form_data.fields[1].value = u""; std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; if (new_password_field_was_cleared) {
diff --git a/components/password_manager/core/browser/stub_password_manager_client.cc b/components/password_manager/core/browser/stub_password_manager_client.cc index 1c6a6b91..29b1612 100644 --- a/components/password_manager/core/browser/stub_password_manager_client.cc +++ b/components/password_manager/core/browser/stub_password_manager_client.cc
@@ -174,4 +174,19 @@ return version_info::Channel::UNKNOWN; } +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || \ + BUILDFLAG(IS_CHROMEOS) +std::unique_ptr< + password_manager::PasswordCrossDomainConfirmationPopupController> +StubPasswordManagerClient::ShowCrossDomainConfirmationPopup( + const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) { + return nullptr; +} +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || + // BUILDFLAG(IS_CHROMEOS) + } // namespace password_manager
diff --git a/components/password_manager/core/browser/stub_password_manager_client.h b/components/password_manager/core/browser/stub_password_manager_client.h index 6562080..6b4acb90 100644 --- a/components/password_manager/core/browser/stub_password_manager_client.h +++ b/components/password_manager/core/browser/stub_password_manager_client.h
@@ -73,6 +73,18 @@ const MockPasswordFeatureManager* GetPasswordFeatureManager() const override; MockPasswordFeatureManager* GetPasswordFeatureManager(); version_info::Channel GetChannel() const override; +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || \ + BUILDFLAG(IS_CHROMEOS) + std::unique_ptr< + password_manager::PasswordCrossDomainConfirmationPopupController> + ShowCrossDomainConfirmationPopup( + const gfx::RectF& element_bounds, + base::i18n::TextDirection text_direction, + const GURL& domain, + const std::u16string& password_origin, + base::OnceClosure confirmation_callback) override; +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || + // BUILDFLAG(IS_CHROMEOS) safe_browsing::PasswordProtectionService* GetPasswordProtectionService() const override;
diff --git a/components/plus_addresses/webdata/plus_address_table.cc b/components/plus_addresses/webdata/plus_address_table.cc index 61579e7..a5f8be46 100644 --- a/components/plus_addresses/webdata/plus_address_table.cc +++ b/components/plus_addresses/webdata/plus_address_table.cc
@@ -4,6 +4,7 @@ #include "components/plus_addresses/webdata/plus_address_table.h" +#include <optional> #include <vector> #include "base/check_op.h" @@ -139,6 +140,24 @@ return result; } +std::optional<PlusProfile> PlusAddressTable::GetPlusProfileForId( + const std::string& profile_id) const { + sql::Statement query(db_->GetUniqueStatement( + base::StringPrintf("SELECT %s, %s, %s FROM %s WHERE %s=?", kProfileId, + kFacet, kPlusAddress, kPlusAddressTable, kProfileId) + .c_str())); + query.BindString(0, profile_id); + if (!query.Step()) { + return std::nullopt; + } + return PlusProfile{ + .profile_id = query.ColumnString(0), + .facet = query.ColumnString(1), + .plus_address = query.ColumnString(2), + .is_confirmed = true, + }; +} + bool PlusAddressTable::AddOrUpdatePlusProfile(const PlusProfile& profile) { CHECK(profile.is_confirmed); sql::Statement query(db_->GetUniqueStatement(
diff --git a/components/plus_addresses/webdata/plus_address_table.h b/components/plus_addresses/webdata/plus_address_table.h index 44792ea..2ddb00e 100644 --- a/components/plus_addresses/webdata/plus_address_table.h +++ b/components/plus_addresses/webdata/plus_address_table.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_PLUS_ADDRESSES_WEBDATA_PLUS_ADDRESS_TABLE_H_ #define COMPONENTS_PLUS_ADDRESSES_WEBDATA_PLUS_ADDRESS_TABLE_H_ +#include <optional> #include <vector> #include "components/plus_addresses/plus_address_types.h" @@ -58,6 +59,11 @@ // Returns all stored PlusProfiles - or an empty vector if reading fails. std::vector<PlusProfile> GetPlusProfiles() const; + // Returns the profile with the given `profile_id` or std::nullopt if it + // doesn't exist. + std::optional<PlusProfile> GetPlusProfileForId( + const std::string& profile_id) const; + // Adds `profile` to the database, if a profile with the same `profile_id` // doesn't already exist. Otherwise, updates the existing `profile`. // Returns true if the operation succeeded.
diff --git a/components/plus_addresses/webdata/plus_address_table_unittest.cc b/components/plus_addresses/webdata/plus_address_table_unittest.cc index 1d6a95c..eaf73e7e 100644 --- a/components/plus_addresses/webdata/plus_address_table_unittest.cc +++ b/components/plus_addresses/webdata/plus_address_table_unittest.cc
@@ -4,6 +4,8 @@ #include "components/plus_addresses/webdata/plus_address_table.h" +#include <optional> + #include "base/files/scoped_temp_dir.h" #include "components/plus_addresses/plus_address_test_utils.h" #include "components/plus_addresses/plus_address_types.h" @@ -49,6 +51,16 @@ testing::UnorderedElementsAre(profile1, profile2)); } +TEST_F(PlusAddressTableTest, GetPlusProfileForId) { + const PlusProfile profile1 = test::CreatePlusProfile(); + const PlusProfile profile2 = test::CreatePlusProfile2(); + ASSERT_TRUE(table_.AddOrUpdatePlusProfile(profile1)); + ASSERT_TRUE(table_.AddOrUpdatePlusProfile(profile2)); + EXPECT_EQ(table_.GetPlusProfileForId(profile1.profile_id), profile1); + EXPECT_EQ(table_.GetPlusProfileForId(profile2.profile_id), profile2); + EXPECT_EQ(table_.GetPlusProfileForId("invalid_id"), std::nullopt); +} + TEST_F(PlusAddressTableTest, AddOrUpdatePlusProfile) { PlusProfile profile1 = test::CreatePlusProfile(); PlusProfile profile2 = test::CreatePlusProfile2();
diff --git a/components/signin/public/identity_manager/account_info.cc b/components/signin/public/identity_manager/account_info.cc index 9532067..6b89fe7 100644 --- a/components/signin/public/identity_manager/account_info.cc +++ b/components/signin/public/identity_manager/account_info.cc
@@ -183,7 +183,7 @@ base::android::ScopedJavaLocalRef<jobject> ConvertToJavaCoreAccountInfo( JNIEnv* env, const CoreAccountInfo& account_info) { - DCHECK(!account_info.IsEmpty()); + CHECK(!account_info.IsEmpty()); return signin::Java_CoreAccountInfo_Constructor( env, ConvertToJavaCoreAccountId(env, account_info.account_id), base::android::ConvertUTF8ToJavaString(env, account_info.email), @@ -193,7 +193,7 @@ base::android::ScopedJavaLocalRef<jobject> ConvertToJavaAccountInfo( JNIEnv* env, const AccountInfo& account_info) { - DCHECK(!account_info.IsEmpty()); + CHECK(!account_info.IsEmpty()); gfx::Image avatar_image = account_info.account_image; return signin::Java_AccountInfo_Constructor( env, ConvertToJavaCoreAccountId(env, account_info.account_id), @@ -210,7 +210,7 @@ base::android::ScopedJavaLocalRef<jobject> ConvertToJavaCoreAccountId( JNIEnv* env, const CoreAccountId& account_id) { - DCHECK(!account_id.empty()); + CHECK(!account_id.empty()); return signin::Java_CoreAccountId_Constructor( env, base::android::ConvertUTF8ToJavaString(env, account_id.ToString())); } @@ -218,7 +218,7 @@ CoreAccountInfo ConvertFromJavaCoreAccountInfo( JNIEnv* env, const base::android::JavaRef<jobject>& j_core_account_info) { - DCHECK(j_core_account_info); + CHECK(j_core_account_info); CoreAccountInfo account; account.account_id = ConvertFromJavaCoreAccountId( env, signin::Java_CoreAccountInfo_getId(env, j_core_account_info)); @@ -232,7 +232,7 @@ CoreAccountId ConvertFromJavaCoreAccountId( JNIEnv* env, const base::android::JavaRef<jobject>& j_core_account_id) { - DCHECK(j_core_account_id); + CHECK(j_core_account_id); CoreAccountId id = CoreAccountId::FromString(base::android::ConvertJavaStringToUTF8( signin::Java_CoreAccountId_getId(env, j_core_account_id)));
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc index 720c774..4eedefa 100644 --- a/components/sync/base/features.cc +++ b/components/sync/base/features.cc
@@ -211,7 +211,7 @@ #if BUILDFLAG(IS_ANDROID) BASE_FEATURE(kSyncShowIdentityErrorsForSignedInUsers, "SyncShowIdentityErrorsForSignedInUsers", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_ANDROID) BASE_FEATURE(kSyncRememberCustomPassphraseAfterSignout,
diff --git a/components/web_package/DEPS b/components/web_package/DEPS index 682d8ff..e2e6e32 100644 --- a/components/web_package/DEPS +++ b/components/web_package/DEPS
@@ -10,7 +10,7 @@ "web_bundle_parser_fuzzer\.cc": [ "+mojo/core/embedder/embedder.h", ], - "(web_bundle_signer|signed_web_bundle_signature_verifier).cc": [ + "(web_bundle_signer|signed_web_bundle_signature_verifier|signed_web_bundle_id).cc": [ "+crypto", ], "(integrity_block_parser|ed25519_public_key|ed25519_signature|web_bundle_parser_unittest|web_bundle_signer|signed_web_bundle_signature_verifier)\.cc": [
diff --git a/components/web_package/signed_web_bundles/signed_web_bundle_id.cc b/components/web_package/signed_web_bundles/signed_web_bundle_id.cc index 7d1dada8..a157689 100644 --- a/components/web_package/signed_web_bundles/signed_web_bundle_id.cc +++ b/components/web_package/signed_web_bundles/signed_web_bundle_id.cc
@@ -8,13 +8,13 @@ #include "base/containers/span.h" #include "base/functional/bind.h" -#include "base/rand_util.h" #include "base/ranges/algorithm.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/types/expected.h" #include "components/base32/base32.h" +#include "crypto/random.h" namespace web_package { @@ -48,12 +48,10 @@ auto decoded_span = base::make_span(decoded_id); auto type_suffix = decoded_span.last<kTypeSuffixLength>(); if (base::ranges::equal(type_suffix, kTypeDevelopment)) { - return SignedWebBundleId(Type::kDevelopment, encoded_id, - decoded_span.first<kDecodedIdLength>()); + return SignedWebBundleId(Type::kDevelopment, encoded_id); } if (base::ranges::equal(type_suffix, kTypeEd25519PublicKey)) { - return SignedWebBundleId(Type::kEd25519PublicKey, encoded_id, - decoded_span.first<kDecodedIdLength>()); + return SignedWebBundleId(Type::kEd25519PublicKey, encoded_id); } return base::unexpected("The signed web bundle ID has an unknown type."); } @@ -69,7 +67,7 @@ auto encoded_id_uppercase = base32::Base32Encode( decoded_id, base32::Base32EncodePolicy::OMIT_PADDING); auto encoded_id = base::ToLowerASCII(encoded_id_uppercase); - return SignedWebBundleId(Type::kEd25519PublicKey, encoded_id, decoded_id); + return SignedWebBundleId(Type::kEd25519PublicKey, encoded_id); } // static @@ -82,24 +80,18 @@ auto encoded_id_uppercase = base32::Base32Encode( decoded_id, base32::Base32EncodePolicy::OMIT_PADDING); auto encoded_id = base::ToLowerASCII(encoded_id_uppercase); - return SignedWebBundleId(Type::kDevelopment, encoded_id, decoded_id); + return SignedWebBundleId(Type::kDevelopment, encoded_id); } // static -SignedWebBundleId SignedWebBundleId::CreateRandomForDevelopment( - base::RepeatingCallback<void(base::span<uint8_t>)> random_generator) { +SignedWebBundleId SignedWebBundleId::CreateRandomForDevelopment() { std::array<uint8_t, kDecodedIdLength - kTypeSuffixLength> random_bytes; - random_generator.Run(random_bytes); + crypto::RandBytes(random_bytes); return CreateForDevelopment(random_bytes); } -SignedWebBundleId::SignedWebBundleId( - Type type, - base::StringPiece encoded_id, - base::span<const uint8_t, kDecodedIdLength> decoded_id) - : type_(type), encoded_id_(encoded_id) { - base::ranges::copy(decoded_id, decoded_id_.begin()); -} +SignedWebBundleId::SignedWebBundleId(Type type, base::StringPiece encoded_id) + : type_(type), encoded_id_(encoded_id) {} SignedWebBundleId::SignedWebBundleId(const SignedWebBundleId& other) = default; SignedWebBundleId& SignedWebBundleId::operator=( @@ -111,13 +103,4 @@ return os << id.id(); } -// static -base::RepeatingCallback<void(base::span<uint8_t>)> -SignedWebBundleId::GetDefaultRandomGenerator() { - // TODO(crbug.com/1490484): Remove the static_cast once all callers of - // base::RandBytes are migrated to the span variant. - return base::BindRepeating( - static_cast<void (*)(base::span<uint8_t>)>(&base::RandBytes)); -} - } // namespace web_package
diff --git a/components/web_package/signed_web_bundles/signed_web_bundle_id.h b/components/web_package/signed_web_bundles/signed_web_bundle_id.h index 418a1b10..f311585 100644 --- a/components/web_package/signed_web_bundles/signed_web_bundle_id.h +++ b/components/web_package/signed_web_bundles/signed_web_bundle_id.h
@@ -57,9 +57,7 @@ static SignedWebBundleId CreateForDevelopment( base::span<const uint8_t, kDecodedIdLength - kTypeSuffixLength> data); - static SignedWebBundleId CreateRandomForDevelopment( - base::RepeatingCallback<void(base::span<uint8_t>)> random_generator = - GetDefaultRandomGenerator()); + static SignedWebBundleId CreateRandomForDevelopment(); SignedWebBundleId(const SignedWebBundleId& other); SignedWebBundleId& operator=(const SignedWebBundleId& other); @@ -70,32 +68,16 @@ const std::string& id() const { return encoded_id_; } - bool operator<(const SignedWebBundleId& other) const { - return decoded_id_ < other.decoded_id_; - } - - bool operator==(const SignedWebBundleId& other) const { - return decoded_id_ == other.decoded_id_; - } - - bool operator!=(const SignedWebBundleId& other) const { - return !(*this == other); - } + auto operator<=>(const SignedWebBundleId&) const = default; friend std::ostream& operator<<(std::ostream& os, const SignedWebBundleId& id); private: - SignedWebBundleId(Type type, - base::StringPiece encoded_id, - base::span<const uint8_t, kDecodedIdLength> decoded_id); + SignedWebBundleId(Type type, base::StringPiece encoded_id); Type type_; std::string encoded_id_; - std::array<uint8_t, kDecodedIdLength> decoded_id_; - - static base::RepeatingCallback<void(base::span<uint8_t>)> - GetDefaultRandomGenerator(); }; } // namespace web_package
diff --git a/components/web_package/signed_web_bundles/signed_web_bundle_id_unittest.cc b/components/web_package/signed_web_bundles/signed_web_bundle_id_unittest.cc index 7924e0d7..a1fc419e 100644 --- a/components/web_package/signed_web_bundles/signed_web_bundle_id_unittest.cc +++ b/components/web_package/signed_web_bundles/signed_web_bundle_id_unittest.cc
@@ -146,23 +146,9 @@ EXPECT_EQ(id.id(), kDevelopmentSignedWebBundleId); } -TEST(SignedWebBundleIdTest, CreateRandomForDevelopmentDefaultGenerator) { +TEST(SignedWebBundleIdTest, CreateRandomForDevelopment) { auto id = SignedWebBundleId::CreateRandomForDevelopment(); EXPECT_EQ(id.type(), SignedWebBundleId::Type::kDevelopment); } -TEST(SignedWebBundleIdTest, CreateRandomForDevelopmentCustomGenerator) { - auto custom_callback = - base::BindLambdaForTesting([](base::span<uint8_t> buffer) -> void { - DCHECK_EQ(buffer.size(), kDevelopmentBytes.size()); - base::ranges::copy(kDevelopmentBytes, buffer.begin()); - }); - - SignedWebBundleId id = - SignedWebBundleId::CreateRandomForDevelopment(custom_callback); - - EXPECT_EQ(id.type(), SignedWebBundleId::Type::kDevelopment); - EXPECT_EQ(id.id(), kDevelopmentSignedWebBundleId); -} - } // namespace web_package
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc index 391e7ce8..faa4e5c 100644 --- a/content/app/content_main_runner_impl.cc +++ b/content/app/content_main_runner_impl.cc
@@ -10,6 +10,7 @@ #include <memory> #include <string> +#include <string_view> #include <tuple> #include <utility> #include <vector> @@ -521,7 +522,7 @@ void CreateChildThreadPool(const std::string& process_type) { // Thread pool should only be initialized once. DCHECK(!base::ThreadPoolInstance::Get()); - base::StringPiece thread_pool_name; + std::string_view thread_pool_name; if (process_type == switches::kGpuProcess) thread_pool_name = "GPU"; else if (process_type == switches::kRendererProcess)
diff --git a/content/app/content_main_runner_impl_browsertest.cc b/content/app/content_main_runner_impl_browsertest.cc index 7db2ca05..75b3797 100644 --- a/content/app/content_main_runner_impl_browsertest.cc +++ b/content/app/content_main_runner_impl_browsertest.cc
@@ -9,7 +9,6 @@ #include "base/command_line.h" #include "base/feature_list.h" #include "base/functional/overloaded.h" -#include "base/strings/string_piece.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "build/build_config.h" #include "content/public/app/content_main_delegate.h"
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc index db788fd..83ec1d82 100644 --- a/content/browser/accessibility/browser_accessibility_state_impl.cc +++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -144,7 +144,7 @@ const int ModeCollectionForTarget::kUserDataKey; // Returns a subset of `mode` for delivery to a WebContents. -ui::AXMode FilterAccessibilityMode(ui::AXMode mode) { +ui::AXMode FilterAccessibilityModeInvariants(ui::AXMode mode) { // Strip kLabelImages if kScreenReader is absent. // TODO(grt): kLabelImages is a feature of //chrome. Find a way to // achieve this filtering without teaching //content about it. Perhaps via @@ -435,8 +435,9 @@ ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityModeForBrowserContext( BrowserContext* browser_context) { - return GetAccessibilityMode() | - ModeCollectionForTarget::GetAccessibilityMode(browser_context); + return FilterAccessibilityModeInvariants( + GetAccessibilityMode() | + ModeCollectionForTarget::GetAccessibilityMode(browser_context)); } void BrowserAccessibilityStateImpl::OnUserInputEvent() { @@ -607,7 +608,7 @@ WebContentsImpl::GetAllWebContents(), [new_mode](WebContentsImpl* web_contents) { if (!web_contents->IsBeingDestroyed()) { - web_contents->SetAccessibilityMode(FilterAccessibilityMode( + web_contents->SetAccessibilityMode(FilterAccessibilityModeInvariants( new_mode | ModeCollectionForTarget::GetAccessibilityMode( web_contents->GetBrowserContext()) | @@ -657,7 +658,7 @@ [browser_context, mode_for_context](WebContentsImpl* web_contents) { if (!web_contents->IsBeingDestroyed() && web_contents->GetBrowserContext() == browser_context) { - web_contents->SetAccessibilityMode(FilterAccessibilityMode( + web_contents->SetAccessibilityMode(FilterAccessibilityModeInvariants( mode_for_context | ModeCollectionForTarget::GetAccessibilityMode(web_contents))); } @@ -684,11 +685,11 @@ // Combine the effective modes for the process, `web_contents`'s // BrowserContext, and for `web_contents. static_cast<WebContentsImpl*>(web_contents) - ->SetAccessibilityMode( - FilterAccessibilityMode(GetAccessibilityMode() | - ModeCollectionForTarget::GetAccessibilityMode( - web_contents->GetBrowserContext()) | - new_mode)); + ->SetAccessibilityMode(FilterAccessibilityModeInvariants( + GetAccessibilityMode() | + ModeCollectionForTarget::GetAccessibilityMode( + web_contents->GetBrowserContext()) | + new_mode)); } void BrowserAccessibilityStateImpl::CallInitBackgroundTasksForTesting(
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index e2559d5..6321af8 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -517,7 +517,8 @@ url_loader_factory::ContentClientParams( browser_context_, frame_tree_node->current_frame_host(), frame_tree_node->current_frame_host()->GetProcess()->GetID(), - url::Origin(), ukm::SourceIdObj::FromInt64(ukm_source_id_), + resource_request_->request_initiator.value_or(url::Origin()), + ukm::SourceIdObj::FromInt64(ukm_source_id_), /*bypass_redirect_checks=*/nullptr, frame_tree_node->navigation_request()->GetNavigationId(), GetUIThreadTaskRunner(
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index f2ab588..1ecee562 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -4936,319 +4936,6 @@ #endif // !BUILDFLAG(IS_ANDROID) -class ServiceWorkerBypassFetchHandlerTest - : public ServiceWorkerBrowserTest, - public testing::WithParamInterface< - std::tuple<bool, - bool, - features::ServiceWorkerBypassFetchHandlerTarget>> { - public: - ServiceWorkerBypassFetchHandlerTest() { - feature_list_.InitWithFeaturesAndParameters( - {{features::kServiceWorkerBypassFetchHandler, - {{"strategy", ShouldUseAllowListStrategy() ? "allowlist" : "optin"}, - {"bypass_for", BypassFetchHandlerTargetStr()}}}, - {features::kServiceWorkerBypassFetchHandlerHashStrings, - {{"script_checksum_to_bypass", - ShouldUseValidChecksum() ? kValidChecksum : kInvalidChecksum}}}}, - {}); - } - ~ServiceWorkerBypassFetchHandlerTest() override = default; - - WebContents* web_contents() const { return shell()->web_contents(); } - - RenderFrameHost* GetPrimaryMainFrame() { - return web_contents()->GetPrimaryMainFrame(); - } - - protected: - bool ShouldUseValidChecksum() { return std::get<0>(GetParam()); } - bool ShouldUseAllowListStrategy() { return std::get<1>(GetParam()); } - features::ServiceWorkerBypassFetchHandlerTarget BypassFetchHandlerTarget() { - return std::get<2>(GetParam()); - } - std::string BypassFetchHandlerTargetStr() { - switch (BypassFetchHandlerTarget()) { - case features::ServiceWorkerBypassFetchHandlerTarget::kMainResource: - return "main_resource"; - case features::ServiceWorkerBypassFetchHandlerTarget:: - kAllOnlyIfServiceWorkerNotStarted: - return "all_only_if_service_worker_not_started"; - case features::ServiceWorkerBypassFetchHandlerTarget::kSubResource: - return "sub_resource"; - case features::ServiceWorkerBypassFetchHandlerTarget:: - kAllWithRaceNetworkRequest: - return "all_with_race_network_request"; - } - } - - private: - base::test::ScopedFeatureList feature_list_; - std::string kValidChecksum = - "B437DA0A66F805F079E1F371F2BFAEF4A35BB9AEEA0A85827B954B05F6D63C6C"; - std::string kInvalidChecksum = ""; -}; - -INSTANTIATE_TEST_SUITE_P( - All, - ServiceWorkerBypassFetchHandlerTest, - testing::Combine( - testing::Bool(), - testing::Bool(), - testing::Values( - features::ServiceWorkerBypassFetchHandlerTarget::kMainResource, - features::ServiceWorkerBypassFetchHandlerTarget:: - kAllOnlyIfServiceWorkerNotStarted, - features::ServiceWorkerBypassFetchHandlerTarget::kSubResource))); - -IN_PROC_BROWSER_TEST_P(ServiceWorkerBypassFetchHandlerTest, All) { - StartServerAndNavigateToSetup(); - - const GURL create_service_worker_url(embedded_test_server()->GetURL( - "/service_worker/create_service_worker.html")); - const GURL out_scope_url(embedded_test_server()->GetURL("/empty.html")); - // |in_scope_url| is a page that has more than one subresources. - const GURL in_scope_url( - embedded_test_server()->GetURL("/service_worker/with_subresources.html")); - - // Register a service worker. - WorkerRunningStatusObserver observer1(public_context()); - EXPECT_TRUE(NavigateToURL(shell(), create_service_worker_url)); - EXPECT_EQ("DONE", - EvalJs(GetPrimaryMainFrame(), - "register('/service_worker/fetch_event_pass_through.js')")); - observer1.WaitUntilRunning(); - scoped_refptr<ServiceWorkerVersion> version = - wrapper()->GetLiveVersion(observer1.version_id()); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kRunning, version->running_status()); - - // Stop the current running service worker. - StopServiceWorker(version.get()); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kStopped, version->running_status()); - - // Navigate away from the service worker's scope. - EXPECT_TRUE(NavigateToURL(shell(), out_scope_url)); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kStopped, version->running_status()); - - // This script asks the service worker what fetch events it saw. - const std::string script = R"( - (async () => { - const saw_message = new Promise(resolve => { - navigator.serviceWorker.onmessage = event => { - resolve(event.data); - }; - }); - const registration = await navigator.serviceWorker.ready; - registration.active.postMessage(''); - const message = await saw_message; - return message.length; - })(); - )"; - - // Navigate to the service worker's scope. - WorkerRunningStatusObserver observer2(public_context()); - EXPECT_TRUE(NavigateToURL(shell(), in_scope_url)); - - switch (BypassFetchHandlerTarget()) { - case features::ServiceWorkerBypassFetchHandlerTarget::kMainResource: - if (ShouldUseAllowListStrategy()) { - if (ShouldUseValidChecksum()) { - // If bypassing is allowed, the service worker was bypassed and the - // navigation request shouldn't be handled by the fetch handler. - // 2 from subresources. - EXPECT_EQ(2, EvalJs(GetPrimaryMainFrame(), script)); - } else { - // If bypassing is not allowed, the navigation request should be - // handled by the fetch handler. 3 = main + subresources - EXPECT_EQ(3, EvalJs(GetPrimaryMainFrame(), script)); - } - } else { - // If the allowlist isn't used, the service worker was bypassed and the - // navigation request shouldn't be handled by the fetch handler. - EXPECT_EQ(2, EvalJs(GetPrimaryMainFrame(), script)); - } - break; - case features::ServiceWorkerBypassFetchHandlerTarget:: - kAllOnlyIfServiceWorkerNotStarted: - // TODO(crbug.com/1371756): Consider supporing the allowlist if needed. - - // this option doesn't involve a fetch handler at all when the - // ServiceWorker is not started yet while the navigation happens. - EXPECT_EQ(0, EvalJs(GetPrimaryMainFrame(), script)); - - // Wait until running. - observer2.WaitUntilRunning(); - version = wrapper()->GetLiveVersion(observer2.version_id()); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kRunning, - version->running_status()); - - // The handler is not used for subsequent requests even if the - // worker has already started. - EXPECT_TRUE( - ExecJs(GetPrimaryMainFrame(), "fetch('/service_worker/empty.html')")); - EXPECT_EQ(0, EvalJs(GetPrimaryMainFrame(), script)); - - // Navigate to the page again while the ServicWorker is running. - EXPECT_TRUE(NavigateToURL(shell(), in_scope_url)); - // Expect both the main resource and subresource are handled. - EXPECT_EQ(3, EvalJs(GetPrimaryMainFrame(), script)); - break; - case features::ServiceWorkerBypassFetchHandlerTarget::kSubResource: - if (ShouldUseAllowListStrategy()) { - if (ShouldUseValidChecksum()) { - // If bypassing is allowed, subresources shouldn't be handled by the - // fetch handler. - // 1 = main resource - EXPECT_EQ(1, EvalJs(GetPrimaryMainFrame(), script)); - } else { - // If bypassing is not allowed, subresources should be handled by the - // fetch handler. - // 3 = main + subresources - EXPECT_EQ(3, EvalJs(GetPrimaryMainFrame(), script)); - } - } else { - // The service worker handles the navigation request, but bypasses fetch - // handlers for subsequent subresources. - EXPECT_EQ(1, EvalJs(GetPrimaryMainFrame(), script)); - } - break; - case features::ServiceWorkerBypassFetchHandlerTarget:: - kAllWithRaceNetworkRequest: - // This case is tested in ServiceWorkerRaceNetworkRequestBrowserTest. - NOTREACHED(); - break; - } -} - -class ServiceWorkerBypassFetchHandlerOriginTrialTest - : public ServiceWorkerBrowserTest { - public: - void SetUpCommandLine(base::CommandLine* command_line) override { - // The public key for the default privatey key used by the - // tools/origin_trials/generate_token.py tool. - static constexpr char kOriginTrialTestPublicKey[] = - "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA="; - command_line->AppendSwitchASCII("origin-trial-public-key", - kOriginTrialTestPublicKey); - } - WebContents* web_contents() const { return shell()->web_contents(); } - - RenderFrameHost* GetPrimaryMainFrame() { - return web_contents()->GetPrimaryMainFrame(); - } -}; - -IN_PROC_BROWSER_TEST_F(ServiceWorkerBypassFetchHandlerOriginTrialTest, - BypassFetchHandlerForMainResource) { - embedded_test_server()->StartAcceptingConnections(); - - // The URL that was used to register the Origin Trial token. - static constexpr char kOriginUrl[] = "https://127.0.0.1:44444"; - // Generated by running (in tools/origin_trials): - // tools/origin_trials/generate_token.py https://127.0.0.1:44444 \ - // ServiceWorkerBypassFetchHandlerForMainResource \ - // --expire-timestamp=2000000000 - static constexpr char kOriginTrialToken[] = - "A7lJi6aWVTbSCCs9Ju3k4SKBnTzE/" - "9j7OMHWdF2pjJLLZU5Fdt7IzilJOFp37hMyoeIUq4gCTdb9wSIC9jhU/" - "wgAAAB4eyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6I" - "CJTZXJ2aWNlV29ya2VyQnlwYXNzRmV0Y2hIYW5kbGVyRm9yTWFpblJlc291cmNlIiwgImV4c" - "GlyeSI6IDIwMDAwMDAwMDB9"; - - const GURL main_page_url( - base::StrCat({kOriginUrl, "/create_service_worker.html"})); - const GURL service_worker_url( - base::StrCat({kOriginUrl, "/fetch_event_pass_through.js"})); - - std::map<GURL, int /* number_of_invocations */> expected_request_urls = { - {main_page_url, 2}, - {service_worker_url, 1}, - }; - - base::RunLoop run_loop; - - // The origin trial token is associated with an origin. We can't guarantee the - // EmbeddedTestServer to use a specific port. So the URLLoaderInterceptor is - // used instead. - URLLoaderInterceptor service_worker_loader(base::BindLambdaForTesting( - [&](URLLoaderInterceptor::RequestParams* params) { - auto it = expected_request_urls.find(params->url_request.url); - if (it == expected_request_urls.end()) { - return false; - } - - const std::string content_type = - base::EndsWith(params->url_request.url.path_piece(), ".js") - ? "text/javascript" - : "text/html"; - - const std::string origin_trial_token = - params->url_request.url == service_worker_url ? kOriginTrialToken - : ""; - - const std::string headers = base::ReplaceStringPlaceholders( - "HTTP/1.1 200 OK\n" - "Content-type: $1\n" - "Origin-Trial: $2\n" - "\n", - {content_type, origin_trial_token}, {}); - - URLLoaderInterceptor::WriteResponse( - "content/test/data/service_worker" + params->url_request.url.path(), - params->client.get(), &headers, std::optional<net::SSLInfo>(), - params->url_request.url); - - if (--it->second == 0) { - expected_request_urls.erase(it); - } - if (expected_request_urls.empty()) { - run_loop.Quit(); - } - return true; - })); - - // Register a service worker. - WorkerRunningStatusObserver observer(public_context()); - EXPECT_TRUE(NavigateToURL(shell(), main_page_url)); - EXPECT_EQ("DONE", EvalJs(GetPrimaryMainFrame(), - "register('/fetch_event_pass_through.js')")); - observer.WaitUntilRunning(); - scoped_refptr<ServiceWorkerVersion> version = - wrapper()->GetLiveVersion(observer.version_id()); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kRunning, version->running_status()); - - // Stop the current running service worker. - StopServiceWorker(version.get()); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kStopped, version->running_status()); - - // Navigate away from the service worker's scope. - EXPECT_TRUE( - NavigateToURL(shell(), embedded_test_server()->GetURL("/empty.html"))); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kStopped, version->running_status()); - - // Navigate to the service worker's scope. - EXPECT_TRUE(NavigateToURL(shell(), main_page_url)); - - // The service worker was bypassed and the navigation request shouldn't be - // handled by the fetch handler. - // The script asks the service worker what fetch events it saw. - EXPECT_EQ(0, EvalJs(GetPrimaryMainFrame(), R"( - (async () => { - const saw_message = new Promise(resolve => { - navigator.serviceWorker.onmessage = event => { - resolve(event.data); - }; - }); - const registration = await navigator.serviceWorker.ready; - registration.active.postMessage(''); - const message = await saw_message; - return message.length; - })(); - )")); - - run_loop.Run(); -} - class ServiceWorkerSkipEmptyFetchHandlerBrowserTest : public ServiceWorkerBrowserTest { public: @@ -5373,22 +5060,22 @@ ServiceWorkerVersion::FetchHandlerType::kEmptyFetchHandler, 1); } -// Test class for BestEffortServiceWorker (crbug.com/1420517) browsertest. -class ServiceWorkerRaceNetworkRequestBrowserTest +// Browser test for the Static Routing API's `race-network-and-fetch-handler` +// source. +class ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest : public ServiceWorkerBrowserTest { public: - ServiceWorkerRaceNetworkRequestBrowserTest() + static constexpr char kSwScriptUrl[] = + "/service_worker/static_router_race_match_all.js"; + + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest() : https_server_(std::make_unique<net::EmbeddedTestServer>( net::EmbeddedTestServer::TYPE_HTTPS)) { - feature_list_.InitWithFeaturesAndParameters( - {{features::kServiceWorkerBypassFetchHandler, - {{"strategy", "optin"}, - {"bypass_for", "all_with_race_network_request"}}}}, - {}); RaceNetworkRequestWriteBufferManager::SetDataPipeCapacityBytesForTesting( 1024); } - ~ServiceWorkerRaceNetworkRequestBrowserTest() override = default; + ~ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest() + override = default; WebContents* web_contents() const { return shell()->web_contents(); } @@ -5397,13 +5084,13 @@ } scoped_refptr<ServiceWorkerVersion> SetupAndRegisterServiceWorker() { - StartServerAndNavigateToSetup(); - return RegisterRaceNetowrkRequestServiceWorker(embedded_test_server()); + return SetupAndRegisterServiceWorkerInternal(kSwScriptUrl); } scoped_refptr<ServiceWorkerVersion> SetupAndRegisterServiceWorkerWithHTTPSServer() { - return RegisterRaceNetowrkRequestServiceWorker(https_server()); + return RegisterRaceNetowrkRequestServiceWorker(https_server(), + kSwScriptUrl); } EvalJsResult GetInnerText() { @@ -5431,6 +5118,13 @@ RegisterRequestHandlerForSlowResponsePage(https_server()); } + scoped_refptr<ServiceWorkerVersion> SetupAndRegisterServiceWorkerInternal( + const std::string& script_url) { + StartServerAndNavigateToSetup(); + return RegisterRaceNetowrkRequestServiceWorker(embedded_test_server(), + script_url); + } + private: void RegisterRequestHandlerForSlowResponsePage( net::EmbeddedTestServer* test_server) { @@ -5503,7 +5197,8 @@ void RegisterRequestMonitorForRequestCount( net::EmbeddedTestServer* test_server) { test_server->RegisterRequestMonitor(base::BindRepeating( - &ServiceWorkerRaceNetworkRequestBrowserTest::MonitorRequestHandler, + &ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest:: + MonitorRequestHandler, base::Unretained(this))); } void MonitorRequestHandler(const net::test_server::HttpRequest& request) { @@ -5511,16 +5206,16 @@ } scoped_refptr<ServiceWorkerVersion> RegisterRaceNetowrkRequestServiceWorker( - net::EmbeddedTestServer* test_server) { + net::EmbeddedTestServer* test_server, + const std::string& script_url) { const GURL create_service_worker_url( test_server->GetURL("/service_worker/create_service_worker.html")); // Register a service worker. WorkerRunningStatusObserver observer1(public_context()); EXPECT_TRUE(NavigateToURL(shell(), create_service_worker_url)); - EXPECT_EQ("DONE", - EvalJs(GetPrimaryMainFrame(), - "register('/service_worker/race_network_request.js')")); + EXPECT_EQ("DONE", EvalJs(GetPrimaryMainFrame(), + base::StrCat({"register('", script_url, "')"}))); observer1.WaitUntilRunning(); scoped_refptr<ServiceWorkerVersion> version = wrapper()->GetLiveVersion(observer1.version_id()); @@ -5539,8 +5234,9 @@ std::unique_ptr<net::EmbeddedTestServer> https_server_; }; -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins) { // Register the ServiceWorker and navigate to the in scope URL. SetupAndRegisterServiceWorker(); // Capture the response head. @@ -5562,8 +5258,9 @@ observer.GetNormalizedResponseHeader("X-Response-From")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins_MarkedAsSecure) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins_MarkedAsSecure) { // Register the ServiceWorker and navigate to the in scope URL. StartServerAndNavigateToSetup(); ASSERT_TRUE(https_server()->Start()); @@ -5586,8 +5283,9 @@ CheckPageIsMarkedSecure(shell(), https_server()->GetCertificate()); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins_MimeTypeSniffed) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins_MimeTypeSniffed) { // Register the ServiceWorker and navigate to the in scope URL. StartServerAndNavigateToSetup(); @@ -5619,8 +5317,9 @@ GetInnerText()); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins_Fetch_No_Respond) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins_Fetch_No_Respond) { // Register the ServiceWorker and navigate to the in scope URL. SetupAndRegisterServiceWorker(); NavigateToURLBlockUntilNavigationsComplete( @@ -5636,8 +5335,9 @@ // TODO(crbug.com/1491332) Add tests for // kURLLoadOptionSendSSLInfoForCertificateError -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins_NotFound_FetchHandler_Respond) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins_NotFound_FetchHandler_Respond) { SetupAndRegisterServiceWorker(); // Network request is faster, but the response is not found. @@ -5653,8 +5353,9 @@ GetInnerText()); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins_NotFound_FetchHandler_NotRespond) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins_NotFound_FetchHandler_NotRespond) { SetupAndRegisterServiceWorker(); // If the fallback request is not found. Then expect 404. @@ -5674,8 +5375,9 @@ #define MAYBE_NetworkRequest_Wins_FetchHandler_Fallback \ NetworkRequest_Wins_FetchHandler_Fallback #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_NetworkRequest_Wins_FetchHandler_Fallback) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_NetworkRequest_Wins_FetchHandler_Fallback) { // If RaceNetworkRequest comes first, there is a network error, and the fetch // handler result is a fallback. In this case the response from // RaceNetworkRequest is not used, because we need to support the case when @@ -5698,8 +5400,9 @@ EXPECT_EQ(2, GetRequestCount(relative_url)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins_FetchHandler_Fallback_LargeData) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins_FetchHandler_Fallback_LargeData) { SetupAndRegisterServiceWorker(); const std::string relative_url = "/service_worker/mock_response?sw_fallback&sw_slow&server_large_data"; @@ -5712,8 +5415,9 @@ observer.GetNormalizedResponseHeader("X-Response-From")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - NetworkRequest_Wins_Post) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + NetworkRequest_Wins_Post) { SetupAndRegisterServiceWorker(); const std::string action = "/service_worker/mock_response?sw_slow&sw_respond"; EXPECT_TRUE(ExecJs(GetPrimaryMainFrame(), @@ -5738,8 +5442,9 @@ #else #define MAYBE_NetworkRequest_Wins_Redirect NetworkRequest_Wins_Redirect #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_NetworkRequest_Wins_Redirect) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_NetworkRequest_Wins_Redirect) { SetupAndRegisterServiceWorker(); const std::string path = "/service_worker/mock_response?server_redirect&sw_slow&sw_respond"; @@ -5767,8 +5472,9 @@ #define MAYBE_NetworkRequest_Wins_Redirect_PassThrough \ NetworkRequest_Wins_Redirect_PassThrough #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_NetworkRequest_Wins_Redirect_PassThrough) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_NetworkRequest_Wins_Redirect_PassThrough) { SetupAndRegisterServiceWorker(); const std::string path = "/service_worker/mock_response?server_redirect&sw_slow&sw_pass_through"; @@ -5789,8 +5495,9 @@ EXPECT_EQ(1, GetRequestCount(path_after_redirect)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - FetchHandler_Wins) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + FetchHandler_Wins) { SetupAndRegisterServiceWorker(); // Need to navigate to the page with slow response. const GURL slow_url = embedded_test_server()->GetURL( @@ -5810,8 +5517,9 @@ observer.GetNormalizedResponseHeader("X-Response-From")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - FetchHandler_Wins_Fallback) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + FetchHandler_Wins_Fallback) { SetupAndRegisterServiceWorker(); // Fetch handler will fallback. This case the response from RaceNetworkRequest // is returned as a final response. @@ -5832,8 +5540,9 @@ EXPECT_FALSE(NavigateToURL(shell(), slow_url)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - FetchHandler_Wins_NotFound) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + FetchHandler_Wins_NotFound) { SetupAndRegisterServiceWorker(); const GURL slow_url = embedded_test_server()->GetURL( "/service_worker/mock_response?server_slow&server_notfound&sw_fallback"); @@ -5850,8 +5559,9 @@ #else #define MAYBE_FetchHandler_Wins_Redirect FetchHandler_Wins_Redirect #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_FetchHandler_Wins_Redirect) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_FetchHandler_Wins_Redirect) { SetupAndRegisterServiceWorker(); const std::string path = "/service_worker/mock_response?server_redirect&server_slow&sw_respond"; @@ -5876,8 +5586,9 @@ #define MAYBE_FetchHandler_Wins_Redirect_PassThrough \ FetchHandler_Wins_Redirect_PassThrough #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_FetchHandler_Wins_Redirect_PassThrough) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_FetchHandler_Wins_Redirect_PassThrough) { SetupAndRegisterServiceWorker(); const std::string path = "/service_worker/" @@ -5898,8 +5609,9 @@ EXPECT_EQ(1, GetRequestCount(path_after_redirect)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - FetchHandler_PassThrough) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + FetchHandler_PassThrough) { // Register the ServiceWorker and navigate to the in scope URL. scoped_refptr<ServiceWorkerVersion> version = SetupAndRegisterServiceWorker(); // Capture the response head. @@ -5928,8 +5640,9 @@ EXPECT_EQ(1, GetRequestCount(relative_url)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - FetchHandler_PassThrough_Clone) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + FetchHandler_PassThrough_Clone) { // Register the ServiceWorker and navigate to the in scope URL. scoped_refptr<ServiceWorkerVersion> version = SetupAndRegisterServiceWorker(); // URL which create a cloned request and pass-through. @@ -5963,8 +5676,9 @@ #else #define MAYBE_Subresource_NetworkRequest_Wins Subresource_NetworkRequest_Wins #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_Subresource_NetworkRequest_Wins) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_Subresource_NetworkRequest_Wins) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -5977,8 +5691,9 @@ "=> response.text())")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_NetworkRequest_Wins_Fetch_No_Respond) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_NetworkRequest_Wins_Fetch_No_Respond) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -5990,8 +5705,9 @@ "=> response.text())")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_NetworkRequest_Wins_NotFound) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_NetworkRequest_Wins_NotFound) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6012,8 +5728,9 @@ "server_notfound').then(response => response.status)")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_NetworkRequest_Wins_FetchHandler_Fallback) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_NetworkRequest_Wins_FetchHandler_Fallback) { SetupAndRegisterServiceWorker(); // Network request is faster, and the fetch handler will fallback. // This case the response from RaceNetworkRequset is used. @@ -6025,7 +5742,7 @@ } IN_PROC_BROWSER_TEST_F( - ServiceWorkerRaceNetworkRequestBrowserTest, + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, Subresource_NetworkRequest_Wins_FetchHandler_Fallback_LargeData) { SetupAndRegisterServiceWorker(); EXPECT_EQ("race-network-request-with-large-data", @@ -6036,7 +5753,7 @@ } IN_PROC_BROWSER_TEST_F( - ServiceWorkerRaceNetworkRequestBrowserTest, + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, Subresource_NetworkRequest_Wins_FetchHandler_Fallback_Redirect) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); @@ -6061,8 +5778,9 @@ EXPECT_EQ(1, GetRequestCount(path_after_redirect)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_NetworkRequest_Wins_Post) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_NetworkRequest_Wins_Post) { SetupAndRegisterServiceWorker(); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6080,8 +5798,9 @@ EvalJs(GetPrimaryMainFrame(), script)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_Redirect_Multiple) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_Redirect_Multiple) { SetupAndRegisterServiceWorker(); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6111,8 +5830,9 @@ #define MAYBE_Subresource_NetworkRequest_Wins_Redirect \ Subresource_NetworkRequest_Wins_Redirect #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_Subresource_NetworkRequest_Wins_Redirect) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_Subresource_NetworkRequest_Wins_Redirect) { SetupAndRegisterServiceWorker(); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6140,7 +5860,7 @@ Subresource_NetworkRequest_Wins_Redirect_PassThrough #endif IN_PROC_BROWSER_TEST_F( - ServiceWorkerRaceNetworkRequestBrowserTest, + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, MAYBE_Subresource_NetworkRequest_Wins_Redirect_PassThrough) { SetupAndRegisterServiceWorker(); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6163,8 +5883,9 @@ EXPECT_EQ(1, GetRequestCount(path_after_redirect)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_FetchHandler_Wins) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_FetchHandler_Wins) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6178,8 +5899,9 @@ "response.text())")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_FetchHandler_Wins_Fallback) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_FetchHandler_Wins_Fallback) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6203,8 +5925,9 @@ EXPECT_FALSE(ExecJs(GetPrimaryMainFrame(), "fetch('" + relative_url + "')")); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_FetchHandler_Wins_Fallback_Redirect) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_FetchHandler_Wins_Fallback_Redirect) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6227,8 +5950,9 @@ EXPECT_EQ(1, GetRequestCount(path_after_redirect)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_FetchHandler_Wins_NotFound) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_FetchHandler_Wins_NotFound) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6251,8 +5975,9 @@ #define MAYBE_Subresource_FetchHandler_Wins_Redirect \ Subresource_FetchHandler_Wins_Redirect #endif -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - MAYBE_Subresource_FetchHandler_Wins_Redirect) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + MAYBE_Subresource_FetchHandler_Wins_Redirect) { SetupAndRegisterServiceWorker(); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6280,7 +6005,7 @@ Subresource_FetchHandler_Wins_Redirect_PassThrough #endif IN_PROC_BROWSER_TEST_F( - ServiceWorkerRaceNetworkRequestBrowserTest, + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, MAYBE_Subresource_FetchHandler_Wins_Redirect_PassThrough) { SetupAndRegisterServiceWorker(); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6304,8 +6029,9 @@ EXPECT_EQ(1, GetRequestCount(path_after_redirect)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestBrowserTest, - Subresource_FetchHandler_PassThrough) { +IN_PROC_BROWSER_TEST_F( + ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, + Subresource_FetchHandler_PassThrough) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); ReloadBlockUntilNavigationsComplete(shell(), 1); @@ -6330,20 +6056,26 @@ } class ServiceWorkerAutoPreloadBrowserTest - : public ServiceWorkerRaceNetworkRequestBrowserTest, + : public ServiceWorkerStaticRouterRaceNetworkAndFetchHandlerSourceBrowserTest, public testing::WithParamInterface<bool> { public: + static constexpr char kSwScriptUrl[] = "/service_worker/auto_preload.js"; + ServiceWorkerAutoPreloadBrowserTest() { feature_list_.InitWithFeaturesAndParameters( {{features::kServiceWorkerAutoPreload, {{"use_two_phase_write", GetParam() ? "true" : "false"}}}}, - {{features::kServiceWorkerBypassFetchHandler}}); + {}); RaceNetworkRequestWriteBufferManager::SetDataPipeCapacityBytesForTesting( 1024); } ~ServiceWorkerAutoPreloadBrowserTest() override = default; + scoped_refptr<ServiceWorkerVersion> SetupAndRegisterServiceWorker() { + return SetupAndRegisterServiceWorkerInternal(kSwScriptUrl); + } + private: base::test::ScopedFeatureList feature_list_; }; @@ -6595,9 +6327,8 @@ blocked_host(), "/service_worker/create_service_worker.html")); WorkerRunningStatusObserver observer1(public_context()); EXPECT_TRUE(NavigateToURL(shell(), create_service_worker_url)); - EXPECT_EQ("DONE", - EvalJs(GetPrimaryMainFrame(), - "register('/service_worker/race_network_request.js')")); + EXPECT_EQ("DONE", EvalJs(GetPrimaryMainFrame(), + "register('/service_worker/auto_preload.js')")); observer1.WaitUntilRunning(); } @@ -6767,150 +6498,83 @@ observer.GetNormalizedResponseHeader("X-Response-From")); } -class ServiceWorkerRaceNetworkRequestOriginTrialBrowserTest - : public ServiceWorkerRaceNetworkRequestBrowserTest { +class ServiceWorkerAutoPreloadAllowListBrowserTest + : public ServiceWorkerAutoPreloadBrowserTest { public: - void SetUpCommandLine(base::CommandLine* command_line) override { - // The public key for the default privatey key used by the - // tools/origin_trials/generate_token.py tool. - static constexpr char kOriginTrialTestPublicKey[] = - "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA="; - command_line->AppendSwitchASCII("origin-trial-public-key", - kOriginTrialTestPublicKey); + ServiceWorkerAutoPreloadAllowListBrowserTest() { + feature_list_.InitWithFeaturesAndParameters( + {{features::kServiceWorkerAutoPreload, + {{"use_allowlist", "true"}, {"use_two_phase_write", "false"}}}, + {features::kServiceWorkerBypassFetchHandlerHashStrings, + {{"script_checksum_to_bypass", + ShouldUseValidChecksum() ? kValidChecksum : kInvalidChecksum}}}}, + {}); } + ~ServiceWorkerAutoPreloadAllowListBrowserTest() override = default; + + WebContents* web_contents() const { return shell()->web_contents(); } + + RenderFrameHost* GetPrimaryMainFrame() { + return web_contents()->GetPrimaryMainFrame(); + } + + protected: + bool ShouldUseValidChecksum() { return GetParam(); } + + private: + base::test::ScopedFeatureList feature_list_; + std::string kValidChecksum = + "042D3C49B5FA366582CEBA01E6E3DCD6259531CCAF64B26635B7F0C11C18BE0D"; + std::string kInvalidChecksum = ""; }; -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestOriginTrialBrowserTest, - RaceNetworkRequest) { - embedded_test_server()->StartAcceptingConnections(); +INSTANTIATE_TEST_SUITE_P(ALL, + ServiceWorkerAutoPreloadAllowListBrowserTest, + testing::Bool()); - // The URL that was used to register the Origin Trial token. - static constexpr char kOriginUrl[] = "https://127.0.0.1:44444"; - // Generated by running (in tools/origin_trials): - // tools/origin_trials/generate_token.py https://127.0.0.1:44444 \ - // ServiceWorkerBypassFetchHandlerWithRaceNetworkRequest \ - // --expire-timestamp=2000000000 - static constexpr char kOriginTrialToken[] = - "AywPGgJULst8eq0LDwGqFRqFTfbNIq+" - "dDh6BpmDRZxazAjL8JCiXtp51bRuaG7X7pxz35vwQ9+5hEPLLW0DMKA4AAAB/" - "eyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJTZXJ2" - "aWNlV29ya2VyQnlwYXNzRmV0Y2hIYW5kbGVyV2l0aFJhY2VOZXR3b3JrUmVxdWVzdCIsICJl" - "eHBpcnkiOiAyMDAwMDAwMDAwfQ=="; +IN_PROC_BROWSER_TEST_P(ServiceWorkerAutoPreloadAllowListBrowserTest, + EnableAutoPreloadIfScriptIsAllowed) { + SetupAndRegisterServiceWorker(); + const std::string relative_url = "/service_worker/mock_response?sw_respond"; + const GURL test_url = embedded_test_server()->GetURL(relative_url); + NavigationHandleObserver observer(web_contents(), test_url); + WorkerRunningStatusObserver service_worker_running_status_observer( + public_context()); + NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1); + EXPECT_TRUE(observer.has_committed()); + service_worker_running_status_observer.WaitUntilRunning(); - const GURL main_page_url( - base::StrCat({kOriginUrl, "/create_service_worker.html"})); - const GURL main_page_url_with_params( - base::StrCat({main_page_url.spec(), "?sw_slow&sw_respond"})); - const GURL service_worker_url( - base::StrCat({kOriginUrl, "/race_network_request.js"})); - const GURL subresource_url_with_params( - base::StrCat({kOriginUrl, "/hello-from-sw.txt?sw_slow&sw_respond"})); - - std::map<GURL, int /* number_of_invocations */> expected_request_urls = { - {main_page_url, 1}, - {main_page_url_with_params, 1}, - {subresource_url_with_params, 1}, - {service_worker_url, 1}, - }; - - base::RunLoop run_loop; - - // The origin trial token is associated with an origin. We can't guarantee the - // EmbeddedTestServer to use a specific port. So the URLLoaderInterceptor is - // used instead. - URLLoaderInterceptor service_worker_loader(base::BindLambdaForTesting( - [&](URLLoaderInterceptor::RequestParams* params) { - auto it = expected_request_urls.find(params->url_request.url); - if (it == expected_request_urls.end()) { - return false; - } - - const std::string content_type = - base::EndsWith(params->url_request.url.path_piece(), ".js") - ? "text/javascript" - : "text/html"; - - const std::string origin_trial_token = - params->url_request.url == service_worker_url ? kOriginTrialToken - : ""; - - const std::string headers = base::ReplaceStringPlaceholders( - "HTTP/1.1 200 OK\n" - "Content-type: $1\n" - "Origin-Trial: $2\n" - "\n", - {content_type, origin_trial_token}, {}); - - URLLoaderInterceptor::WriteResponse( - "content/test/data/service_worker" + params->url_request.url.path(), - params->client.get(), &headers, std::optional<net::SSLInfo>(), - params->url_request.url); - - if (--it->second == 0) { - expected_request_urls.erase(it); - } - if (expected_request_urls.empty()) { - run_loop.Quit(); - } - return true; - })); - - // Register a service worker. - WorkerRunningStatusObserver observer(public_context()); - EXPECT_TRUE(NavigateToURL(shell(), main_page_url)); - EXPECT_EQ("DONE", EvalJs(GetPrimaryMainFrame(), - "register('/race_network_request.js')")); - observer.WaitUntilRunning(); - scoped_refptr<ServiceWorkerVersion> version = - wrapper()->GetLiveVersion(observer.version_id()); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kRunning, version->running_status()); - - // Stop the current running service worker. - StopServiceWorker(version.get()); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kStopped, version->running_status()); - - // Navigate away from the service worker's scope. - EXPECT_TRUE( - NavigateToURL(shell(), embedded_test_server()->GetURL("/empty.html"))); - EXPECT_EQ(blink::EmbeddedWorkerStatus::kStopped, version->running_status()); - - // Navigate to the service worker's scope. - EXPECT_TRUE(NavigateToURL(shell(), main_page_url_with_params)); - - // ServiceWorker will respond after the delay, so we expect the response from - // the network request initiated by the RaceNetworkRequest mode comes first. - EXPECT_EQ("create service worker", - EvalJs(GetPrimaryMainFrame(), "document.title")); - EXPECT_EQ( - "hello from the service worker\n", - EvalJs(GetPrimaryMainFrame(), - "fetch('/hello-from-sw.txt?sw_slow&sw_respond').then(response " - "=> response.text())")); - - run_loop.Run(); + // The final response comes from the fetch handler, which returns a custom + // response without requiring network request. Expect the network request by + // the AutoPrealod feature only when the script checksum is in the allowlist. + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(ShouldUseValidChecksum() ? 1 : 0, GetRequestCount(relative_url)); + EXPECT_EQ("[ServiceWorkerRaceNetworkRequest] Response from the fetch handler", + GetInnerText()); } -class ServiceWorkerRaceNetworkRequestOptOutBrowserTest - : public ServiceWorkerRaceNetworkRequestBrowserTest { +class ServiceWorkerAutoPreloadOptOutBrowserTest + : public ServiceWorkerAutoPreloadBrowserTest { public: - ServiceWorkerRaceNetworkRequestOptOutBrowserTest() { + ServiceWorkerAutoPreloadOptOutBrowserTest() { feature_list_.InitWithFeaturesAndParameters( { - {features::kServiceWorkerBypassFetchHandler, - {{"strategy", "optin"}, - {"bypass_for", "all_with_race_network_request"}}}, - {features::kServiceWorkerStaticRouter, {}}, + {features::kServiceWorkerAutoPreload, {{"strategy", "optin"}}}, {blink::features::kServiceWorkerStaticRouterNotConditionEnabled, {}}, }, {}); } - ~ServiceWorkerRaceNetworkRequestOptOutBrowserTest() override = default; + ~ServiceWorkerAutoPreloadOptOutBrowserTest() override = default; base::test::ScopedFeatureList feature_list_; }; -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestOptOutBrowserTest, +INSTANTIATE_TEST_SUITE_P(ALL, + ServiceWorkerAutoPreloadOptOutBrowserTest, + testing::Bool()); + +IN_PROC_BROWSER_TEST_P(ServiceWorkerAutoPreloadOptOutBrowserTest, MainResourceFetchHandlerShouldNotRace) { SetupAndRegisterServiceWorker(); const std::string relative_url = "/service_worker/no_race?sw_slow&sw_respond"; @@ -6937,7 +6601,7 @@ EXPECT_EQ(0, GetRequestCount(relative_url)); } -IN_PROC_BROWSER_TEST_F(ServiceWorkerRaceNetworkRequestOptOutBrowserTest, +IN_PROC_BROWSER_TEST_P(ServiceWorkerAutoPreloadOptOutBrowserTest, SubresourceFetchHandlerShouldNotRace) { SetupAndRegisterServiceWorker(); WorkerRunningStatusObserver observer(public_context()); @@ -7089,7 +6753,7 @@ } else if (type == TestType::kRaceNetworkAndFetch) { ASSERT_EQ("DONE", EvalJs(GetPrimaryMainFrame(), - "register('/service_worker/race_network_request.js')")); + "register('/service_worker/static_router_race.js')")); } observer1.WaitUntilRunning(); active_version_ = wrapper()->GetLiveVersion(observer1.version_id());
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc index bbe546d..9d52914 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -87,72 +87,6 @@ return "empty fetch handler"; } } - -bool ShouldBypassFetchHandlerForMainResource(ServiceWorkerVersion& version) { - if (!base::FeatureList::IsEnabled( - features::kServiceWorkerBypassFetchHandler)) { - return false; - } - - if (features::kServiceWorkerBypassFetchHandlerTarget.Get() != - features::ServiceWorkerBypassFetchHandlerTarget::kMainResource) { - return false; - } - - // If the feature is enabled, the main resource request bypasses ServiceWorker - // and starts the worker in parallel for subsequent subresources. - switch (features::kServiceWorkerBypassFetchHandlerStrategy.Get()) { - // kFeatureOptIn means that the feature relies on the manual feature - // toggle from about://flags etc, which is triggered by developers. We - // bypass fetch handler regardless of the url matching in this case. - case features::ServiceWorkerBypassFetchHandlerStrategy::kFeatureOptIn: - RecordSkipReason( - ServiceWorkerControlleeRequestHandler::FetchHandlerSkipReason:: - kMainResourceSkippedDueToFeatureFlag); - return true; - // If kAllowList, the allowlist should be specified. In this case, main - // resource fetch handlers are bypassed only when the sha256 checksum of the - // script is in the allowlist. - case features::ServiceWorkerBypassFetchHandlerStrategy::kAllowList: - if (content::service_worker_loader_helpers:: - FetchHandlerBypassedHashStrings() - .contains(version.sha256_script_checksum())) { - version.CountFeature( - blink::mojom::WebFeature:: - kServiceWorkerBypassFetchHandlerForMainResource); - RecordSkipReason( - ServiceWorkerControlleeRequestHandler::FetchHandlerSkipReason:: - kMainResourceSkippedBecauseMatchedWithAllowedScriptList); - return true; - } - return false; - } - - NOTREACHED(); - return false; -} - -bool ShouldBypassFetchHandlerForMainResourceByOriginTrial( - ServiceWorkerVersion& version) { - if (version.origin_trial_tokens() && - version.origin_trial_tokens()->contains( - "ServiceWorkerBypassFetchHandlerForMainResource")) { - RecordSkipReason( - ServiceWorkerControlleeRequestHandler::FetchHandlerSkipReason:: - kMainResourceSkippedDueToOriginTrial); - // The UseCounter for - // kServiceWorkerBypassFetchHandlerForMainResourceByOriginTrial should only - // capture the usage of this feature invoked by the Origin Trial for the OT - // measurement purpose. - version.CountFeature( - blink::mojom::WebFeature:: - kServiceWorkerBypassFetchHandlerForMainResourceByOriginTrial); - return true; - } - - return false; -} - } // namespace std::optional<int> ServiceWorkerControlleeRequestHandler:: @@ -572,62 +506,6 @@ return; } case ServiceWorkerVersion::FetchHandlerType::kNotSkippable: { - // When FetchHandlerType::kNotSkippable, then check if the fetch handler - // should bypassed or not. First, check the origin trial token. If there - // is no valid origin trial token, then check the eligibility based on the - // feature flag and the url. - if (ShouldBypassFetchHandlerForMainResourceByOriginTrial( - *active_version) || - ShouldBypassFetchHandlerForMainResource(*active_version)) { - // If true, the main resource request bypasses ServiceWorker and starts - // the worker in parallel for subsequent subresources. - CompleteWithoutLoader(); - MaybeStartServiceWorker( - std::move(active_version), - ServiceWorkerMetrics::EventType::BYPASS_MAIN_RESOURCE); - return; - } - // If the feature param ServiceWorkerBypassFetchHandlerTarget is - // |kAllOnlyIfServiceWorkerNotStarted| takes effect and the ServiceWorker - // isn't started yet, skip the fetch handler and then start the - // ServiceWorker. - if (base::FeatureList::IsEnabled( - features::kServiceWorkerBypassFetchHandler) && - features::kServiceWorkerBypassFetchHandlerTarget.Get() == - features::ServiceWorkerBypassFetchHandlerTarget:: - kAllOnlyIfServiceWorkerNotStarted) { - switch (active_version->running_status()) { - case blink::EmbeddedWorkerStatus::kStopped: - case blink::EmbeddedWorkerStatus::kStopping: - case blink::EmbeddedWorkerStatus::kStarting: - // If the status is STARTING, the Serviceworker is not actually - // started yet. So it makes sense to skip the fetch handler. - active_version->set_fetch_handler_bypass_option( - blink::mojom::ServiceWorkerFetchHandlerBypassOption:: - kBypassOnlyIfServiceWorkerNotStarted); - CompleteWithoutLoader(); - RecordSkipReason( - active_version->running_status() == - blink::EmbeddedWorkerStatus::kStarting - ? FetchHandlerSkipReason:: - kBypassFetchHandlerForAllOnlyIfServiceWorkerNotStarted_Status_Starting - : FetchHandlerSkipReason:: - kBypassFetchHandlerForAllOnlyIfServiceWorkerNotStarted_Status_Stop); - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce(&ServiceWorkerControlleeRequestHandler:: - MaybeStartServiceWorker, - weak_factory_.GetWeakPtr(), - std::move(active_version), - ServiceWorkerMetrics::EventType:: - BYPASS_ONLY_IF_SERVICE_WORKER_NOT_STARTED)); - return; - case blink::EmbeddedWorkerStatus::kRunning: - active_version->set_fetch_handler_bypass_option( - blink::mojom::ServiceWorkerFetchHandlerBypassOption::kDefault); - break; - } - } // Otherwise, record the skip reason as kNotSkipped. RecordSkipReason(FetchHandlerSkipReason::kNotSkipped); TRACE_EVENT_WITH_FLOW1(
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.h b/content/browser/service_worker/service_worker_controllee_request_handler.h index 1f5c9029..0ab206f6 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.h +++ b/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -62,15 +62,15 @@ kNoFetchHandler = 0, kNotSkipped = 1, kSkippedForEmptyFetchHandler = 2, - kMainResourceSkippedDueToOriginTrial = 3, - kMainResourceSkippedDueToFeatureFlag = 4, + // kMainResourceSkippedDueToOriginTrial = 3, + // kMainResourceSkippedDueToFeatureFlag = 4, // kMainResourceSkippedBecauseMatchedWithAllowedOriginList = 5, - kMainResourceSkippedBecauseMatchedWithAllowedScriptList = 6, - kBypassFetchHandlerForAllOnlyIfServiceWorkerNotStarted_Status_Stop = 7, - kBypassFetchHandlerForAllOnlyIfServiceWorkerNotStarted_Status_Starting = 8, + // kMainResourceSkippedBecauseMatchedWithAllowedScriptList = 6, + // kBypassFetchHandlerForAllOnlyIfServiceWorkerNotStarted_Status_Stop = 7, + // kBypassFetchHandlerForAllOnlyIfServiceWorkerNotStarted_Status_Starting = + // 8, - kMaxValue = - kBypassFetchHandlerForAllOnlyIfServiceWorkerNotStarted_Status_Starting, + kMaxValue = kSkippedForEmptyFetchHandler, }; // Default duration to start fetch handler when service worker is started in @@ -160,11 +160,8 @@ // Runs after ServiceWorker has started. // Normally ServiceWorker starts before dispatching the main resource request, - // but if the ServiceWorkerBypassFetchHandler feature is enabled, we bypass - // the main resource request and then start ServiceWorker for subresources. - // Also, if we decided to start the service worker for - // the ServiceWorkerSkipEmptyFetchHandler feature and the browser handles - // an empty fetch handler, this runs after the service worker starts. + // but if the browser handles an empty fetch handler, this runs after the + // service worker starts. void DidStartWorker(blink::ServiceWorkerStatusCode status); int GetServiceWorkerForEmptyFetchHandlerDurationMs();
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.cc b/content/browser/service_worker/service_worker_main_resource_loader.cc index 8071590..e573273e 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader.cc
@@ -78,45 +78,12 @@ // Check the eligibility based on the allowlist. This doesn't mean the // experiment is actually enabled. The eligibility is checked and UMA is // reported for the analysis purpose. -bool HasRaceNetworkRequestEligibleScript( - scoped_refptr<ServiceWorkerVersion> version) { +bool HasAutoPreloadEligibleScript(scoped_refptr<ServiceWorkerVersion> version) { return content::service_worker_loader_helpers:: FetchHandlerBypassedHashStrings() .contains(version->sha256_script_checksum()); } -bool IsEligibleForRaceNetworkRequestByOriginTrial( - scoped_refptr<ServiceWorkerVersion> version) { - return version->origin_trial_tokens() && - version->origin_trial_tokens()->contains( - "ServiceWorkerBypassFetchHandlerWithRaceNetworkRequest"); -} - -bool IsEligibleForRaceNetworkRequest( - scoped_refptr<ServiceWorkerVersion> version) { - if (!base::FeatureList::IsEnabled( - features::kServiceWorkerBypassFetchHandler)) { - return false; - } - if (features::kServiceWorkerBypassFetchHandlerTarget.Get() != - features::ServiceWorkerBypassFetchHandlerTarget:: - kAllWithRaceNetworkRequest) { - return false; - } - - switch (features::kServiceWorkerBypassFetchHandlerStrategy.Get()) { - // kFeatureOptIn means that the feature relies on the manual feature - // toggle from about://flags etc, which is triggered by developers. - case features::ServiceWorkerBypassFetchHandlerStrategy::kFeatureOptIn: - return true; - // If kAllowList, the allowlist should be specified. In this case, - // RaceNetworkRequest is allowed only when the sha256 checksum of the - // script is in the allowlist. - case features::ServiceWorkerBypassFetchHandlerStrategy::kAllowList: - return HasRaceNetworkRequestEligibleScript(version); - } -} - std::string GetContainerHostClientId(int frame_tree_node_id) { std::string client_uuid; auto* frame_tree_node = FrameTreeNode::GloballyFindByID(frame_tree_node_id); @@ -451,39 +418,34 @@ switch (race_network_request_mode) { case RaceNetworkRequestMode::kForced: if (StartRaceNetworkRequest(context_wrapper, version)) { - return; + SetDispatchedPreloadType(DispatchedPreloadType::kRaceNetworkRequest); } break; case RaceNetworkRequestMode::kDefault: - if (MaybeStartRaceNetworkRequest(context_wrapper, version)) { - return; + if (base::GetFieldTrialParamByFeatureAsBool( + features::kServiceWorkerAutoPreload, "respect_navigation_preload", + /*default_value=*/true)) { + // Prioritize NavigationPreload than AutoPreload if the + // respect_navigation_preload feature param is true. + if (MaybeStartNavigationPreload(context_wrapper)) { + return; + } + if (MaybeStartAutoPreload(context_wrapper, version)) { + return; + } + } else { + if (MaybeStartAutoPreload(context_wrapper, version)) { + return; + } + if (MaybeStartNavigationPreload(context_wrapper)) { + return; + } } break; case RaceNetworkRequestMode::kSkipped: + MaybeStartNavigationPreload(context_wrapper); break; } - - bool respect_navigation_preload = base::GetFieldTrialParamByFeatureAsBool( - features::kServiceWorkerAutoPreload, "respect_navigation_preload", - /*default_value=*/true); - - if (respect_navigation_preload) { - // Prioritize NavigationPreload than AutoPreload if the - // respect_navigation_preload feature param is true. - if (MaybeStartNavigationPreload(context_wrapper)) { - return; - } - if (MaybeStartAutoPreload(context_wrapper, version)) { - return; - } - } else { - if (MaybeStartAutoPreload(context_wrapper, version)) { - return; - } - if (MaybeStartNavigationPreload(context_wrapper)) { - return; - } - } } bool ServiceWorkerMainResourceLoader::MaybeStartAutoPreload( @@ -501,7 +463,7 @@ bool use_allowlist = base::GetFieldTrialParamByFeatureAsBool( features::kServiceWorkerAutoPreload, "use_allowlist", /*default_value=*/false); - if (use_allowlist && !HasRaceNetworkRequestEligibleScript(version)) { + if (use_allowlist && !HasAutoPreloadEligibleScript(version)) { return false; } @@ -553,42 +515,6 @@ return result; } -bool ServiceWorkerMainResourceLoader::MaybeStartRaceNetworkRequest( - scoped_refptr<ServiceWorkerContextWrapper> context, - scoped_refptr<ServiceWorkerVersion> version) { - bool is_enabled_by_feature_flag = IsEligibleForRaceNetworkRequest(version); - bool is_enabled_by_origin_trial = - IsEligibleForRaceNetworkRequestByOriginTrial(version); - - if (!(is_enabled_by_feature_flag || is_enabled_by_origin_trial)) { - // Even if the feature is not enabled, if the SW has an eligible script, set - // the option as |kRaceNetworkRequestHoldback| for the measuring purpose. - if (HasRaceNetworkRequestEligibleScript(version)) { - version->set_fetch_handler_bypass_option( - blink::mojom::ServiceWorkerFetchHandlerBypassOption:: - kRaceNetworkRequestHoldback); - } - return false; - } - - bool result = StartRaceNetworkRequest(context, version); - if (is_enabled_by_origin_trial) { - version->CountFeature( - blink::mojom::WebFeature:: - kServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequestByOriginTrial); - } else if (is_enabled_by_feature_flag) { - version->CountFeature( - blink::mojom::WebFeature:: - kServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequest); - } - - if (result) { - SetDispatchedPreloadType(DispatchedPreloadType::kRaceNetworkRequest); - } - - return result; -} - bool ServiceWorkerMainResourceLoader::StartRaceNetworkRequest( scoped_refptr<ServiceWorkerContextWrapper> context, scoped_refptr<ServiceWorkerVersion> version) {
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.h b/content/browser/service_worker/service_worker_main_resource_loader.h index 0f621ed..c7f1cf8 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader.h +++ b/content/browser/service_worker/service_worker_main_resource_loader.h
@@ -229,10 +229,6 @@ scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, scoped_refptr<ServiceWorkerVersion> version); - bool MaybeStartRaceNetworkRequest( - scoped_refptr<ServiceWorkerContextWrapper> context_wrapper, - scoped_refptr<ServiceWorkerVersion> version); - // Returns false if fails to start the race network request. // The caller should run the regular path instead. bool StartRaceNetworkRequest(
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index 0460688..3ded083c 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h
@@ -241,8 +241,8 @@ void set_fetch_handler_type(FetchHandlerType fetch_handler_type); // Return the option indicating how the fetch handler should be bypassed. - // ServiceWorkerBypassFetchHandler feature uses this to let the renderer know - // to bypass fetch handlers for subresources. + // This is used to let the renderer know to bypass fetch handlers for + // subresources. FetchHandlerBypassOption fetch_handler_bypass_option() { return fetch_handler_bypass_option_; }
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 3f5849a..a67c09e5 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -7,6 +7,7 @@ #include <math.h> #include <memory> +#include <string_view> #include <vector> #include "base/command_line.h" @@ -20,7 +21,6 @@ #include "base/run_loop.h" #include "base/sequence_checker.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" @@ -160,7 +160,7 @@ WebData BlinkPlatformImpl::GetDataResource( int resource_id, ui::ResourceScaleFactor scale_factor) { - base::StringPiece resource = + std::string_view resource = GetContentClient()->GetDataResource(resource_id, scale_factor); return WebData(resource.data(), resource.size()); }
diff --git a/content/child/dwrite_font_proxy/dwrite_localized_strings_win.cc b/content/child/dwrite_font_proxy/dwrite_localized_strings_win.cc index 8fb97bd6..c7fff85 100644 --- a/content/child/dwrite_font_proxy/dwrite_localized_strings_win.cc +++ b/content/child/dwrite_font_proxy/dwrite_localized_strings_win.cc
@@ -4,10 +4,9 @@ #include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h" -#include "base/strings/string_piece.h" - #include <stddef.h> +#include <string_view> namespace content { @@ -19,7 +18,7 @@ UINT32* index, BOOL* exists) { static_assert(sizeof(WCHAR) == sizeof(char16_t), "WCHAR should be UTF-16."); - const base::StringPiece16 locale_name_str( + const std::u16string_view locale_name_str( reinterpret_cast<const char16_t*>(locale_name)); for (size_t n = 0; n < strings_.size(); ++n) { if (strings_[n].first == locale_name_str) {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 500bc649..671eec05 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -340,8 +340,6 @@ #endif {wf::EnableRemoveMobileViewportDoubleTap, raw_ref(features::kRemoveMobileViewportDoubleTap)}, - {wf::EnableServiceWorkerBypassFetchHandler, - raw_ref(features::kServiceWorkerBypassFetchHandler)}, {wf::EnableServiceWorkerStaticRouter, raw_ref(features::kServiceWorkerStaticRouter)}, };
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc index 4f6a4731..2ff46a1 100644 --- a/content/common/content_switches_internal.cc +++ b/content/common/content_switches_internal.cc
@@ -43,7 +43,7 @@ #if BUILDFLAG(IS_WIN) -std::wstring ToNativeString(base::StringPiece string) { +std::wstring ToNativeString(std::string_view string) { return base::ASCIIToWide(string); }
diff --git a/content/common/service_worker/race_network_request_url_loader_client.cc b/content/common/service_worker/race_network_request_url_loader_client.cc index 78c279b..86ec1d1a 100644 --- a/content/common/service_worker/race_network_request_url_loader_client.cc +++ b/content/common/service_worker/race_network_request_url_loader_client.cc
@@ -874,8 +874,9 @@ "This request is issued by a navigation to fetch the content of the " "page that is being navigated to, or by a renderer to fetch " "subresources in the case where a service worker has been registered " - "for the page and the ServiceWorkerBypassFetchHandler feature and the " - "RaceNetworkRequest param are enabled." + "for the page and the ServiceWorkerAutoPreload feature is enabled, or " + "`race-network-and-fetch-handler` source in the Service Worker Static " + "Routing API is specified." trigger: "Navigating Chrome (by clicking on a link, bookmark, history item, " "using session restore, etc) and subsequent resource loading."
diff --git a/content/public/browser/authenticator_request_client_delegate.cc b/content/public/browser/authenticator_request_client_delegate.cc index 79446c9..26b3b74 100644 --- a/content/public/browser/authenticator_request_client_delegate.cc +++ b/content/public/browser/authenticator_request_client_delegate.cc
@@ -4,11 +4,11 @@ #include "content/public/browser/authenticator_request_client_delegate.h" +#include <string_view> #include <utility> #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "content/browser/webauth/authenticator_environment.h" @@ -215,7 +215,7 @@ const device::FidoAuthenticator& authenticator) {} void AuthenticatorRequestClientDelegate::FidoAuthenticatorRemoved( - base::StringPiece device_id) {} + std::string_view device_id) {} bool AuthenticatorRequestClientDelegate::SupportsPIN() const { return false;
diff --git a/content/public/browser/authenticator_request_client_delegate.h b/content/public/browser/authenticator_request_client_delegate.h index 12d0bc2..186e501 100644 --- a/content/public/browser/authenticator_request_client_delegate.h +++ b/content/public/browser/authenticator_request_client_delegate.h
@@ -7,6 +7,7 @@ #include <optional> #include <string> +#include <string_view> #include "base/containers/span.h" #include "base/functional/callback_forward.h" @@ -369,7 +370,7 @@ void BluetoothAdapterPowerChanged(bool is_powered_on) override; void FidoAuthenticatorAdded( const device::FidoAuthenticator& authenticator) override; - void FidoAuthenticatorRemoved(base::StringPiece device_id) override; + void FidoAuthenticatorRemoved(std::string_view device_id) override; bool SupportsPIN() const override; void CollectPIN( CollectPINOptions options,
diff --git a/content/public/browser/back_forward_cache.h b/content/public/browser/back_forward_cache.h index 388d89a..f2671c8cc 100644 --- a/content/public/browser/back_forward_cache.h +++ b/content/public/browser/back_forward_cache.h
@@ -10,7 +10,6 @@ #include <optional> #include <set> -#include "base/strings/string_piece.h" #include "content/common/content_export.h" #include "content/public/browser/global_routing_id.h" #include "services/metrics/public/cpp/ukm_source_id.h"
diff --git a/content/public/browser/background_tracing_manager.h b/content/public/browser/background_tracing_manager.h index ad0f038d2..2f5ca395 100644 --- a/content/public/browser/background_tracing_manager.h +++ b/content/public/browser/background_tracing_manager.h
@@ -8,7 +8,6 @@ #include <memory> #include <string> -#include "base/strings/string_piece.h" #include "base/time/time.h" #include "base/token.h" #include "base/trace_event/trace_event_impl.h"
diff --git a/content/public/browser/child_process_security_policy.h b/content/public/browser/child_process_security_policy.h index 186baf81a..4c1312c 100644 --- a/content/public/browser/child_process_security_policy.h +++ b/content/public/browser/child_process_security_policy.h
@@ -7,6 +7,7 @@ #include <optional> #include <string> +#include <string_view> #include <vector> #include "content/common/content_export.h" @@ -340,7 +341,7 @@ // Note that wildcards can only be added using this version of // AddFutureIsolatedOrigins(); they cannot be specified in a url::Origin(). virtual void AddFutureIsolatedOrigins( - base::StringPiece origins_to_add, + std::string_view origins_to_add, IsolatedOriginSource source, BrowserContext* browser_context = nullptr) = 0;
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 3888089..5fb0d5f 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -5,6 +5,7 @@ #include "content/public/browser/content_browser_client.h" #include <optional> +#include <string_view> #include <utility> #include "base/check.h" @@ -13,7 +14,6 @@ #include "base/functional/callback_helpers.h" #include "base/no_destructor.h" #include "base/notreached.h" -#include "base/strings/string_piece.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/values.h" @@ -186,13 +186,13 @@ } bool ContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel( - base::StringPiece scheme, + std::string_view scheme, bool is_embedded_origin_secure) { return false; } bool ContentBrowserClient::ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel( - base::StringPiece scheme, + std::string_view scheme, bool is_embedded_origin_secure) { return false; } @@ -1188,7 +1188,7 @@ return false; } -bool ContentBrowserClient::CreateThreadPool(base::StringPiece name) { +bool ContentBrowserClient::CreateThreadPool(std::string_view name) { base::ThreadPoolInstance::Create(name); return true; }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 0956279..9983d8b 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -12,13 +12,13 @@ #include <optional> #include <set> #include <string> +#include <string_view> #include <vector> #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/functional/callback_forward.h" #include "base/memory/scoped_refptr.h" -#include "base/strings/string_piece.h" #include "base/time/time.h" #include "base/types/strong_alias.h" #include "base/values.h" @@ -461,7 +461,7 @@ // matching_scheme_cookies_allowed_schemes, but maybe we should remove that // anyway. virtual bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel( - base::StringPiece scheme, + std::string_view scheme, bool is_embedded_origin_secure); // Similar to the above. Returns whether SameSite cookie restrictions should @@ -472,7 +472,7 @@ // be different, as SameSite restrictions and third-party cookie blocking are // related but have different semantics. virtual bool ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel( - base::StringPiece scheme, + std::string_view scheme, bool is_embedded_origin_secure); // Gets a user friendly display name for a given |site_url| to be used in the @@ -2164,7 +2164,7 @@ // ThreadPoolInstance was created. // Note: the embedder should *not* start the ThreadPoolInstance for // BrowserMainLoop, BrowserMainLoop itself is responsible for that. - virtual bool CreateThreadPool(base::StringPiece name); + virtual bool CreateThreadPool(std::string_view name); // Returns true if the tab security level is acceptable to allow WebAuthn // requests, false otherwise. This is not attached to
diff --git a/content/public/browser/document_service.h b/content/public/browser/document_service.h index 81dc8237..f0bb70a 100644 --- a/content/public/browser/document_service.h +++ b/content/public/browser/document_service.h
@@ -6,12 +6,12 @@ #define CONTENT_PUBLIC_BROWSER_DOCUMENT_SERVICE_H_ #include <cstdint> +#include <string_view> #include <utility> #include "base/check.h" #include "base/compiler_specific.h" #include "base/functional/bind.h" -#include "base/strings/string_piece.h" #include "base/threading/thread_checker.h" #include "content/public/browser/document_service_internal.h" #include "content/public/browser/render_frame_host.h" @@ -128,7 +128,7 @@ // // Prefer over `mojo::ReportBadMessage()`, since using this method avoids the // need to run any pending reply callbacks with placeholder arguments. - NOT_TAIL_CALLED void ReportBadMessageAndDeleteThis(base::StringPiece error) { + NOT_TAIL_CALLED void ReportBadMessageAndDeleteThis(std::string_view error) { receiver_.ReportBadMessage(error); delete this; } @@ -136,7 +136,7 @@ // Resets the `mojo::Receiver` with a `reason` and `description` and deletes // `this`. void ResetWithReasonAndDeleteThis(uint32_t reason, - base::StringPiece description) { + std::string_view description) { receiver_.ResetWithReason(reason, description); delete this; }
diff --git a/content/public/browser/gpu_utils.cc b/content/public/browser/gpu_utils.cc index 9e464331..6b5339b 100644 --- a/content/public/browser/gpu_utils.cc +++ b/content/public/browser/gpu_utils.cc
@@ -5,6 +5,7 @@ #include "content/public/browser/gpu_utils.h" #include <string> +#include <string_view> #include "base/command_line.h" #include "base/functional/bind.h" @@ -42,7 +43,7 @@ } bool GetUintFromSwitch(const base::CommandLine* command_line, - const base::StringPiece& switch_string, + const std::string_view& switch_string, uint32_t* value) { std::string switch_value(command_line->GetSwitchValueASCII(switch_string)); return base::StringToUint(switch_value, value);
diff --git a/content/public/browser/mojo_binder_policy_map.h b/content/public/browser/mojo_binder_policy_map.h index 1c92eed..778d9b9 100644 --- a/content/public/browser/mojo_binder_policy_map.h +++ b/content/public/browser/mojo_binder_policy_map.h
@@ -5,8 +5,9 @@ #ifndef CONTENT_PUBLIC_BROWSER_MOJO_BINDER_POLICY_MAP_H_ #define CONTENT_PUBLIC_BROWSER_MOJO_BINDER_POLICY_MAP_H_ +#include <string_view> + #include "base/check_op.h" -#include "base/strings/string_piece.h" #include "content/common/content_export.h" namespace content { @@ -67,10 +68,10 @@ } private: - virtual void SetPolicyByName(const base::StringPiece& name, + virtual void SetPolicyByName(const std::string_view& name, MojoBinderAssociatedPolicy policy) = 0; - virtual void SetPolicyByName(const base::StringPiece& name, + virtual void SetPolicyByName(const std::string_view& name, MojoBinderNonAssociatedPolicy policy) = 0; };
diff --git a/content/public/browser/origin_trials_controller_delegate.h b/content/public/browser/origin_trials_controller_delegate.h index 230b9cd8..0e75d479 100644 --- a/content/public/browser/origin_trials_controller_delegate.h +++ b/content/public/browser/origin_trials_controller_delegate.h
@@ -9,7 +9,6 @@ #include "base/containers/flat_set.h" #include "base/observer_list_types.h" -#include "base/strings/string_piece.h" #include "base/time/time.h" #include "content/common/content_export.h" #include "third_party/blink/public/mojom/origin_trial_feature/origin_trial_feature.mojom-shared.h"
diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h index f39b0299..0062d2c 100644 --- a/content/public/browser/service_process_host.h +++ b/content/public/browser/service_process_host.h
@@ -15,7 +15,6 @@ #include "base/functional/callback.h" #include "base/observer_list_types.h" #include "base/process/process_handle.h" -#include "base/strings/string_piece.h" #include "content/common/content_export.h" #include "content/public/browser/service_process_info.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
diff --git a/content/public/browser/web_contents_media_capture_id.cc b/content/public/browser/web_contents_media_capture_id.cc index 44cb121..4f83528a 100644 --- a/content/public/browser/web_contents_media_capture_id.cc +++ b/content/public/browser/web_contents_media_capture_id.cc
@@ -4,10 +4,10 @@ #include "content/public/browser/web_contents_media_capture_id.h" +#include <string_view> #include <tuple> #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" namespace { @@ -29,12 +29,12 @@ if (sep_pos == std::string::npos) return false; - const base::StringPiece component1(device_id.data(), sep_pos); + const std::string_view component1(device_id.data(), sep_pos); size_t end_pos = device_id.find('?'); if (end_pos == std::string::npos) end_pos = device_id.length(); - const base::StringPiece component2(device_id.data() + sep_pos + 1, - end_pos - sep_pos - 1); + const std::string_view component2(device_id.data() + sep_pos + 1, + end_pos - sep_pos - 1); return (base::StringToInt(component1, render_process_id) && base::StringToInt(component2, main_render_frame_id)); @@ -57,8 +57,8 @@ option_pos_end = device_id.find(kOptionSeparator, option_pos + 1); if (option_pos_end == std::string::npos) option_pos_end = device_id.length(); - const base::StringPiece component(device_id.data() + option_pos + 1, - option_pos_end - option_pos - 1); + const std::string_view component(device_id.data() + option_pos + 1, + option_pos_end - option_pos - 1); if (component.compare(kDisableLocalEchoFlag) == 0) *disable_local_echo = true;
diff --git a/content/public/browser/web_ui.h b/content/public/browser/web_ui.h index 1f517a28..6d2eea5 100644 --- a/content/public/browser/web_ui.h +++ b/content/public/browser/web_ui.h
@@ -7,12 +7,12 @@ #include <memory> #include <string> +#include <string_view> #include <utility> #include <vector> #include "base/functional/bind.h" #include "base/functional/callback.h" -#include "base/strings/string_piece.h" #include "base/values.h" #include "content/common/content_export.h" #include "ui/base/page_transition_types.h" @@ -41,9 +41,9 @@ // Returns JavaScript code that, when executed, calls the function specified // by |function_name| with the arguments specified in |arg_list|. static std::u16string GetJavascriptCall( - base::StringPiece function_name, + std::string_view function_name, base::span<const base::ValueView> arg_list); - static std::u16string GetJavascriptCall(base::StringPiece function_name, + static std::u16string GetJavascriptCall(std::string_view function_name, const base::Value::List& arg_list); virtual ~WebUI() {} @@ -88,12 +88,12 @@ // the call has no effect. using MessageCallback = base::RepeatingCallback<void(const base::Value::List&)>; - virtual void RegisterMessageCallback(base::StringPiece message, + virtual void RegisterMessageCallback(std::string_view message, MessageCallback callback) = 0; template <typename... Args> void RegisterHandlerCallback( - base::StringPiece message, + std::string_view message, base::RepeatingCallback<void(Args...)> callback) { RegisterMessageCallback( message, base::BindRepeating( @@ -121,15 +121,14 @@ // // All function names in WebUI must consist of only ASCII characters. // There are variants for calls with more arguments. - virtual void CallJavascriptFunctionUnsafe( - base::StringPiece function_name) = 0; + virtual void CallJavascriptFunctionUnsafe(std::string_view function_name) = 0; virtual void CallJavascriptFunctionUnsafe( - base::StringPiece function_name, + std::string_view function_name, base::span<const base::ValueView> args) = 0; template <typename... Args> - void CallJavascriptFunctionUnsafe(base::StringPiece function_name, + void CallJavascriptFunctionUnsafe(std::string_view function_name, const base::ValueView arg1, const Args&... arg) { base::ValueView args[] = {arg1, arg...}; @@ -155,7 +154,7 @@ template <size_t... Is, typename... Args> struct Call<std::index_sequence<Is...>, Args...> { static void Impl(base::RepeatingCallback<void(Args...)> callback, - base::StringPiece message, + std::string_view message, const base::Value::List& list) { CHECK_EQ(list.size(), sizeof...(Args)) << message; callback.Run(GetValue<Args>(list[Is])...);
diff --git a/content/public/browser/web_ui_data_source.h b/content/public/browser/web_ui_data_source.h index 193cddab..1420dc7 100644 --- a/content/public/browser/web_ui_data_source.h +++ b/content/public/browser/web_ui_data_source.h
@@ -9,11 +9,11 @@ #include <memory> #include <string> +#include <string_view> #include <vector> #include "base/containers/span.h" #include "base/functional/callback.h" -#include "base/strings/string_piece.h" #include "base/values.h" #include "content/common/content_export.h" #include "services/network/public/mojom/content_security_policy.mojom-forward.h" @@ -49,15 +49,15 @@ const base::Value::Dict& update); // Adds a string keyed to its name to our dictionary. - virtual void AddString(base::StringPiece name, + virtual void AddString(std::string_view name, const std::u16string& value) = 0; // Adds a string keyed to its name to our dictionary. - virtual void AddString(base::StringPiece name, const std::string& value) = 0; + virtual void AddString(std::string_view name, const std::string& value) = 0; // Adds a localized string with resource |ids| keyed to its name to our // dictionary. - virtual void AddLocalizedString(base::StringPiece name, int ids) = 0; + virtual void AddLocalizedString(std::string_view name, int ids) = 0; // Calls AddLocalizedString() in a for-loop for |strings|. Reduces code size // vs. reimplementing the same for-loop. @@ -69,22 +69,22 @@ const base::Value::Dict& localized_strings) = 0; // Adds a boolean keyed to its name to our dictionary. - virtual void AddBoolean(base::StringPiece name, bool value) = 0; + virtual void AddBoolean(std::string_view name, bool value) = 0; // Adds a signed 32-bit integer keyed to its name to our dictionary. Larger // integers may not be exactly representable in JavaScript. See // MAX_SAFE_INTEGER in /v8/src/globals.h. - virtual void AddInteger(base::StringPiece name, int32_t value) = 0; + virtual void AddInteger(std::string_view name, int32_t value) = 0; // Adds a double keyed to its name to our dictionary. - virtual void AddDouble(base::StringPiece name, double value) = 0; + virtual void AddDouble(std::string_view name, double value) = 0; // Call this to enable a virtual "strings.js" (or "strings.m.js" for modules) // URL that provides translations and dynamic data when requested. virtual void UseStringsJs() = 0; // Adds a mapping between a path name and a resource to return. - virtual void AddResourcePath(base::StringPiece path, int resource_id) = 0; + virtual void AddResourcePath(std::string_view path, int resource_id) = 0; // Calls AddResourcePath() in a for-loop for |paths|. Reduces code size vs. // reimplementing the same for-loop. @@ -148,7 +148,7 @@ virtual std::string GetSource() = 0; // Set supported scheme if not one of the default supported schemes. - virtual void SetSupportedScheme(base::StringPiece scheme) = 0; + virtual void SetSupportedScheme(std::string_view scheme) = 0; }; } // namespace content
diff --git a/content/public/browser/web_ui_message_handler.h b/content/public/browser/web_ui_message_handler.h index 0e7c23d6..04b32a8 100644 --- a/content/public/browser/web_ui_message_handler.h +++ b/content/public/browser/web_ui_message_handler.h
@@ -6,6 +6,7 @@ #define CONTENT_PUBLIC_BROWSER_WEB_UI_MESSAGE_HANDLER_H_ #include <ostream> +#include <string_view> #include "base/check.h" #include "base/gtest_prod_util.h" @@ -88,8 +89,7 @@ // Helper method for notifying Javascript listeners added with // cr.addWebUIListener() (defined in cr.js). template <typename... Values> - void FireWebUIListener(base::StringPiece event_name, - const Values&... values) { + void FireWebUIListener(std::string_view event_name, const Values&... values) { // cr.webUIListenerCallback is a global JS function exposed from cr.js. CallJavascriptFunction("cr.webUIListenerCallback", base::Value(event_name), values...); @@ -102,7 +102,7 @@ // All function names in WebUI must consist of only ASCII characters. // These functions will crash if JavaScript is not currently allowed. template <typename... Values> - void CallJavascriptFunction(base::StringPiece function_name, + void CallJavascriptFunction(std::string_view function_name, const Values&... values) { CHECK(IsJavascriptAllowed()) << "Cannot CallJavascriptFunction before " "explicitly allowing JavaScript.";
diff --git a/content/public/browser/webui_config.cc b/content/public/browser/webui_config.cc index 96a947c..e9b4330 100644 --- a/content/public/browser/webui_config.cc +++ b/content/public/browser/webui_config.cc
@@ -4,9 +4,11 @@ #include "content/public/browser/webui_config.h" +#include <string_view> + namespace content { -WebUIConfig::WebUIConfig(base::StringPiece scheme, base::StringPiece host) +WebUIConfig::WebUIConfig(std::string_view scheme, std::string_view host) : scheme_(scheme), host_(host) {} WebUIConfig::~WebUIConfig() = default;
diff --git a/content/public/browser/webui_config.h b/content/public/browser/webui_config.h index e138e57..a6ae1c2 100644 --- a/content/public/browser/webui_config.h +++ b/content/public/browser/webui_config.h
@@ -7,8 +7,8 @@ #include <memory> #include <string> +#include <string_view> -#include "base/strings/string_piece.h" #include "content/common/content_export.h" #include "url/gurl.h" @@ -31,7 +31,7 @@ // all existing WebUI pages use this. class CONTENT_EXPORT WebUIConfig { public: - explicit WebUIConfig(base::StringPiece scheme, base::StringPiece host); + explicit WebUIConfig(std::string_view scheme, std::string_view host); virtual ~WebUIConfig(); WebUIConfig(const WebUIConfig&) = delete; WebUIConfig& operator=(const WebUIConfig&) = delete; @@ -76,7 +76,7 @@ template <typename T> class CONTENT_EXPORT DefaultWebUIConfig : public WebUIConfig { public: - explicit DefaultWebUIConfig(base::StringPiece scheme, base::StringPiece host) + explicit DefaultWebUIConfig(std::string_view scheme, std::string_view host) : WebUIConfig(scheme, host) {} ~DefaultWebUIConfig() override = default;
diff --git a/content/public/common/content_client.cc b/content/public/common/content_client.cc index 617960a..c558c75 100644 --- a/content/public/common/content_client.cc +++ b/content/public/common/content_client.cc
@@ -4,10 +4,11 @@ #include "content/public/common/content_client.h" +#include <string_view> + #include "base/memory/ref_counted_memory.h" #include "base/no_destructor.h" #include "base/notreached.h" -#include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/values.h" @@ -108,10 +109,10 @@ return std::u16string(); } -base::StringPiece ContentClient::GetDataResource( +std::string_view ContentClient::GetDataResource( int resource_id, ui::ResourceScaleFactor scale_factor) { - return base::StringPiece(); + return std::string_view(); } base::RefCountedMemory* ContentClient::GetDataResourceBytes(int resource_id) {
diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h index 2387517..42d7889 100644 --- a/content/public/common/content_client.h +++ b/content/public/common/content_client.h
@@ -7,11 +7,11 @@ #include <set> #include <string> +#include <string_view> #include <vector> #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #include "content/common/content_export.h" #include "mojo/public/cpp/system/message_pipe.h" @@ -167,7 +167,7 @@ const std::u16string& replacement); // Return the contents of a resource in a StringPiece given the resource id. - virtual base::StringPiece GetDataResource( + virtual std::string_view GetDataResource( int resource_id, ui::ResourceScaleFactor scale_factor);
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index e8553ec..5f083d5e 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -837,48 +837,6 @@ &kProcessPerSiteUpToMainFrameThreshold, "ProcessPerSiteMainFrameAllowDevToolsAttached", false}; -// Enables bypassing the service worker fetch handler. This feature starts the -// service worker for subsequent requests. -BASE_FEATURE(kServiceWorkerBypassFetchHandler, - "ServiceWorkerBypassFetchHandler", - base::FEATURE_DISABLED_BY_DEFAULT); - -const base::FeatureParam<ServiceWorkerBypassFetchHandlerStrategy>::Option - service_worker_bypass_fetch_handler_strategy_options[] = { - {ServiceWorkerBypassFetchHandlerStrategy::kFeatureOptIn, "optin"}, - {ServiceWorkerBypassFetchHandlerStrategy::kAllowList, "allowlist"}}; -const base::FeatureParam<ServiceWorkerBypassFetchHandlerStrategy> - kServiceWorkerBypassFetchHandlerStrategy{ - &kServiceWorkerBypassFetchHandler, "strategy", - ServiceWorkerBypassFetchHandlerStrategy::kFeatureOptIn, - &service_worker_bypass_fetch_handler_strategy_options}; - -const base::FeatureParam<ServiceWorkerBypassFetchHandlerTarget>::Option - service_worker_bypass_fetch_handler_target_options[] = { - { - ServiceWorkerBypassFetchHandlerTarget::kMainResource, - "main_resource", - }, - { - ServiceWorkerBypassFetchHandlerTarget:: - kAllOnlyIfServiceWorkerNotStarted, - "all_only_if_service_worker_not_started", - }, - { - ServiceWorkerBypassFetchHandlerTarget::kAllWithRaceNetworkRequest, - "all_with_race_network_request", - }, - { - ServiceWorkerBypassFetchHandlerTarget::kSubResource, - "sub_resource", - }, -}; -const base::FeatureParam<ServiceWorkerBypassFetchHandlerTarget> - kServiceWorkerBypassFetchHandlerTarget{ - &kServiceWorkerBypassFetchHandler, "bypass_for", - ServiceWorkerBypassFetchHandlerTarget::kMainResource, - &service_worker_bypass_fetch_handler_target_options}; - // Enables ServiceWorker static routing API. // https://github.com/WICG/service-worker-static-routing-api BASE_FEATURE(kServiceWorkerStaticRouter,
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index eea5cdde..8ce1af1 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -208,53 +208,6 @@ CONTENT_EXPORT extern const base::FeatureParam<base::TimeDelta> kSiteIsolationForCrossOriginOpenerPolicyExpirationTimeoutParam; CONTENT_EXPORT BASE_DECLARE_FEATURE(kDisableProcessReuse); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kServiceWorkerBypassFetchHandler); -// ServiceWorkerBypassFetchHandlerStrategy provides the info how to decide if -// the request should bypass fetch handlers or not. -enum class ServiceWorkerBypassFetchHandlerStrategy { - // Use the allowlist provided by - // kServiceWorkerBypassFetchHandlerBypassedOrigins. If the request url's - // origin is in the list, fetch handlers are bypassed. - kAllowList, - - // This option is to run the feature locally for the debugging purpose. It is - // used for the feature toggle in about:flags etc. It simply bypasses fetch - // handlers for all the main resource requests regardless of the url while the - // feature is enabled. - // - // This is set as a default value, but the origin trial uses a different - // mechanism to enable the feature per origin. When the feature is enabled by - // the origin trial, ServiceWorkerVersion in content/browser should contain - // the origin trial token. If the browser successfully confirm the token, - // fetch handlers are always bypassed regardless of - // ServiceWorkerBypassFetchHandlerStrategy. - kFeatureOptIn, -}; -CONTENT_EXPORT extern const base::FeatureParam< - ServiceWorkerBypassFetchHandlerStrategy> - kServiceWorkerBypassFetchHandlerStrategy; -enum class ServiceWorkerBypassFetchHandlerTarget { - // Bypass fetch handlers for main resource (navigation) requests. Fetch - // handlers will be bypassed regardless of the current ServiceWorker running - // status. - kMainResource, - // If the ServiceWorker is not started yet when the main resource request - // happens, it bypasses fetch handlers for the main resource and subsequent - // subresources. If the ServiceWorker is running, it invokes fetch handlers as - // usual. - kAllOnlyIfServiceWorkerNotStarted, - // BestEffortServiceWorker(crbug.com/1420517). It allows the browser to - // dispatch a request directly to the network even if there is a registered - // ServiceWorker. This behavior races the network request and the - // ServiceWorker fetch handler and uses the result of whichever is faster. - kAllWithRaceNetworkRequest, - // Bypass fetch handlers for subresource requests. Fetch handlers will be - // bypassed regardless of the current ServiceWorker running status. - kSubResource, -}; -CONTENT_EXPORT extern const base::FeatureParam< - ServiceWorkerBypassFetchHandlerTarget> - kServiceWorkerBypassFetchHandlerTarget; CONTENT_EXPORT BASE_DECLARE_FEATURE(kServiceWorkerStaticRouter); CONTENT_EXPORT BASE_DECLARE_FEATURE(kUserMediaCaptureOnFocus); CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebLockScreenApi);
diff --git a/content/public/common/pseudonymization_util.cc b/content/public/common/pseudonymization_util.cc index 3ebf6e2d..04c5ad5d 100644 --- a/content/public/common/pseudonymization_util.cc +++ b/content/public/common/pseudonymization_util.cc
@@ -6,20 +6,21 @@ #include <string.h> +#include <string_view> + #include "base/hash/sha1.h" -#include "base/strings/string_piece.h" #include "content/common/pseudonymization_salt.h" namespace content { // static uint32_t PseudonymizationUtil::PseudonymizeStringForTesting( - base::StringPiece string) { + std::string_view string) { return PseudonymizeString(string); } // static -uint32_t PseudonymizationUtil::PseudonymizeString(base::StringPiece string) { +uint32_t PseudonymizationUtil::PseudonymizeString(std::string_view string) { // Include `string` in the SHA1 hash. base::SHA1Context sha1_context; base::SHA1Init(sha1_context); @@ -32,7 +33,7 @@ // retained or sent anywhere). uint32_t salt = GetPseudonymizationSalt(); base::SHA1Update( - base::StringPiece(reinterpret_cast<const char*>(&salt), sizeof(salt)), + std::string_view(reinterpret_cast<const char*>(&salt), sizeof(salt)), sha1_context); // Compute the SHA1 hash.
diff --git a/content/public/common/pseudonymization_util.h b/content/public/common/pseudonymization_util.h index 5a919e9..e73602a 100644 --- a/content/public/common/pseudonymization_util.h +++ b/content/public/common/pseudonymization_util.h
@@ -5,10 +5,10 @@ #ifndef CONTENT_PUBLIC_COMMON_PSEUDONYMIZATION_UTIL_H_ #define CONTENT_PUBLIC_COMMON_PSEUDONYMIZATION_UTIL_H_ -#include "stdint.h" +#include <string_view> -#include "base/strings/string_piece.h" #include "content/common/content_export.h" +#include "stdint.h" // Forward-declarations of classes approved for using the PseudonymizationUtil. // @@ -31,7 +31,7 @@ public: // This is a test only interface that is identical to the public interface, // but does not require friending. - static uint32_t PseudonymizeStringForTesting(base::StringPiece string); + static uint32_t PseudonymizeStringForTesting(std::string_view string); private: // Pseudonymizes the input `string` by passing it through a one-way hash @@ -46,7 +46,7 @@ // and Renderer processes). // // This method is thread-safe - it can be called on any thread. - static uint32_t PseudonymizeString(base::StringPiece string); + static uint32_t PseudonymizeString(std::string_view string); // NOTE: All usages of the PseudonymizationUtil class should be reviewed by // chrome-privacy-core@google.com (and when approved added to the friend list
diff --git a/content/public/common/user_agent.h b/content/public/common/user_agent.h index 714ad81..323f5db4 100644 --- a/content/public/common/user_agent.h +++ b/content/public/common/user_agent.h
@@ -7,7 +7,6 @@ #include <string> -#include "base/strings/string_piece.h" #include "build/build_config.h" #include "content/common/content_export.h"
diff --git a/content/public/test/back_forward_cache_util.h b/content/public/test/back_forward_cache_util.h index 4b65bb2..6031eba1 100644 --- a/content/public/test/back_forward_cache_util.h +++ b/content/public/test/back_forward_cache_util.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/feature_list.h" -#include "base/strings/string_piece.h" #include "base/test/scoped_feature_list.h" #include "content/public/browser/back_forward_cache.h"
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 96a94fc..0c518ce 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -8,6 +8,7 @@ #include <cstdint> #include <set> +#include <string_view> #include <tuple> #include <utility> @@ -27,7 +28,6 @@ #include "base/strings/pattern.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" @@ -351,7 +351,7 @@ // Replace the host of the URL with the one passed in the URL. GURL::Replacements replace_host; - replace_host.SetHostStr(base::StringPiece(params).substr(0, slash)); + replace_host.SetHostStr(std::string_view(params).substr(0, slash)); GURL redirect_server = test_server->base_url().ReplaceComponents(replace_host); @@ -653,7 +653,7 @@ } bool NavigateIframeToURL(WebContents* web_contents, - base::StringPiece iframe_id, + std::string_view iframe_id, const GURL& url) { TestNavigationObserver load_observer(web_contents); bool result = BeginNavigateIframeToURL(web_contents, iframe_id, url); @@ -662,7 +662,7 @@ } bool BeginNavigateIframeToURL(WebContents* web_contents, - base::StringPiece iframe_id, + std::string_view iframe_id, const GURL& url) { std::string script = base::StrCat({"setTimeout(\"var iframes = document.getElementById('", @@ -707,7 +707,7 @@ } GURL GetFileUrlWithQuery(const base::FilePath& path, - base::StringPiece query_string) { + std::string_view query_string) { GURL url = net::FilePathToFileURL(path); if (!query_string.empty()) { GURL::Replacements replacements; @@ -970,7 +970,7 @@ gfx::PointF GetCenterCoordinatesOfElementWithId( const ToRenderFrameHost& adapter, - base::StringPiece id) { + std::string_view id) { float x = EvalJs(adapter, JsReplace("const bounds = " "document.getElementById($1)." @@ -989,7 +989,7 @@ } void SimulateMouseClickOrTapElementWithId(content::WebContents* web_contents, - base::StringPiece id) { + std::string_view id) { gfx::Point point = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents, id)); @@ -1427,7 +1427,7 @@ } void ExecuteScriptAsync(const ToRenderFrameHost& adapter, - base::StringPiece script) { + std::string_view script) { // Prerendering pages will never have user gesture. if (adapter.render_frame_host()->GetLifecycleState() == RenderFrameHost::LifecycleState::kPrerendering) { @@ -1439,13 +1439,13 @@ } void ExecuteScriptAsyncWithoutUserGesture(const ToRenderFrameHost& adapter, - base::StringPiece script) { + std::string_view script) { adapter.render_frame_host()->ExecuteJavaScriptForTests( base::UTF8ToUTF16(script), base::NullCallback()); } // EvalJsResult methods. -EvalJsResult::EvalJsResult(base::Value value, base::StringPiece error) +EvalJsResult::EvalJsResult(base::Value value, std::string_view error) : value(error.empty() ? std::move(value) : base::Value()), error(error) {} EvalJsResult::EvalJsResult(const EvalJsResult& other) @@ -1519,9 +1519,9 @@ // // TODO(nick): Elide snippets to 80 chars, since it is common for sources to not // include newlines. -std::string AnnotateAndAdjustJsStackTraces(base::StringPiece js_error, +std::string AnnotateAndAdjustJsStackTraces(std::string_view js_error, std::string source_name, - base::StringPiece source, + std::string_view source, int column_adjustment_for_line_one) { // Escape wildcards in |source_name| for use in MatchPattern. base::ReplaceChars(source_name, "\\", "\\\\", &source_name); @@ -1529,7 +1529,7 @@ base::ReplaceChars(source_name, "?", "\\?", &source_name); // This vector maps line numbers to the corresponding text in |source|. - const std::vector<base::StringPiece> source_lines = base::SplitStringPiece( + const std::vector<std::string_view> source_lines = base::SplitStringPiece( source, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); // |source_frame_pattern| should match any line that looks like a stack frame @@ -1540,19 +1540,19 @@ // This is the amount of indentation that is applied to the lines of inserted // annotations. const std::string indent(8, ' '); - const base::StringPiece elision_mark = ""; + const std::string_view elision_mark = ""; // Loop over each line of |js_error|, and append each to |annotated_error| -- // possibly rewriting to include extra context. std::ostringstream annotated_error; - for (const base::StringPiece& error_line : base::SplitStringPiece( + for (const std::string_view& error_line : base::SplitStringPiece( js_error, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) { // Does this look like a stack frame whose URL source matches |source_name|? if (base::MatchPattern(error_line, source_frame_pattern)) { // When a match occurs, annotate the stack trace with the corresponding // line from |source|, along with a ^^^ underneath, indicating the column // position. - std::vector<base::StringPiece> error_line_parts = base::SplitStringPiece( + std::vector<std::string_view> error_line_parts = base::SplitStringPiece( error_line, ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); CHECK_GE(error_line_parts.size(), 2u); @@ -1680,8 +1680,8 @@ EvalJsResult EvalJsRunner( const ToRenderFrameHost& execution_target, - base::StringPiece script, - base::StringPiece source_url, + std::string_view script, + std::string_view source_url, int options, int32_t world_id, base::OnceClosure after_script_invoke = base::DoNothing()) { @@ -1732,7 +1732,7 @@ } // namespace ::testing::AssertionResult ExecJs(const ToRenderFrameHost& execution_target, - base::StringPiece script, + std::string_view script, int options, int32_t world_id) { // TODO(nick): Do we care enough about folks shooting themselves in the foot @@ -1748,7 +1748,7 @@ } EvalJsResult EvalJs(const ToRenderFrameHost& execution_target, - base::StringPiece script, + std::string_view script, int options, int32_t world_id, base::OnceClosure after_script_invoke) { @@ -1771,8 +1771,8 @@ EvalJsResult EvalJsAfterLifecycleUpdate( const ToRenderFrameHost& execution_target, - base::StringPiece raf_script, - base::StringPiece script, + std::string_view raf_script, + std::string_view script, int options, int32_t world_id) { TRACE_EVENT2("test", "EvalJsAfterLifecycleUpdate", "raf_script", raf_script, @@ -1840,7 +1840,7 @@ return rfh; } -bool FrameMatchesName(base::StringPiece name, RenderFrameHost* frame) { +bool FrameMatchesName(std::string_view name, RenderFrameHost* frame) { return frame->GetFrameName() == name; } @@ -2102,7 +2102,7 @@ } bool AccessibilityTreeContainsNodeWithName(BrowserAccessibility* node, - base::StringPiece name) { + std::string_view name) { // If an image annotation is set, it plays the same role as a name, so it // makes sense to check both in the same test helper. if (node->GetStringAttribute(ax::mojom::StringAttribute::kName) == name || @@ -2123,7 +2123,7 @@ } void WaitForAccessibilityTreeToContainNodeWithName(WebContents* web_contents, - base::StringPiece name) { + std::string_view name) { WebContentsImpl* web_contents_impl = static_cast<WebContentsImpl*>(web_contents); RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>( @@ -2424,7 +2424,7 @@ RenderProcessHostKillWaiter::RenderProcessHostKillWaiter( RenderProcessHost* render_process_host, - base::StringPiece uma_name) + std::string_view uma_name) : exit_watcher_(render_process_host, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT), uma_name_(uma_name) {} @@ -3567,7 +3567,7 @@ void DevToolsInspectorLogWatcher::DispatchProtocolMessage( DevToolsAgentHost* host, base::span<const uint8_t> message) { - base::StringPiece message_str(reinterpret_cast<const char*>(message.data()), + std::string_view message_str(reinterpret_cast<const char*>(message.data()), message.size()); auto parsed_message = std::move(base::JSONReader::Read(message_str)->GetDict());
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 0d104b32..d7e7400 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -8,6 +8,7 @@ #include <memory> #include <optional> #include <string> +#include <string_view> #include <utility> #include <vector> @@ -23,7 +24,6 @@ #include "base/process/process.h" #include "base/run_loop.h" #include "base/scoped_observation.h" -#include "base/strings/string_piece.h" #include "base/template_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/types/strong_alias.h" @@ -256,18 +256,18 @@ // necessary, a user activation can be triggered right before calling this // method, e.g. by calling |ExecJs(frame_tree_node, "")|. bool NavigateIframeToURL(WebContents* web_contents, - base::StringPiece iframe_id, + std::string_view iframe_id, const GURL& url); // Similar to |NavigateIframeToURL()| but returns as soon as the navigation is // initiated. bool BeginNavigateIframeToURL(WebContents* web_contents, - base::StringPiece iframe_id, + std::string_view iframe_id, const GURL& url); // Generate a URL for a file path including a query string. GURL GetFileUrlWithQuery(const base::FilePath& path, - base::StringPiece query_string); + std::string_view query_string); // Checks whether the page type of the last committed navigation entry matches // |page_type|. @@ -359,12 +359,12 @@ // friendly by taking zooming into account. gfx::PointF GetCenterCoordinatesOfElementWithId( const ToRenderFrameHost& adapter, - base::StringPiece id); + std::string_view id); // Retrieves the center coordinates of the element with id |id| and simulates a // mouse click there using SimulateMouseClickAt(). void SimulateMouseClickOrTapElementWithId(content::WebContents* web_contents, - base::StringPiece id); + std::string_view id); // Simulates asynchronously a mouse enter/move/leave event. The mouse event is // routed through RenderWidgetHostInputEventRouter and thus can target OOPIFs. @@ -622,12 +622,12 @@ // - EvalJs (if you want to retrieve a value) // - DOMMessageQueue (to manually wait for domAutomationController.send(...)) void ExecuteScriptAsync(const ToRenderFrameHost& adapter, - base::StringPiece script); + std::string_view script); // Same as `content::ExecuteScriptAsync()`, but doesn't send a user gesture to // the renderer. void ExecuteScriptAsyncWithoutUserGesture(const ToRenderFrameHost& adapter, - base::StringPiece script); + std::string_view script); // JsLiteralHelper is a helper class that determines what types are legal to // pass to StringifyJsLiteral. Legal types include int, string, StringPiece, @@ -705,7 +705,7 @@ // This becomes "window.location.reload(true);" -- because bool values are // supported by base::Value. Numbers, lists, and dicts also work. template <typename... Args> -std::string JsReplace(base::StringPiece script_template, Args&&... args) { +std::string JsReplace(std::string_view script_template, Args&&... args) { base::Value::List values = ListValueOf(std::forward<Args>(args)...).TakeList(); std::vector<std::string> replacements(values.size()); @@ -744,7 +744,7 @@ // Creates an EvalJs result. If |error| is non-empty, |value| will be // ignored. - EvalJsResult(base::Value value, base::StringPiece error); + EvalJsResult(base::Value value, std::string_view error); // Copy ctor. EvalJsResult(const EvalJsResult& value); @@ -906,7 +906,7 @@ // It is guaranteed that EvalJs works even when the target frame is frozen. [[nodiscard]] EvalJsResult EvalJs( const ToRenderFrameHost& execution_target, - base::StringPiece script, + std::string_view script, int options = EXECUTE_SCRIPT_DEFAULT_OPTIONS, int32_t world_id = ISOLATED_WORLD_ID_GLOBAL, base::OnceClosure after_script_invoke = base::DoNothing()); @@ -918,8 +918,8 @@ // processed by the browser. [[nodiscard]] EvalJsResult EvalJsAfterLifecycleUpdate( const ToRenderFrameHost& execution_target, - base::StringPiece raf_script, - base::StringPiece script, + std::string_view raf_script, + std::string_view script, int options = EXECUTE_SCRIPT_DEFAULT_OPTIONS, int32_t world_id = ISOLATED_WORLD_ID_GLOBAL); @@ -933,7 +933,7 @@ // until it resolves (by default). [[nodiscard]] ::testing::AssertionResult ExecJs( const ToRenderFrameHost& execution_target, - base::StringPiece script, + std::string_view script, int options = EXECUTE_SCRIPT_DEFAULT_OPTIONS, int32_t world_id = ISOLATED_WORLD_ID_GLOBAL); @@ -952,7 +952,7 @@ base::RepeatingCallback<bool(RenderFrameHost*)> predicate); // Predicates for use with FrameMatchingPredicate[OrNullPtr](). -bool FrameMatchesName(base::StringPiece name, RenderFrameHost* frame); +bool FrameMatchesName(std::string_view name, RenderFrameHost* frame); bool FrameIsChildOfMainFrame(RenderFrameHost* frame); bool FrameHasSourceUrl(const GURL& url, RenderFrameHost* frame); @@ -1077,7 +1077,7 @@ // WaitForAccessibilityTreeToChange, above, and then checks again. // Keeps looping until the text is found (or the test times out). void WaitForAccessibilityTreeToContainNodeWithName(WebContents* web_contents, - base::StringPiece name); + std::string_view name); // Get a snapshot of a web page's accessibility tree. ui::AXTreeUpdate GetAccessibilityTreeSnapshot(WebContents* web_contents); @@ -1249,7 +1249,7 @@ // |uma_name| is the name of the histogram from which the |bad_message_reason| // can be extracted. RenderProcessHostKillWaiter(RenderProcessHost* render_process_host, - base::StringPiece uma_name); + std::string_view uma_name); RenderProcessHostKillWaiter(const RenderProcessHostKillWaiter&) = delete; RenderProcessHostKillWaiter& operator=(const RenderProcessHostKillWaiter&) =
diff --git a/content/public/test/content_browser_test_content_browser_client.cc b/content/public/test/content_browser_test_content_browser_client.cc index a6d58e47..44d6198f 100644 --- a/content/public/test/content_browser_test_content_browser_client.cc +++ b/content/public/test/content_browser_test_content_browser_client.cc
@@ -4,6 +4,8 @@ #include "content/public/test/content_browser_test_content_browser_client.h" +#include <string_view> + #include "base/test/task_environment.h" #include "content/public/common/content_client.h" @@ -32,7 +34,7 @@ } bool ContentBrowserTestContentBrowserClient::CreateThreadPool( - base::StringPiece name) { + std::string_view name) { // Injects a test TaskTracker to watch for long-running tasks and produce a // useful timeout message in order to find the cause of flaky timeout tests. base::test::TaskEnvironment::CreateThreadPool();
diff --git a/content/public/test/content_browser_test_content_browser_client.h b/content/public/test/content_browser_test_content_browser_client.h index 833e9f3a..5940061 100644 --- a/content/public/test/content_browser_test_content_browser_client.h +++ b/content/public/test/content_browser_test_content_browser_client.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_CONTENT_BROWSER_CLIENT_H_ #define CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_CONTENT_BROWSER_CLIENT_H_ +#include <string_view> + #include "content/shell/browser/shell_content_browser_client.h" namespace content { @@ -19,7 +21,7 @@ ContentBrowserTestContentBrowserClient(); ~ContentBrowserTestContentBrowserClient() override; - bool CreateThreadPool(base::StringPiece name) override; + bool CreateThreadPool(std::string_view name) override; void OnNetworkServiceCreated( network::mojom::NetworkService* network_service) override; };
diff --git a/content/public/test/content_test_suite_base.cc b/content/public/test/content_test_suite_base.cc index ecbbe6ff..62829d2 100644 --- a/content/public/test/content_test_suite_base.cc +++ b/content/public/test/content_test_suite_base.cc
@@ -11,7 +11,6 @@ #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/path_service.h" -#include "base/strings/string_piece.h" #include "base/test/test_suite.h" #include "build/build_config.h" #include "content/browser/gpu/gpu_main_thread_factory.h"
diff --git a/content/public/test/scoped_page_focus_override.cc b/content/public/test/scoped_page_focus_override.cc index 2e9c4d08..e3f8803 100644 --- a/content/public/test/scoped_page_focus_override.cc +++ b/content/public/test/scoped_page_focus_override.cc
@@ -7,6 +7,7 @@ #include <memory> #include <optional> #include <string> +#include <string_view> #include "base/containers/span.h" #include "base/functional/callback.h" @@ -33,8 +34,8 @@ void ScopedPageFocusOverride::DispatchProtocolMessage( DevToolsAgentHost* agent_host, base::span<const uint8_t> message) { - base::StringPiece message_str(reinterpret_cast<const char*>(message.data()), - message.size()); + std::string_view message_str(reinterpret_cast<const char*>(message.data()), + message.size()); std::optional<base::Value> parsed_message = base::JSONReader::Read(message_str); ASSERT_TRUE(parsed_message.has_value());
diff --git a/content/public/test/test_devtools_protocol_client.cc b/content/public/test/test_devtools_protocol_client.cc index c5fefc9..14fdff1 100644 --- a/content/public/test/test_devtools_protocol_client.cc +++ b/content/public/test/test_devtools_protocol_client.cc
@@ -5,6 +5,7 @@ #include "content/public/test/test_devtools_protocol_client.h" #include <memory> +#include <string_view> #include "base/auto_reset.h" #include "base/json/json_reader.h" @@ -152,8 +153,8 @@ void TestDevToolsProtocolClient::DispatchProtocolMessage( DevToolsAgentHost* agent_host, base::span<const uint8_t> message) { - base::StringPiece message_str(reinterpret_cast<const char*>(message.data()), - message.size()); + std::string_view message_str(reinterpret_cast<const char*>(message.data()), + message.size()); base::Value parsed = *base::JSONReader::Read(message_str); if (std::optional<int> id = parsed.GetDict().FindInt("id")) { received_responses_count_++;
diff --git a/content/public/test/test_web_ui.cc b/content/public/test/test_web_ui.cc index 1a17b54..eafb973 100644 --- a/content/public/test/test_web_ui.cc +++ b/content/public/test/test_web_ui.cc
@@ -4,13 +4,13 @@ #include "content/public/test/test_web_ui.h" +#include <string_view> #include <utility> #include "base/functional/callback.h" #include "base/memory/ptr_util.h" #include "base/no_destructor.h" #include "base/notreached.h" -#include "base/strings/string_piece.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_message_handler.h" @@ -90,7 +90,7 @@ handlers_.push_back(std::move(handler)); } -void TestWebUI::RegisterMessageCallback(base::StringPiece message, +void TestWebUI::RegisterMessageCallback(std::string_view message, MessageCallback callback) { message_callbacks_[static_cast<std::string>(message)].push_back( std::move(callback)); @@ -113,13 +113,13 @@ return true; } -void TestWebUI::CallJavascriptFunctionUnsafe(base::StringPiece function_name) { +void TestWebUI::CallJavascriptFunctionUnsafe(std::string_view function_name) { call_data_.push_back(base::WrapUnique(new CallData(function_name))); OnJavascriptCall(*call_data_.back()); } void TestWebUI::CallJavascriptFunctionUnsafe( - base::StringPiece function_name, + std::string_view function_name, base::span<const base::ValueView> args) { call_data_.push_back(base::WrapUnique(new CallData(function_name))); for (const auto& arg : args) { @@ -138,7 +138,7 @@ return &handlers_; } -TestWebUI::CallData::CallData(base::StringPiece function_name) +TestWebUI::CallData::CallData(std::string_view function_name) : function_name_(function_name.data(), function_name.size()) {} TestWebUI::CallData::~CallData() {
diff --git a/content/public/test/test_web_ui.h b/content/public/test/test_web_ui.h index d78dcf2..a89e775 100644 --- a/content/public/test/test_web_ui.h +++ b/content/public/test/test_web_ui.h
@@ -6,6 +6,7 @@ #define CONTENT_PUBLIC_TEST_TEST_WEB_UI_H_ #include <memory> +#include <string_view> #include <vector> #include "base/containers/flat_map.h" @@ -53,22 +54,22 @@ const std::vector<std::string>& GetRequestableSchemes() override; void AddRequestableScheme(const char* scheme) override; void AddMessageHandler(std::unique_ptr<WebUIMessageHandler> handler) override; - void RegisterMessageCallback(base::StringPiece message, + void RegisterMessageCallback(std::string_view message, MessageCallback callback) override; void ProcessWebUIMessage(const GURL& source_url, const std::string& message, base::Value::List args) override; bool CanCallJavascript() override; - void CallJavascriptFunctionUnsafe(base::StringPiece function_name) override; + void CallJavascriptFunctionUnsafe(std::string_view function_name) override; void CallJavascriptFunctionUnsafe( - base::StringPiece function_name, + std::string_view function_name, base::span<const base::ValueView> args) override; std::vector<std::unique_ptr<WebUIMessageHandler>>* GetHandlersForTesting() override; class CallData { public: - explicit CallData(base::StringPiece function_name); + explicit CallData(std::string_view function_name); ~CallData(); void AppendArgument(base::Value arg);
diff --git a/content/public/test/url_loader_interceptor.cc b/content/public/test/url_loader_interceptor.cc index 7bad6b3..b262c24 100644 --- a/content/public/test/url_loader_interceptor.cc +++ b/content/public/test/url_loader_interceptor.cc
@@ -5,6 +5,7 @@ #include "content/public/test/url_loader_interceptor.h" #include <string> +#include <string_view> #include <utility> #include "base/containers/unique_ptr_adapters.h" @@ -467,8 +468,8 @@ } void URLLoaderInterceptor::WriteResponse( - base::StringPiece headers, - base::StringPiece body, + std::string_view headers, + std::string_view body, network::mojom::URLLoaderClient* client, std::optional<net::SSLInfo> ssl_info, std::optional<GURL> url) {
diff --git a/content/public/test/url_loader_interceptor.h b/content/public/test/url_loader_interceptor.h index 8422a5f5..f623bf24 100644 --- a/content/public/test/url_loader_interceptor.h +++ b/content/public/test/url_loader_interceptor.h
@@ -9,11 +9,11 @@ #include <optional> #include <set> #include <string> +#include <string_view> #include "base/files/file_path.h" #include "base/functional/callback_helpers.h" #include "base/memory/scoped_refptr.h" -#include "base/strings/string_piece.h" #include "base/synchronization/lock.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -120,8 +120,8 @@ // Helper methods for use when intercepting. // Writes the given response body, header, and SSL Info to `client`. // If `url` is present, also computes the ParsedHeaders for the response. - static void WriteResponse(base::StringPiece headers, - base::StringPiece body, + static void WriteResponse(std::string_view headers, + std::string_view body, network::mojom::URLLoaderClient* client, std::optional<net::SSLInfo> ssl_info = std::nullopt, std::optional<GURL> url = std::nullopt);
diff --git a/content/public/test/web_ui_browsertest_util.cc b/content/public/test/web_ui_browsertest_util.cc index 5710948..c0baed3 100644 --- a/content/public/test/web_ui_browsertest_util.cc +++ b/content/public/test/web_ui_browsertest_util.cc
@@ -6,6 +6,7 @@ #include <memory> #include <string> +#include <string_view> #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -233,7 +234,7 @@ url::kStandardSchemeSeparator + host_and_path); } -TestWebUIConfig::TestWebUIConfig(base::StringPiece host) +TestWebUIConfig::TestWebUIConfig(std::string_view host) : WebUIConfig(content::kChromeUIScheme, host) {} std::unique_ptr<WebUIController> TestWebUIConfig::CreateWebUIController(
diff --git a/content/public/test/web_ui_browsertest_util.h b/content/public/test/web_ui_browsertest_util.h index 02731a5..9cdaf34 100644 --- a/content/public/test/web_ui_browsertest_util.h +++ b/content/public/test/web_ui_browsertest_util.h
@@ -8,6 +8,7 @@ #include <memory> #include <optional> #include <string> +#include <string_view> #include <utility> #include "content/public/browser/web_ui_controller.h" @@ -46,7 +47,7 @@ class TestWebUIConfig : public content::WebUIConfig { public: - explicit TestWebUIConfig(base::StringPiece host); + explicit TestWebUIConfig(std::string_view host); ~TestWebUIConfig() override = default;
diff --git a/content/renderer/accessibility/annotations/ax_image_annotator.cc b/content/renderer/accessibility/annotations/ax_image_annotator.cc index 2ff1771..bb6c8a4 100644 --- a/content/renderer/accessibility/annotations/ax_image_annotator.cc +++ b/content/renderer/accessibility/annotations/ax_image_annotator.cc
@@ -5,6 +5,7 @@ #include "content/renderer/accessibility/annotations/ax_image_annotator.h" #include <string> +#include <string_view> #include <utility> #include <vector> @@ -58,7 +59,7 @@ int GetMessageIdForIconEnum(const std::string& icon_type) { static constexpr auto kIconTypeToMessageIdMap = - base::MakeFixedFlatMap<base::StringPiece, int>({ + base::MakeFixedFlatMap<std::string_view, int>({ {"ICON_PLUS", IDS_AX_IMAGE_ANNOTATION_ICON_PLUS}, {"ICON_ARROW_BACKWARD", IDS_AX_IMAGE_ANNOTATION_ICON_ARROW_BACKWARD}, {"ICON_ARROW_FORWARD", IDS_AX_IMAGE_ANNOTATION_ICON_ARROW_FORWARD},
diff --git a/content/renderer/accessibility/annotations/ax_image_stopwords.cc b/content/renderer/accessibility/annotations/ax_image_stopwords.cc index 0187f8a..cb6b9b2 100644 --- a/content/renderer/accessibility/annotations/ax_image_stopwords.cc +++ b/content/renderer/accessibility/annotations/ax_image_stopwords.cc
@@ -5,6 +5,7 @@ #include "content/renderer/accessibility/annotations/ax_image_stopwords.h" #include <string> +#include <string_view> #include <vector> #include "base/containers/contains.h" @@ -12,7 +13,6 @@ #include "base/i18n/case_conversion.h" #include "base/i18n/char_iterator.h" #include "base/no_destructor.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "third_party/icu/source/common/unicode/uchar.h" @@ -507,7 +507,7 @@ // because it avoids ever needing to copy any of the strings; each StringPiece // is just a pointer into kImageStopwordsUtf8 and flat_set acts like a set but // basically just does a binary search. - std::vector<base::StringPiece> stopwords = + std::vector<std::string_view> stopwords = base::SplitStringPiece(kImageStopwordsUtf8, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
diff --git a/content/renderer/accessibility/annotations/ax_image_stopwords.h b/content/renderer/accessibility/annotations/ax_image_stopwords.h index 02fbd118..013bfbd5 100644 --- a/content/renderer/accessibility/annotations/ax_image_stopwords.h +++ b/content/renderer/accessibility/annotations/ax_image_stopwords.h
@@ -5,9 +5,10 @@ #ifndef CONTENT_RENDERER_ACCESSIBILITY_ANNOTATIONS_AX_IMAGE_STOPWORDS_H_ #define CONTENT_RENDERER_ACCESSIBILITY_ANNOTATIONS_AX_IMAGE_STOPWORDS_H_ +#include <string_view> + #include "base/containers/flat_set.h" #include "base/no_destructor.h" -#include "base/strings/string_piece.h" #include "content/common/content_export.h" namespace content { @@ -62,7 +63,7 @@ AXImageStopwords(); ~AXImageStopwords(); - base::flat_set<base::StringPiece> stopword_set_; + base::flat_set<std::string_view> stopword_set_; }; } // namespace content
diff --git a/content/renderer/gpu_benchmarking_extension.cc b/content/renderer/gpu_benchmarking_extension.cc index e2e3881..da85268d 100644 --- a/content/renderer/gpu_benchmarking_extension.cc +++ b/content/renderer/gpu_benchmarking_extension.cc
@@ -8,6 +8,7 @@ #include <memory> #include <string> +#include <string_view> #include <tuple> #include <utility> #include <vector> @@ -351,7 +352,7 @@ return std::nullopt; } -int ToKeyModifiers(const base::StringPiece& key) { +int ToKeyModifiers(const std::string_view& key) { if (key == "Alt") return blink::WebInputEvent::kAltKey; if (key == "Control") @@ -370,7 +371,7 @@ return 0; } -int ToButtonModifiers(const base::StringPiece& button) { +int ToButtonModifiers(const std::string_view& button) { if (button == "Left") return blink::WebMouseEvent::kLeftButtonDown; if (button == "Middle") @@ -850,9 +851,9 @@ return false; gfx::Vector2dF fling_velocity(0, 0); int modifiers = 0; - std::vector<base::StringPiece> key_list = base::SplitStringPiece( + std::vector<std::string_view> key_list = base::SplitStringPiece( keys_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - for (const base::StringPiece& key : key_list) { + for (const std::string_view& key : key_list) { int key_modifier = ToKeyModifiers(key); if (key_modifier == 0) { return false; @@ -938,9 +939,9 @@ gfx::Vector2dF distances(pixels_to_scroll_x, pixels_to_scroll_y); gfx::Vector2dF fling_velocity(0, 0); int modifiers = 0; - std::vector<base::StringPiece> key_list = base::SplitStringPiece( + std::vector<std::string_view> key_list = base::SplitStringPiece( keys_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - for (const base::StringPiece& key : key_list) { + for (const std::string_view& key : key_list) { int key_modifier = ToKeyModifiers(key); if (key_modifier == 0) { return false; @@ -948,9 +949,9 @@ modifiers |= key_modifier; } - std::vector<base::StringPiece> button_list = base::SplitStringPiece( + std::vector<std::string_view> button_list = base::SplitStringPiece( buttons_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - for (const base::StringPiece& button : button_list) { + for (const std::string_view& button : button_list) { int button_modifier = ToButtonModifiers(button); if (button_modifier == 0) { return false;
diff --git a/content/renderer/pepper/event_conversion.cc b/content/renderer/pepper/event_conversion.cc index ee6b1909d..a2cb3ef 100644 --- a/content/renderer/pepper/event_conversion.cc +++ b/content/renderer/pepper/event_conversion.cc
@@ -11,6 +11,7 @@ #include <algorithm> #include <memory> #include <string> +#include <string_view> #include "base/check_op.h" #include "base/feature_list.h" @@ -192,7 +193,7 @@ // Make a separate InputEventData for each Unicode character in the input. for (base::i18n::UTF16CharIterator iter( - base::StringPiece16(key_event.text, utf16_char_count)); + std::u16string_view(key_event.text, utf16_char_count)); !iter.end(); iter.Advance()) { InputEventData result = GetEventWithCommonFieldsAndType(event); result.event_modifiers = ConvertEventModifiers(key_event.GetModifiers());
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 66b99f7..0f373870 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -40,7 +40,6 @@ #include "base/ranges/algorithm.h" #include "base/run_loop.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -1448,7 +1447,7 @@ } bool RenderFrameImpl::UniqueNameFrameAdapter::IsCandidateUnique( - base::StringPiece name) const { + std::string_view name) const { // This method is currently O(N), where N = number of frames in the tree. DCHECK(!name.empty()); @@ -1484,7 +1483,7 @@ std::vector<std::string> RenderFrameImpl::UniqueNameFrameAdapter::CollectAncestorNames( BeginPoint begin_point, - bool (*should_stop)(base::StringPiece)) const { + bool (*should_stop)(std::string_view)) const { std::vector<std::string> result; for (blink::WebFrame* frame = begin_point == BeginPoint::kParentFrame ? GetWebFrame()->Parent()
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index d45223d..47100d8 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -1234,12 +1234,12 @@ // FrameAdapter overrides: bool IsMainFrame() const override; - bool IsCandidateUnique(base::StringPiece name) const override; + bool IsCandidateUnique(std::string_view name) const override; int GetSiblingCount() const override; int GetChildCount() const override; std::vector<std::string> CollectAncestorNames( BeginPoint begin_point, - bool (*should_stop)(base::StringPiece)) const override; + bool (*should_stop)(std::string_view)) const override; std::vector<int> GetFramePosition(BeginPoint begin_point) const override; private:
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index b4032a579..77dfb48 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -8,6 +8,7 @@ #include <map> #include <memory> #include <string> +#include <string_view> #include <utility> #include <vector> @@ -411,7 +412,7 @@ return true; if (!sanitized_host.empty()) { - std::vector<base::StringPiece> host_tokens = base::SplitStringPiece( + std::vector<std::string_view> host_tokens = base::SplitStringPiece( sanitized_host, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); if (host_tokens.size() >= 2) {
diff --git a/content/renderer/sandbox_mac_v2_unittest.mm b/content/renderer/sandbox_mac_v2_unittest.mm index dcb3abe..26136d52 100644 --- a/content/renderer/sandbox_mac_v2_unittest.mm +++ b/content/renderer/sandbox_mac_v2_unittest.mm
@@ -13,6 +13,8 @@ #include <sys/types.h> #include <unistd.h> +#include <string_view> + #include "base/apple/bundle_locations.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -114,8 +116,8 @@ CHECK(result) << error; // Test the properties of the sandbox profile. - constexpr base::StringPiece log_msg = "logged"; - CHECK(base::WriteFile(log_file, base::StringPiece(log_msg))); + constexpr std::string_view log_msg = "logged"; + CHECK(base::WriteFile(log_file, std::string_view(log_msg))); // Log file is write only. char read_buf[log_msg.size()]; CHECK_EQ(-1, base::ReadFile(log_file, read_buf, sizeof(read_buf)));
diff --git a/content/renderer/service_worker/service_worker_provider_context.cc b/content/renderer/service_worker/service_worker_provider_context.cc index e2146f1..59f28043 100644 --- a/content/renderer/service_worker/service_worker_provider_context.cc +++ b/content/renderer/service_worker/service_worker_provider_context.cc
@@ -64,36 +64,6 @@ std::move(pending_fallback_factory)), std::move(receiver), std::move(task_runner)); } - -// Returns the set of hash strings of fetch handlers which can be bypassed. -const base::flat_set<std::string> FetchHandlerBypassedHashStrings() { - const static base::NoDestructor<base::flat_set<std::string>> result( - base::SplitString( - features::kServiceWorkerBypassFetchHandlerBypassedHashStrings.Get(), - ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)); - - return *result; -} - -bool ShouldBypassFetchHandlerForSubresource( - std::optional<std::string> sha256_script_checksum) { - if (!base::FeatureList::IsEnabled( - features::kServiceWorkerBypassFetchHandler)) { - return false; - } - if (features::kServiceWorkerBypassFetchHandlerTarget.Get() != - features::ServiceWorkerBypassFetchHandlerTarget::kSubResource) { - return false; - } - - switch (features::kServiceWorkerBypassFetchHandlerStrategy.Get()) { - case features::ServiceWorkerBypassFetchHandlerStrategy::kFeatureOptIn: - return true; - case features::ServiceWorkerBypassFetchHandlerStrategy::kAllowList: - return FetchHandlerBypassedHashStrings().contains(sha256_script_checksum); - } -} - } // namespace ServiceWorkerProviderContext::ServiceWorkerProviderContext( @@ -158,21 +128,6 @@ blink::mojom::WebFeature::kServiceWorkerSkippedForSubresourceLoad); return nullptr; } - - if (fetch_handler_bypass_option_ == - blink::mojom::ServiceWorkerFetchHandlerBypassOption:: - kBypassOnlyIfServiceWorkerNotStarted) { - // If the fetch handler for the main resource is skipped by - // ServiceWorkerBypassFetchHandler, the fetch handler doesn't handle - // subresources too. - return nullptr; - } - - if (ShouldBypassFetchHandlerForSubresource(sha256_script_checksum_)) { - CountFeature(blink::mojom::WebFeature:: - kServiceWorkerBypassFetchHandlerForSubResource); - return nullptr; - } } if (!subresource_loader_factory_) {
diff --git a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc index 6c83cc7c..141f382 100644 --- a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc +++ b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -18,6 +18,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h" +#include "content/common/features.h" #include "content/public/common/content_features.h" #include "content/public/test/browser_task_environment.h" #include "content/renderer/service_worker/controller_service_worker_connector.h" @@ -978,9 +979,7 @@ DropController_RestartFetchEvent_RaceNetworkRequest) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeatureWithParameters( - features::kServiceWorkerBypassFetchHandler, - {{"strategy", "opt-in"}, - {"bypass_for", "all_with_race_network_request"}}); + features::kServiceWorkerAutoPreload, {{"strategy", "opt-in"}}); mojo::Remote<network::mojom::URLLoaderFactory> factory = CreateSubresourceLoaderFactory();
diff --git a/content/renderer/v8_value_converter_impl.cc b/content/renderer/v8_value_converter_impl.cc index 19b30cdc..277dc47 100644 --- a/content/renderer/v8_value_converter_impl.cc +++ b/content/renderer/v8_value_converter_impl.cc
@@ -10,6 +10,7 @@ #include <cmath> #include <memory> #include <string> +#include <string_view> #include <utility> #include <vector> @@ -261,7 +262,7 @@ return v8::Number::New(isolate, value); } - v8::Local<v8::Value> operator()(base::StringPiece value) { + v8::Local<v8::Value> operator()(std::string_view value) { return v8::String::NewFromUtf8(isolate, value.data(), v8::NewStringType::kNormal, value.length()) .ToLocalChecked();
diff --git a/content/services/auction_worklet/auction_v8_helper.cc b/content/services/auction_worklet/auction_v8_helper.cc index 6002aae..26479c1 100644 --- a/content/services/auction_worklet/auction_v8_helper.cc +++ b/content/services/auction_worklet/auction_v8_helper.cc
@@ -6,6 +6,7 @@ #include <limits> #include <memory> +#include <string_view> #include <utility> #include "base/check.h" @@ -401,7 +402,7 @@ } v8::MaybeLocal<v8::String> AuctionV8Helper::CreateUtf8String( - base::StringPiece utf8_string) { + std::string_view utf8_string) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!base::IsStringUTF8(utf8_string)) return v8::MaybeLocal<v8::String>(); @@ -412,7 +413,7 @@ v8::MaybeLocal<v8::Value> AuctionV8Helper::CreateValueFromJson( v8::Local<v8::Context> context, - base::StringPiece utf8_json) { + std::string_view utf8_json) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); v8::Local<v8::String> v8_string; if (!CreateUtf8String(utf8_json).ToLocal(&v8_string)) @@ -420,7 +421,7 @@ return v8::JSON::Parse(context, v8_string); } -bool AuctionV8Helper::AppendUtf8StringValue(base::StringPiece utf8_string, +bool AuctionV8Helper::AppendUtf8StringValue(std::string_view utf8_string, v8::LocalVector<v8::Value>* args) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); v8::Local<v8::String> value; @@ -431,7 +432,7 @@ } bool AuctionV8Helper::AppendJsonValue(v8::Local<v8::Context> context, - base::StringPiece utf8_json, + std::string_view utf8_json, v8::LocalVector<v8::Value>* args) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); v8::Local<v8::Value> value; @@ -441,7 +442,7 @@ return true; } -bool AuctionV8Helper::InsertValue(base::StringPiece key, +bool AuctionV8Helper::InsertValue(std::string_view key, v8::Local<v8::Value> value, v8::Local<v8::Object> object) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -454,8 +455,8 @@ } bool AuctionV8Helper::InsertJsonValue(v8::Local<v8::Context> context, - base::StringPiece key, - base::StringPiece utf8_json, + std::string_view key, + std::string_view utf8_json, v8::Local<v8::Object> object) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); v8::Local<v8::Value> v8_value; @@ -653,7 +654,7 @@ v8::Local<v8::Context> context, const DebugId* debug_id, const std::string& script_name, - base::StringPiece function_name, + std::string_view function_name, base::span<v8::Local<v8::Value>> args, TimeLimit* script_timeout, std::vector<std::string>& error_out) {
diff --git a/content/services/auction_worklet/auction_v8_helper.h b/content/services/auction_worklet/auction_v8_helper.h index 58dcfa3..78ff16c 100644 --- a/content/services/auction_worklet/auction_v8_helper.h +++ b/content/services/auction_worklet/auction_v8_helper.h
@@ -9,6 +9,7 @@ #include <memory> #include <optional> #include <string> +#include <string_view> #include <vector> #include "base/containers/span.h" @@ -18,7 +19,6 @@ #include "base/memory/ref_counted_delete_on_sequence.h" #include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" -#include "base/strings/string_piece.h" #include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" @@ -227,32 +227,32 @@ // Attempts to create a v8::String from a UTF-8 string. Returns empty string // if input is not UTF-8. - v8::MaybeLocal<v8::String> CreateUtf8String(base::StringPiece utf8_string); + v8::MaybeLocal<v8::String> CreateUtf8String(std::string_view utf8_string); // The passed in JSON must be a valid UTF-8 JSON string. v8::MaybeLocal<v8::Value> CreateValueFromJson(v8::Local<v8::Context> context, - base::StringPiece utf8_json); + std::string_view utf8_json); // Convenience wrappers around the above Create* methods. Attempt to create // the corresponding value type and append it to the passed in argument // vector. Useful for assembling arguments to a Javascript function. Return // false on failure. - [[nodiscard]] bool AppendUtf8StringValue(base::StringPiece utf8_string, + [[nodiscard]] bool AppendUtf8StringValue(std::string_view utf8_string, v8::LocalVector<v8::Value>* args); [[nodiscard]] bool AppendJsonValue(v8::Local<v8::Context> context, - base::StringPiece utf8_json, + std::string_view utf8_json, v8::LocalVector<v8::Value>* args); // Convenience wrapper that adds the specified value into the provided Object. - [[nodiscard]] bool InsertValue(base::StringPiece key, + [[nodiscard]] bool InsertValue(std::string_view key, v8::Local<v8::Value> value, v8::Local<v8::Object> object); // Convenience wrapper that creates an Object by parsing `utf8_json` as JSON // and then inserts it into the provided Object. [[nodiscard]] bool InsertJsonValue(v8::Local<v8::Context> context, - base::StringPiece key, - base::StringPiece utf8_json, + std::string_view key, + std::string_view utf8_json, v8::Local<v8::Object> object); enum class ExtractJsonResult { kSuccess, kFailure, kTimeout }; @@ -361,7 +361,7 @@ v8::MaybeLocal<v8::Value> CallFunction(v8::Local<v8::Context> context, const DebugId* debug_id, const std::string& script_name, - base::StringPiece function_name, + std::string_view function_name, base::span<v8::Local<v8::Value>> args, TimeLimit* script_timeout, std::vector<std::string>& error_out);
diff --git a/content/services/auction_worklet/auction_v8_inspector_util.cc b/content/services/auction_worklet/auction_v8_inspector_util.cc index 18b68965..8f248b5 100644 --- a/content/services/auction_worklet/auction_v8_inspector_util.cc +++ b/content/services/auction_worklet/auction_v8_inspector_util.cc
@@ -7,6 +7,7 @@ #include <stdint.h> #include <string> +#include <string_view> #include <vector> #include "base/strings/utf_string_conversions.h" @@ -17,7 +18,7 @@ if (s.is8Bit()) { return std::vector<uint8_t>(s.characters8(), s.characters8() + s.length()); } else { - std::string converted = base::UTF16ToUTF8(base::StringPiece16( + std::string converted = base::UTF16ToUTF8(std::u16string_view( reinterpret_cast<const char16_t*>(s.characters16()), s.length())); const uint8_t* data = reinterpret_cast<const uint8_t*>(converted.data()); return std::vector<uint8_t>(data, data + converted.size());
diff --git a/content/services/auction_worklet/lazy_filler.cc b/content/services/auction_worklet/lazy_filler.cc index 13e37bb..16d827c8 100644 --- a/content/services/auction_worklet/lazy_filler.cc +++ b/content/services/auction_worklet/lazy_filler.cc
@@ -28,7 +28,7 @@ } bool LazyFiller::DefineLazyAttribute(v8::Local<v8::Object> object, - base::StringPiece name, + std::string_view name, v8::AccessorNameGetterCallback getter) { v8::Isolate* isolate = v8_helper_->isolate(); @@ -44,7 +44,7 @@ bool LazyFiller::DefineLazyAttributeWithMetadata( v8::Local<v8::Object> object, v8::Local<v8::Value> metadata, - base::StringPiece name, + std::string_view name, v8::AccessorNameGetterCallback getter, v8::Local<v8::ObjectTemplate>& lazy_filler_template) { v8::Isolate* isolate = v8_helper_->isolate();
diff --git a/content/services/auction_worklet/lazy_filler.h b/content/services/auction_worklet/lazy_filler.h index 39a0756..1ef85e7 100644 --- a/content/services/auction_worklet/lazy_filler.h +++ b/content/services/auction_worklet/lazy_filler.h
@@ -8,7 +8,6 @@ #include <string_view> #include "base/memory/raw_ptr.h" -#include "base/strings/string_piece.h" #include "v8/include/v8-external.h" #include "v8/include/v8-forward.h" #include "v8/include/v8-function-callback.h" @@ -68,7 +67,7 @@ v8::Local<v8::Value> result); bool DefineLazyAttribute(v8::Local<v8::Object> object, - base::StringPiece name, + std::string_view name, v8::AccessorNameGetterCallback getter); // `lazy_filler_template` is used to construct an internal v8 object with a @@ -78,7 +77,7 @@ bool DefineLazyAttributeWithMetadata( v8::Local<v8::Object> object, v8::Local<v8::Value> metadata, - base::StringPiece name, + std::string_view name, v8::AccessorNameGetterCallback getter, v8::Local<v8::ObjectTemplate>& lazy_filler_template);
diff --git a/content/services/auction_worklet/public/cpp/auction_downloader.cc b/content/services/auction_worklet/public/cpp/auction_downloader.cc index 6dcc89e..93b28ae 100644 --- a/content/services/auction_worklet/public/cpp/auction_downloader.cc +++ b/content/services/auction_worklet/public/cpp/auction_downloader.cc
@@ -7,6 +7,7 @@ #include <cstddef> #include <memory> #include <string> +#include <string_view> #include <utility> #include "base/functional/bind.h" @@ -68,14 +69,14 @@ // Returns the MIME type string to send for the Accept header for `mime_type`. // These are the official IANA MIME type strings, though other MIME type strings // are allows in the response. -base::StringPiece MimeTypeToString(AuctionDownloader::MimeType mime_type) { +std::string_view MimeTypeToString(AuctionDownloader::MimeType mime_type) { switch (mime_type) { case AuctionDownloader::MimeType::kJavascript: - return base::StringPiece("application/javascript"); + return std::string_view("application/javascript"); case AuctionDownloader::MimeType::kJson: - return base::StringPiece("application/json"); + return std::string_view("application/json"); case AuctionDownloader::MimeType::kWebAssembly: - return base::StringPiece(kWebAssemblyMime); + return std::string_view(kWebAssemblyMime); } } @@ -107,7 +108,7 @@ // Checks if `charset` is a valid charset, in lowercase ASCII. Takes `body` as // well, to ensure it uses the specified charset. -bool IsAllowedCharset(base::StringPiece charset, const std::string& body) { +bool IsAllowedCharset(std::string_view charset, const std::string& body) { if (charset == "utf-8" || charset.empty()) { return base::IsStringUTF8(body); } else if (charset == "us-ascii") {
diff --git a/content/services/auction_worklet/seller_lazy_filler.cc b/content/services/auction_worklet/seller_lazy_filler.cc index 5e40cd5..3ac3439 100644 --- a/content/services/auction_worklet/seller_lazy_filler.cc +++ b/content/services/auction_worklet/seller_lazy_filler.cc
@@ -110,7 +110,7 @@ bool InsertPrioritySignals( AuctionV8Helper* v8_helper, - base::StringPiece key, + std::string_view key, const base::flat_map<std::string, double>& priority_signals, v8::Local<v8::Object> object) { v8::Isolate* isolate = v8_helper->isolate();
diff --git a/content/services/auction_worklet/seller_worklet.cc b/content/services/auction_worklet/seller_worklet.cc index cb05a30b..8a65226 100644 --- a/content/services/auction_worklet/seller_worklet.cc +++ b/content/services/auction_worklet/seller_worklet.cc
@@ -11,6 +11,7 @@ #include <memory> #include <optional> #include <string> +#include <string_view> #include <utility> #include <vector> @@ -310,7 +311,7 @@ std::optional<blink::AdCurrency> expected_seller_currency, std::optional<blink::AdCurrency> component_expect_bid_currency, const GURL& script_url, - base::StringPiece bid_label, + std::string_view bid_label, std::vector<std::string>& errors_out) { if (!blink::VerifyAdCurrencyCode(expected_seller_currency, provided_currency)) {
diff --git a/content/services/auction_worklet/webidl_compat_unittest.cc b/content/services/auction_worklet/webidl_compat_unittest.cc index 5cd5b519..950eb868 100644 --- a/content/services/auction_worklet/webidl_compat_unittest.cc +++ b/content/services/auction_worklet/webidl_compat_unittest.cc
@@ -7,6 +7,7 @@ #include <cmath> #include <initializer_list> #include <memory> +#include <string_view> #include "base/check.h" #include "base/strings/strcat.h" @@ -100,7 +101,7 @@ } bool GetSequence(DictConverter* converter, - base::StringPiece field, + std::string_view field, v8::LocalVector<v8::Value>& out) { out.clear(); // For tests that re-use `out`. bool got_it = false;
diff --git a/content/shell/browser/fuchsia_view_presenter.cc b/content/shell/browser/fuchsia_view_presenter.cc index d5b8679..ca59f19 100644 --- a/content/shell/browser/fuchsia_view_presenter.cc +++ b/content/shell/browser/fuchsia_view_presenter.cc
@@ -11,7 +11,6 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/location.h" -#include "base/strings/string_piece.h" #include "ui/platform_window/fuchsia/initialize_presenter_api_view.h" namespace content {
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h index c217090..c96e6cc5 100644 --- a/content/shell/browser/shell.h +++ b/content/shell/browser/shell.h
@@ -13,7 +13,6 @@ #include "base/functional/callback_forward.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #include "content/public/browser/session_storage_namespace.h" #include "content/public/browser/web_contents_delegate.h"
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 5a87ec33..5f2cc5ce 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -9,6 +9,7 @@ #include <functional> #include <memory> #include <string> +#include <string_view> #include <utility> #include <vector> @@ -23,7 +24,6 @@ #include "base/no_destructor.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/sequence_local_storage_slot.h" @@ -239,11 +239,11 @@ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kIsolatedContextOrigins)); - std::vector<base::StringPiece> origin_strings = base::SplitStringPiece( + std::vector<std::string_view> origin_strings = base::SplitStringPiece( cmdline_origins, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); base::flat_set<url::Origin> origin_set; - for (const base::StringPiece& origin_string : origin_strings) { + for (const std::string_view& origin_string : origin_strings) { url::Origin allowed_origin = url::Origin::Create(GURL(origin_string)); if (!allowed_origin.opaque()) { origin_set.insert(allowed_origin);
diff --git a/content/shell/browser/shell_devtools_bindings.cc b/content/shell/browser/shell_devtools_bindings.cc index a528b235..9b91a8a 100644 --- a/content/shell/browser/shell_devtools_bindings.cc +++ b/content/shell/browser/shell_devtools_bindings.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include <string_view> #include <utility> #include <vector> @@ -20,7 +21,6 @@ #include "base/no_destructor.h" #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/uuid.h" @@ -117,7 +117,7 @@ response_headers_ = response_head.headers; } - void OnDataReceived(base::StringPiece chunk, + void OnDataReceived(std::string_view chunk, base::OnceClosure resume) override { base::Value chunkValue; @@ -401,8 +401,8 @@ void ShellDevToolsBindings::DispatchProtocolMessage( DevToolsAgentHost* agent_host, base::span<const uint8_t> message) { - base::StringPiece str_message(reinterpret_cast<const char*>(message.data()), - message.size()); + std::string_view str_message(reinterpret_cast<const char*>(message.data()), + message.size()); if (str_message.length() < kShellMaxMessageChunkSize) { CallClientFunction("DevToolsAPI", "dispatchMessage", base::Value(std::string(str_message))); @@ -410,7 +410,7 @@ size_t total_size = str_message.length(); for (size_t pos = 0; pos < str_message.length(); pos += kShellMaxMessageChunkSize) { - base::StringPiece str_message_chunk = + std::string_view str_message_chunk = str_message.substr(pos, kShellMaxMessageChunkSize); CallClientFunction(
diff --git a/content/shell/browser/shell_platform_delegate_android.cc b/content/shell/browser/shell_platform_delegate_android.cc index 37297f1..0115366 100644 --- a/content/shell/browser/shell_platform_delegate_android.cc +++ b/content/shell/browser/shell_platform_delegate_android.cc
@@ -11,7 +11,6 @@ #include "base/command_line.h" #include "base/containers/contains.h" #include "base/notreached.h" -#include "base/strings/string_piece.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h"
diff --git a/content/shell/common/shell_content_client.cc b/content/shell/common/shell_content_client.cc index 71c04cb..2af9f0b 100644 --- a/content/shell/common/shell_content_client.cc +++ b/content/shell/common/shell_content_client.cc
@@ -4,8 +4,9 @@ #include "content/shell/common/shell_content_client.h" +#include <string_view> + #include "base/command_line.h" -#include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" @@ -44,7 +45,7 @@ return l10n_util::GetStringUTF16(message_id); } -base::StringPiece ShellContentClient::GetDataResource( +std::string_view ShellContentClient::GetDataResource( int resource_id, ui::ResourceScaleFactor scale_factor) { return ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
diff --git a/content/shell/common/shell_content_client.h b/content/shell/common/shell_content_client.h index 31cd0f69..954c922 100644 --- a/content/shell/common/shell_content_client.h +++ b/content/shell/common/shell_content_client.h
@@ -6,6 +6,7 @@ #define CONTENT_SHELL_COMMON_SHELL_CONTENT_CLIENT_H_ #include <string> +#include <string_view> #include <vector> #include "content/public/common/content_client.h" @@ -19,7 +20,7 @@ ~ShellContentClient() override; std::u16string GetLocalizedString(int message_id) override; - base::StringPiece GetDataResource( + std::string_view GetDataResource( int resource_id, ui::ResourceScaleFactor scale_factor) override; base::RefCountedMemory* GetDataResourceBytes(int resource_id) override;
diff --git a/content/shell/common/shell_origin_trial_policy.h b/content/shell/common/shell_origin_trial_policy.h index 5dd0756e..2a1e22c 100644 --- a/content/shell/common/shell_origin_trial_policy.h +++ b/content/shell/common/shell_origin_trial_policy.h
@@ -7,7 +7,6 @@ #include <vector> -#include "base/strings/string_piece.h" #include "third_party/blink/public/common/origin_trials/origin_trial_policy.h" namespace content {
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist index 51a8b65..aebd91f 100644 --- a/content/test/content_test_bundle_data.filelist +++ b/content/test/content_test_bundle_data.filelist
@@ -7160,6 +7160,7 @@ data/send-beacon.html data/service_worker/add_save_data_to_title.js data/service_worker/add_save_data_to_title.js.mock-http-headers +data/service_worker/auto_preload.js data/service_worker/cached_fetch_event.js data/service_worker/client_api_worker.js data/service_worker/clients_claim_worker.js @@ -7229,7 +7230,7 @@ data/service_worker/non_function_fetch_event.js data/service_worker/one_subframe.html data/service_worker/race_network_request.html -data/service_worker/race_network_request.js +data/service_worker/race_network_request_base.js data/service_worker/race_network_request_from_fetch_handler.html data/service_worker/request_navigate.html data/service_worker/request_origin_worker.js @@ -7238,6 +7239,8 @@ data/service_worker/static_import_worker.js data/service_worker/static_router.js data/service_worker/static_router_no_handler.js +data/service_worker/static_router_race.js +data/service_worker/static_router_race_match_all.js data/service_worker/sync.js.mock-http-headers data/service_worker/throttling_blocking_cache_addall_sw.js data/service_worker/throttling_blocking_sw.js
diff --git a/content/test/data/service_worker/auto_preload.js b/content/test/data/service_worker/auto_preload.js new file mode 100644 index 0000000..eb9dad2 --- /dev/null +++ b/content/test/data/service_worker/auto_preload.js
@@ -0,0 +1,16 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +importScripts('./race_network_request_base.js'); + +self.addEventListener('install', e => { + e.addRoutes([ + { + condition: { + urlPattern: {pathname: "/service_worker/no_race"} + }, + source: "fetch-event" + } + ]); + self.skipWaiting(); +});
diff --git a/content/test/data/service_worker/race_network_request.js b/content/test/data/service_worker/race_network_request_base.js similarity index 72% rename from content/test/data/service_worker/race_network_request.js rename to content/test/data/service_worker/race_network_request_base.js index 3267dda..16b3fac 100644 --- a/content/test/data/service_worker/race_network_request.js +++ b/content/test/data/service_worker/race_network_request_base.js
@@ -1,4 +1,4 @@ -// Copyright 2023 The Chromium Authors +// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const composeCustomResponse = () => { @@ -16,26 +16,6 @@ options); }; -self.addEventListener('install', e => { - if (e.addRoutes) { - e.addRoutes([ - { - condition: { - urlPattern: {pathname: "/service_worker/race_network_and_fetch"} - }, - source: "race-network-and-fetch-handler" - }, - { - condition: { - urlPattern: {pathname: "/service_worker/no_race"} - }, - source: "fetch-event" - } - ]); - } - self.skipWaiting(); -}); - self.addEventListener('activate', e => { e.waitUntil(clients.claim()); });
diff --git a/content/test/data/service_worker/static_router_race.js b/content/test/data/service_worker/static_router_race.js new file mode 100644 index 0000000..2a04fc9 --- /dev/null +++ b/content/test/data/service_worker/static_router_race.js
@@ -0,0 +1,22 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +importScripts('./race_network_request_base.js'); + +self.addEventListener('install', e => { + e.addRoutes([ + { + condition: { + urlPattern: {pathname: "/service_worker/race_network_and_fetch"} + }, + source: "race-network-and-fetch-handler" + }, + { + condition: { + urlPattern: {pathname: "/service_worker/no_race"} + }, + source: "fetch-event" + } + ]); + self.skipWaiting(); +});
diff --git a/content/test/data/service_worker/static_router_race_match_all.js b/content/test/data/service_worker/static_router_race_match_all.js new file mode 100644 index 0000000..b061a5f --- /dev/null +++ b/content/test/data/service_worker/static_router_race_match_all.js
@@ -0,0 +1,14 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +importScripts('./race_network_request_base.js'); + +self.addEventListener('install', e => { + e.addRoutes({ + condition: { + urlPattern: new URLPattern({}) + }, + source: "race-network-and-fetch-handler" + }); + self.skipWaiting(); +});
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index f3fc292..8546982 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -451,7 +451,6 @@ #################### crbug.com/angleproject/4417 [ win angle-d3d11 ] conformance2/rendering/framebuffer-render-to-layer-angle-issue.html [ Failure ] -crbug.com/angleproject/7109 [ angle-d3d11 win10 ] conformance2/renderbuffers/invalidate-framebuffer.html [ Failure ] crbug.com/angleproject/1465 [ win angle-d3d11 ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ] ## Win / NVIDIA ## @@ -469,24 +468,8 @@ # wildcard flaky suppression for all of the tests. crbug.com/483282 [ angle-d3d11 win amd ] conformance2/rendering/blitframebuffer-stencil-only.html [ Failure ] -# Failing on AMD RX 5500 XT -crbug.com/1152597 [ win amd-0x7340 angle-d3d11 ] conformance/renderbuffers/framebuffer-state-restoration.html [ Failure ] -crbug.com/1152599 [ win amd-0x7340 angle-d3d11 ] conformance/rendering/polygon-offset.html [ Failure ] -crbug.com/1409858 [ win amd-0x7340 angle-d3d11 ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ] -crbug.com/1152603 [ win amd-0x7340 angle-d3d11 ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ] -crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fboinvalidate/* [ Failure ] -crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fbomultisample.2_samples.html [ Failure ] -crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fborender/shared_colorbuffer_01.html [ Failure ] -crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fborender/shared_colorbuffer_02.html [ Failure ] -crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/framebufferblit/depth_stencil.html [ Failure ] -crbug.com/1499404 [ win amd-0x7340 angle-d3d11 ] conformance2/textures/misc/tex-srgb-mipmap.html [ Failure ] -# New extensions failing on Win/AMD -crbug.com/1473838 [ win amd-0x7340 angle-d3d11 ] conformance/extensions/ext-clip-control.html [ Failure ] -crbug.com/1473838 [ win amd-0x7340 angle-d3d11 ] conformance/extensions/webgl-polygon-mode.html [ Failure ] -# D3D11 / AMD RX 5500 XT / Passthrough command decoder -crbug.com/1159539 [ win amd-0x7340 angle-d3d11 passthrough ] deqp/functional/gles3/fborender/recreate_color_* [ RetryOnFailure ] ## Win / Intel ## @@ -494,7 +477,6 @@ ## Win / Adreno 690 / D3D11 crbug.com/1523062 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ] crbug.com/1523062 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance/textures/misc/mipmap-fbo.html [ Failure ] -crbug.com/1523062 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance/textures/misc/texture-mips.html [ Failure ] crbug.com/1523323 [ win11 qualcomm-0x41333430 angle-d3d11 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ Failure ] crbug.com/1523323 [ win11 qualcomm-0x41333430 angle-d3d11 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ Failure ] crbug.com/1523323 [ win11 qualcomm-0x41333430 angle-d3d11 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ Failure ] @@ -523,7 +505,6 @@ crbug.com/41496352 [ win11 qualcomm-0x41333430 angle-d3d11 ] deqp/functional/gles3/shaderprecision_float.html [ RetryOnFailure ] crbug.com/329211596 [ win11 qualcomm-0x41333430 angle-d3d11 ] deqp/functional/gles3/shaderprecision_int.html [ RetryOnFailure ] crbug.com/329211596 [ win11 qualcomm-0x41333430 angle-d3d11 ] deqp/functional/gles3/shaderprecision_uint.html [ RetryOnFailure ] -crbug.com/323824490 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance/ogles/GL/ceil/ceil_001_to_006.html [ RetryOnFailure ] # Graphite crbug.com/329322651 [ win graphite-enabled ] conformance/textures/misc/texture-corner-case-videos.html [ Failure ] @@ -572,7 +553,7 @@ crbug.com/1316389 [ amd-0x67ef angle-metal passthrough ventura ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ Failure ] crbug.com/1487266 [ amd-0x679e angle-metal monterey passthrough release ] deqp/functional/gles3/texturefiltering/2d_array_combinations_05.html [ Failure ] -crbug.com/328100306 [ angle-metal graphite-enabled intel-0x3e9b sonoma ] conformance/glsl/bugs/sampler-array-using-loop-index.html [ Failure ] +crbug.com/328100306 [ amd-0x67ef angle-metal graphite-enabled sonoma ] conformance/glsl/bugs/sampler-array-using-loop-index.html [ Failure ] ## SkiaGraphite on Metal AMD ## @@ -621,8 +602,6 @@ ## Metal Graphite ## -crbug.com/329285449 [ mac angle-metal graphite-enabled apple ] conformance/textures/misc/texture-active-bind.html [ RetryOnFailure ] -crbug.com/329285449 [ mac angle-metal graphite-enabled intel-0x3e9b ] conformance/textures/misc/texture-active-bind.html [ RetryOnFailure ] ###################################################################### # Mac failures (mainly OpenGL; some need to be reevaluated on Metal) # @@ -657,7 +636,7 @@ crbug.com/795052 [ mac nvidia-0xfe9 ] conformance2/uniforms/draw-with-uniform-blocks.html [ Failure ] crbug.com/1457723 [ bigsur nvidia-0xfe9 angle-opengl ] conformance2/textures/canvas_sub_rectangle/tex-3d-* [ Failure ] crbug.com/1475765 [ bigsur nvidia-0xfe9 angle-opengl ] conformance/textures/canvas_sub_rectangle/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ] -crbug.com/1475765 [ bigsur nvidia-0xfe9 angle-opengl ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html [ Failure ] +crbug.com/1475765 [ angle-opengl bigsur nvidia-0xfe9 nvidia_lt_31.0.15.4601 ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html [ Failure ] crbug.com/1488444 [ mac-x86_64 nvidia-0xfe9 angle-opengl passthrough ] conformance2/rendering/vertex-id-large-count.html [ Failure ] ## Mac AMD ## @@ -899,7 +878,6 @@ crbug.com/1488973 [ chromeos cros-chrome chromeos-board-jacuzzi ] conformance/glsl/bugs/constant-precision-qualifier.html [ Failure ] crbug.com/1488978 [ chromeos cros-chrome chromeos-board-jacuzzi ] conformance/limits/gl-max-texture-dimensions.html [ Failure ] crbug.com/1488979 [ chromeos cros-chrome chromeos-board-jacuzzi ] conformance/misc/shader-precision-format.html [ Failure ] -crbug.com/1492240 [ chromeos cros-chrome chromeos-board-jacuzzi ] conformance2/extensions/ext-disjoint-timer-query-webgl2.html [ Failure ] crbug.com/1492241 [ chromeos cros-chrome chromeos-board-jacuzzi ] conformance/rendering/clear-default-framebuffer-with-scissor-test.html [ Failure ] crbug.com/1492242 [ chromeos cros-chrome chromeos-board-jacuzzi ] conformance2/buffers/uniform-buffers.html [ Failure ] crbug.com/1492245 [ chromeos cros-chrome chromeos-board-jacuzzi ] conformance2/extensions/oes-sample-variables.html [ Failure ] @@ -955,7 +933,6 @@ crbug.com/326490772 [ chromeos lacros-chrome chromeos-board-jacuzzi passthrough ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ] crbug.com/326490772 [ chromeos lacros-chrome chromeos-board-jacuzzi passthrough ] conformance2/glsl3/texture-bias.html [ Failure ] -crbug.com/326490772 [ chromeos lacros-chrome chromeos-board-jacuzzi passthrough ] conformance/rendering/clear-default-framebuffer-with-scissor-test.html [ Failure ] crbug.com/326490772 [ chromeos lacros-chrome chromeos-board-jacuzzi passthrough ] conformance2/extensions/oes-sample-variables.html [ Failure ] ##############################
diff --git a/content/test/mock_reduce_accept_language_controller_delegate.cc b/content/test/mock_reduce_accept_language_controller_delegate.cc index a0bf384..fbc9690 100644 --- a/content/test/mock_reduce_accept_language_controller_delegate.cc +++ b/content/test/mock_reduce_accept_language_controller_delegate.cc
@@ -4,6 +4,8 @@ #include "content/test/mock_reduce_accept_language_controller_delegate.h" +#include <string_view> + #include "base/strings/string_split.h" #include "content/public/common/origin_util.h" #include "net/http/http_util.h" @@ -13,7 +15,7 @@ namespace { -std::string GetFirstLanguage(base::StringPiece language_list) { +std::string GetFirstLanguage(std::string_view language_list) { auto end = language_list.find(","); return std::string(language_list.substr(0, end)); }
diff --git a/content/test/test_content_client.cc b/content/test/test_content_client.cc index cbb4e73..99f5e34 100644 --- a/content/test/test_content_client.cc +++ b/content/test/test_content_client.cc
@@ -4,6 +4,8 @@ #include "content/test/test_content_client.h" +#include <string_view> + #include "ui/base/resource/resource_bundle.h" namespace content { @@ -12,7 +14,7 @@ TestContentClient::~TestContentClient() = default; -base::StringPiece TestContentClient::GetDataResource( +std::string_view TestContentClient::GetDataResource( int resource_id, ui::ResourceScaleFactor scale_factor) { return ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
diff --git a/content/test/test_content_client.h b/content/test/test_content_client.h index 3c87423..6778f07 100644 --- a/content/test/test_content_client.h +++ b/content/test/test_content_client.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_TEST_TEST_CONTENT_CLIENT_H_ #define CONTENT_TEST_TEST_CONTENT_CLIENT_H_ +#include <string_view> + #include "content/public/common/content_client.h" namespace content { @@ -19,7 +21,7 @@ ~TestContentClient() override; // ContentClient: - base::StringPiece GetDataResource( + std::string_view GetDataResource( int resource_id, ui::ResourceScaleFactor scale_factor) override; base::RefCountedMemory* GetDataResourceBytes(int resource_id) override;
diff --git a/content/web_test/browser/devtools_protocol_test_bindings.cc b/content/web_test/browser/devtools_protocol_test_bindings.cc index 42cdd37..b1ccde0 100644 --- a/content/web_test/browser/devtools_protocol_test_bindings.cc +++ b/content/web_test/browser/devtools_protocol_test_bindings.cc
@@ -4,6 +4,8 @@ #include "content/web_test/browser/devtools_protocol_test_bindings.h" +#include <string_view> + #include "base/command_line.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" @@ -175,7 +177,7 @@ if (log_enabled_) { NOTREACHED_NORETURN() << "Unexpected messages dispatched by the browser"; } - base::StringPiece str_message(reinterpret_cast<const char*>(message.data()), + std::string_view str_message(reinterpret_cast<const char*>(message.data()), message.size()); WebTestControlHost::Get()->PrintMessageToStderr( "Protocol message: " + std::string(str_message) + "\n");
diff --git a/content/web_test/browser/web_test_bluetooth_adapter_provider.cc b/content/web_test/browser/web_test_bluetooth_adapter_provider.cc index d06fc6d..f2adc3a 100644 --- a/content/web_test/browser/web_test_bluetooth_adapter_provider.cc +++ b/content/web_test/browser/web_test_bluetooth_adapter_provider.cc
@@ -34,7 +34,6 @@ namespace { -using ::base::StringPiece; using ::base::test::RunOnceCallback; using ::device::BluetoothAdapter; using ::device::BluetoothDevice;
diff --git a/content/web_test/browser/web_test_control_host.cc b/content/web_test/browser/web_test_control_host.cc index 414beb6..4bff48d 100644 --- a/content/web_test/browser/web_test_control_host.cc +++ b/content/web_test/browser/web_test_control_host.cc
@@ -15,6 +15,7 @@ #include <queue> #include <set> #include <string> +#include <string_view> #include <utility> #include <vector> @@ -448,7 +449,7 @@ *output_ << "Content-Transfer-Encoding: base64\n"; std::string data_base64 = base::Base64Encode( - base::StringPiece(reinterpret_cast<const char*>(&data[0]), data.size())); + std::string_view(reinterpret_cast<const char*>(&data[0]), data.size())); *output_ << "Content-Length: " << data_base64.length() << "\n"; output_->write(data_base64.c_str(), data_base64.length());
diff --git a/content/web_test/common/web_test_string_util.cc b/content/web_test/common/web_test_string_util.cc index 22e1567..bb20d0e 100644 --- a/content/web_test/common/web_test_string_util.cc +++ b/content/web_test/common/web_test_string_util.cc
@@ -6,6 +6,8 @@ #include <stddef.h> +#include <string_view> + #include "base/containers/heap_array.h" #include "base/lazy_instance.h" #include "base/rand_util.h" @@ -17,8 +19,8 @@ namespace { -constexpr base::StringPiece kWebTestsPattern = "/web_tests/"; -constexpr base::StringPiece kFileURLPattern = "file://"; +constexpr std::string_view kWebTestsPattern = "/web_tests/"; +constexpr std::string_view kFileURLPattern = "file://"; const char* kFileTestPrefix = "(file test):"; const char* kPolicyDownload = "download"; const char* kPolicyCurrentTab = "current tab"; @@ -37,7 +39,7 @@ if (base::StartsWith(url, kFileURLPattern)) { // Adjust the file URL by removing the part depending on the testing // environment. - size_t pos = base::StringPiece(url).find(kWebTestsPattern); + size_t pos = std::string_view(url).find(kWebTestsPattern); if (pos != std::string::npos) result.replace(0, pos + kWebTestsPattern.size(), kFileTestPrefix); }
diff --git a/content/web_test/renderer/blink_test_helpers.cc b/content/web_test/renderer/blink_test_helpers.cc index b44dcea6..7c78ae7 100644 --- a/content/web_test/renderer/blink_test_helpers.cc +++ b/content/web_test/renderer/blink_test_helpers.cc
@@ -4,10 +4,11 @@ #include "content/web_test/renderer/blink_test_helpers.h" +#include <string_view> + #include "base/command_line.h" #include "base/files/file_util.h" #include "base/path_service.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -27,7 +28,7 @@ namespace { -constexpr base::StringPiece kFileScheme = "file:///"; +constexpr std::string_view kFileScheme = "file:///"; base::FilePath GetWebTestsFilePath() { static base::FilePath path; @@ -63,7 +64,7 @@ // the WPT test directory. // // Note that this doesn't apply when the WPT tests are run by the python script. -WebURL RewriteWPTAbsolutePath(base::StringPiece utf8_url) { +WebURL RewriteWPTAbsolutePath(std::string_view utf8_url) { if (!base::StartsWith(utf8_url, kFileScheme, base::CompareCase::SENSITIVE) || utf8_url.find("/web_tests/") != std::string::npos) { return WebURL(GURL(utf8_url)); @@ -74,9 +75,9 @@ static constexpr size_t kFileSchemeAndDriveLen = kFileScheme.size() + 3; if (utf8_url.size() <= kFileSchemeAndDriveLen) return WebURL(); - base::StringPiece path = utf8_url.substr(kFileSchemeAndDriveLen); + std::string_view path = utf8_url.substr(kFileSchemeAndDriveLen); #else - base::StringPiece path = utf8_url.substr(kFileScheme.size()); + std::string_view path = utf8_url.substr(kFileScheme.size()); #endif base::FilePath new_path = GetExternalWPTFilePath().AppendASCII(path); return WebURL(net::FilePathToFileURL(new_path)); @@ -126,11 +127,11 @@ return result; } -WebURL RewriteWebTestsURL(base::StringPiece utf8_url, bool is_wpt_mode) { +WebURL RewriteWebTestsURL(std::string_view utf8_url, bool is_wpt_mode) { if (is_wpt_mode) return RewriteWPTAbsolutePath(utf8_url); - static constexpr base::StringPiece kGenPrefix = "file:///gen/"; + static constexpr std::string_view kGenPrefix = "file:///gen/"; // Map "file:///gen/" to "file://<build directory>/gen/". if (base::StartsWith(utf8_url, kGenPrefix, base::CompareCase::SENSITIVE)) { @@ -142,7 +143,7 @@ return WebURL(GURL(new_url)); } - static constexpr base::StringPiece kPrefix = "file:///tmp/web_tests/"; + static constexpr std::string_view kPrefix = "file:///tmp/web_tests/"; if (!base::StartsWith(utf8_url, kPrefix, base::CompareCase::SENSITIVE)) return WebURL(GURL(utf8_url)); @@ -153,11 +154,11 @@ return WebURL(GURL(new_url)); } -WebURL RewriteFileURLToLocalResource(base::StringPiece resource) { +WebURL RewriteFileURLToLocalResource(std::string_view resource) { return RewriteWebTestsURL(resource, /*is_wpt_mode=*/false); } -bool IsWebPlatformTest(base::StringPiece test_url) { +bool IsWebPlatformTest(std::string_view test_url) { // ://web-platform.test is a part of the http/https URL of a wpt test run by // the python script. return test_url.find("://web-platform.test") != std::string::npos ||
diff --git a/content/web_test/renderer/blink_test_helpers.h b/content/web_test/renderer/blink_test_helpers.h index 6622da9..e05eb541 100644 --- a/content/web_test/renderer/blink_test_helpers.h +++ b/content/web_test/renderer/blink_test_helpers.h
@@ -5,7 +5,8 @@ #ifndef CONTENT_WEB_TEST_RENDERER_BLINK_TEST_HELPERS_H_ #define CONTENT_WEB_TEST_RENDERER_BLINK_TEST_HELPERS_H_ -#include "base/strings/string_piece.h" +#include <string_view> + #include "third_party/blink/public/platform/web_url.h" namespace blink { @@ -32,13 +33,13 @@ // to a temporary file under the web_tests directory. // 3. If the URL starts with file:///gen/, then return a file URL to the file // under the gen/ directory of the build out. -blink::WebURL RewriteWebTestsURL(base::StringPiece utf8_url, bool is_wpt_mode); +blink::WebURL RewriteWebTestsURL(std::string_view utf8_url, bool is_wpt_mode); // Applies the rewrite rules except 1 of RewriteWebTestsURL(). -blink::WebURL RewriteFileURLToLocalResource(base::StringPiece resource); +blink::WebURL RewriteFileURLToLocalResource(std::string_view resource); // Returns true if |test_url| points to a web platform test (WPT). -bool IsWebPlatformTest(base::StringPiece test_url); +bool IsWebPlatformTest(std::string_view test_url); } // namespace content
diff --git a/content/web_test/renderer/fake_subresource_filter.cc b/content/web_test/renderer/fake_subresource_filter.cc index 5fe6aed..aa90cc3 100644 --- a/content/web_test/renderer/fake_subresource_filter.cc +++ b/content/web_test/renderer/fake_subresource_filter.cc
@@ -4,6 +4,8 @@ #include "content/web_test/renderer/fake_subresource_filter.h" +#include <string_view> + #include "base/ranges/algorithm.h" #include "base/strings/string_util.h" #include "third_party/blink/public/platform/web_url.h" @@ -40,7 +42,7 @@ blink::WebDocumentSubresourceFilter::LoadPolicy FakeSubresourceFilter::GetLoadPolicyImpl(const blink::WebURL& url) { GURL gurl(url); - base::StringPiece path(gurl.path_piece()); + std::string_view path(gurl.path_piece()); // Allows things not listed in |disallowed_path_suffixes_|. if (base::ranges::none_of(
diff --git a/content/web_test/renderer/test_runner.cc b/content/web_test/renderer/test_runner.cc index b29938b..0cd72b5 100644 --- a/content/web_test/renderer/test_runner.cc +++ b/content/web_test/renderer/test_runner.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include <clocale> #include <limits> +#include <string_view> #include <utility> #include <vector> @@ -19,7 +20,6 @@ #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" @@ -2781,15 +2781,15 @@ printing::PageRanges TestRunner::GetPrintingPageRanges( blink::WebLocalFrame* frame) const { const std::string page_ranges_string = GetPageRangesStringFromMetadata(frame); - const std::vector<base::StringPiece> range_strings = + const std::vector<std::string_view> range_strings = base::SplitStringPiece(page_ranges_string, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); printing::PageRanges result; - for (const base::StringPiece& range_string : range_strings) { + for (const std::string_view& range_string : range_strings) { // The format for each range is "<int> | <int>? - <int>?" where the page // numbers are 1-indexed. - const std::vector<base::StringPiece> page_strings = base::SplitStringPiece( + const std::vector<std::string_view> page_strings = base::SplitStringPiece( range_string, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); bool invalid = false;
diff --git a/content/web_test/renderer/test_websocket_handshake_throttle_provider.cc b/content/web_test/renderer/test_websocket_handshake_throttle_provider.cc index e56c55b..bdeb093a 100644 --- a/content/web_test/renderer/test_websocket_handshake_throttle_provider.cc +++ b/content/web_test/renderer/test_websocket_handshake_throttle_provider.cc
@@ -4,10 +4,11 @@ #include "content/web_test/renderer/test_websocket_handshake_throttle_provider.h" +#include <string_view> + #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -29,13 +30,13 @@ url::Component query = url.parsed_for_possibly_invalid_spec().query; url::Component key; url::Component value; - base::StringPiece spec = url.possibly_invalid_spec(); + std::string_view spec = url.possibly_invalid_spec(); while (url::ExtractQueryKeyValue(spec, &query, &key, &value)) { - base::StringPiece key_piece = spec.substr(key.begin, key.len); + std::string_view key_piece = spec.substr(key.begin, key.len); if (key_piece != "content-shell-websocket-delay-ms") continue; - base::StringPiece value_piece = spec.substr(value.begin, value.len); + std::string_view value_piece = spec.substr(value.begin, value.len); int value_int; if (!base::StringToInt(value_piece, &value_int) || value_int < 0) return base::TimeDelta();
diff --git a/docs/telemetry_extension/api_overview.md b/docs/telemetry_extension/api_overview.md index 346f2bf..d68ca27 100644 --- a/docs/telemetry_extension/api_overview.md +++ b/docs/telemetry_extension/api_overview.md
@@ -374,14 +374,19 @@ | buttonType | VolumeButtonType | The volume button to be tested | | timeoutSeconds | number | Length of time to listen to the volume button events. The value should be positive and less or equal to 600 seconds | +### CreateNetworkBandwidthRoutineArguments +| Property Name | Type | Description | +------------ | ------- | ----------- | + ### CreateRoutineArgumentsUnion This is a union type. Exactly one field is set. -| Property Name | Type | Released in Chrome version | Description | ------------- | ------- | ----------- | ----------- | -| memory | CreateMemoryRoutineArguments | M125 | Arguments to create a memory routine | -| volumeButton | CreateVolumeButtonRoutineArguments | M125 | Arguments to create a volume button routine | -| fan | CreateFanRoutineArguments | M125 | Arguments to create a fan routine | +| Property Name | Type | Released in Chrome version | Description | Additional permission needed to access | +------------ | ------- | ----------- | ----------- | ----------- | +| memory | CreateMemoryRoutineArguments | M125 | Arguments to create a memory routine | None | +| volumeButton | CreateVolumeButtonRoutineArguments | M125 | Arguments to create a volume button routine | None | +| fan | CreateFanRoutineArguments | M125 | Arguments to create a fan routine | None | +| networkBandwidth | CreateNetworkBandwidthRoutineArguments | M125 | Arguments to create a network bandwidth routine | `os.diagnostics.network_info_mlab` | ### CreateRoutineResponse | Property Name | Type | Description |
diff --git a/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/properties.json b/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/properties.json index 68522486..7294a8b 100644 --- a/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/properties.json +++ b/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/properties.json
@@ -59,7 +59,9 @@ ], "enable_cloud_profiler": true, "enable_cloud_trace": true, - "experiments": [], + "experiments": [ + "no-fallback" + ], "project": "rbe-chromium-untrusted" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/build/mac-build-perf-siso/properties.json b/infra/config/generated/builders/build/mac-build-perf-siso/properties.json index d0896ff..2e69767 100644 --- a/infra/config/generated/builders/build/mac-build-perf-siso/properties.json +++ b/infra/config/generated/builders/build/mac-build-perf-siso/properties.json
@@ -60,7 +60,9 @@ ], "enable_cloud_profiler": true, "enable_cloud_trace": true, - "experiments": [], + "experiments": [ + "no-fallback" + ], "project": "rbe-chromium-untrusted" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/linux-full-remote-rel/properties.json b/infra/config/generated/builders/try/linux-full-remote-rel/properties.json index b317759..7280dc9 100644 --- a/infra/config/generated/builders/try/linux-full-remote-rel/properties.json +++ b/infra/config/generated/builders/try/linux-full-remote-rel/properties.json
@@ -153,7 +153,8 @@ "builder": "Linux Tests", "project": "chromium" } - ] + ], + "is_compile_only": true } }, "$build/code_coverage": {
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl index 9a0f7ec..f7b0405 100644 --- a/infra/config/generated/testing/test_suites.pyl +++ b/infra/config/generated/testing/test_suites.pyl
@@ -1976,6 +1976,28 @@ }, }, + 'devtools_web_isolated_scripts': { + 'blink_web_tests': { + 'results_handler': 'layout tests', + 'mixins': [ + 'has_native_resultdb_integration', + 'blink_tests_write_run_histories', + ], + 'args': [ + '--num-retries=3', + ], + 'swarming': { + 'shards': 5, + }, + 'merge': { + 'script': '//third_party/blink/tools/merge_web_test_results.py', + 'args': [ + '--verbose', + ], + }, + }, + }, + 'devtools_webkit_isolated_scripts': { 'blink_web_tests': { 'results_handler': 'layout tests',
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index d457a9a..1d11ec4 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -267,16 +267,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 125.0.6411.0', + 'description': 'Run with ash-chrome version 125.0.6412.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v125.0.6411.0', - 'revision': 'version:125.0.6411.0', + 'location': 'lacros_version_skew_tests_v125.0.6412.0', + 'revision': 'version:125.0.6412.0', }, ], },
diff --git a/infra/config/subprojects/build/build.star b/infra/config/subprojects/build/build.star index 9bcc2f7..b617dc1 100644 --- a/infra/config/subprojects/build/build.star +++ b/infra/config/subprojects/build/build.star
@@ -368,6 +368,7 @@ category = "cros", short_name = "siso", ), + siso_experiments = ["no-fallback"], ) cq_build_perf_builder( @@ -435,6 +436,7 @@ category = "mac", short_name = "siso", ), + siso_experiments = ["no-fallback"], ) cq_build_perf_builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star index da1c3db..9e0c544 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -393,6 +393,9 @@ name = "linux-full-remote-rel", description_html = "Experimental " + linkify_builder("try", "linux-rel", "chromium") + " builder with more kinds of remote actions. e.g. remote linking", mirrors = builder_config.copy_from("linux-rel"), + builder_config_settings = builder_config.try_settings( + is_compile_only = True, + ), gn_args = "try/linux-rel", compilator = "linux-full-remote-rel-compilator", contact_team_email = "chrome-build-team@google.com",
diff --git a/infra/config/targets/basic_suites.star b/infra/config/targets/basic_suites.star index e5d6b0b..14820f0f 100644 --- a/infra/config/targets/basic_suites.star +++ b/infra/config/targets/basic_suites.star
@@ -1859,6 +1859,17 @@ ) targets.legacy_basic_suite( + name = "devtools_web_isolated_scripts", + tests = { + "blink_web_tests": targets.legacy_test_config( + swarming = targets.swarming( + shards = 5, + ), + ), + }, +) + +targets.legacy_basic_suite( name = "devtools_webkit_isolated_scripts", tests = { "blink_web_tests": targets.legacy_test_config(
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index a5519a0..0ce3610 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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.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_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ] }
diff --git a/ios/chrome/app/application_delegate/app_state.h b/ios/chrome/app/application_delegate/app_state.h index fbc105e..89260d6e 100644 --- a/ios/chrome/app/application_delegate/app_state.h +++ b/ios/chrome/app/application_delegate/app_state.h
@@ -13,7 +13,6 @@ #import "ios/chrome/browser/ui/scoped_iphone_portrait_only/iphone_portrait_only_manager.h" #import "ios/chrome/browser/ui/scoped_ui_blocker/ui_blocker_manager.h" -@class AppState; class ChromeBrowserState; @class CommandDispatcher; @class SceneState;
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 6e52b27..c12a6d6 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -351,6 +351,8 @@ // Handles collecting metrics on user triggered screenshots @property(nonatomic, strong) ScreenshotMetricsRecorder* screenshotMetricsRecorder; +// Cleanup any persisted data for the session restration on disk. +- (void)cleanupSessionStateCache; // Cleanup snapshots on disk. - (void)cleanupSnapshots; // Cleanup discarded sessions on disk. @@ -1087,19 +1089,10 @@ } - (void)scheduleSessionStateCacheCleanup { - // TODO(crbug.com/325612229): Refactor this to handle multiple browser states. - // Consider dedicated handling in DeferredInitializationRunner. [[DeferredInitializationRunner sharedInstance] enqueueBlockNamed:kPurgeWebSessionStates block:^{ - ChromeBrowserState* browserState = - self.appState.mainBrowserState; - - if (browserState) { - SessionRestorationServiceFactory::GetForBrowserState( - browserState) - ->PurgeUnassociatedData(base::DoNothing()); - } + [self cleanupSessionStateCache]; }]; } @@ -1416,6 +1409,17 @@ #pragma mark - Helper methods. +- (void)cleanupSessionStateCache { + std::vector<ChromeBrowserState*> loadedBrowserStates = + GetApplicationContext() + ->GetChromeBrowserStateManager() + ->GetLoadedBrowserStates(); + for (ChromeBrowserState* browserState : loadedBrowserStates) { + SessionRestorationServiceFactory::GetForBrowserState(browserState) + ->PurgeUnassociatedData(base::DoNothing()); + } +} + - (void)cleanupSnapshots { // TODO(crbug.com/1116496): Browsers for disconnected scenes are not in the // BrowserList, so this may not reach all folders.
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm index 46ffe2f..3b5cc4ad 100644 --- a/ios/chrome/browser/ui/menu/action_factory.mm +++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -380,11 +380,13 @@ block:addTabToNewGroupBlock]; } - UIImage* image = DefaultSymbolWithPointSize(kMoveTabToGroupActionSymbol, - kSymbolActionPointSize); - NSMutableArray<UIMenuElement*>* groupsMenu = [[NSMutableArray alloc] init]; + UIImage* circleImage = + DefaultSymbolWithPointSize(kCircleFillSymbol, kSymbolActionPointSize); + circleImage = + [circleImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + for (const TabGroup* group : groups) { NSString* title = group->GetTitle(); ProceduralBlock groupBlock = ^{ @@ -395,7 +397,7 @@ UIAction* groupAction = [self actionWithTitle:title - image:nil + image:[circleImage imageWithTintColor:group->GetColor()] type:MenuActionType::AddTabToExistingGroup block:groupBlock]; [groupsMenu addObject:groupAction]; @@ -418,6 +420,9 @@ menu ]; + UIImage* image = DefaultSymbolWithPointSize(kMoveTabToGroupActionSymbol, + kSymbolActionPointSize); + return [UIMenu menuWithTitle:l10n_util::GetPluralNSStringF( IDS_IOS_CONTENT_CONTEXT_ADDTABTOTABGROUP, tabsNumber)
diff --git a/ios/chrome/browser/ui/menu/action_factory_unittest.mm b/ios/chrome/browser/ui/menu/action_factory_unittest.mm index 156a58d..d9e7762 100644 --- a/ios/chrome/browser/ui/menu/action_factory_unittest.mm +++ b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
@@ -473,7 +473,9 @@ NSMutableSet* titles = [NSMutableSet set]; for (UIMenuElement* group in submenu.children) { [titles addObject:group.title]; - EXPECT_EQ(nil, group.image); + // The image should be colorful circle but it is hard to test. Just check + // non-nil. + EXPECT_NE(nil, group.image); } EXPECT_EQ(2u, titles.count);
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm index f14dd81..b87c088 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.mm
@@ -540,7 +540,8 @@ authenticationService->GetPrimaryIdentity(signin::ConsentLevel::kSignin); if (identity) { self.userEmail = identity.userEmail; - self.syncEnabled = _personalDataManager->IsSyncFeatureEnabledForAutofill(); + self.syncEnabled = _personalDataManager->address_data_manager() + .IsSyncFeatureEnabledForAutofill(); } }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm index 7723f9ee..6de4cc7 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/create_tab_group_view_controller.mm
@@ -277,9 +277,7 @@ UIFontDescriptor* boldDescriptor = [[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody] fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold]; - UIFont* fontAttribute = - isCompact ? [UIFont fontWithDescriptor:boldDescriptor size:0.0] - : [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + UIFont* fontAttribute = [UIFont fontWithDescriptor:boldDescriptor size:0.0]; NSDictionary* attributes = @{ NSFontAttributeName : fontAttribute, NSForegroundColorAttributeName : textColor
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_view_controller.mm index d966328..63b06ff4 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_view_controller.mm
@@ -33,6 +33,7 @@ constexpr CGFloat kSubTitleHorizontalPadding = 7; constexpr CGFloat kThreeDotButtonSize = 19; constexpr CGFloat kTitleBackgroundCornerRadius = 17; +constexpr CGFloat kPlusImageSize = 20; } // namespace @interface TabGroupViewController () <UINavigationBarDelegate> @@ -232,10 +233,12 @@ // Returns the navigation item which contain the plus button. - (UINavigationItem*)configuredPlusButton { UINavigationItem* plus = [[UINavigationItem alloc] init]; - plus.rightBarButtonItem = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemAdd - target:self - action:@selector(didTapPlusButton)]; + UIImage* plusImage = DefaultSymbolWithPointSize(kPlusSymbol, kPlusImageSize); + plus.rightBarButtonItem = + [[UIBarButtonItem alloc] initWithImage:plusImage + style:UIBarButtonItemStylePlain + target:self + action:@selector(didTapPlusButton)]; return plus; }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm index d64ffa7..1fe848c8 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -1012,10 +1012,12 @@ switch (page) { case TabGridPageIncognitoTabs: DCHECK_GT(self.incognitoBrowser->GetWebStateList()->count(), 0); + self.activePage = page; activeBrowser = self.incognitoBrowser; break; case TabGridPageRegularTabs: DCHECK_GT(self.regularBrowser->GetWebStateList()->count(), 0); + self.activePage = page; activeBrowser = self.regularBrowser; break; case TabGridPageRemoteTabs:
diff --git a/ios_internal b/ios_internal index c448ce7..debd0ef 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit c448ce76c3e84201da5db9ac4a2a579c2fabfdf3 +Subproject commit debd0ef81bb8df6520b9cc80141ec587cd8e1c56
diff --git a/media/audio/reconfigurable_audio_bus_pool_unittest.cc b/media/audio/reconfigurable_audio_bus_pool_unittest.cc index 17a3013ea..8244912 100644 --- a/media/audio/reconfigurable_audio_bus_pool_unittest.cc +++ b/media/audio/reconfigurable_audio_bus_pool_unittest.cc
@@ -85,18 +85,12 @@ reconfigurable_audio_bus_pool_->InsertAudioBus(std::move(first_audio_bus)); AudioBus* second_audio_bus_ptr = second_audio_bus.get(); reconfigurable_audio_bus_pool_->InsertAudioBus(std::move(second_audio_bus)); - AudioBus* third_audio_bus_ptr = third_audio_bus.get(); reconfigurable_audio_bus_pool_->InsertAudioBus(std::move(third_audio_bus)); EXPECT_EQ(second_audio_bus_ptr, reconfigurable_audio_bus_pool_->GetAudioBus().get()); EXPECT_EQ(first_audio_bus_ptr, reconfigurable_audio_bus_pool_->GetAudioBus().get()); - - // The third audio bus was not recycled because the max capacity of the pool - // is 2. - EXPECT_NE(third_audio_bus_ptr, - reconfigurable_audio_bus_pool_->GetAudioBus().get()); } } // namespace media
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index 3b22bd2..b52e943 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -270,14 +270,14 @@ } HostCache::Entry::Entry( - std::set<std::unique_ptr<HostResolverInternalResult>> results, + const std::set<std::unique_ptr<HostResolverInternalResult>>& results, base::Time now, base::TimeTicks now_ticks, Source empty_source) { - std::unique_ptr<HostResolverInternalResult> data_result; - std::unique_ptr<HostResolverInternalResult> metadata_result; - std::unique_ptr<HostResolverInternalResult> error_result; - std::vector<std::unique_ptr<HostResolverInternalResult>> alias_results; + const HostResolverInternalResult* data_result = nullptr; + const HostResolverInternalResult* metadata_result = nullptr; + const HostResolverInternalResult* error_result = nullptr; + std::vector<const HostResolverInternalResult*> alias_results; std::optional<base::TimeDelta> smallest_ttl = TtlFromInternalResults(results, now, now_ticks); @@ -304,18 +304,18 @@ switch (result->type()) { case HostResolverInternalResult::Type::kData: DCHECK(!data_result); // Expect at most one data result. - data_result = std::move(results.extract(result).value()); + data_result = result.get(); break; case HostResolverInternalResult::Type::kMetadata: DCHECK(!metadata_result); // Expect at most one metadata result. - metadata_result = std::move(results.extract(result).value()); + metadata_result = result.get(); break; case HostResolverInternalResult::Type::kError: DCHECK(!error_result); // Expect at most one error result. - error_result = std::move(results.extract(result).value()); + error_result = result.get(); break; case HostResolverInternalResult::Type::kAlias: - alias_results.push_back(std::move(results.extract(result).value())); + alias_results.emplace_back(result.get()); break; } @@ -362,7 +362,7 @@ hostnames_ = data_result->AsData().hosts(); canonical_names_ = {data_result->domain_name()}; - for (const auto& alias_result : alias_results) { + for (const auto* alias_result : alias_results) { aliases_.insert(alias_result->domain_name()); aliases_.insert(alias_result->AsAlias().alias_target()); }
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index 9f5449da..6a9735b8 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -160,7 +160,7 @@ // results extracted from a single DnsTransaction. `empty_source` is Source // to assume if `results` is empty of any results from which Source can be // read. - Entry(std::set<std::unique_ptr<HostResolverInternalResult>> results, + Entry(const std::set<std::unique_ptr<HostResolverInternalResult>>& results, base::Time now, base::TimeTicks now_ticks, Source empty_source = SOURCE_UNKNOWN);
diff --git a/net/dns/host_resolver_dns_task.cc b/net/dns/host_resolver_dns_task.cc index 4e89cdd..cde346bb 100644 --- a/net/dns/host_resolver_dns_task.cc +++ b/net/dns/host_resolver_dns_task.cc
@@ -113,6 +113,21 @@ } // namespace +HostResolverDnsTask::SingleTransactionResults::SingleTransactionResults( + DnsQueryType query_type, + Results results) + : query_type(query_type), results(std::move(results)) {} + +HostResolverDnsTask::SingleTransactionResults::~SingleTransactionResults() = + default; + +HostResolverDnsTask::SingleTransactionResults::SingleTransactionResults( + SingleTransactionResults&&) = default; + +HostResolverDnsTask::SingleTransactionResults& +HostResolverDnsTask::SingleTransactionResults::operator=( + SingleTransactionResults&&) = default; + HostResolverDnsTask::TransactionInfo::TransactionInfo( DnsQueryType type, TransactionErrorBehavior error_behavior) @@ -352,10 +367,13 @@ } } + // Clear in-progress and scheduled transactions so that + // OnTransactionsFinished() doesn't call delegate's + // OnIntermediateTransactionComplete(). transactions_needed_.clear(); transactions_in_progress_.clear(); - OnTransactionsFinished(); + OnTransactionsFinished(/*single_transaction_results=*/std::nullopt); } void HostResolverDnsTask::OnDnsTransactionComplete( @@ -738,8 +756,8 @@ // TODO(crbug.com/1381506): Use new results type directly instead of // converting to HostCache::Entry. - HostCache::Entry legacy_results(std::move(transaction_results), - base::Time::Now(), tick_clock_->NowTicks(), + HostCache::Entry legacy_results(transaction_results, base::Time::Now(), + tick_clock_->NowTicks(), HostCache::Entry::SOURCE_DNS); // Merge results with saved results from previous transactions. @@ -777,13 +795,18 @@ } saved_results_ = std::move(legacy_results); - OnTransactionsFinished(); + + OnTransactionsFinished(SingleTransactionResults( + transaction_info.type, std::move(transaction_results))); } -void HostResolverDnsTask::OnTransactionsFinished() { +void HostResolverDnsTask::OnTransactionsFinished( + std::optional<SingleTransactionResults> single_transaction_results) { if (!transactions_in_progress_.empty() || !transactions_needed_.empty()) { - delegate_->OnIntermediateTransactionsComplete(); MaybeStartTimeoutTimer(); + delegate_->OnIntermediateTransactionsComplete( + std::move(single_transaction_results)); + // `this` may be deleted by `delegate_`. Do not add code below. return; } @@ -883,7 +906,7 @@ saved_results_is_failure_ = true; CancelNonFatalTransactions(); - OnTransactionsFinished(); + OnTransactionsFinished(/*single_transaction_results=*/std::nullopt); return; }
diff --git a/net/dns/host_resolver_dns_task.h b/net/dns/host_resolver_dns_task.h index e4314af8..7630249 100644 --- a/net/dns/host_resolver_dns_task.h +++ b/net/dns/host_resolver_dns_task.h
@@ -43,6 +43,24 @@ class NET_EXPORT_PRIVATE HostResolverDnsTask : public base::SupportsWeakPtr<HostResolverDnsTask> { public: + using Results = std::set<std::unique_ptr<HostResolverInternalResult>>; + + // Represents a single transaction results. + struct SingleTransactionResults { + SingleTransactionResults(DnsQueryType query_type, Results results); + ~SingleTransactionResults(); + + SingleTransactionResults(SingleTransactionResults&&); + SingleTransactionResults& operator=(SingleTransactionResults&&); + + SingleTransactionResults(const SingleTransactionResults&) = delete; + SingleTransactionResults& operator=(const SingleTransactionResults&) = + delete; + + DnsQueryType query_type; + Results results; + }; + class Delegate { public: virtual void OnDnsTaskComplete(base::TimeTicks start_time, @@ -50,10 +68,13 @@ HostCache::Entry results, bool secure) = 0; - // Called when one or more transactions complete or get cancelled, but only - // if more transactions are needed. If no more transactions are needed, - // expect `OnDnsTaskComplete()` to be called instead. - virtual void OnIntermediateTransactionsComplete() = 0; + // Called when one transaction completes successfully, or one more + // transactions get cancelled, but only if more transactions are + // needed. If no more transactions are needed, expect `OnDnsTaskComplete()` + // to be called instead. `single_transaction_results` is passed only when + // one transaction completes successfully. + virtual void OnIntermediateTransactionsComplete( + std::optional<SingleTransactionResults> single_transaction_results) = 0; virtual RequestPriority priority() const = 0; @@ -94,8 +115,6 @@ void StartNextTransaction(); private: - using Results = std::set<std::unique_ptr<HostResolverInternalResult>>; - enum class TransactionErrorBehavior { // Errors lead to task fallback (immediately unless another pending/started // transaction has the `kFatalOrEmpty` behavior). @@ -164,7 +183,8 @@ void HandleTransactionResults(TransactionInfo transaction_info, Results transaction_results); - void OnTransactionsFinished(); + void OnTransactionsFinished( + std::optional<SingleTransactionResults> single_transaction_results); void OnSortComplete(base::TimeTicks sort_start_time, HostCache::Entry results,
diff --git a/net/dns/host_resolver_manager_job.cc b/net/dns/host_resolver_manager_job.cc index 3cb4e408..0d2daeb 100644 --- a/net/dns/host_resolver_manager_job.cc +++ b/net/dns/host_resolver_manager_job.cc
@@ -741,7 +741,9 @@ secure ? TaskType::SECURE_DNS : TaskType::DNS); } -void HostResolverManager::Job::OnIntermediateTransactionsComplete() { +void HostResolverManager::Job::OnIntermediateTransactionsComplete( + std::optional<HostResolverDnsTask::SingleTransactionResults> + single_transaction_results) { if (dispatched_) { DCHECK_GE(num_occupied_job_slots_, dns_task_->num_transactions_in_progress()); @@ -770,6 +772,10 @@ } else if (dns_task_->num_additional_transactions_needed() >= 1) { dns_task_->StartNextTransaction(); } + + // TODO(crbug.com/41493696): Use `single_transaction_results` for the + // ServiceEndpointRequest API. Be sure to handle the case where `this` was + // deleted while processing the intermediate results. } void HostResolverManager::Job::AddTransactionTimeQueued(
diff --git a/net/dns/host_resolver_manager_job.h b/net/dns/host_resolver_manager_job.h index 4535262..3055e39 100644 --- a/net/dns/host_resolver_manager_job.h +++ b/net/dns/host_resolver_manager_job.h
@@ -217,7 +217,9 @@ bool allow_fallback, HostCache::Entry results, bool secure) override; - void OnIntermediateTransactionsComplete() override; + void OnIntermediateTransactionsComplete( + std::optional<HostResolverDnsTask::SingleTransactionResults> + single_transaction_results) override; void AddTransactionTimeQueued(base::TimeDelta time_queued) override; void StartMdnsTask();
diff --git a/net/third_party/quiche/src b/net/third_party/quiche/src index acbdda4..718c901 160000 --- a/net/third_party/quiche/src +++ b/net/third_party/quiche/src
@@ -1 +1 @@ -Subproject commit acbdda4e4aa43e72a19aa72115b71e8eba57babb +Subproject commit 718c9019fe67253ca9aa76498dff0f35ef97b15e
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 343081e..ec639872 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -29,6 +29,7 @@ #include "base/ranges/algorithm.h" #include "base/sequence_checker.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task/current_thread.h" #include "base/task/sequenced_task_runner.h" @@ -444,13 +445,12 @@ } std::string HashesToBase64String(const net::HashValueVector& hashes) { - std::string str; - for (size_t i = 0; i != hashes.size(); ++i) { - if (i != 0) - str += ","; - str += hashes[i].ToString(); + std::vector<std::string> strings; + strings.reserve(hashes.size()); + for (const auto& hash : hashes) { + strings.push_back(hash.ToString()); } - return str; + return base::JoinString(strings, ","); } #if BUILDFLAG(IS_CT_SUPPORTED) @@ -643,7 +643,8 @@ url_request_context_owner_ = MakeURLRequestContext( std::move(url_loader_factory_for_cert_net_fetcher), session_cleanup_cookie_store, - std::move(on_url_request_context_builder_configured)); + std::move(on_url_request_context_builder_configured), + params_->bound_network); url_request_context_ = url_request_context_owner_.url_request_context.get(); cookie_manager_ = std::make_unique<CookieManager>( @@ -2309,11 +2310,17 @@ url_loader_factory_for_cert_net_fetcher, scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store, OnURLRequestContextBuilderConfiguredCallback - on_url_request_context_builder_configured) { + on_url_request_context_builder_configured, + net::handles::NetworkHandle bound_network) { URLRequestContextBuilderMojo builder; const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + bool is_network_bound = bound_network != net::handles::kInvalidNetworkHandle; + if (is_network_bound) { + builder.BindToNetwork(bound_network); + } + std::unique_ptr<net::CertVerifier> cert_verifier; if (g_cert_verifier_for_testing) { cert_verifier = std::make_unique<WrappedTestingCertVerifier>(); @@ -2402,10 +2409,15 @@ if (network_service_) { net_log = network_service_->net_log(); builder.set_net_log(net_log); - builder.set_host_resolver_manager( - network_service_->host_resolver_manager()); - builder.set_host_resolver_factory( - network_service_->host_resolver_factory()); + if (!is_network_bound) { + // Network bound URLRequestContexts build and configure their own special + // HostResolverManager and HostResolver. So, don't inject the + // NetworkService one even if NetworkService is enabled. + builder.set_host_resolver_manager( + network_service_->host_resolver_manager()); + builder.set_host_resolver_factory( + network_service_->host_resolver_factory()); + } builder.SetHttpAuthHandlerFactory( network_service_->CreateHttpAuthHandlerFactory(this)); builder.set_network_quality_estimator( @@ -2487,6 +2499,8 @@ cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY; } else { + // Network-bound NetworkContexts should not persist state on disk. + CHECK(!is_network_bound); cache_params.path = params_->file_paths->http_cache_directory->path(); cache_params.type = network_session_configurator::ChooseCacheType(); if (params_->http_cache_file_operations_factory) { @@ -2532,6 +2546,8 @@ &network::mojom::NetworkContextFilePaths:: http_server_properties_file_name, http_server_properties_file_name)) { + // Network-bound NetworkContexts should not persist state on disk. + CHECK(!is_network_bound); scoped_refptr<JsonPrefStore> json_pref_store(new JsonPrefStore( http_server_properties_file_name, nullptr, base::ThreadPool::CreateSequencedTaskRunner( @@ -2559,6 +2575,8 @@ &network::mojom::NetworkContextFilePaths:: transport_security_persister_file_name, transport_security_persister_file_name)) { + // Network-bound NetworkContexts should not persist state on disk. + CHECK(!is_network_bound); builder.set_transport_security_persister_file_path( transport_security_persister_file_name); } @@ -2589,6 +2607,8 @@ reporting_and_nel_store_database_name, reporting_and_nel_store_database_name) && (reporting_enabled || nel_enabled)) { + // Network-bound NetworkContexts should not persist state on disk. + CHECK(!is_network_bound); scoped_refptr<base::SequencedTaskRunner> client_task_runner = base::SingleThreadTaskRunner::GetCurrentDefault(); scoped_refptr<base::SequencedTaskRunner> background_task_runner =
diff --git a/services/network/network_context.h b/services/network/network_context.h index 598cd51..acd59fe 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -685,7 +685,8 @@ url_loader_factory_for_cert_net_fetcher, scoped_refptr<SessionCleanupCookieStore>, OnURLRequestContextBuilderConfiguredCallback - on_url_request_context_builder_configured); + on_url_request_context_builder_configured, + net::handles::NetworkHandle bound_network); scoped_refptr<SessionCleanupCookieStore> MakeSessionCleanupCookieStore() const;
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index c5ab0e4d..0c7a743 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -65,6 +65,7 @@ #include "net/base/http_user_agent_settings.h" #include "net/base/ip_endpoint.h" #include "net/base/isolation_info.h" +#include "net/base/mock_network_change_notifier.h" #include "net/base/net_errors.h" #include "net/base/network_change_notifier.h" #include "net/base/network_isolation_key.h" @@ -173,6 +174,10 @@ #include "services/network/public/mojom/p2p_trusted.mojom.h" #endif // BUILDFLAG(IS_P2P_ENABLED) +#if BUILDFLAG(IS_ANDROID) +#include "base/android/build_info.h" +#endif // BUILDFLAG(IS_ANDROID) + namespace network { namespace { @@ -713,6 +718,44 @@ } } +TEST_F(NetworkContextTest, BoundNetwork) { +#if BUILDFLAG(IS_ANDROID) + if (base::android::BuildInfo::GetInstance()->sdk_int() < + base::android::SDK_VERSION_MARSHMALLOW) { + GTEST_SKIP() + << "bound_network is supported starting from Android Marshmallow"; + } + + // The actual network handle doesn't really matter, this test just wants to + // confirm that it is correctly passed down to the owned URLRequestContext. + constexpr net::handles::NetworkHandle network = 2; + auto scoped_mock_network_change_notifier = + std::make_unique<net::test::ScopedMockNetworkChangeNotifier>(); + auto* mock_ncn = + scoped_mock_network_change_notifier->mock_network_change_notifier(); + mock_ncn->ForceNetworkHandlesSupported(); + + mojom::NetworkContextParamsPtr context_params = + CreateNetworkContextParamsForTesting(); + context_params->bound_network = network; + std::unique_ptr<NetworkContext> network_context = + CreateContextWithParams(std::move(context_params)); + + EXPECT_EQ(network_context->url_request_context()->bound_network(), network); + EXPECT_EQ(network_context->url_request_context() + ->host_resolver() + ->GetTargetNetworkForTesting(), + network); + EXPECT_EQ(network_context->url_request_context() + ->host_resolver() + ->GetManagerForTesting() + ->target_network_for_testing(), + network); +#else // !BUILDFLAG(IS_ANDROID) + GTEST_SKIP() << "bound_network is supported only on Android"; +#endif // BUILDFLAG(IS_ANDROID) +} + TEST_F(NetworkContextTest, UnhandedProtocols) { const GURL kUnsupportedUrls[] = { // These are handled outside the network service.
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 5010e07..76a41bf 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -601,6 +601,15 @@ // Enables Device Bound Session Credential for this network context. bool device_bound_sessions_enabled = false; + + // Represents a net::handles::NetworkHandle. + // If != net::handles::kInvalidNetworkHandle (== -1), then the NetworkContext + // built out of this will own a URLRequestContext bound to that network (refer + // to net::UrlRequestContextBuilder::bindToNetwork documentation). This + // effectively means that URLLoaderFactories, returned by the NetworkContext + // created out of this, will perform all network request using only + // |bound_network|. + int64 bound_network = -1; }; struct NetworkConditions {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index fea2751..6b12440b 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5484,9 +5484,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5496,8 +5496,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -5640,9 +5640,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5652,8 +5652,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index 8c6a9c4..0000f76 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -19715,9 +19715,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19727,8 +19727,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -19865,9 +19865,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19877,8 +19877,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 9cc35d3a..14698c0 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -41638,9 +41638,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41649,8 +41649,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -41788,9 +41788,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41799,8 +41799,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -43137,9 +43137,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43149,8 +43149,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -43293,9 +43293,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43305,8 +43305,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -44618,9 +44618,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44629,8 +44629,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -44768,9 +44768,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_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44779,8 +44779,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index b952614..0e168b03 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -15765,12 +15765,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_v125.0.6411.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15780,8 +15780,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": { @@ -15941,12 +15941,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_v125.0.6411.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6412.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15956,8 +15956,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6412.0", + "revision": "version:125.0.6412.0" } ], "dimensions": {
diff --git a/testing/buildbot/client.devtools-frontend.integration.json b/testing/buildbot/client.devtools-frontend.integration.json index 0b5e9ba2..b96e927 100644 --- a/testing/buildbot/client.devtools-frontend.integration.json +++ b/testing/buildbot/client.devtools-frontend.integration.json
@@ -65,33 +65,6 @@ }, "test": "blink_web_tests", "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ - "--num-retries=3", - "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "os": "Ubuntu-22.04" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 7 - }, - "test": "blink_wpt_tests", - "test_id_prefix": "ninja://:blink_wpt_tests/" } ] }, @@ -159,33 +132,6 @@ }, "test": "blink_web_tests", "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ - "--num-retries=3", - "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "os": "Ubuntu-22.04" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 7 - }, - "test": "blink_wpt_tests", - "test_id_prefix": "ninja://:blink_wpt_tests/" } ] }
diff --git a/testing/buildbot/filters/pixel_tests.filter b/testing/buildbot/filters/pixel_tests.filter index 8b0658d..0308380 100644 --- a/testing/buildbot/filters/pixel_tests.filter +++ b/testing/buildbot/filters/pixel_tests.filter
@@ -11,6 +11,7 @@ AppInfoDialogBrowserTest.* AppMenuBrowserTest*.InvokeUi_* AskGoogleForSuggestionsDialogTest.* +AutofillBubbleSignInPromoInteractiveUITest.* BookmarkBubbleViewBrowserTest.* BookmarkEditorViewBrowserTest.* BubbleFrameViewBrowserTest.*
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 9a0f7ec..f7b0405 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1976,6 +1976,28 @@ }, }, + 'devtools_web_isolated_scripts': { + 'blink_web_tests': { + 'results_handler': 'layout tests', + 'mixins': [ + 'has_native_resultdb_integration', + 'blink_tests_write_run_histories', + ], + 'args': [ + '--num-retries=3', + ], + 'swarming': { + 'shards': 5, + }, + 'merge': { + 'script': '//third_party/blink/tools/merge_web_test_results.py', + 'args': [ + '--verbose', + ], + }, + }, + }, + 'devtools_webkit_isolated_scripts': { 'blink_web_tests': { 'results_handler': 'layout tests',
diff --git a/testing/buildbot/tryserver.devtools-frontend.json b/testing/buildbot/tryserver.devtools-frontend.json index 6fab82c..8f3137b 100644 --- a/testing/buildbot/tryserver.devtools-frontend.json +++ b/testing/buildbot/tryserver.devtools-frontend.json
@@ -131,33 +131,6 @@ }, "test": "blink_web_tests", "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ - "--num-retries=3", - "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "os": "Ubuntu-22.04" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 7 - }, - "test": "blink_wpt_tests", - "test_id_prefix": "ninja://:blink_wpt_tests/" } ] }
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index d457a9a..1d11ec4 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -267,16 +267,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 125.0.6411.0', + 'description': 'Run with ash-chrome version 125.0.6412.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6412.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v125.0.6411.0', - 'revision': 'version:125.0.6411.0', + 'location': 'lacros_version_skew_tests_v125.0.6412.0', + 'revision': 'version:125.0.6412.0', }, ], },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e74c9f1e..70ed4f9c 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -6240,7 +6240,7 @@ 'additional_compile_targets': ['blink_tests'], 'test_suites': { 'gtest_tests': 'devtools_gtests', - 'isolated_scripts': 'devtools_webkit_isolated_scripts', + 'isolated_scripts': 'devtools_web_isolated_scripts', }, }, 'DevTools Linux Fastbuild': { @@ -6250,7 +6250,7 @@ 'additional_compile_targets': ['blink_tests'], 'test_suites': { 'gtest_tests': 'devtools_gtests', - 'isolated_scripts': 'devtools_webkit_isolated_scripts', + 'isolated_scripts': 'devtools_web_isolated_scripts', }, }, }, @@ -7062,7 +7062,7 @@ ], 'test_suites': { 'gtest_tests': 'devtools_browser_tests_suite', - 'isolated_scripts': 'devtools_webkit_isolated_scripts', + 'isolated_scripts': 'devtools_web_isolated_scripts', }, }, 'devtools_frontend_linux_blink_light_rel_fastbuild': { @@ -7071,7 +7071,7 @@ ], 'test_suites': { 'gtest_tests': 'devtools_browser_tests_suite', - 'isolated_scripts': 'devtools_webkit_isolated_scripts', + 'isolated_scripts': 'devtools_web_isolated_scripts', }, }, 'devtools_frontend_linux_blink_rel': { @@ -7079,7 +7079,7 @@ 'linux-jammy', ], 'test_suites': { - 'isolated_scripts': 'devtools_webkit_isolated_scripts', + 'isolated_scripts': 'devtools_web_isolated_scripts', }, }, }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index db4063f4..7571b675 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -18592,21 +18592,6 @@ ] } ], - "SyncShowIdentityErrorsForSignedInUsers": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "SyncShowIdentityErrorsForSignedInUsers" - ] - } - ] - } - ], "SysUiHoldbackStudy": [ { "platforms": [
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index 1fd8eaf..2ba9490 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3748,7 +3748,7 @@ kCSSAtRuleSwash = 4407 , kCSSAtRuleOrnaments = 4408, kCSSAtRuleAnnotation = 4409, - kServiceWorkerBypassFetchHandlerForMainResource = 4410, + kOBSOLETE_ServiceWorkerBypassFetchHandlerForMainResource = 4410, kV8Document_HasPrivateToken_Method = 4411, kServiceWorkerSkippedForEmptyFetchHandler = 4412, kImageSet = 4413, @@ -3799,7 +3799,7 @@ kOptionLabelInQuirksMode = 4454, kParseFromStringIncludeShadows = 4455, kWebAppManifestScopeExtensions = 4456, - kServiceWorkerBypassFetchHandlerForMainResourceByOriginTrial = 4457, + kOBSOLETE_ServiceWorkerBypassFetchHandlerForMainResourceByOriginTrial = 4457, kOBSOLETE_V8RegExpUnicodeSetIncompatibilitiesWithUnicodeMode = 4458, kFedCmAutoReauthn = 4459, kTopicsAPIFetch = 4460, @@ -3829,7 +3829,7 @@ kRTCPeerConnectionLegacyGetStatsTrial = 4482, kExecutedEmptyJavaScriptURLFromFrame = 4483, kExecutedJavaScriptURLFromFrame = 4484, - kServiceWorkerBypassFetchHandlerForSubResource = 4485, + kOBSOLETE_ServiceWorkerBypassFetchHandlerForSubResource = 4485, kCSSAtRuleStartingStyle = 4486, kPrivateAggregationApiFledgeExtensions = 4487, kDeprecatedInterestGroupDailyUpdateUrl = 4488, @@ -3894,7 +3894,7 @@ kOBSOLETE_TextWrapBalanceFail = 4545, kAttributionReportingCrossAppWeb = 4546, kSecurePaymentConfirmationActivationlessShow = 4547, - kServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequest = 4548, + kOBSOLETE_ServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequest = 4548, // The items above roughly this point are available in the M114 branch. kFlexIntrinsicSizesCacheMiss = 4549, @@ -3907,7 +3907,7 @@ kCSSValueAppearanceSliderVertical = 4556, kCSSValueAppearanceSliderthumbHorizontal = 4557, kCSSValueAppearanceSliderthumbVertical = 4558, - kServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequestByOriginTrial = 4559, + kOBSOLETE_ServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequestByOriginTrial = 4559, kOBSOLETE_EventTimingPaintedPresentationPromiseResolvedWithEarlierPromiseUnresolved = 4560, kLinkRelPreloadAsFont = 4561, kCrossWindowAccessToBrowserGeneratedDocument = 4562,
diff --git a/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc b/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc index b44b536..a1638a79 100644 --- a/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc +++ b/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc
@@ -34,7 +34,6 @@ #include "third_party/blink/renderer/core/css/container_query.h" #include "third_party/blink/renderer/core/css/container_query_evaluator.h" #include "third_party/blink/renderer/core/css/css_resolution_units.h" -#include "third_party/blink/renderer/core/css/out_of_flow_data.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" @@ -295,19 +294,12 @@ } CSSToLengthConversionData::AnchorData::AnchorData( - Element* anchored, AnchorEvaluator* evaluator, const ScopedCSSName* position_anchor, const std::optional<InsetAreaOffsets>& inset_area_offsets) : evaluator_(evaluator), position_anchor_(position_anchor), - inset_area_offsets_(inset_area_offsets) { - if (!evaluator_ && anchored) { - if (OutOfFlowData* out_of_flow_data = anchored->GetOutOfFlowData()) { - evaluator_ = &out_of_flow_data->GetAnchorResults(); - } - } -} + inset_area_offsets_(inset_area_offsets) {} CSSToLengthConversionData::CSSToLengthConversionData( WritingMode writing_mode,
diff --git a/third_party/blink/renderer/core/css/css_to_length_conversion_data.h b/third_party/blink/renderer/core/css/css_to_length_conversion_data.h index a357fb26..17a56fb 100644 --- a/third_party/blink/renderer/core/css/css_to_length_conversion_data.h +++ b/third_party/blink/renderer/core/css/css_to_length_conversion_data.h
@@ -251,8 +251,7 @@ public: AnchorData() = default; - AnchorData(Element* anchored, - AnchorEvaluator*, + AnchorData(AnchorEvaluator*, const ScopedCSSName* position_anchor, const std::optional<InsetAreaOffsets>&); AnchorEvaluator* GetEvaluator() const { return evaluator_; }
diff --git a/third_party/blink/renderer/core/css/css_to_length_conversion_data_test.cc b/third_party/blink/renderer/core/css/css_to_length_conversion_data_test.cc index f7dda468..7b95bc3 100644 --- a/third_party/blink/renderer/core/css/css_to_length_conversion_data_test.cc +++ b/third_party/blink/renderer/core/css/css_to_length_conversion_data_test.cc
@@ -98,7 +98,7 @@ CSSToLengthConversionData::ViewportSize(GetDocument().GetLayoutView()), CSSToLengthConversionData::ContainerSizes(), CSSToLengthConversionData::AnchorData( - div, options.anchor_evaluator, + options.anchor_evaluator, /* position_anchor */ nullptr, /* inset_area_offsets */ std::nullopt), options.data_zoom.value_or(div->GetComputedStyle()->EffectiveZoom()), @@ -554,7 +554,7 @@ CSSToLengthConversionData::ViewportSize(GetDocument().GetLayoutView()), CSSToLengthConversionData::ContainerSizes(child), CSSToLengthConversionData::AnchorData( - child, nullptr, + nullptr, /* position_anchor */ nullptr, /* inset_area_offsets */ std::nullopt), child->GetComputedStyle()->EffectiveZoom(), flags);
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc index a383f67..0388ef6 100644 --- a/third_party/blink/renderer/core/css/element_rule_collector.cc +++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -396,6 +396,12 @@ if (!property_set) { return; } + if (!style_recalc_context_.is_interleaved_oof) { + // TODO(crbug.com/333608683): The anchor result cache is currently disabled + // for non-OOF recalcs to work around invalidation problems. See + // `ComputeAnchorEvaluator` in style_resolver_state.cc for more information. + return; + } auto link_match_type = static_cast<unsigned>(CSSSelector::kMatchAll); result_.AddMatchedProperties( property_set, CascadeOrigin::kAuthor, @@ -410,6 +416,12 @@ if (!property_set) { return; } + if (!style_recalc_context_.is_interleaved_oof) { + // TODO(crbug.com/333608683): The anchor result cache is currently disabled + // for non-OOF recalcs to work around invalidation problems. See + // `ComputeAnchorEvaluator` in style_resolver_state.cc for more information. + return; + } auto link_match_type = static_cast<unsigned>(CSSSelector::kMatchAll); result_.AddMatchedProperties( property_set, CascadeOrigin::kAuthor,
diff --git a/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc b/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc index d9e66eb..f8dd56c 100644 --- a/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc +++ b/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc
@@ -658,6 +658,9 @@ // The parsing was successful, so we need to consume the input. input_range = range; + // TODO(b/40949047): Counters for out-of-gamut are disabled because of + // repeated merge-conflict creating reverts. Remove this parameter. + const bool kEnableCounters = false; if (is_relative_color_) { context.Count(WebFeature::kCSSRelativeColor); } else { @@ -668,16 +671,20 @@ case Color::ColorSpace::kA98RGB: case Color::ColorSpace::kProPhotoRGB: case Color::ColorSpace::kRec2020: - context.Count(WebFeature::kCSSColor_SpaceRGB); - if (!IsInGamutRec2020(result)) { - context.Count(WebFeature::kCSSColor_SpaceRGB_outOfRec2020); + if (kEnableCounters) { + context.Count(WebFeature::kCSSColor_SpaceRGB); + if (!IsInGamutRec2020(result)) { + context.Count(WebFeature::kCSSColor_SpaceRGB_outOfRec2020); + } } break; case Color::ColorSpace::kOklab: case Color::ColorSpace::kOklch: - context.Count(WebFeature::kCSSColor_SpaceOkLxx); - if (!IsInGamutRec2020(result)) { - context.Count(WebFeature::kCSSColor_SpaceOkLxx_outOfRec2020); + if (kEnableCounters) { + context.Count(WebFeature::kCSSColor_SpaceOkLxx); + if (!IsInGamutRec2020(result)) { + context.Count(WebFeature::kCSSColor_SpaceOkLxx_outOfRec2020); + } } break; case Color::ColorSpace::kXYZD50:
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc index 6194e869..e7ad1867 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -27,6 +27,7 @@ #include "third_party/blink/renderer/core/core_probes_inl.h" #include "third_party/blink/renderer/core/css/css_light_dark_value_pair.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" +#include "third_party/blink/renderer/core/css/out_of_flow_data.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/pseudo_element.h" @@ -50,6 +51,49 @@ return styled_element; } +AnchorEvaluator* ComputeAnchorEvaluator( + Element* styled_element, + const StyleRecalcContext* style_recalc_context) { + if (!style_recalc_context) { + return nullptr; + } + if (style_recalc_context->anchor_evaluator) { + return style_recalc_context->anchor_evaluator; + } + if (style_recalc_context->is_interleaved_oof) { + // If we don't have an anchor evaluator, then we're resolving the style for + // a descendant of the anchored element. Normally, if that descendant is + // also anchored, then we'd enter UpdateStyleForOutOfFlow separately for + // that descendant, but this is not the case for ::backdrop, where + // UpdateStyleForOutOfFlow calls appear in the reverse order. For example: + // + // - Say ::backdrop and its <dialog> are both absolutely positioned, + // and <dialog> uses the anchor attribute. + // - We get a call to UpdateStyleForOutOfFlow to ::backdrop first, + // which evaluates any anchor queries correctly for ::backdrop. + // - We then get another call to UpdateStyleForOutOfFlow for <dialog>, + // which also updates the ::backdrop (again), but this time we lose the + // AnchorEvaluator on our way into ::backdrop. (This is the correct + // behavior as the AnchorEvaluator passed into UpdateStyleForOutOfFlow is + // only supposed to apply to the interleaving root itself). + // + // For this reason, we use the AnchorResults (the most recently seen anchor + // query results) as the AnchorEvaluator if we end up with no (incoming) + // AnchorEvaluator during is_interleaved_oof. + // + // The AnchorResults cache was originally implemented as an optimization for + // regular style recalcs, but is currently disabled due to issues with + // invalidation. + // + // TODO(crbug.com/333608683): Make use of AnchorResults for regular recalcs. + if (styled_element) { + OutOfFlowData* out_of_flow_data = styled_element->GetOutOfFlowData(); + return out_of_flow_data ? &out_of_flow_data->GetAnchorResults() : nullptr; + } + } + return nullptr; +} + } // namespace StyleResolverState::StyleResolverState( @@ -75,9 +119,8 @@ container_unit_context_(style_recalc_context ? style_recalc_context->container : element.ParentOrShadowHostElement()), - anchor_evaluator_(style_recalc_context - ? style_recalc_context->anchor_evaluator - : nullptr), + anchor_evaluator_( + ComputeAnchorEvaluator(styled_element_, style_recalc_context)), originating_element_style_(style_request.originating_element_style), is_for_highlight_(IsHighlightPseudoElement(style_request.pseudo_id)), uses_highlight_pseudo_inheritance_( @@ -161,7 +204,7 @@ *style_builder_, ParentStyle(), RootElementStyle(), GetDocument().GetStyleEngine().GetViewportSize(), CSSToLengthConversionData::ContainerSizes(container_unit_context_), - CSSToLengthConversionData::AnchorData(styled_element_, anchor_evaluator_, + CSSToLengthConversionData::AnchorData(anchor_evaluator_, StyleBuilder().PositionAnchor(), StyleBuilder().InsetAreaOffsets()), StyleBuilder().EffectiveZoom(), length_conversion_flags_); @@ -183,7 +226,7 @@ CSSToLengthConversionData::ContainerSizes container_sizes( container_unit_context_); CSSToLengthConversionData::AnchorData anchor_data( - styled_element_, anchor_evaluator_, StyleBuilder().PositionAnchor(), + anchor_evaluator_, StyleBuilder().PositionAnchor(), StyleBuilder().InsetAreaOffsets()); return CSSToLengthConversionData( StyleBuilder().GetWritingMode(), font_sizes, line_height_size, @@ -285,7 +328,7 @@ StyleBuilder().SetPositionAnchor(position_anchor); css_to_length_conversion_data_.SetAnchorData( CSSToLengthConversionData::AnchorData( - styled_element_, anchor_evaluator_, position_anchor, + anchor_evaluator_, position_anchor, StyleBuilder().InsetAreaOffsets())); } } @@ -295,9 +338,9 @@ if (StyleBuilder().InsetAreaOffsets() != inset_area_offsets) { StyleBuilder().SetInsetAreaOffsets(inset_area_offsets); css_to_length_conversion_data_.SetAnchorData( - CSSToLengthConversionData::AnchorData( - styled_element_, anchor_evaluator_, StyleBuilder().PositionAnchor(), - inset_area_offsets)); + CSSToLengthConversionData::AnchorData(anchor_evaluator_, + StyleBuilder().PositionAnchor(), + inset_area_offsets)); } }
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc index e6d28fea..f55130a8 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -52,12 +52,13 @@ class StyleResolverTest : public PageTestBase { protected: - const ComputedStyle* StyleForId(const char* id) { + const ComputedStyle* StyleForId( + const char* id, + StyleRecalcContext style_recalc_context = {}) { Element* element = GetElementById(id); - StyleRecalcContext recalc_context; - recalc_context.old_style = element->GetComputedStyle(); + style_recalc_context.old_style = element->GetComputedStyle(); const auto* style = GetStyleEngine().GetStyleResolver().ResolveStyle( - element, recalc_context); + element, style_recalc_context); DCHECK(style); return style; } @@ -1939,18 +1940,28 @@ // the AnchorResults. OutOfFlowData* out_of_flow_data = anchored->GetOutOfFlowData(); ASSERT_TRUE(out_of_flow_data); - EXPECT_FALSE(out_of_flow_data->GetAnchorResults().IsEmpty()); + AnchorResults& anchor_results = out_of_flow_data->GetAnchorResults(); + EXPECT_FALSE(anchor_results.IsEmpty()); - // Calls StyleResolver::ResolveStyle with a nullptr AnchorEvaluator. - const ComputedStyle* non_interleaved_style = StyleForId("anchored"); - ASSERT_TRUE(non_interleaved_style); + const ComputedStyle* old_style = anchored->GetComputedStyle(); - // Results should be the same as before, because we're fetching them - // from the AnchorResults on OutOfFlowData. - EXPECT_EQ("300px", ComputedValue("left", *non_interleaved_style)); - EXPECT_EQ("450px", ComputedValue("top", *non_interleaved_style)); - EXPECT_EQ("150px", ComputedValue("width", *non_interleaved_style)); - EXPECT_EQ("100px", ComputedValue("height", *non_interleaved_style)); + // Freshen the style using the previous results as the evaluator. + // We are using a copy, because UpdateStyleForOutOfFlow clears the results + // on the element's OutOfFlowData. + AnchorResults anchor_results_copy(anchor_results); + GetStyleEngine().UpdateStyleForOutOfFlow( + *anchored, /* try_set */ nullptr, kNoTryTactics, + /* anchor_evaluator */ &anchor_results_copy); + + // We should have created a new ComputedStyle object with the same computed + // values as before. + const ComputedStyle* new_style = anchored->GetComputedStyle(); + ASSERT_TRUE(new_style); + EXPECT_NE(old_style, new_style); + EXPECT_EQ("300px", ComputedValue("left", *new_style)); + EXPECT_EQ("450px", ComputedValue("top", *new_style)); + EXPECT_EQ("150px", ComputedValue("width", *new_style)); + EXPECT_EQ("100px", ComputedValue("height", *new_style)); } TEST_P(ParameterizedStyleResolverTest, NoCascadeLayers) { @@ -3324,63 +3335,6 @@ } } -TEST_P(ParameterizedStyleResolverTest, - PositionFallback_PersistentPositionTrySet) { - ScopedCSSAnchorPositioningForTest enabled(true); - ScopedCSSAnchorPositioningCascadeFallbackForTest cascade(true); - - SetBodyInnerHTML(R"HTML( - <style> - @position-try --f1 { left: 100px; } - @position-try --f2 { top: 100px; } - #target { - position: absolute; - left: 400000px; - position-try-options: --f1, --f2; - } - </style> - <div id="target"></div> - )HTML"); - - UpdateAllLifecyclePhasesForTest(); - - Element* target = GetElementById("target"); - const ComputedStyle* style = target->GetComputedStyle(); - ASSERT_TRUE(style); - EXPECT_EQ(Length::Fixed(100), GetLeft(*style)); - EXPECT_EQ(Length::Auto(), GetTop(*style)); - EXPECT_TRUE(target->GetOutOfFlowData() && - target->GetOutOfFlowData()->GetTryPropertyValueSet()); - - // The set should be cleared when 'position-try-options' is cleared. - target->SetInlineStyleProperty(CSSPropertyID::kPositionTryOptions, "none"); - UpdateAllLifecyclePhasesForTest(); - style = target->GetComputedStyle(); - EXPECT_EQ(Length::Fixed(400000), GetLeft(*style)); - EXPECT_EQ(Length::Auto(), GetTop(*style)); - EXPECT_FALSE(target->GetOutOfFlowData() && - target->GetOutOfFlowData()->GetTryPropertyValueSet()); - - target->SetInlineStyleProperty(CSSPropertyID::kPositionTryOptions, - "--f1, --f2"); - UpdateAllLifecyclePhasesForTest(); - style = target->GetComputedStyle(); - EXPECT_EQ(Length::Fixed(100), GetLeft(*style)); - EXPECT_EQ(Length::Auto(), GetTop(*style)); - EXPECT_TRUE(target->GetOutOfFlowData() && - target->GetOutOfFlowData()->GetTryPropertyValueSet()); - - // The set should also be cleared when referencing a non-existent fallback. - target->SetInlineStyleProperty(CSSPropertyID::kPositionTryOptions, - "--unknown"); - UpdateAllLifecyclePhasesForTest(); - style = target->GetComputedStyle(); - EXPECT_EQ(Length::Fixed(400000), GetLeft(*style)); - EXPECT_EQ(Length::Auto(), GetTop(*style)); - EXPECT_FALSE(target->GetOutOfFlowData() && - target->GetOutOfFlowData()->GetTryPropertyValueSet()); -} - TEST_P(ParameterizedStyleResolverTest, PositionTry_PaintInvalidation) { ScopedCSSAnchorPositioningForTest enabled(true); ScopedCSSAnchorPositioningCascadeFallbackForTest cascade(true); @@ -3445,7 +3399,8 @@ ASSERT_TRUE(try_set); div->EnsureOutOfFlowData().SetTryPropertyValueSet(try_set); - const ComputedStyle* try_style = StyleForId("div"); + const ComputedStyle* try_style = + StyleForId("div", StyleRecalcContext{.is_interleaved_oof = true}); ASSERT_TRUE(try_style); EXPECT_EQ("20px", ComputedValue("left", *try_style)); EXPECT_EQ("30px", ComputedValue("right", *try_style)); @@ -3476,7 +3431,8 @@ ASSERT_TRUE(try_set); div->EnsureOutOfFlowData().SetTryPropertyValueSet(try_set); - const ComputedStyle* try_style = StyleForId("div"); + const ComputedStyle* try_style = + StyleForId("div", StyleRecalcContext{.is_interleaved_oof = true}); ASSERT_TRUE(try_style); EXPECT_EQ("10px", ComputedValue("left", *try_style)); EXPECT_EQ("30px", ComputedValue("right", *try_style)); @@ -3507,7 +3463,8 @@ ASSERT_TRUE(try_set); div->EnsureOutOfFlowData().SetTryPropertyValueSet(try_set); - const ComputedStyle* try_style = StyleForId("div"); + const ComputedStyle* try_style = + StyleForId("div", StyleRecalcContext{.is_interleaved_oof = true}); ASSERT_TRUE(try_style); EXPECT_EQ("auto", ComputedValue("left", *try_style)); EXPECT_EQ("30px", ComputedValue("right", *try_style)); @@ -3539,7 +3496,8 @@ ASSERT_TRUE(try_set); div->EnsureOutOfFlowData().SetTryPropertyValueSet(try_set); - const ComputedStyle* try_style = StyleForId("div"); + const ComputedStyle* try_style = + StyleForId("div", StyleRecalcContext{.is_interleaved_oof = true}); ASSERT_TRUE(try_style); EXPECT_EQ("10px", ComputedValue("left", *try_style)); EXPECT_EQ("auto", ComputedValue("right", *try_style)); @@ -3574,7 +3532,8 @@ div->SetInlineStyleProperty(CSSPropertyID::kPosition, "static"); div->EnsureOutOfFlowData().SetTryPropertyValueSet(try_set); - const ComputedStyle* try_style = StyleForId("div"); + const ComputedStyle* try_style = + StyleForId("div", StyleRecalcContext{.is_interleaved_oof = true}); ASSERT_TRUE(try_style); EXPECT_EQ("10px", ComputedValue("left", *try_style)); EXPECT_EQ("auto", ComputedValue("right", *try_style)); @@ -3619,7 +3578,8 @@ ASSERT_TRUE(try_tactics_set); div->EnsureOutOfFlowData().SetTryTacticsPropertyValueSet(try_tactics_set); - const ComputedStyle* try_style = StyleForId("div"); + const ComputedStyle* try_style = + StyleForId("div", StyleRecalcContext{.is_interleaved_oof = true}); ASSERT_TRUE(try_style); EXPECT_EQ("200px", ComputedValue("left", *try_style)); EXPECT_EQ("100px", ComputedValue("right", *try_style));
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index b0787edc..057118f0 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -3470,18 +3470,12 @@ const TryTacticList& tactic_list, AnchorEvaluator* anchor_evaluator) { // Note that we enter this function for any OOF element, not just those that - // use position-try-options. Therefore, it's important to return immediately - // without doing any work when `try_set` and `existing_try_set` both are - // nullptr. + // use position-try-options. Therefore, it's important to return without + // doing style recalc when anchor positioning features are not in use. - const CSSPropertyValueSet* existing_try_set = nullptr; - const CSSPropertyValueSet* existing_try_tactics_set = nullptr; - - OutOfFlowData* out_of_flow_data = element.GetOutOfFlowData(); - if (out_of_flow_data) { - existing_try_set = out_of_flow_data->GetTryPropertyValueSet(); - existing_try_tactics_set = - out_of_flow_data->GetTryTacticsPropertyValueSet(); + if (OutOfFlowData* out_of_flow_data = element.GetOutOfFlowData()) { + out_of_flow_data->SetTryPropertyValueSet(nullptr); + out_of_flow_data->SetTryTacticsPropertyValueSet(nullptr); } const CSSPropertyValueSet* try_tactics_set = @@ -3489,11 +3483,11 @@ bool needs_update = false; - if (existing_try_set != try_set) { + if (try_set) { element.EnsureOutOfFlowData().SetTryPropertyValueSet(try_set); needs_update = true; } - if (existing_try_tactics_set != try_tactics_set) { + if (try_tactics_set) { element.EnsureOutOfFlowData().SetTryTacticsPropertyValueSet( try_tactics_set); needs_update = true; @@ -3506,16 +3500,12 @@ needs_update = true; } if (element.ComputedStyleRef().HasAnchorFunctions()) { - AnchorResults& anchor_results = - element.EnsureOutOfFlowData().GetAnchorResults(); - if (anchor_results.IsEmpty() || - anchor_results.IsAnyResultDifferent(element.ComputedStyleRef(), - anchor_evaluator)) { - needs_update = true; - } + needs_update = true; } if (!needs_update) { + CHECK(!try_set); + CHECK(!try_tactics_set); return; } @@ -3524,13 +3514,11 @@ // - The existing AnchorResults are immediately cleared, and // - The result of any Evaluate() call made will be stored // in the AnchorResults. + // + // TODO(crbug.com/333608683): The results of ResultCachingAnchorEvaluator is + // currently not used outside of tests. ResultCachingAnchorEvaluator result_caching_anchor_evaluator( anchor_evaluator, element.EnsureOutOfFlowData().GetAnchorResults()); - - // The last seen `try_set` is persisted on Element, such that subsequent - // regular style recalcs can continue to include this set. - element.EnsureOutOfFlowData().SetTryPropertyValueSet(try_set); - base::AutoReset<bool> pt_recalc(&in_position_try_style_recalc_, true); UpdateViewportSize();
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 903fd39f..47a7ef95 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -4556,45 +4556,6 @@ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdateForNode(*a)); } -TEST_F(StyleEngineTest, UpdateStyleForOutOfFlow_TacticsCache) { - GetDocument().body()->setInnerHTML(R"HTML( - <style> - #anchored { - position: absolute; - width: 100px; - height: 100px; - } - </style> - <div id=anchored>Foo</div> - )HTML"); - - UpdateAllLifecyclePhases(); - - Element* anchored = GetDocument().getElementById(AtomicString("anchored")); - ASSERT_TRUE(anchored); - - auto tactic = - TryTacticList{TryTactic::kFlipBlock, TryTactic::kNone, TryTactic::kNone}; - - GetStyleEngine().SetStatsEnabled(true); - StyleResolverStats* stats = GetStyleEngine().Stats(); - ASSERT_TRUE(stats); - EXPECT_EQ(0u, stats->elements_styled); - - GetStyleEngine().UpdateStyleForOutOfFlow(*anchored, - /* try_set */ nullptr, tactic, - /* anchor_evaluator */ nullptr); - - EXPECT_EQ(1u, stats->elements_styled); - - // The same call again should not recalc any elements. - GetStyleEngine().UpdateStyleForOutOfFlow(*anchored, - /* try_set */ nullptr, tactic, - /* anchor_evaluator */ nullptr); - - EXPECT_EQ(1u, stats->elements_styled); -} - TEST_F(StyleEngineTest, UpdateStyleAndLayoutTreeWithAnchorQuery) { GetDocument().documentElement()->setInnerHTML(R"HTML( <style>
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 0374589..d24a76b 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -2853,8 +2853,6 @@ GetPage()->GetPageLifecycleState()->is_in_back_forward_cache) { return WebInputEventResult::kNotHandled; } - // Input events should not be routed to a prerendered page. - CHECK(!GetPage()->IsPrerendering()); if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl()) { auto result = devtools->HandleInputEvent(input_event);
diff --git a/third_party/blink/renderer/core/layout/inline/inline_node.cc b/third_party/blink/renderer/core/layout/inline/inline_node.cc index 0cea526..fd5b961 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_node.cc +++ b/third_party/blink/renderer/core/layout/inline/inline_node.cc
@@ -19,6 +19,7 @@ #include "third_party/blink/renderer/core/layout/inline/initial_letter_utils.h" #include "third_party/blink/renderer/core/layout/inline/inline_break_token.h" #include "third_party/blink/renderer/core/layout/inline/inline_item.h" +#include "third_party/blink/renderer/core/layout/inline/inline_item_result_ruby_column.h" #include "third_party/blink/renderer/core/layout/inline/inline_items_builder.h" #include "third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.h" #include "third_party/blink/renderer/core/layout/inline/inline_text_auto_space.h" @@ -1797,6 +1798,7 @@ const LineBreaker::MaxSizeCache& max_size_cache; FloatsMaxSize* floats; bool is_after_break = true; + wtf_size_t annotation_nesting_level = 0; explicit MaxSizeFromMinSize(const InlineItemsData& items_data, const LineBreaker::MaxSizeCache& max_size_cache, @@ -1812,7 +1814,14 @@ void AddTextUntil(const InlineItem* end) { DCHECK(end); for (; next_item != end; ++next_item) { - if (next_item->Type() == InlineItem::kText && next_item->Length()) { + if (next_item->Type() == InlineItem::kOpenTag && + next_item->GetLayoutObject()->IsInlineRubyText()) { + ++annotation_nesting_level; + } else if (next_item->Type() == InlineItem::kCloseTag && + next_item->GetLayoutObject()->IsInlineRubyText()) { + --annotation_nesting_level; + } else if (next_item->Type() == InlineItem::kText && + next_item->Length() && annotation_nesting_level == 0) { DCHECK(next_item->TextShapeResult()); const ShapeResult& shape_result = *next_item->TextShapeResult(); position += shape_result.SnappedWidth().ClampNegativeToZero(); @@ -1858,6 +1867,17 @@ is_after_break = false; } + ComputeFromMinSizeInternal(line_info); + + // Compute the forced break after all results were handled, because + // when close tags appear after a forced break, they are included in + // the line, and they may have inline sizes. crbug.com/991320. + if (line_info.HasForcedBreak()) { + ForceLineBreak(line_info); + } + } + + void ComputeFromMinSizeInternal(const LineInfo& line_info) { for (const InlineItemResult& result : line_info.Results()) { const InlineItem& item = *result.item; if (item.Type() == InlineItem::kText) { @@ -1893,13 +1913,12 @@ continue; } } + if (item.Type() == InlineItem::kOpenRubyColumn && result.ruby_column) { + ComputeFromMinSizeInternal(result.ruby_column->base_line); + continue; + } position += result.inline_size; } - // Compute the forced break after all results were handled, because - // when close tags appear after a forced break, they are included in - // the line, and they may have inline sizes. crbug.com/991320. - if (line_info.HasForcedBreak()) - ForceLineBreak(line_info); } }; @@ -1974,7 +1993,8 @@ // `box-decoration-break: clone` clones box decorations to each // fragment (line) that we cannot compute max-content from // min-content. - !line_breaker.HasClonedBoxDecorations(); + !line_breaker.HasClonedBoxDecorations() && + !line_breaker.MayHaveRubyOverhang(); if (can_compute_max_size_from_min_size) max_size_from_min_size.ComputeFromMinSize(line_info); } else {
diff --git a/third_party/blink/renderer/core/layout/inline/line_breaker.cc b/third_party/blink/renderer/core/layout/inline/line_breaker.cc index 543c7cb5..0721681e 100644 --- a/third_party/blink/renderer/core/layout/inline/line_breaker.cc +++ b/third_party/blink/renderer/core/layout/inline/line_breaker.cc
@@ -733,6 +733,7 @@ hyphen_index_.reset(); has_any_hyphens_ = false; resume_block_in_inline_in_same_flow_ = false; + may_have_ruby_overhang_ = false; // Use 'text-indent' as the initial position. This lets tab positions to align // regardless of 'text-indent'. @@ -2979,6 +2980,16 @@ LayoutUnit ruby_size = MaxLineWidth(base_line_info, annotation_line_list); { + // Recreate lines because lines created with LineBreakerMode::kMaxContent + // are not usable in InlineLayoutAlgorithm. + base_line_info = + CreateSubLineInfo(base_start, base_end_index, LayoutUnit::NearlyMax()); + for (wtf_size_t i = 0; i < annotation_data.size(); ++i) { + annotation_line_list[i] = CreateSubLineInfo( + annotation_data[i].start, annotation_data[i].end_item_index, + LayoutUnit::NearlyMax()); + } + AddRubyColumnResult(item, base_line_info, annotation_line_list, annotation_data, ruby_size, *line_info); position_ += ruby_size; @@ -3038,6 +3049,10 @@ column_result->text_offset.end = annotation_line_list[0].EndTextOffset(); column_result->should_create_line_box = true; column_result->can_break_after = CanBreakAfterRubyColumn(*column_result); + + if (base_line_info.Width() < ruby_size) { + may_have_ruby_overhang_ = true; + } return column_result; }
diff --git a/third_party/blink/renderer/core/layout/inline/line_breaker.h b/third_party/blink/renderer/core/layout/inline/line_breaker.h index 3f7ffcd..aed1a956 100644 --- a/third_party/blink/renderer/core/layout/inline/line_breaker.h +++ b/third_party/blink/renderer/core/layout/inline/line_breaker.h
@@ -61,6 +61,9 @@ // True if the last line has `box-decoration-break: clone`, which affected the // size. bool HasClonedBoxDecorations() const { return has_cloned_box_decorations_; } + // True if the last processed line might contain ruby overhang. It affects + // min-max computation. + bool MayHaveRubyOverhang() const { return may_have_ruby_overhang_; } // Compute the next line break point and produces InlineItemResults for // the line. @@ -360,6 +363,8 @@ // True if the resultant line contains a RubyColumn with inline-end overhang. bool maybe_have_end_overhang_ = false; + // True if the last processed line might contain ruby overhang. + bool may_have_ruby_overhang_ = false; // True if ShouldCreateNewSvgSegment() should be called. bool needs_svg_segmentation_ = false;
diff --git a/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc b/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc index 7a81fd1..dbc09c29 100644 --- a/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc +++ b/third_party/blink/renderer/core/layout/inline/logical_line_builder.cc
@@ -155,7 +155,14 @@ main_line_helper->PlaceBlockInInline(item, &item_result, line_box); } else if (item.Type() == InlineItem::kOpenRubyColumn) { DCHECK(RuntimeEnabledFeatures::RubyLineBreakableEnabled()); - box = PlaceRubyColumn(line_info, item_result, *line_box, box); + if (item_result.ruby_column) { + box = PlaceRubyColumn(line_info, item_result, *line_box, box); + } else { + line_box->AddChild(item.BidiLevel()); + } + } else if (item.Type() == InlineItem::kCloseRubyColumn) { + DCHECK(RuntimeEnabledFeatures::RubyLineBreakableEnabled()); + line_box->AddChild(item.BidiLevel()); } else if (item.Type() == InlineItem::kListMarker) { PlaceListMarker(item, &item_result); } else if (item.Type() == InlineItem::kOutOfFlowPositioned) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc index 5fac6c32..3ca021cc 100644 --- a/third_party/blink/renderer/modules/mediastream/media_devices.cc +++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -645,11 +645,12 @@ ExceptionState& exception_state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); LocalDOMWindow* const window = DomWindow(); - // This timeout of base::Seconds(6) is an initial value and based on the data - // in Media.MediaDevices.GetDisplayMedia.Latency, it should be iterated upon. + // Using timeout of base::Seconds(12) based on the + // Media.MediaDevices.GetDisplayMedia.Latency values. With the earlier value + // of base::Seconds(6), we got about 25% of results counted as kTimeout. auto* resolver = MakeGarbageCollected< ScriptPromiseResolverWithTracker<UserMediaRequestResult, MediaStream>>( - script_state, "Media.MediaDevices.GetDisplayMedia", base::Seconds(6)); + script_state, "Media.MediaDevices.GetDisplayMedia", base::Seconds(12)); auto promise = resolver->Promise(); if (!window) {
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc index e038b3ce..35049da 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
@@ -2191,9 +2191,7 @@ auto validated_output = webnn::ValidateTransposeAndInferOutput( ConvertToComponentOperand(input), permutation); if (!validated_output.has_value()) { - exception_state.ThrowDOMException( - DOMExceptionCode::kDataError, - String::FromUTF8(validated_output.error())); + exception_state.ThrowTypeError(String::FromUTF8(validated_output.error())); return nullptr; } @@ -2207,8 +2205,7 @@ this, ComponentOperandTypeToBlink(validated_output->data_type), Vector<uint32_t>(validated_output->dimensions), transpose); if (!output.has_value()) { - exception_state.ThrowDOMException(DOMExceptionCode::kDataError, - output.error()); + exception_state.ThrowTypeError(output.error()); return nullptr; } transpose->Connect({input}, {output.value()});
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc index 41be54cf..c8b55ef0 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
@@ -2966,96 +2966,6 @@ } } -MLOperand* BuildTranspose(V8TestingScope& scope, - MLGraphBuilder* builder, - const MLOperand* input, - const MLTransposeOptions* options) { - auto* output = builder->transpose(input, options, scope.GetExceptionState()); - EXPECT_THAT(output, testing::NotNull()); - EXPECT_EQ(output->Kind(), webnn::mojom::blink::Operand::Kind::kOutput); - EXPECT_EQ(output->DataType(), input->DataType()); - auto* transpose = output->Operator(); - EXPECT_THAT(transpose, testing::NotNull()); - EXPECT_EQ(transpose->Kind(), webnn::mojom::blink::Operation::Tag::kTranspose); - EXPECT_TRUE(transpose->IsConnected()); - EXPECT_THAT(transpose->Options(), testing::NotNull()); - return output; -} - -TEST_F(MLGraphBuilderTest, TransposeTest) { - V8TestingScope scope; - MLGraphBuilder* builder = - CreateMLGraphBuilder(scope.GetExecutionContext(), scope.GetScriptState(), - scope.GetExceptionState()); - { - // Test building transpose with default options. - auto* input = BuildInput(builder, "input", {1, 2, 3, 4}, - V8MLOperandDataType::Enum::kFloat32, - scope.GetExceptionState()); - auto* output = BuildTranspose(scope, builder, input); - EXPECT_EQ(output->Dimensions(), Vector<uint32_t>({4, 3, 2, 1})); - } - { - // Test building transpose with permutation = {0, 2, 3, 1}. - auto* input = BuildInput(builder, "input", {1, 2, 3, 4}, - V8MLOperandDataType::Enum::kFloat32, - scope.GetExceptionState()); - auto* options = MLTransposeOptions::Create(); - options->setPermutation({0, 2, 3, 1}); - auto* output = BuildTranspose(scope, builder, input, options); - EXPECT_EQ(output->Dimensions(), Vector<uint32_t>({1, 3, 4, 2})); - } - { - // Test throwing error when the number of values in permutation is not the - // same as the rank of the input tensor. - auto* input = BuildInput(builder, "input", {1, 2, 4}, - V8MLOperandDataType::Enum::kInt32, - scope.GetExceptionState()); - auto* options = MLTransposeOptions::Create(); - options->setPermutation({0, 2, 3, 1}); - auto* output = - builder->transpose(input, options, scope.GetExceptionState()); - EXPECT_THAT(output, testing::IsNull()); - EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(), - DOMExceptionCode::kDataError); - EXPECT_EQ( - scope.GetExceptionState().Message(), - "The number of values in permutation must be the same as the rank " - "of the input tensor."); - } - { - // Test throwing error when two values in permutation are same. - auto* input = BuildInput(builder, "input", {1, 2, 3, 4}, - V8MLOperandDataType::Enum::kInt32, - scope.GetExceptionState()); - auto* options = MLTransposeOptions::Create(); - options->setPermutation({0, 2, 3, 2}); - auto* output = - builder->transpose(input, options, scope.GetExceptionState()); - EXPECT_THAT(output, testing::IsNull()); - EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(), - DOMExceptionCode::kDataError); - EXPECT_EQ(scope.GetExceptionState().Message(), - "Two or more values are same in the axes sequence."); - } - { - // Test throwing error when one value in permutation is greater than - // input_rank-1. - auto* input = BuildInput(builder, "input", {1, 2, 3, 4}, - V8MLOperandDataType::Enum::kInt32, - scope.GetExceptionState()); - auto* options = MLTransposeOptions::Create(); - options->setPermutation({0, 1, 2, 4}); - auto* output = - builder->transpose(input, options, scope.GetExceptionState()); - EXPECT_THAT(output, testing::IsNull()); - EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(), - DOMExceptionCode::kDataError); - EXPECT_EQ(scope.GetExceptionState().Message(), - "The values in axes must be in the range [0, 4)."); - } -} - MLOperand* BuildClamp(V8TestingScope& scope, MLGraphBuilder* builder, const MLOperand* input,
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h index 6de08296..b3f88e3a 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.h
@@ -26,7 +26,6 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_reduce_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_softplus_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_split_options.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_ml_transpose_options.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/modules/ml/webnn/ml_graph.h" #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_utils.h" @@ -133,13 +132,6 @@ MLGraphBuilder* builder, const MLOperand* input, const MLSoftplusOptions* options = MLSoftplusOptions::Create()); - -MLOperand* BuildTranspose( - V8TestingScope& scope, - MLGraphBuilder* builder, - const MLOperand* input, - const MLTransposeOptions* options = MLTransposeOptions::Create()); - } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ML_WEBNN_ML_GRAPH_BUILDER_TEST_H_
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_mojo_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_mojo_test.cc index c400c427..6594680e 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_mojo_test.cc +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_mojo_test.cc
@@ -4073,97 +4073,6 @@ } } -struct TransposeTester { - OperandInfoBlink input; - std::optional<Vector<uint32_t>> permutation; - OperandInfoMojo expected_operand; - Vector<uint32_t> expected_permutation; - - void Test(MLGraphTestMojo& helper, - V8TestingScope& scope, - MLGraphBuilder* builder) { - // Build the graph. - auto* input_operand = - BuildInput(builder, "input", input.dimensions, input.data_type, - scope.GetExceptionState()); - MLTransposeOptions* options = MLTransposeOptions::Create(); - if (permutation.has_value()) { - options->setPermutation(permutation.value()); - } - auto* output_operand = - builder->transpose(input_operand, options, scope.GetExceptionState()); - auto [graph, error_name, error_message] = - helper.BuildGraph(scope, builder, {{"output", output_operand}}); - ASSERT_THAT(graph, testing::NotNull()); - - auto graph_info = helper.GetGraphInfo(); - // Verify the graph information of mojo are as expected. - ASSERT_EQ(graph_info->operations.size(), 1u); - auto& operation = graph_info->operations[0]; - ASSERT_TRUE(operation->is_transpose()); - auto& transpose = operation->get_transpose(); - - // Validate the permutation of transpose operation. - EXPECT_EQ(transpose->permutation, expected_permutation); - - // Validate the input operand. - EXPECT_EQ(graph_info->input_operands.size(), 1u); - auto input_operand_id = graph_info->input_operands[0]; - EXPECT_EQ(transpose->input_operand_id, input_operand_id); - auto input_operand_iter = - graph_info->id_to_operand_map.find(input_operand_id); - ASSERT_TRUE(input_operand_iter != graph_info->id_to_operand_map.end()); - EXPECT_EQ(input_operand_iter->value->data_type, expected_operand.data_type); - EXPECT_EQ(input_operand_iter->value->dimensions, input.dimensions); - - // Validate the output operand. - EXPECT_EQ(graph_info->output_operands.size(), 1u); - auto output_operand_id = graph_info->output_operands[0]; - EXPECT_EQ(transpose->output_operand_id, output_operand_id); - auto output_operand_iter = - graph_info->id_to_operand_map.find(output_operand_id); - ASSERT_TRUE(output_operand_iter != graph_info->id_to_operand_map.end()); - EXPECT_EQ(output_operand_iter->value->data_type, - expected_operand.data_type); - EXPECT_EQ(output_operand_iter->value->dimensions, - expected_operand.dimensions); - } -}; - -TEST_P(MLGraphTestMojo, TransposeTest) { - V8TestingScope scope; - // Bind fake WebNN Context in the service for testing. - ScopedWebNNServiceBinder scoped_setup_binder(*this, scope); - - auto* options = MLContextOptions::Create(); - // Create WebNN Context with GPU device type. - options->setDeviceType(V8MLDeviceType::Enum::kGpu); - auto* builder = CreateGraphBuilder(scope, options); - { - // Test transpose operator with default options. - TransposeTester{ - .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, - .dimensions = {1, 2, 3, 4}}, - .expected_operand = {.data_type = - blink_mojom::Operand::DataType::kFloat32, - .dimensions = {4, 3, 2, 1}}, - .expected_permutation = {3, 2, 1, 0}} - .Test(*this, scope, builder); - } - { - // Test transpose operator with a given permutation. - TransposeTester{ - .input = {.data_type = V8MLOperandDataType::Enum::kFloat16, - .dimensions = {1, 2, 3, 4}}, - .permutation = Vector<uint32_t>{3, 0, 2, 1}, - .expected_operand = {.data_type = - blink_mojom::Operand::DataType::kFloat16, - .dimensions = {4, 1, 3, 2}}, - .expected_permutation = {3, 0, 2, 1}} - .Test(*this, scope, builder); - } -} - struct ReduceTester { OperandInfoBlink input; std::optional<Vector<uint32_t>> axes;
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc index 190c379..eced28c 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
@@ -1717,81 +1717,6 @@ } template <typename T> -struct TransposeTester { - OperandInfo<T> input; - Vector<T> expected; - - void Test(MLGraphTest& helper, - V8TestingScope& scope, - MLGraphBuilder* builder, - MLTransposeOptions* options = MLTransposeOptions::Create()) { - auto* input_operand = - BuildInput(builder, "input", input.dimensions, input.data_type, - scope.GetExceptionState()); - auto* output_operand = - BuildTranspose(scope, builder, input_operand, options); - auto [graph, error_name, error_message] = - helper.BuildGraph(scope, builder, {{"output", output_operand}}); - ASSERT_THAT(graph, testing::NotNull()); - - MLNamedArrayBufferViews inputs( - {{"input", - CreateArrayBufferViewForOperand(input_operand, input.values)}}); - MLNamedArrayBufferViews outputs( - {{"output", CreateArrayBufferViewForOperand(output_operand)}}); - std::tie(error_name, error_message) = - helper.ComputeGraph(scope, graph, inputs, outputs); - EXPECT_TRUE(error_name.IsNull()); - auto results = GetArrayBufferViewValues<T>(outputs[0].second); - EXPECT_EQ(results, expected); - } -}; - -TEST_P(MLGraphTest, TransposeTest) { - V8TestingScope scope; - auto* builder = - CreateMLGraphBuilder(scope.GetExecutionContext(), scope.GetScriptState(), - scope.GetExceptionState()); - { - // Test transpose operator with default options. - auto* options = MLTransposeOptions::Create(); - TransposeTester<float>{ - .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, - .dimensions = {2, 3, 4}, - .values = - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - }}, - .expected = - { - 0, 12, 4, 16, 8, 20, 1, 13, 5, 17, 9, 21, - 2, 14, 6, 18, 10, 22, 3, 15, 7, 19, 11, 23, - }} - .Test(*this, scope, builder, options); - } - { - // Test transpose with permutation = {0, 2, 1}. - auto* options = MLTransposeOptions::Create(); - options->setPermutation({{0, 2, 1}}); - TransposeTester<float>{ - .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, - .dimensions = {2, 3, 4}, - .values = - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - }}, - .expected = - { - 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, - 12, 16, 20, 13, 17, 21, 14, 18, 22, 15, 19, 23, - }} - .Test(*this, scope, builder, options); - } -} - -template <typename T> struct ConcatTester { Vector<OperandInfo<T>> inputs; uint32_t axis;
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index d6d6df0..7f4308fa 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -1648,20 +1648,6 @@ GetThread()->GetTaskRunner(TaskType::kNetworking)); fetch_response_callbacks_.Set(event_id, WrapDisallowNew(std::move(remote))); - if (params->race_network_request_loader_factory) { - UseCounter::Count( - this, - // If the runtime flag is enabled, that means the feature is enabled via - // OriginTrial. We count the feature usage separatefy from the a/b - // experiment to monitor the actual usage respectively. - RuntimeEnabledFeatures::ServiceWorkerRaceNetworkRequestEnabled( - ExecutionContext::From(ScriptController()->GetScriptState())) - ? WebFeature:: - kServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequestByOriginTrial - : WebFeature:: - kServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequest); - } - if (RequestedTermination()) { event_queue_->EnqueuePending( event_id,
diff --git a/third_party/blink/renderer/platform/network/DEPS b/third_party/blink/renderer/platform/network/DEPS index f30e7c1..308e3bd 100644 --- a/third_party/blink/renderer/platform/network/DEPS +++ b/third_party/blink/renderer/platform/network/DEPS
@@ -23,6 +23,7 @@ "+third_party/blink/renderer/platform/loader", "+third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h", "+third_party/blink/renderer/platform/platform_export.h", + "+third_party/blink/renderer/platform/runtime_enabled_features.h", "+third_party/blink/renderer/platform/scheduler", "+third_party/blink/renderer/platform/wtf/shared_buffer.h", "+third_party/blink/renderer/platform/testing",
diff --git a/third_party/blink/renderer/platform/network/http_parsers.cc b/third_party/blink/renderer/platform/network/http_parsers.cc index ac2a549..5264314 100644 --- a/third_party/blink/renderer/platform/network/http_parsers.cc +++ b/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -56,6 +56,7 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/network/header_field_tokenizer.h" #include "third_party/blink/renderer/platform/network/http_names.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/date_math.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" @@ -370,8 +371,6 @@ for (unsigned i = 0; i < source.length(); ++i) { UChar ch = source[i]; if (ch == kFullstopCharacter) { - // TODO(tkent): According to the HTML specification, we should support - // only integers. However we support fractional numbers. if (++full_stop_count == 2) number_end = i; } else if (!IsASCIIDigit(ch)) { @@ -380,6 +379,9 @@ } bool ok; double time = source.Left(number_end).ToDouble(&ok); + if (RuntimeEnabledFeatures::MetaRefreshNoFractionalEnabled()) { + time = floor(time); + } if (!ok) return false; delay = base::Seconds(time);
diff --git a/third_party/blink/renderer/platform/network/http_parsers_test.cc b/third_party/blink/renderer/platform/network/http_parsers_test.cc index 05a3d5af..623cef0 100644 --- a/third_party/blink/renderer/platform/network/http_parsers_test.cc +++ b/third_party/blink/renderer/platform/network/http_parsers_test.cc
@@ -297,11 +297,11 @@ EXPECT_TRUE( ParseHTTPRefresh("1.5; url=dest", IsASCIISpace<UChar>, delay, url)); - EXPECT_EQ(base::Seconds(1.5), delay); + EXPECT_EQ(base::Seconds(1), delay); EXPECT_EQ("dest", url); EXPECT_TRUE( ParseHTTPRefresh("1.5.9; url=dest", IsASCIISpace<UChar>, delay, url)); - EXPECT_EQ(base::Seconds(1.5), delay); + EXPECT_EQ(base::Seconds(1), delay); EXPECT_EQ("dest", url); EXPECT_TRUE( ParseHTTPRefresh("7..; url=dest", IsASCIISpace<UChar>, delay, url));
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index e2e0c93..a03bd97e 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1063,7 +1063,7 @@ { // Explainer: https://drafts.csswg.org/css-values/#round-func name: "CSSSteppedValueFunctions", - status: "experimental", + status: "stable", }, { name: "CSSStickyContainerQueries", @@ -2448,6 +2448,13 @@ name: "MessagePortCloseEvent", status: "test", }, + // This is a killswitch for <meta http-equiv="refresh"> no + // longer accepting fractions, landed around M125. + // It can be removed in M127 if there are no problems. + { + name: "MetaRefreshNoFractional", + status: "stable", + }, // This is enabled by default on Windows only. The only part that's // "experimental" is the support on other platforms. { @@ -3460,22 +3467,10 @@ base_feature: "none", }, { - name: "ServiceWorkerBypassFetchHandler", - base_feature: "none", - origin_trial_feature_name: "ServiceWorkerBypassFetchHandlerForMainResource", - public: true, - }, - { name: "ServiceWorkerClientLifecycleState", status: "experimental", }, { - name: "ServiceWorkerRaceNetworkRequest", - base_feature: "none", - origin_trial_feature_name: "ServiceWorkerBypassFetchHandlerWithRaceNetworkRequest", - public: true, - }, - { name: "ServiceWorkerStaticRouter", base_feature: "none", origin_trial_feature_name: "ServiceWorkerStaticRouter",
diff --git a/third_party/blink/web_tests/ChromeTestExpectations b/third_party/blink/web_tests/ChromeTestExpectations index dfcccce7..dcdccc7 100644 --- a/third_party/blink/web_tests/ChromeTestExpectations +++ b/third_party/blink/web_tests/ChromeTestExpectations
@@ -53,7 +53,7 @@ crbug.com/324436866 external/wpt/webdriver/tests/classic/get_current_url/file.py [ Failure Pass Timeout ] crbug.com/626703 external/wpt/webdriver/tests/bidi/input/set_files/invalid.py [ Failure Timeout ] external/wpt/webdriver/tests/bidi/input/set_files/set_files.py [ Timeout ] -[ Debug ] external/wpt/webdriver/tests/bidi/network/add_intercept/contexts.py [ Timeout ] +[ Debug ] external/wpt/webdriver/tests/bidi/network/add_intercept/contexts.py [ Timeout Failure Pass ] [ Debug ] external/wpt/webdriver/tests/bidi/storage/delete_cookies/filter.py [ Timeout ] [ Debug ] external/wpt/webdriver/tests/bidi/storage/delete_cookies/invalid.py [ Timeout ] [ Debug ] external/wpt/webdriver/tests/bidi/storage/delete_cookies/partition.py [ Timeout ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 03ca2f5..f08c21e1 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -319,7 +319,7 @@ crbug.com/309675 compositing/gestures/gesture-tapHighlight-simple-longPress.html [ Failure ] crbug.com/845267 [ Mac ] http/tests/inspector-protocol/page/page-lifecycleEvents.js [ Failure Pass ] -crbug.com/1046784 http/tests/inspector-protocol/page/page-events-associated-isolation.js [ Failure Pass ] +crbug.com/333842054 http/tests/inspector-protocol/page/page-events-associated-isolation.js [ Failure Pass ] # Counters failures to be fixed with new implementation crbug.com/990657 external/wpt/css/css-contain/contain-style-counters-004.html [ Failure ] @@ -628,7 +628,7 @@ crbug.com/898394 [ Debug ] virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure Timeout ] -crbug.com/1046784 http/tests/devtools/elements/styles-3/styles-disable-then-delete.js [ Crash Failure Pass Timeout ] +crbug.com/333831247 http/tests/devtools/elements/styles-3/styles-disable-then-delete.js [ Crash Failure Pass Timeout ] # Subpixel rounding differences that are incorrect. crbug.com/997202 compositing/overflow/scaled-overflow.html [ Failure ] @@ -4197,7 +4197,7 @@ crbug.com/1043675 [ Win ] svg/custom/svg-root-with-opacity.html [ Failure ] # Sheriff 2020-01-23 -crbug.com/1046784 http/tests/inspector-protocol/service-worker/target-reloaded-after-crash.js [ Failure Pass Timeout ] +crbug.com/333831246 http/tests/inspector-protocol/service-worker/target-reloaded-after-crash.js [ Failure Pass Timeout ] # Sheriff 2020-01-28 crbug.com/1046440 fast/loader/submit-form-while-parsing-2.html [ Failure Pass Timeout ] @@ -4357,7 +4357,7 @@ crbug.com/1071189 [ Debug Linux ] editing/selection/programmatic-selection-on-mac-is-directionless.html [ Pass Timeout ] # Sheriff 2020-05-27 -crbug.com/1046784 http/tests/devtools/elements/styles/stylesheet-tracking.js [ Failure Pass Timeout ] +crbug.com/333787228 http/tests/devtools/elements/styles/stylesheet-tracking.js [ Failure Pass Timeout ] # Sheriff 2020-05-29 crbug.com/1084637 compositing/video/video-reflection.html [ Failure Pass ] @@ -4452,7 +4452,7 @@ crbug.com/1042877 http/tests/security/mixedContent/strict-mode-image-reportonly.https.php [ Failure ] crbug.com/1042877 http/tests/security/mixedContent/strict-mode-via-pref-image-blocked.https.html [ Failure ] -crbug.com/1046784 http/tests/devtools/sources/debugger/anonymous-script-with-source-map-breakpoint.js [ Failure Pass ] +crbug.com/333787229 http/tests/devtools/sources/debugger/anonymous-script-with-source-map-breakpoint.js [ Failure Pass ] # Mixed content autoupgrades cause test to fail because test relied on http subresources to test a different origin, needs to be changed to not rely on HTTP URLs. crbug.com/1042877 http/tests/security/img-crossorigin-redirect-credentials.https.html [ Failure ] @@ -4488,7 +4488,6 @@ crbug.com/1150475 fast/dom/open-and-close-by-DOM.html [ Failure Pass ] #Sheriff 2020-11-23 -# Sheriff 2021-01-22 added Timeout per crbug.com/1046784: crbug.com/1149734 http/tests/devtools/sources/debugger-frameworks/frameworks-sourcemap.js [ Failure Pass ] crbug.com/1149734 http/tests/devtools/sources/debugger-ui/continue-to-location-markers.js [ Failure Pass Timeout ] crbug.com/1149734 http/tests/devtools/sources/debugger-ui/inline-scope-variables.js [ Failure Pass Timeout ] @@ -6802,9 +6801,6 @@ # May fail due to test framework issue. Disabling while this is being resolved. crbug.com/1367312 [ Win ] fast/dom/timer-throttling-hidden-page.html [ Failure Pass ] -# Gardener: 2024-01-23 -crbug.com/1521090 [ Mac12 ] virtual/static-routing-api/http/tests/inspector-protocol/service-worker/tentative/static-router/receive-router-rules-on-update.js [ Failure Pass ] - ### sheriff 2023-01-24 crbug.com/1521311 http/tests/devtools/service-workers/sw-navigate-useragent.js [ Failure Pass ] @@ -7166,6 +7162,58 @@ crbug.com/332068449 [ Mac ] external/wpt/focus/cross-origin-ancestor-activeelement-after-child-lose-focus.sub.html [ Failure Pass ] crbug.com/330761492 external/wpt/html/editing/the-hidden-attribute/beforematch-scroll-to-text-fragment.html [ Failure Pass ] +# RubyLineBreakable +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/br-clear-all-002.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/empty-ruby-text-container-abs.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/empty-ruby-text-container-float.html [ Crash ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/line-break-around-ruby-001.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/line-spacing.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/nested-ruby-pairing-001.html [ Crash Failure Timeout ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-align-001.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-align-001a.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-align-002.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-align-002a.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-base-container-float.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-bidi-003.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-float-handling-001.html [ Crash Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-intra-level-whitespace-001.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-line-breaking-002.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/after-doesnt-crash.html [ Crash Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/base-shorter-than-text.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/before-doesnt-crash.html [ Crash Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/float-object-doesnt-crash.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/float-overhang-from-ruby-text.html [ Crash Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/line-break-ruby.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/modify-positioned-ruby-text-crash.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/nested-ruby.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-horizontal-no-overlap1.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-horizontal-no-overlap2.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-horizontal.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-vertical-no-overlap1.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-vertical-no-overlap2.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/overhang-vertical.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/percentage-height-child-crash.html [ Crash ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/position-after.html [ Crash ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-column-break.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-columns-spans.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-columns.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-empty-rt.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-first-letter.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-illegal-7.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-illegal-combined.html [ Crash Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-length.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-position-modern-japanese-fonts.html [ Crash Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-simple-rp.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-simple.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-text-before-after-content.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/ruby-trailing.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-rt-block-1.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-rt-block-2.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-rt-block-3.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/rubyDOM-insert-text2.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/select-ruby.html [ Failure ] +crbug.com/324111880 virtual/ruby-lb/fast/ruby/split-ruby-column-percentage-height-descendant.html [ Failure ] + # line-clamp crbug.com/40336192 external/wpt/css/css-overflow/line-clamp-001.tentative.html [ Failure ] crbug.com/40336192 external/wpt/css/css-overflow/line-clamp-004.tentative.html [ Failure ] @@ -7252,10 +7300,9 @@ # Branch Gardener 2024-04-10 crbug.com/333639341 [ Fuchsia ] fast/writing-mode/english-lr-text.html [ Failure Pass ] -crbug.com/333638402 [ Linux ] external/wpt/css/css-color/parsing/color-computed-color-function.html [ Failure ] -crbug.com/333638402 [ Linux ] external/wpt/css/css-color/parsing/color-computed-lab.html [ Failure ] -crbug.com/333638402 [ Linux ] external/wpt/css/css-color/parsing/color-valid-color-function.html [ Failure ] -crbug.com/333638402 [ Linux ] external/wpt/css/css-color/parsing/color-valid-lab.html [ Failure ] # Gardener 2024-04-11 crbug.com/333739617 [ Mac ] fast/peerconnection/RTCEncodedVideoFrameMetadata-timestamp.html [ Timeout ] + +# Test requires rebaseline after rolling V8. +crbug.com/333182464 external/wpt/streams/readable-streams/global.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 6a6d5d4..71fb060f 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -2833,5 +2833,13 @@ "bases": ["external/wpt/css/css-overflow", "fast/overflow"], "args": ["--enable-blink-features=CSSLineClamp"], "owners": ["abotella@igalia.com"] + }, + { + "prefix": "ruby-lb", + "platforms": ["Mac"], + "bases": ["external/wpt/css/css-ruby", "fast/ruby"], + "args": ["--enable-blink-features=RubyLineBreakable"], + "owners": ["tkent@chromium.org"], + "expires": "Oct 10, 2024" } ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/base-style-invalidation.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/base-style-invalidation.html new file mode 100644 index 0000000..8e8e69f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/base-style-invalidation.html
@@ -0,0 +1,64 @@ +<!DOCTYPE html> +<title>CSS Anchor Positioning: Invalidation from changing the base style</title> +<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/"> +<link rel="help" href="https://issues.chromium.org/issues/333608683"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + @position-try --pt { + width: 50px; /* Undo force overflow */ + } + #cb { + position: relative; + width: 200px; + height: 200px; + border: 1px solid black; + } + #anchor { + position: absolute; + left: 75px; + top: 75px; + width: 50px; + height: 50px; + background: coral; + anchor-name: --a; + } + #anchored { + position: absolute; + position-anchor: --a; + position-try-options: --pt flip-start; + inset: 0; + top: anchor(top); + bottom: anchor(bottom); + right: calc(anchor(left) + 5px); + width: 50px; + height: 50px; + background: skyblue; + justify-self: end; + } + #anchored.flip { + background: seagreen; + width: 300px; /* Force overflow */ + } +</style> +<div id=cb> + <div id=anchor></div> + <div id=anchored></div> +</div> +<script> + test(() => { + // Initially to the left. + assert_equals(anchored.offsetLeft, 20); + assert_equals(anchored.offsetTop, 75); + + // Flips to the right. + anchored.classList.toggle('flip'); + assert_equals(anchored.offsetLeft, 75); + assert_equals(anchored.offsetTop, 20); + + // Flips to the original position. + anchored.classList.toggle('flip'); + assert_equals(anchored.offsetLeft, 20); + assert_equals(anchored.offsetTop, 75); + }, 'The chosen position options changes when the base style differs'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/meta/refresh-time.html b/third_party/blink/web_tests/external/wpt/html/meta/refresh-time.html new file mode 100644 index 0000000..7aef126 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/meta/refresh-time.html
@@ -0,0 +1,53 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test fractional values in meta http-equiv=refresh</title> +<link rel="author" title="Psychpsyo" href="mailto:psychpsyo@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/#pragma-directives"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> + async function sleep(ms, test) { + return new Promise(resolve => {test.step_timeout(resolve, ms)}); + } + + promise_test(async test => { + const frame = document.createElement("iframe"); + document.body.appendChild(frame); + frame.src = "resources/refresh1.html"; + await sleep(500, test); + assert_equals(frame.contentWindow.document.title, "refresh 1"); + await sleep(1000, test); + assert_equals(frame.contentWindow.document.title, "got refreshed"); + }, "Ensure that refresh is observed"); + + promise_test(async test => { + const frame = document.createElement("iframe"); + document.body.appendChild(frame); + frame.src = "resources/refresh.99.html"; + await sleep(500, test); + assert_equals(frame.contentWindow.document.title, "got refreshed"); + }, "Ensure that fractions in refresh time are ignored"); + + promise_test(async test => { + const frame = document.createElement("iframe"); + document.body.appendChild(frame); + frame.src = "resources/refresh1.99.html"; + await sleep(500, test); + assert_equals(frame.contentWindow.document.title, "refresh 1.99"); + await sleep(1000, test); + assert_equals(frame.contentWindow.document.title, "got refreshed"); + }, "Ensure that non-fractional part in refresh time does not get discarded"); + + promise_test(async test => { + const frame = document.createElement("iframe"); + document.body.appendChild(frame); + frame.src = "resources/refresh1dotdot5dot.html"; + await sleep(500, test); + assert_equals(frame.contentWindow.document.title, "refresh 1..5."); + await sleep(750, test); + assert_equals(frame.contentWindow.document.title, "got refreshed"); + }, "Ensure that multiple periods in refresh time just get ignored"); +</script> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/meta/resources/gotRefreshed.html b/third_party/blink/web_tests/external/wpt/html/meta/resources/gotRefreshed.html new file mode 100644 index 0000000..c894269 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/meta/resources/gotRefreshed.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>got refreshed</title> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh.99.html b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh.99.html new file mode 100644 index 0000000..ca4e346 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh.99.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>refresh .99</title> + +<meta http-equiv="refresh" content=".99;url=gotRefreshed.html"> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1.99.html b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1.99.html new file mode 100644 index 0000000..76121cfd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1.99.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>refresh 1.99</title> + +<meta http-equiv="refresh" content="1.99;url=gotRefreshed.html"> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1.html b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1.html new file mode 100644 index 0000000..14819dc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>refresh 1</title> + +<meta http-equiv="refresh" content="1;url=gotRefreshed.html"> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1dotdot5dot.html b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1dotdot5dot.html new file mode 100644 index 0000000..085b9e9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/meta/resources/refresh1dotdot5dot.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>refresh 1..5.</title> + +<meta http-equiv="refresh" content="1..5.;url=gotRefreshed.html"> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/transpose.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/transpose.https.any.js index 9ea5a5d..3475a427 100644 --- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/transpose.https.any.js +++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/transpose.https.any.js
@@ -5,3 +5,54 @@ 'use strict'; validateInputFromAnotherBuilder('transpose'); + +const tests = [ + { + name: '[transpose] Test building transpose with default options.', + input: {dataType: 'float32', dimensions: [1, 2, 3, 4]}, + output: {dataType: 'float32', dimensions: [4, 3, 2, 1]} + }, + { + name: '[transpose] Test building transpose with permutation=[0, 2, 3, 1].', + input: {dataType: 'float32', dimensions: [1, 2, 3, 4]}, + options: {permutation: [0, 2, 3, 1]}, + output: {dataType: 'float32', dimensions: [1, 3, 4, 2]} + }, + { + name: + '[transpose] Throw if permutation\'s size is not the same as input\'s rank.', + input: {dataType: 'int32', dimensions: [1, 2, 4]}, + options: {permutation: [0, 2, 3, 1]}, + }, + { + name: '[transpose] Throw if two values in permutation are same.', + input: {dataType: 'int32', dimensions: [1, 2, 3, 4]}, + options: {permutation: [0, 2, 3, 2]}, + }, + { + name: + '[transpose] Throw if any value in permutation is not in the range [0,input\'s rank).', + input: {dataType: 'int32', dimensions: [1, 2, 3, 4]}, + options: {permutation: [0, 1, 2, 4]}, + }, + { + name: '[transpose] Throw if any value in permutation is negative.', + input: {dataType: 'int32', dimensions: [1, 2, 3, 4]}, + options: {permutation: [0, -1, 2, 3]}, + } +]; + +tests.forEach( + test => promise_test(async t => { + const input = builder.input( + 'input', + {dataType: test.input.dataType, dimensions: test.input.dimensions}); + if (test.output) { + const output = builder.transpose(input, test.options); + assert_equals(output.dataType(), test.output.dataType); + assert_array_equals(output.shape(), test.output.dimensions); + } else { + assert_throws_js( + TypeError, () => builder.transpose(input, test.options)); + } + }, test.name));
diff --git a/third_party/blink/web_tests/fast/url/invalid-urls-utf8-expected.txt b/third_party/blink/web_tests/fast/url/invalid-urls-utf8-expected.txt index 20722e79..8d6f496b 100644 --- a/third_party/blink/web_tests/fast/url/invalid-urls-utf8-expected.txt +++ b/third_party/blink/web_tests/fast/url/invalid-urls-utf8-expected.txt
@@ -8,11 +8,9 @@ PASS src is expected PASS src is expected PASS src is expected -FAIL src should be foo://tête à tête@host/. Was foo://t%C3%AAte %C3%A0 t%C3%AAte@host/. -FAIL src should be foo://user:tête à tête@host/. Was foo://user:t%C3%AAte %C3%A0 t%C3%AAte@host/. PASS src is expected PASS src is expected -FAIL src should be foo://user:password@[xxxxx]/tête à tête/. Was foo://user:password@[xxxxx]/t%C3%AAte %C3%A0 t%C3%AAte/. +FAIL src should be foo://user:password@[xxxxx]/ . Was foo://user:password@[xxxxx]/. FAIL src should be foo://user:password@[?tête à tête/. Was foo://user:password@[?t%C3%AAte%20%C3%A0%20t%C3%AAte/. FAIL src should be foo://user:password@[?tête à tête]/. Was foo://user:password@[?t%C3%AAte%20%C3%A0%20t%C3%AAte]/. FAIL src should be foo://user:password@host:tête à tête/. Was foo://user:password@host:t%C3%AAte %C3%A0 t%C3%AAte/.
diff --git a/third_party/blink/web_tests/fast/url/invalid-urls-utf8.html b/third_party/blink/web_tests/fast/url/invalid-urls-utf8.html index d10be35d..b25b553 100644 --- a/third_party/blink/web_tests/fast/url/invalid-urls-utf8.html +++ b/third_party/blink/web_tests/fast/url/invalid-urls-utf8.html
@@ -21,13 +21,11 @@ 'gopher:///', 'ws:///', 'wss:///', + ' wss:/// ', // Invalid Authority. - 'foo://tête à tête@host/', - 'foo://user:tête à tête@host/', - ' foo://<>@host/ ', - ' foo://user:<>@host/ ', - 'foo://user:password@[xxxxx]/tête à tête/', + 'foo://user:password@[xxxxx]/', + ' foo://user:password@[xxxxx]/ ', // The '?' is a path separator and make sure the hostname is not encoded in punicode. The hostname is an invalid IPV6 hostname. 'foo://user:password@[?tête à tête/', @@ -45,7 +43,7 @@ for (var i = 0; i < testSet.length; ++i) { src = canonicalize(testSet[i]); - expected = testSet[i].trim(); + expected = testSet[i]; shouldBe('src', 'expected'); }
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/tentative/static-router/receive-router-rules-on-update.js b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/tentative/static-router/receive-router-rules-on-update.js index 866022d9..f97b510 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/tentative/static-router/receive-router-rules-on-update.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/service-worker/tentative/static-router/receive-router-rules-on-update.js
@@ -1,7 +1,6 @@ (async function(/** @type {import('test_runner').TestRunner} */ testRunner) { - var {page, session, dp} = await testRunner.startURL( - 'resources/service-worker-with-static-router.html', - 'Tests receiving static router rules from the service worker.'); + const {dp, page} = await testRunner.startBlank( + 'Tests receiving static router rules from the service worker.'); async function waitForServiceWorkerActivation() { let versions = []; @@ -13,9 +12,12 @@ } await dp.Runtime.enable(); - await dp.ServiceWorker.enable(); - const versions = await waitForServiceWorkerActivation(); + const versionsPromise = waitForServiceWorkerActivation(); + await dp.ServiceWorker.enable(); + await page.navigate('resources/service-worker-with-static-router.html'); + + const versions = await versionsPromise; testRunner.log(versions[0].routerRules); testRunner.completeTest(); });
diff --git a/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/invalid-urls-utf8-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/invalid-urls-utf8-expected.txt index 6c10a121..d4675c36 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/invalid-urls-utf8-expected.txt +++ b/third_party/blink/web_tests/platform/linux/virtual/url-non-special/fast/url/invalid-urls-utf8-expected.txt
@@ -8,10 +8,8 @@ PASS src is expected PASS src is expected PASS src is expected -FAIL src should be foo://tête à tête@host/. Was foo://t%C3%AAte%20%C3%A0%20t%C3%AAte@host/. -FAIL src should be foo://user:tête à tête@host/. Was foo://user:t%C3%AAte%20%C3%A0%20t%C3%AAte@host/. -FAIL src should be foo://<>@host/. Was foo://%3C%3E@host/. -FAIL src should be foo://user:<>@host/. Was foo://user:%3C%3E@host/. +PASS src is expected +PASS src is expected PASS src is expected PASS src is expected PASS src is expected
diff --git a/third_party/blink/web_tests/virtual/ruby-lb/README.md b/third_party/blink/web_tests/virtual/ruby-lb/README.md new file mode 100644 index 0000000..600b94f0 --- /dev/null +++ b/third_party/blink/web_tests/virtual/ruby-lb/README.md
@@ -0,0 +1,6 @@ +Tests for the RubyLineBreakable feature. + +The feature affects all <ruby> rendering, but it's under development. We don't +want to enable the feature for all tests yet. + +crbug.com/324111880
diff --git a/third_party/fuzztest/BUILD.gn b/third_party/fuzztest/BUILD.gn index aa1f99a..c3abf67f 100644 --- a/third_party/fuzztest/BUILD.gn +++ b/third_party/fuzztest/BUILD.gn
@@ -214,6 +214,8 @@ "src/fuzztest/domain.h", "src/fuzztest/domain_core.h", "src/fuzztest/fuzztest.h", + "src/fuzztest/fuzztest_macros.cc", + "src/fuzztest/fuzztest_macros.h", "src/fuzztest/googletest_fixture_adapter.h", "src/fuzztest/internal/any.h", "src/fuzztest/internal/centipede_adaptor.h",
diff --git a/third_party/fuzztest/src b/third_party/fuzztest/src index d7c63cd..65354bf 160000 --- a/third_party/fuzztest/src +++ b/third_party/fuzztest/src
@@ -1 +1 @@ -Subproject commit d7c63cd216941e297569428e40f9b8bc155e0423 +Subproject commit 65354bf09a2479945b4683c42948695d4f2f7c07
diff --git a/third_party/libsrtp b/third_party/libsrtp index 5b7c744..7a7e64c 160000 --- a/third_party/libsrtp +++ b/third_party/libsrtp
@@ -1 +1 @@ -Subproject commit 5b7c744eb8310250ccc534f3f86a2015b3887a0a +Subproject commit 7a7e64c8b5a632f55929cb3bb7d3e6fb48c3205a
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index 5a9d3a1..2df1bcef 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: 78505e91f7e054444030aec55110893b4fc62500 +Version: 03f0b3dae98d218e8420add5a13893822d290855 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/nearby/src b/third_party/nearby/src index 78505e9..03f0b3d 160000 --- a/third_party/nearby/src +++ b/third_party/nearby/src
@@ -1 +1 @@ -Subproject commit 78505e91f7e054444030aec55110893b4fc62500 +Subproject commit 03f0b3dae98d218e8420add5a13893822d290855
diff --git a/third_party/skia b/third_party/skia index 28579a8..2a2fe43 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 28579a88aa9c12ef23c1d3ab798aba40f85ea0d8 +Subproject commit 2a2fe430350798bf10c28ad55daf61c08c6a4121
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src index acb4750..e5fb882 160000 --- a/third_party/webgpu-cts/src +++ b/third_party/webgpu-cts/src
@@ -1 +1 @@ -Subproject commit acb475026d7ac90725c629ef3664267c7aed72a1 +Subproject commit e5fb8824ade85fae690f2bb45cc347a1398cca2f
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt index ed6e32cd..390e30ca 100644 --- a/third_party/webgpu-cts/ts_sources.txt +++ b/third_party/webgpu-cts/ts_sources.txt
@@ -772,7 +772,10 @@ src/webgpu/shader/validation/expression/call/builtin/min.spec.ts src/webgpu/shader/validation/expression/call/builtin/modf.spec.ts src/webgpu/shader/validation/expression/call/builtin/normalize.spec.ts +src/webgpu/shader/validation/expression/call/builtin/pack2x16snorm.spec.ts +src/webgpu/shader/validation/expression/call/builtin/pack2x16unorm.spec.ts src/webgpu/shader/validation/expression/call/builtin/pack4x8snorm.spec.ts +src/webgpu/shader/validation/expression/call/builtin/pack4x8unorm.spec.ts src/webgpu/shader/validation/expression/call/builtin/pack4xI8.spec.ts src/webgpu/shader/validation/expression/call/builtin/pack4xI8Clamp.spec.ts src/webgpu/shader/validation/expression/call/builtin/pack4xU8.spec.ts
diff --git a/third_party/webrtc b/third_party/webrtc index 0bb59b4..f942a29 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 0bb59b4edd23d4e69de14b316312571146b6448d +Subproject commit f942a2901aa45546ec525c0adf977071f312f6f3
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index bd2c8a0..2c0843a7 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -10913,7 +10913,8 @@ <int value="4407" label="CSSAtRuleSwash"/> <int value="4408" label="CSSAtRuleOrnaments"/> <int value="4409" label="CSSAtRuleAnnotation"/> - <int value="4410" label="ServiceWorkerBypassFetchHandlerForMainResource"/> + <int value="4410" + label="OBSOLETE_ServiceWorkerBypassFetchHandlerForMainResource"/> <int value="4411" label="V8Document_HasPrivateToken_Method"/> <int value="4412" label="ServiceWorkerSkippedForEmptyFetchHandler"/> <int value="4413" label="ImageSet"/> @@ -10967,7 +10968,7 @@ <int value="4455" label="ParseFromStringIncludeShadows"/> <int value="4456" label="WebAppManifestScopeExtensions"/> <int value="4457" - label="ServiceWorkerBypassFetchHandlerForMainResourceByOriginTrial"/> + label="OBSOLETE_ServiceWorkerBypassFetchHandlerForMainResourceByOriginTrial"/> <int value="4458" label="OBSOLETE_V8RegExpUnicodeSetIncompatibilitiesWithUnicodeMode"/> <int value="4459" label="FedCmAutoReauthn"/> @@ -10998,7 +10999,8 @@ <int value="4482" label="RTCPeerConnectionLegacyGetStatsTrial"/> <int value="4483" label="ExecutedEmptyJavaScriptURLFromFrame"/> <int value="4484" label="ExecutedJavaScriptURLFromFrame"/> - <int value="4485" label="ServiceWorkerBypassFetchHandlerForSubResource"/> + <int value="4485" + label="OBSOLETE_ServiceWorkerBypassFetchHandlerForSubResource"/> <int value="4486" label="CSSAtRuleStartingStyle"/> <int value="4487" label="PrivateAggregationApiFledgeExtensions"/> <int value="4488" label="DeprecatedInterestGroupDailyUpdateUrl"/> @@ -11063,7 +11065,7 @@ <int value="4546" label="AttributionReportingCrossAppWeb"/> <int value="4547" label="SecurePaymentConfirmationActivationlessShow"/> <int value="4548" - label="ServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequest"/> + label="OBSOLETE_ServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequest"/> <int value="4549" label="FlexIntrinsicSizesCacheMiss"/> <int value="4550" label="CSSStyleContainerQuery"/> <int value="4551" label="CSSValueAppearanceMediaSlider"/> @@ -11075,7 +11077,7 @@ <int value="4557" label="CSSValueAppearanceSliderthumbHorizontal"/> <int value="4558" label="CSSValueAppearanceSliderthumbVertical"/> <int value="4559" - label="ServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequestByOriginTrial"/> + label="OBSOLETE_ServiceWorkerBypassFetchHandlerForAllWithRaceNetworkRequestByOriginTrial"/> <int value="4560" label="OBSOLETE_EventTimingPaintedPresentationPromiseResolvedWithEarlierPromiseUnresolved"/> <int value="4561" label="LinkRelPreloadAsFont"/>
diff --git a/tools/metrics/histograms/metadata/search/histograms.xml b/tools/metrics/histograms/metadata/search/histograms.xml index 7e3ad0e..96682bd 100644 --- a/tools/metrics/histograms/metadata/search/histograms.xml +++ b/tools/metrics/histograms/metadata/search/histograms.xml
@@ -1149,26 +1149,34 @@ </histogram> <histogram name="Search.SearchEngineListedInPromoDialog" - enum="OmniboxSearchEngineType" expires_after="M81"> + enum="OmniboxSearchEngineType" expires_after="M130"> <!-- Name completed by histogram_suffixes name="SearchEnginePromoOrdering" and name="SearchEnginePromoDeviceType" --> <owner>yusufo@chromium.org</owner> + <owner>dgn@chromium.org</owner> <summary> The search engines listed in the options for search engine promo. This is an Android specific dialog prompting the user to pick a default search engine. The dialog was shown on a device that had Chrome before it was first introduced. + + Warning: this histogram was expired from M81 to M124; data may be missing. </summary> </histogram> <histogram name="Search.SearchEngineSelectionInPromoDialog" - enum="OmniboxSearchEngineType" expires_after="M81"> + enum="OmniboxSearchEngineType" expires_after="M130"> +<!-- Name completed by histogram_suffixes name="SearchEnginePromoDeviceType" --> + <owner>yusufo@chromium.org</owner> + <owner>dgn@chromium.org</owner> <summary> The search engine selected by the user from the search engine promo. This is an Android specific dialog prompting the user to pick a default search engine. The dialog was shown on a device that had Chrome before it was first introduced. + + Warning: this histogram was expired from M81 to M124; data may be missing. </summary> </histogram>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 8e9ba61d..69dc002d 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -383,7 +383,7 @@ <item id="wallpaper_download_google_photo" added_in_milestone="102" content_hash_code="0565daa5" os_list="chromeos" file_path="ash/wallpaper/wallpaper_image_downloader.cc" /> <item id="wallpaper_online_downloader" added_in_milestone="110" content_hash_code="00286fc5" os_list="chromeos" file_path="ash/wallpaper/wallpaper_image_downloader.cc" /> <item id="chrome_support_tool_file_upload" added_in_milestone="113" content_hash_code="04a07122" os_list="chromeos" file_path="chrome/browser/policy/messaging_layer/upload/file_upload_impl.cc" /> - <item id="service_worker_race_network_request" added_in_milestone="113" content_hash_code="0090e590" os_list="linux,windows,android,chromeos" file_path="content/common/service_worker/race_network_request_url_loader_client.cc" /> + <item id="service_worker_race_network_request" added_in_milestone="113" content_hash_code="01177377" os_list="linux,windows,android,chromeos" file_path="content/common/service_worker/race_network_request_url_loader_client.cc" /> <item id="safe_browsing_ohttp_key_fetch" added_in_milestone="113" content_hash_code="0572fe6f" os_list="linux,windows,android,chromeos" file_path="components/safe_browsing/core/browser/hashprefix_realtime/ohttp_key_service.cc" /> <item id="glanceables_tasks_integration" added_in_milestone="113" content_hash_code="033ddfed" os_list="chromeos" file_path="chrome/browser/ui/ash/glanceables/glanceables_keyed_service.cc" /> <item id="bookmarks_image_fetcher" added_in_milestone="114" content_hash_code="01dd68ad" os_list="chromeos,linux,windows" file_path="chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc" />
diff --git a/ui/file_manager/file_manager/foreground/js/ui/command.ts b/ui/file_manager/file_manager/foreground/js/ui/command.ts index 9b18124..343e7a5 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/command.ts +++ b/ui/file_manager/file_manager/foreground/js/ui/command.ts
@@ -257,6 +257,12 @@ for (const command of target.ownerDocument.querySelectorAll<Command>( 'command')) { + if (!command.matchesEvent) { + // Because Command uses injected methods the <command> in the DOM might + // not have been initialized yet. + continue; + } + if (!command.matchesEvent(e)) { continue; }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/list_container.ts b/ui/file_manager/file_manager/foreground/js/ui/list_container.ts index 51b9eab..50ec9db 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/list_container.ts +++ b/ui/file_manager/file_manager/foreground/js/ui/list_container.ts
@@ -89,6 +89,20 @@ this.table.list.id = 'file-list'; this.grid.setAttribute('role', 'listbox'); this.grid.id = 'file-list'; + + // Ensure the list and grid are marked ARIA single select for save as. + if (type === DialogType.SELECT_SAVEAS_FILE) { + const list = table.querySelector('#file-list'); + list?.setAttribute('aria-multiselectable', 'false'); + grid.setAttribute('aria-multiselectable', 'false'); + } + } + + /** + * Avoid adding event listeners in the constructor because the ListContainer + * isn't fully usable until setCurrentListType() is called. + */ + private addEventListeners_() { this.element.addEventListener('keydown', this.onKeyDown_.bind(this)); this.element.addEventListener('keypress', this.onKeyPress_.bind(this)); this.element.addEventListener( @@ -107,13 +121,6 @@ setTimeout(() => this.allowContextMenuByTouch_ = false); } }); - - // Ensure the list and grid are marked ARIA single select for save as. - if (type === DialogType.SELECT_SAVEAS_FILE) { - const list = table.querySelector('#file-list'); - list?.setAttribute('aria-multiselectable', 'false'); - grid.setAttribute('aria-multiselectable', 'false'); - } } get currentView(): FileTable|FileGrid { @@ -160,6 +167,8 @@ assert(this.dataModel); assert(this.selectionModel); + this.addEventListeners_(); + this.startBatchUpdates(); this.currentListType = listType;
diff --git a/ui/webui/resources/cr_components/most_visited/most_visited.ts b/ui/webui/resources/cr_components/most_visited/most_visited.ts index e3650445..bb502c4 100644 --- a/ui/webui/resources/cr_components/most_visited/most_visited.ts +++ b/ui/webui/resources/cr_components/most_visited/most_visited.ts
@@ -250,7 +250,7 @@ private mediaEventTracker_: EventTracker; private eventTracker_: EventTracker; private boundOnDocumentKeyDown_: (e: KeyboardEvent) => void; - private preloadingTimer_: undefined|ReturnType<typeof setTimeout>; + private prerenderTimer_: undefined|ReturnType<typeof setTimeout>; private preconnectTimer_: undefined|ReturnType<typeof setTimeout>; private get tileElements_() { @@ -850,14 +850,18 @@ return; } - if (loadTimeData.getBoolean('prerenderEnabled') && + if (loadTimeData.getBoolean('prerenderOnHoverEnabled') && loadTimeData.getInteger('prerenderStartTimeThreshold') >= 0) { - this.preloadingTimer_ = setTimeout(() => { + this.prerenderTimer_ = setTimeout(() => { this.pageHandler_.prerenderMostVisitedTile(e.model.item, true); }, loadTimeData.getInteger('prerenderStartTimeThreshold')); } - if (loadTimeData.getBoolean('prerenderEnabled') && + // Preconnect is intended to be run on mouse hover when prerender is + // enabled, so it is allowed regardless of prerenderOnHoverEnabled or + // prerenderOnPressEnabled. + if ((loadTimeData.getBoolean('prerenderOnHoverEnabled') || + loadTimeData.getBoolean('prerenderOnPressEnabled')) && loadTimeData.getInteger('preconnectStartTimeThreshold') >= 0) { this.preconnectTimer_ = setTimeout(() => { this.pageHandler_.preconnectMostVisitedTile(e.model.item); @@ -871,7 +875,7 @@ return; } - if (loadTimeData.getBoolean('prerenderEnabled')) { + if (loadTimeData.getBoolean('prerenderOnPressEnabled')) { this.pageHandler_.prerenderMostVisitedTile(e.model.item, false); } } @@ -882,11 +886,18 @@ return; } - if (this.preloadingTimer_) { - clearTimeout(this.preloadingTimer_); + if (this.prerenderTimer_) { + clearTimeout(this.prerenderTimer_); } - this.pageHandler_.cancelPrerender(); + if (this.preconnectTimer_) { + clearTimeout(this.preconnectTimer_); + } + + if (loadTimeData.getBoolean('prerenderOnHoverEnabled') || + loadTimeData.getBoolean('prerenderOnPressEnabled')) { + this.pageHandler_.cancelPrerender(); + } } private onUndoClick_() {
diff --git a/v8 b/v8 index de7ce80..555084e 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit de7ce8021831d4f3c4e49336623f25b2fc406fbc +Subproject commit 555084e67f98736a41e52d13e485ab0febc3cbae