diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 5dcdaf1..c2ce175f 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs
@@ -667,7 +667,6 @@ 0b20ccad48bc63b0e6bf07b8511b32b8e3d963b1 # Reformat .java code with google-java-format. Tagged with Bug: 1491626 (part 2) -fd85d4fb7579adf095a94232268201342f89d836 c89f6078b3d03a07e8859e4e2be5dc9baaf1d5f0 a46fbc6634d0ac2fcdf88f35fa743fa5fd072575 54443fc172332d6c7053d0d028405e396aa283e2
diff --git a/DEPS b/DEPS index 8567779..a040289 100644 --- a/DEPS +++ b/DEPS
@@ -303,7 +303,7 @@ # 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': 'e40b61c3dfefe6a5ac8f200b0041148d5108cfa0', + 'skia_revision': '276075b975675ba92d907dd64247937b7b73245e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -311,7 +311,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '40f4de8fa1ff252fd57552a6a1d5cf4067f83883', + 'angle_revision': 'd704273d78967f286c300d445bdc0eb9f43b2389', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -319,7 +319,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'b2d4f1104c43ccd42df2e48902ae857f0d5a188a', + 'pdfium_revision': '57e284ba20215dfa5cdbf732b4e158c544323d86', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -378,7 +378,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': '42bf9b85713027338720203624f1ee98d0982a89', + 'chromium_variations_revision': '6a94fae344833b2e4c170955c9b10fa3a40c5550', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -394,7 +394,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '0a48a3bd9f916f605f225b4e7e2760380d0a9cc9', + 'devtools_frontend_revision': 'c67fdadcd104ba82740a25feed4fec2931b5f6f3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -418,7 +418,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '673e8b4639e3e19b97380992f2a82bc4442d9643', + 'dawn_revision': '0b6ca39d38735c9177dc8f7291dad5314fed3b11', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -462,7 +462,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. - 'cros_components_revision': '075d293d1a98cce55cdb88185239126eb64f6d55', + 'cros_components_revision': 'f448b44c03202bdb5fb1305216d4723724d5288b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1196,7 +1196,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '2854d4287a81c0a177ea4d6fa64737f1b9640614', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '457fec8b5b9ff390f9e7a8e64f8a886d97cbe1f9', 'condition': 'checkout_src_internal', }, @@ -1701,7 +1701,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'w4FEa7Y-q3MIsKwjR0LC_-fPnANe8DlIIAWD_pMF5z0C', + 'version': 'FxJgCW2a6MbqM5WkyXAxu91pykj7_QAYNerG9ettPPAC', }, ], 'condition': 'checkout_android', @@ -1846,7 +1846,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'eb1892c3e4ab734a135e8752f5442e270a4738d1', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '57b06646bee860edb996c9c9f4ea6372a12a9536', + Var('webrtc_git') + '/src.git' + '@' + 'acdc89d65328911b4e98afe0757028eca162cbb3', # 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. @@ -1969,7 +1969,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'g-I-PwburVWHBeonmaD-13CmqUNK7ON2TgtGs9hqwpYC', + 'version': 'hcJkUNq4GNucggif13hh9d7PC4peMyeDEjR9rxUoplsC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2013,7 +2013,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'C7_AlVVK21i8vPumd7UHvaEn2bnZiserzk1ZupW--xAC', + 'version': 'OsU5JXgg5Dwp_hNGhKpewhghTUEzP7JAImCtVFeSV-0C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4003,7 +4003,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - 'e0a71e95e946c2884c2980332683abf210fd3ffc', + 'f94bc05bf5ee979b36eb2d58b336e469404524c1', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/android_webview/browser/aw_form_database_service.cc b/android_webview/browser/aw_form_database_service.cc index affe917b..b2280ff 100644 --- a/android_webview/browser/aw_form_database_service.cc +++ b/android_webview/browser/aw_form_database_service.cc
@@ -12,6 +12,7 @@ #include "base/task/thread_pool.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autocomplete_table.h" #include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/webdata/common/webdata_constants.h" @@ -48,6 +49,7 @@ // `AwFormDatabaseService::ClearFormData()` also clear Autofill-related data. // This is likely a bug. // Once crbug.com/1501199 is resolved, all tables can be removed. + web_database_->AddTable(std::make_unique<autofill::AddressAutofillTable>()); web_database_->AddTable(std::make_unique<autofill::AutofillTable>()); web_database_->LoadDatabase();
diff --git a/android_webview/browser/gfx/hardware_renderer.cc b/android_webview/browser/gfx/hardware_renderer.cc index 8649210..4693ef6 100644 --- a/android_webview/browser/gfx/hardware_renderer.cc +++ b/android_webview/browser/gfx/hardware_renderer.cc
@@ -893,10 +893,6 @@ std::vector<viz::ReturnedResource> resources, const viz::FrameSinkId& frame_sink_id, uint32_t layer_tree_frame_sink_id) { - if (!base::FeatureList::IsEnabled(features::kWebViewCheckReturnResources) && - layer_tree_frame_sink_id != last_committed_layer_tree_frame_sink_id_) { - return; - } render_thread_manager_->InsertReturnedResourcesOnRT( std::move(resources), frame_sink_id, layer_tree_frame_sink_id); }
diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc index 429a75e1..2b922fc 100644 --- a/android_webview/common/aw_features.cc +++ b/android_webview/common/aw_features.cc
@@ -16,11 +16,6 @@ "WebViewBrotliSupport", base::FEATURE_ENABLED_BY_DEFAULT); -// Check layer_tree_frame_sink_id when return resources to compositor. -BASE_FEATURE(kWebViewCheckReturnResources, - "WebViewCheckReturnResources", - base::FEATURE_ENABLED_BY_DEFAULT); - // Whether to destroy the WebView rendering functor when after a WebView window // becomes invisible. //
diff --git a/android_webview/common/aw_features.h b/android_webview/common/aw_features.h index a3de562..4b8b2536 100644 --- a/android_webview/common/aw_features.h +++ b/android_webview/common/aw_features.h
@@ -17,7 +17,6 @@ // Alphabetical: BASE_DECLARE_FEATURE(kWebViewBrotliSupport); -BASE_DECLARE_FEATURE(kWebViewCheckReturnResources); BASE_DECLARE_FEATURE(kWebViewConnectionlessSafeBrowsing); BASE_DECLARE_FEATURE(kWebViewCheckPakFileDescriptors); BASE_DECLARE_FEATURE(kWebViewClearFunctorInBackground);
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index bd2d6a4..fdb67fa 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -318,6 +318,10 @@ AutofillFeatures.AUTOFILL_TEXT_AREA_CHANGE_EVENTS, "When enabled, autofill responds to textarea change events."), Flag.baseFeature( + AutofillFeatures.AUTOFILL_ENABLE_CACHE_FOR_REGEX_MATCHING, + "When enabled, autofill uses an extra cache for matching regular expressions " + + "while executing local heuristics."), + Flag.baseFeature( FeatureConstants.KEYBOARD_ACCESSORY_PAYMENT_VIRTUAL_CARD_FEATURE, "When enabled, merchant bound virtual cards will be offered in the keyboard " + "accessory."),
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 400f894..583ac09d 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -1337,11 +1337,6 @@ "HandwritingLegacyRecognition", base::FEATURE_ENABLED_BY_DEFAULT); -// Enables downloading the handwriting libraries via DLC. -BASE_FEATURE(kHandwritingLibraryDlc, - "HandwritingLibraryDlc", - base::FEATURE_ENABLED_BY_DEFAULT); - // If enabled, the Help app will render the App Detail Page and entry point. BASE_FEATURE(kHelpAppAppDetailPage, "HelpAppAppDetailPage",
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index de7c105..e4e897d 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -438,7 +438,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kProductivityLauncherImageSearch); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kLauncherItemColorSync); -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kHandwritingLibraryDlc); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kHelpAppAppDetailPage); COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/constants/geolocation_access_level.h b/ash/constants/geolocation_access_level.h index a38d4c2..11c9302 100644 --- a/ash/constants/geolocation_access_level.h +++ b/ash/constants/geolocation_access_level.h
@@ -11,7 +11,8 @@ // Affects the entire ChromeOS system and all client applications. // Don't modify or reorder the enum elements. New values can be added at the // end. These values shall be in sync with the -// `DeviceLoginScreenGeolocationAccessLevelProto::GeolocationAccessLevel`. +// `DeviceLoginScreenGeolocationAccessLevelProto::GeolocationAccessLevel` and +// //tools/metrics/histograms/metadata/chromeos/enums.xml. enum class GeolocationAccessLevel { kDisallowed = 0, kAllowed = 1,
diff --git a/ash/metrics/login_unlock_throughput_recorder.cc b/ash/metrics/login_unlock_throughput_recorder.cc index 1b87af97..892857e 100644 --- a/ash/metrics/login_unlock_throughput_recorder.cc +++ b/ash/metrics/login_unlock_throughput_recorder.cc
@@ -46,9 +46,8 @@ // A class used to wait for animations. class AnimationObserver : public views::BoundsAnimatorObserver { public: - AnimationObserver(ShelfView* shelf_view, base::OnceClosure& on_animation_end) - : shelf_view_(shelf_view), - on_animation_end_(std::move(on_animation_end)) {} + AnimationObserver(base::OnceClosure& on_animation_end) + : on_animation_end_(std::move(on_animation_end)) {} AnimationObserver(const AnimationObserver&) = delete; AnimationObserver& operator=(const AnimationObserver&) = delete; @@ -58,13 +57,14 @@ // ShelfViewObserver overrides: void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override {} void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override { - shelf_view_->RemoveAnimationObserver(this); + GetShelfView()->RemoveAnimationObserver(this); RunCallbackAndDestroy(); } void StartObserving() { - if (shelf_view_->IsAnimating()) { - shelf_view_->AddAnimationObserver(this); + ShelfView* shelf_view = GetShelfView(); + if (shelf_view->IsAnimating()) { + shelf_view->AddAnimationObserver(this); return; } RunCallbackAndDestroy(); @@ -76,7 +76,15 @@ delete this; } - raw_ptr<ShelfView, LeakedDanglingUntriaged> shelf_view_; + ShelfView* GetShelfView() { + return RootWindowController::ForWindow( + Shell::Get()->window_tree_host_manager()->GetPrimaryRootWindow()) + ->shelf() + ->hotseat_widget() + ->scrollable_shelf_view() + ->shelf_view(); + } + base::OnceClosure on_animation_end_; }; @@ -483,13 +491,6 @@ shelf_container->SchedulePaintInRect(bounds); } - ShelfView* shelf_view = - RootWindowController::ForWindow( - Shell::Get()->window_tree_host_manager()->GetPrimaryRootWindow()) - ->shelf() - ->hotseat_widget() - ->scrollable_shelf_view() - ->shelf_view(); base::OnceCallback on_animation_end = base::BindOnce( [](base::WeakPtr<LoginUnlockThroughputRecorder> self) { self->shelf_animation_finished_ = true; @@ -507,7 +508,7 @@ }, weak_ptr_factory_.GetWeakPtr()); - (new AnimationObserver(shelf_view, on_animation_end))->StartObserving(); + (new AnimationObserver(on_animation_end))->StartObserving(); } void LoginUnlockThroughputRecorder::OnAllExpectedShelfIconsLoaded() {
diff --git a/ash/system/privacy_hub/geolocation_privacy_switch_controller_unittest.cc b/ash/system/privacy_hub/geolocation_privacy_switch_controller_unittest.cc index 83f8280e..055344288 100644 --- a/ash/system/privacy_hub/geolocation_privacy_switch_controller_unittest.cc +++ b/ash/system/privacy_hub/geolocation_privacy_switch_controller_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/constants/ash_switches.h" +#include "ash/constants/geolocation_access_level.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" @@ -139,17 +140,21 @@ EXPECT_TRUE(features::IsCrosPrivacyHubLocationEnabled()); EXPECT_TRUE(controller_); controller_->TrackGeolocationAttempted(app_name); + + const auto kGeolocationAccessLevels = { + GeolocationAccessLevel::kDisallowed, GeolocationAccessLevel::kAllowed, + GeolocationAccessLevel::kOnlyAllowedForSystem}; + ASSERT_EQ(static_cast<unsigned long>(GeolocationAccessLevel::kMaxValue) + 1, + kGeolocationAccessLevels.size()); + // We didn't log any notification clicks so far. - EXPECT_EQ(histogram_tester_.GetBucketCount( - privacy_hub_metrics:: - kPrivacyHubGeolocationEnabledFromNotificationHistogram, - true), - 0); - EXPECT_EQ(histogram_tester_.GetBucketCount( - privacy_hub_metrics:: - kPrivacyHubGeolocationEnabledFromNotificationHistogram, - false), - 0); + for (auto access_level : kGeolocationAccessLevels) { + EXPECT_EQ(0, + histogram_tester_.GetBucketCount( + privacy_hub_metrics:: + kPrivacyHubGeolocationAccessLevelChangedFromNotification, + access_level)); + } EXPECT_TRUE(FindNotification()); EXPECT_NE(GetUserPref(), GeolocationAccessLevel::kAllowed); @@ -162,16 +167,18 @@ EXPECT_FALSE(FindNotification()); // The histograms were updated. - EXPECT_EQ(histogram_tester_.GetBucketCount( - privacy_hub_metrics:: - kPrivacyHubGeolocationEnabledFromNotificationHistogram, - true), - 1); - EXPECT_EQ(histogram_tester_.GetBucketCount( - privacy_hub_metrics:: - kPrivacyHubGeolocationEnabledFromNotificationHistogram, - false), - 0); + EXPECT_EQ(1, histogram_tester_.GetBucketCount( + privacy_hub_metrics:: + kPrivacyHubGeolocationAccessLevelChangedFromNotification, + GeolocationAccessLevel::kAllowed)); + EXPECT_EQ(0, histogram_tester_.GetBucketCount( + privacy_hub_metrics:: + kPrivacyHubGeolocationAccessLevelChangedFromNotification, + GeolocationAccessLevel::kDisallowed)); + EXPECT_EQ(0, histogram_tester_.GetBucketCount( + privacy_hub_metrics:: + kPrivacyHubGeolocationAccessLevelChangedFromNotification, + GeolocationAccessLevel::kOnlyAllowedForSystem)); } } // namespace ash
diff --git a/ash/system/privacy_hub/privacy_hub_metrics.cc b/ash/system/privacy_hub/privacy_hub_metrics.cc index 98c0d1f3..32ef841 100644 --- a/ash/system/privacy_hub/privacy_hub_metrics.cc +++ b/ash/system/privacy_hub/privacy_hub_metrics.cc
@@ -4,33 +4,31 @@ #include "ash/system/privacy_hub/privacy_hub_metrics.h" +#include "ash/system/privacy_hub/privacy_hub_controller.h" + #include "base/metrics/histogram_functions.h" namespace ash::privacy_hub_metrics { -void LogSensorEnabledFromSettings(Sensor sensor, bool enabled) { - const char* histogram = nullptr; - switch (sensor) { - case Sensor::kCamera: { - histogram = kPrivacyHubCameraEnabledFromSettingsHistogram; - break; - } - case Sensor::kMicrophone: { - histogram = kPrivacyHubMicrophoneEnabledFromSettingsHistogram; - break; - } - case Sensor::kLocation: { - histogram = kPrivacyHubGeolocationEnabledFromSettingsHistogram; - break; - } - } - CHECK(histogram); - base::UmaHistogramBoolean(histogram, enabled); -} - void LogSensorEnabledFromNotification(Sensor sensor, bool enabled) { const char* histogram = nullptr; switch (sensor) { + // Location needs to be handled separately as it has 3 states. + case Sensor::kLocation: { + histogram = kPrivacyHubGeolocationAccessLevelChangedFromNotification; + + // Only collect events that trigger system geolocation state changes. When + // `enabled==false` it means the user just dismissed the notification, so + // no change has happened. + if (enabled) { + // Enable events originated from PWAs are processed similarly to ARC++. + auto access_level = + PrivacyHubController::ArcToCrosGeolocationPermissionMapping( + enabled); + base::UmaHistogramEnumeration(histogram, access_level); + } + return; + } case Sensor::kCamera: { histogram = kPrivacyHubCameraEnabledFromNotificationHistogram; break; @@ -39,10 +37,6 @@ histogram = kPrivacyHubMicrophoneEnabledFromNotificationHistogram; break; } - case Sensor::kLocation: { - histogram = kPrivacyHubGeolocationEnabledFromNotificationHistogram; - break; - } } CHECK(histogram); base::UmaHistogramBoolean(histogram, enabled);
diff --git a/ash/system/privacy_hub/privacy_hub_metrics.h b/ash/system/privacy_hub/privacy_hub_metrics.h index 7498bd2..db43caca4 100644 --- a/ash/system/privacy_hub/privacy_hub_metrics.h +++ b/ash/system/privacy_hub/privacy_hub_metrics.h
@@ -29,25 +29,20 @@ kMaxValue = kGeolocation }; -static constexpr char kPrivacyHubMicrophoneEnabledFromSettingsHistogram[] = - "ChromeOS.PrivacyHub.Microphone.Settings.Enabled"; -static constexpr char kPrivacyHubMicrophoneEnabledFromNotificationHistogram[] = +inline constexpr char kPrivacyHubMicrophoneEnabledFromNotificationHistogram[] = "ChromeOS.PrivacyHub.Microphone.Notification.Enabled"; -static constexpr char kPrivacyHubCameraEnabledFromSettingsHistogram[] = - "ChromeOS.PrivacyHub.Camera.Settings.Enabled"; -static constexpr char kPrivacyHubCameraEnabledFromNotificationHistogram[] = +inline constexpr char kPrivacyHubCameraEnabledFromNotificationHistogram[] = "ChromeOS.PrivacyHub.Camera.Notification.Enabled"; -static constexpr char kPrivacyHubGeolocationEnabledFromSettingsHistogram[] = - "ChromeOS.PrivacyHub.Geolocation.Settings.Enabled"; -static constexpr char kPrivacyHubGeolocationEnabledFromNotificationHistogram[] = - "ChromeOS.PrivacyHub.Geolocation.Notification.Enabled"; -static constexpr char kPrivacyHubOpenedHistogram[] = +inline constexpr char + kPrivacyHubGeolocationAccessLevelChangedFromNotification[] = + "ChromeOS.PrivacyHub.Geolocation.AccessLevelChanged." + "LocationPermissionNotification"; +inline constexpr char kPrivacyHubOpenedHistogram[] = "ChromeOS.PrivacyHub.Opened"; -static constexpr char kPrivacyHubLearnMorePageOpenedHistogram[] = +inline constexpr char kPrivacyHubLearnMorePageOpenedHistogram[] = "ChromeOS.PrivacyHub.LearnMorePage.Opened"; -// Report sensor events from system and notifications. -ASH_EXPORT void LogSensorEnabledFromSettings(Sensor sensor, bool enabled); +// Report sensor events from notifications. ASH_EXPORT void LogSensorEnabledFromNotification(Sensor sensor, bool enabled); // Report that Privacy Hub has been opened from a notification.
diff --git a/ash/system/privacy_hub/privacy_hub_metrics_unittest.cc b/ash/system/privacy_hub/privacy_hub_metrics_unittest.cc index bf550aa..3d153dd 100644 --- a/ash/system/privacy_hub/privacy_hub_metrics_unittest.cc +++ b/ash/system/privacy_hub/privacy_hub_metrics_unittest.cc
@@ -4,16 +4,27 @@ #include "ash/system/privacy_hub/privacy_hub_metrics.h" +#include "ash/constants/geolocation_access_level.h" #include "base/test/metrics/histogram_tester.h" #include "testing/gtest/include/gtest/gtest.h" namespace ash::privacy_hub_metrics { +namespace { + +const auto kGeolocationAccessLevels = { + GeolocationAccessLevel::kDisallowed, + GeolocationAccessLevel::kAllowed, + GeolocationAccessLevel::kOnlyAllowedForSystem, +}; + +} // namespace using Sensor = SensorDisabledNotificationDelegate::Sensor; TEST(PrivacyHubMetricsTest, EnableFromNotification) { const base::HistogramTester histogram_tester; + // Test Microphone and Camera: for (const bool enabled : {true, false}) { histogram_tester.ExpectBucketCount( kPrivacyHubCameraEnabledFromNotificationHistogram, enabled, 0); @@ -26,37 +37,20 @@ LogSensorEnabledFromNotification(Sensor::kMicrophone, enabled); histogram_tester.ExpectBucketCount( kPrivacyHubMicrophoneEnabledFromNotificationHistogram, enabled, 1); - - histogram_tester.ExpectBucketCount( - kPrivacyHubGeolocationEnabledFromNotificationHistogram, enabled, 0); - LogSensorEnabledFromNotification(Sensor::kLocation, enabled); - histogram_tester.ExpectBucketCount( - kPrivacyHubGeolocationEnabledFromNotificationHistogram, enabled, 1); } -} -TEST(PrivacyHubMetricsTest, EnableFromSettings) { - const base::HistogramTester histogram_tester; - - for (const bool enabled : {true, false}) { + // Test Location: + // Notification dismissal is not recorded for location access level change. + LogSensorEnabledFromNotification(Sensor::kLocation, false); + for (auto access_level : kGeolocationAccessLevels) { histogram_tester.ExpectBucketCount( - kPrivacyHubCameraEnabledFromSettingsHistogram, enabled, 0); - LogSensorEnabledFromSettings(Sensor::kCamera, enabled); - histogram_tester.ExpectBucketCount( - kPrivacyHubCameraEnabledFromSettingsHistogram, enabled, 1); - - histogram_tester.ExpectBucketCount( - kPrivacyHubMicrophoneEnabledFromSettingsHistogram, enabled, 0); - LogSensorEnabledFromSettings(Sensor::kMicrophone, enabled); - histogram_tester.ExpectBucketCount( - kPrivacyHubMicrophoneEnabledFromSettingsHistogram, enabled, 1); - - histogram_tester.ExpectBucketCount( - kPrivacyHubGeolocationEnabledFromSettingsHistogram, enabled, 0); - LogSensorEnabledFromSettings(Sensor::kLocation, enabled); - histogram_tester.ExpectBucketCount( - kPrivacyHubGeolocationEnabledFromSettingsHistogram, enabled, 1); + kPrivacyHubGeolocationAccessLevelChangedFromNotification, access_level, + 0); } + LogSensorEnabledFromNotification(Sensor::kLocation, true); + histogram_tester.ExpectBucketCount( + kPrivacyHubGeolocationAccessLevelChangedFromNotification, + GeolocationAccessLevel::kAllowed, 1); } TEST(PrivacyHubMetricsTest, OpenFromNotification) {
diff --git a/ash/webui/media_app_ui/BUILD.gn b/ash/webui/media_app_ui/BUILD.gn index 0373139..4a4f044 100644 --- a/ash/webui/media_app_ui/BUILD.gn +++ b/ash/webui/media_app_ui/BUILD.gn
@@ -8,7 +8,6 @@ import("//build/buildflag_header.gni") import("//build/config/chromeos/ui_mode.gni") import("//mojo/public/tools/bindings/mojom.gni") -import("//third_party/closure_compiler/compile_js.gni") import("//tools/typescript/ts_library.gni") assert(is_chromeos_ash, "Media App is ash-chrome only") @@ -63,7 +62,7 @@ deps = [ ":media_app_ui", - ":test_media_app_guest_ui_browsertest_ts", + ":test_build_ts", "//ash/public/cpp:cpp", "//ash/webui/web_applications/test:test_support", "//chrome/test:test_support_ui", @@ -105,10 +104,10 @@ # ./gen/resources/js. In order for those paths to be merged, the `ts_library` # rules must be here, in the common ancestor. Staging in ./test would trigger # `Error: root_dir (...) should be within gen/.../test or ../../.../test`. -ts_library("test_media_app_guest_ui_browsertest_ts") { +ts_library("test_build_ts") { root_dir = ts_root_dir testonly = true - in_files = media_app_test_ts + media_app_test_unconverted_js_sources + in_files = media_app_test_ts definitions = media_app_definitions_staged + media_app_test_definitions_staged deps = [ ":build_ts" ] extra_deps = [ @@ -121,8 +120,6 @@ group("closure_compile") { testonly = true deps = [ - ":closure_compile_browsertests", - ":closure_compile_test_lib", "resources/js:closure_compile", "resources/mock/js:closure_compile", ] @@ -138,75 +135,6 @@ deps = [ "//ui/gfx/geometry/mojom:mojom" ] } -media_test_lib_closure_flags = system_app_closure_flags_strict + [ - "hide_warnings_for=ash/webui/media_app_ui/media_app_ui.mojom-lite-for-compile.js", - "js_module_root=" + - rebase_path(".", root_build_dir), - "js_module_root=" + - rebase_path(target_gen_dir, - root_build_dir), - ] - -# Use relaxed flags for the browsertest files themselves. This removes null -# checks and "could not determine type" errors which don't add a lot of value. -media_browsertest_closure_flags = system_app_closure_flags + [ - "hide_warnings_for=ash/webui/media_app_ui/media_app_ui.mojom-lite-for-compile.js", - "js_module_root=" + - rebase_path(".", root_build_dir), - "js_module_root=" + - rebase_path(target_gen_dir, - root_build_dir), - ] - -js_type_check("closure_compile_test_lib") { - testonly = true - closure_flags = media_test_lib_closure_flags - deps = [ - ":test_driver_api_js", - ":test_driver_js", - ] -} - -js_type_check("closure_compile_browsertests") { - testonly = true - closure_flags = media_browsertest_closure_flags - deps = [ ":test_media_app_ui_browsertest_js" ] -} - -js_library("test_driver_api_js") { - testonly = true - externs_list = - [ "//ash/webui/web_applications/externs/file_handling.externs.js" ] - sources = [ "test/driver_api.js" ] -} - -js_library("test_driver_js") { - testonly = true - sources = [ "test/driver.js" ] - externs_list = [ "//third_party/closure_compiler/externs/chai-3.5.js" ] - deps = [ - ":test_driver_api_js", - "//ash/webui/media_app_ui/resources/js:launch", - "//ash/webui/system_apps/public/js:message_pipe", - ] -} - -js_library("test_worker_js") { - testonly = true - sources = [ "test/test_worker.js" ] -} - -js_library("test_media_app_ui_browsertest_js") { - testonly = true - sources = [ "test/media_app_ui_browsertest.js" ] - externs_list = [ "//ash/webui/web_applications/js2gtest_support.externs.js" ] - deps = [ - ":test_driver_js", - "//ash/webui/media_app_ui/resources/js:launch", - "//ash/webui/system_apps/public/js:message_pipe", - ] -} - # Used to turn off tests that only work with our CIPD package e.g. loading ink. buildflag_header("buildflags") { header = "buildflags.h"
diff --git a/ash/webui/media_app_ui/media_app_files.gni b/ash/webui/media_app_ui/media_app_files.gni index 7e62e784..66c0f8e7b 100644 --- a/ash/webui/media_app_ui/media_app_files.gni +++ b/ash/webui/media_app_ui/media_app_files.gni
@@ -9,7 +9,10 @@ # tsc in the staging folder. These are also copied for rollup. media_app_unconverted_js_sources = [ "app_context_test_support.js", + "error_reporter.js", + "launch.js", "message_types.js", + "mojo_api_bootstrap.js", "mojo_api_bootstrap_untrusted.js", "piex_module_loader.js", ] @@ -25,12 +28,7 @@ # Inputs to rollup with no additional deps. These are also fed to tsc in case # they ever get converted to .ts in future. -media_app_static_js_sources = [ - "error_reporter.js", - "launch.js", - "mojo_api_bootstrap.js", - "piex_module.js", -] +media_app_static_js_sources = [ "piex_module.js" ] media_app_static_defs = [ "extra_types.d.ts", @@ -55,27 +53,18 @@ [ "$root_gen_dir/ash/webui/system_apps/public/js/message_pipe.d.ts" ] media_app_defs_for_external_js_staged = [ "$ts_root_dir/message_pipe.d.ts" ] -# Unconverted test JS sources. Since these may potentially be .ts in future, -# they must be fed to `ts_library` rules to avoid a .ts file potentially -# poisioning the build folder when rolling back to an earlier commit. Doing this -# also copies them to the typescript output folder, which allows the test -# harness to load everything from the same place. -media_app_test_unconverted_js_sources = [ - "driver.js", - "driver_api.js", - "guest_query_receiver.js", - "media_app_ui_browsertest.js", - "test_worker.js", -] - # Testing .d.ts and .ts files that are staged and consumed by tsc. -media_app_test_ts = [ "media_app_guest_ui_browsertest.ts" ] - -media_app_test_defs = [ - "guest_query_receiver.d.ts", - "test_api.d.ts", +media_app_test_ts = [ + "driver_api.ts", + "driver.ts", + "guest_query_receiver.ts", + "media_app_guest_ui_browsertest.ts", + "media_app_ui_browsertest.ts", + "test_worker.ts", ] +media_app_test_defs = [ "test_api.d.ts" ] + media_app_test_definitions_staged = process_file_template(media_app_test_defs, "$ts_root_dir/{{source_file_part}}")
diff --git a/ash/webui/media_app_ui/resources/js/extra_types.d.ts b/ash/webui/media_app_ui/resources/js/extra_types.d.ts index 115e64e..2d8957f 100644 --- a/ash/webui/media_app_ui/resources/js/extra_types.d.ts +++ b/ash/webui/media_app_ui/resources/js/extra_types.d.ts
@@ -15,6 +15,32 @@ setConsumer(consumer: (params: LaunchParams) => void): void; } +interface FilePickerAcceptType { + description: string; + accept: Record<string, string|string[]>; +} + +interface FilePickerOptions { + types: FilePickerAcceptType[]; + excludeAcceptAllOption?: boolean; + id?: string; + startIn?: string|FileSystemHandle; +} + +interface OpenFilePickerOptions extends FilePickerOptions { + multiple?: boolean; +} + interface Window { readonly launchQueue: LaunchQueue; + + // These are cleared in the untrusted context to prevent accidental usage. + // (They are guaranteed to fail). + showOpenFilePicker: null| + ((options: OpenFilePickerOptions) => + Promise<FileSystemFileHandle|FileSystemFileHandle[]>); + showSaveFilePicker: null| + ((options: FilePickerOptions) => Promise<FileSystemFileHandle>); + showDirectoryPicker: null| + ((options: FilePickerOptions) => Promise<FileSystemDirectoryHandle>); }
diff --git a/ash/webui/media_app_ui/resources/js/receiver.ts b/ash/webui/media_app_ui/resources/js/receiver.ts index 2f7106d..d23b895 100644 --- a/ash/webui/media_app_ui/resources/js/receiver.ts +++ b/ash/webui/media_app_ui/resources/js/receiver.ts
@@ -26,9 +26,8 @@ /** * A file received from the privileged context, and decorated with IPC methods * added in the untrusted (this) context to communicate back. - * @implements {mediaApp.AbstractFile} */ -class ReceivedFile implements AbstractFile { +export class ReceivedFile implements AbstractFile { blob: Blob; name: string; token: number; @@ -184,7 +183,7 @@ length: number; currentFileIndex: number; - private files: ReceivedFile[]; + files: ReceivedFile[]; // Public for tests. private observers: Array<(files: AbstractFileList) => unknown> = []; constructor(filesMessage: LoadFilesMessage) { @@ -418,9 +417,6 @@ declare global { interface Window { chooseFileSystemEntries: null; - showOpenFilePicker: null; - showSaveFilePicker: null; - showDirectoryPicker: null; addColorChangeListener: (listener: EventListenerOrEventListenerObject| null) => unknown; removeColorChangeListener: (listener: EventListenerOrEventListenerObject|
diff --git a/ash/webui/media_app_ui/test/BUILD.gn b/ash/webui/media_app_ui/test/BUILD.gn index b5768bd..c489a0a5 100644 --- a/ash/webui/media_app_ui/test/BUILD.gn +++ b/ash/webui/media_app_ui/test/BUILD.gn
@@ -8,7 +8,6 @@ assert(is_chromeos_ash) copy("stage_for_test_tsc") { - sources = media_app_test_ts + media_app_test_defs + - media_app_test_unconverted_js_sources + sources = media_app_test_ts + media_app_test_defs outputs = [ ts_root_dir + "/{{source_file_part}}" ] }
diff --git a/ash/webui/media_app_ui/test/driver.js b/ash/webui/media_app_ui/test/driver.ts similarity index 62% rename from ash/webui/media_app_ui/test/driver.js rename to ash/webui/media_app_ui/test/driver.ts index 4d75406..cdebdf42 100644 --- a/ash/webui/media_app_ui/test/driver.js +++ b/ash/webui/media_app_ui/test/driver.ts
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {FileSnapshot, LastLoadedFilesResponse, TestMessageQueryData, TestMessageResponseData, TestMessageRunTestCase} from './driver_api.js'; import {TEST_ONLY} from './launch.js'; const { @@ -16,7 +17,7 @@ } = TEST_ONLY; // See message_pipe.js. -function assertCast(condition) { +function assertCast<A>(condition: A): NonNullable<A> { if (!condition) { throw new Error('Failed assertion'); } @@ -26,7 +27,6 @@ /** * Promise that signals the guest is ready to receive test messages (in addition * to messages handled by receiver.js). - * @type {!Promise<undefined>} */ const testMessageHandlersReady = new Promise(resolve => { guestMessagePipe.registerHandler('test-handlers-ready', resolve); @@ -44,13 +44,12 @@ * @return Promise<string> JSON.stringify()'d value of the property, or * tagName if unspecified. */ - async waitForElementInGuest(query, opt_property, opt_commands = {}) { - /** @type {!TestMessageQueryData} */ - const message = {testQuery: query, property: opt_property}; + async waitForElementInGuest( + query: string, property?: string, commands: Object = {}) { + const message: TestMessageQueryData = {testQuery: query, property}; await testMessageHandlersReady; - const result = /** @type {!TestMessageResponseData} */ ( - await guestMessagePipe.sendMessage( - 'test', {...message, ...opt_commands})); + const result: TestMessageResponseData = + await guestMessagePipe.sendMessage('test', {...message, ...commands}); return result.testQueryResult; } } @@ -59,9 +58,8 @@ * Runs the given `testCase` in the guest context. * @param {string} testCase */ -export async function runTestInGuest(testCase) { - /** @type {!TestMessageRunTestCase} */ - const message = {testCase}; +export async function runTestInGuest(testCase: string) { + const message: TestMessageRunTestCase = {testCase}; await testMessageHandlersReady; await guestMessagePipe.sendMessage('run-test-case', message); } @@ -70,10 +68,10 @@ * @param {!Object=} data * @return {!Promise<!TestMessageResponseData>} */ -export async function sendTestMessage(data = undefined) { +export async function sendTestMessage(data?: Object): + Promise<TestMessageResponseData> { await testMessageHandlersReady; - return /** @type {!Promise<!TestMessageResponseData>} */ ( - guestMessagePipe.sendMessage('test', data)); + return guestMessagePipe.sendMessage('test', data); } /** @@ -81,37 +79,38 @@ * currently open file is always at index 0. * @return {!Promise<string>} */ -export async function getFileErrors() { +export async function getFileErrors(): Promise<string> { await testMessageHandlersReady; const message = {getFileErrors: true}; - const response = /** @type {!TestMessageResponseData} */ ( - await guestMessagePipe.sendMessage('test', message)); + const response: TestMessageResponseData = + await guestMessagePipe.sendMessage('test', message); return response.testQueryResult; } export class FakeWritableFileSink { - constructor(/** !Blob= */ data = new Blob()) { - this.data = data; + writes: Array<{position: number, size?: number}> = []; + resolveClose!: (blob: Blob) => void; + closePromise = new Promise<Blob>(resolve => { + this.resolveClose = resolve; + }); - /** @type {!Array<{position: number, size: (number|undefined)}>} */ - this.writes = []; + constructor(public data = new Blob()) {} - /** @type {function(!Blob)} */ - this.resolveClose; - this.closePromise = new Promise((/** function(!Blob) */ resolve) => { - this.resolveClose = resolve; - }); - } /** @param {?BufferSource|!Blob|string|!WriteParams} data */ - async write(data) { + async write(dataParam: BufferSource|Blob|string|WriteParams) { const position = 0; // Assume no seeks. - if (!data) { + if (!dataParam) { this.writes.push({position, size: 0}); return; } + interface HasLengthOrSize { + size?: number; + length: number; + } + const data = dataParam as BlobPart & HasLengthOrSize; const dataSize = data.size === undefined ? data.length : data.size; - this.writes.push({position, size: /** @type {number} */ (dataSize)}); + this.writes.push({position, size: dataSize}); this.data = new Blob([ this.data.slice(0, position), data, @@ -119,7 +118,7 @@ ]); } /** @param {number} size */ - async truncate(size) { + async truncate(size: number) { this.data = this.data.slice(0, size); } /** Resolves the close promise. */ @@ -127,60 +126,37 @@ this.resolveClose(this.data); } /** @param {number} offset */ - async seek(offset) { + async seek(_offset: number) { throw new Error('seek() not implemented.'); } } /** @implements FileSystemHandle */ -export class FakeFileSystemHandle { - /** - * @param {string=} name - */ - constructor(name = 'fake_file.png') { - this.kind = 'file'; - this.name = name; - } - /** @override */ - async isSameEntry(other) { +export class FakeFileSystemHandle implements FileSystemHandle { + kind: FileSystemHandleKind = 'file'; + constructor(public name: string = 'fake_file.png') {} + async isSameEntry(other: FileSystemHandle): Promise<boolean> { return this === other; } - /** @override */ - async queryPermission(descriptor) {} - /** @override */ - async requestPermission(descriptor) {} } /** @implements FileSystemFileHandle */ -export class FakeFileSystemFileHandle extends FakeFileSystemHandle { - /** - * @param {string=} name - * @param {string=} type - * @param {number=} lastModified - * @param {!Blob=} blob - */ +export class FakeFileSystemFileHandle extends FakeFileSystemHandle implements + FileSystemFileHandle { + override kind: 'file' = 'file'; + lastWritable: FakeWritableFileSink; + nextCreateWritableError?: DOMException|Error; + + /** Used simulate an error thrown from directory traversal. */ + errorToFireOnIterate?: null|DOMException; + constructor( - name = 'fake_file.png', type = '', lastModified = 0, blob = new Blob()) { + name = 'fake_file.png', public type: string = '', + public lastModified: number = 0, blob: Blob = new Blob()) { super(name); this.lastWritable = new FakeWritableFileSink(blob); - - /** @type {string} */ - this.type = type; - - /** @type {number} */ - this.lastModified = lastModified; - - /** @type {!DOMException|!Error|undefined} */ - this.nextCreateWritableError; - - /** - * Used simulate an error thrown from directory traversal. - * @type {?DOMException|undefined} - */ - this.errorToFireOnIterate; } - /** @override */ - async createWritable(options) { + async createWritable(_options: FileSystemCreateWritableOptions) { if (this.nextCreateWritableError) { throw this.nextCreateWritableError; } @@ -189,9 +165,10 @@ // The FileSystemWritableFileStream supports both streams and direct writes. // Splice on the direct writing capabilities by delegating to the sink. - const writable = /** @type {!FileSystemWritableFileStream} */ (stream); - writable.write = (data) => sink.write(data); - writable.truncate = (size) => sink.truncate(size); + const writable = stream as FileSystemWritableFileStream; + writable.write = (data: BufferSource|Blob|string|WriteParams) => + sink.write(data); + writable.truncate = (size: number) => sink.truncate(size); writable.close = () => sink.close(); return writable; } @@ -209,40 +186,36 @@ } /** @implements FileSystemDirectoryHandle */ -export class FakeFileSystemDirectoryHandle extends FakeFileSystemHandle { - /** - * @param {string=} name - */ +export class FakeFileSystemDirectoryHandle extends FakeFileSystemHandle + implements FileSystemDirectoryHandle { + override kind: 'directory' = 'directory'; + + /** Internal state mocking file handles in a directory handle. */ + files: FakeFileSystemFileHandle[] = []; + + /** Used to spy on the last deleted file. */ + lastDeleted?: null|FakeFileSystemFileHandle = null; + constructor(name = 'fake-dir') { super(name); - this.kind = 'directory'; - /** - * Internal state mocking file handles in a directory handle. - * @type {!Array<!FakeFileSystemFileHandle>} - */ - this.files = []; - /** - * Used to spy on the last deleted file. - * @type {?FakeFileSystemFileHandle} - */ - this.lastDeleted = null; } + /** * Use to populate `FileSystemFileHandle`s for tests. * @param {!FakeFileSystemFileHandle} fileHandle */ - addFileHandleForTest(fileHandle) { + addFileHandleForTest(fileHandle: FakeFileSystemFileHandle) { this.files.push(fileHandle); } /** * Helper to get all entries as File. * @return {!Array<!File>} */ - getFilesSync() { + getFilesSync(): File[] { return this.files.map(f => f.getFileSync()); } - /** @override */ - async getFileHandle(name, options) { + + async getFileHandle(name: string, options?: FileSystemGetFileOptions) { const fileHandle = this.files.find(f => f.name === name); if (!fileHandle && options && options.create === true) { // Simulate creating a new file, assume it is an image. This is needed for @@ -257,14 +230,18 @@ 'NotFoundError', `File ${name} not found`))); } /** @override */ - getDirectoryHandle(name, options) {} + async getDirectoryHandle( + _name: string, _options?: FileSystemGetDirectoryOptions): + Promise<FakeFileSystemDirectoryHandle> { + throw new Error('Not implemented'); + } /** * @override * @return {!AsyncIterable<!Array<string|!FileSystemHandle>>} * @suppress {reportUnknownTypes} suppress [JSC_UNKNOWN_EXPR_TYPE] for `yield * [file.name, file]`. */ - async * entries() { + async * entries(): AsyncIterable<Array<string|FileSystemHandle>> { for (const file of this.files) { yield [file.name, file]; } @@ -275,18 +252,12 @@ * @suppress {reportUnknownTypes} suppress [JSC_UNKNOWN_EXPR_TYPE] for `yield * file.name`. */ - async * keys() { + async * keys(): AsyncIterable<string> { for (const file of this.files) { yield file.name; } } - /** - * @override - * @return {!AsyncIterable<!FileSystemHandle>} - * @suppress {reportUnknownTypes} suppress [JSC_UNKNOWN_EXPR_TYPE] for `yield - * file`. - */ - async * values() { + async * values(): AsyncIterable<FileSystemHandle> { for (const file of this.files) { if (file.errorToFireOnIterate) { const error = file.errorToFireOnIterate; @@ -297,7 +268,7 @@ } } /** @override */ - async removeEntry(name, options) { + async removeEntry(name: string, _options: FileSystemRemoveOptions) { // Remove file handle from internal state. const fileHandleIndex = this.files.findIndex(f => f.name === name); // Store the file removed for spying in tests. @@ -319,16 +290,22 @@ * arrayBuffer: (function(): (!Promise<!ArrayBuffer>)|undefined) * }} */ -export let FileDesc; +export interface FileDesc { + name?: string; + type?: string; + lastModified?: number; + arrayBuffer?: () => Promise<ArrayBuffer>; +} /** * Creates a mock directory with the provided files in it. * @param {!Array<!FileDesc>=} files * @return {!Promise<!FakeFileSystemDirectoryHandle>} */ -export async function createMockTestDirectory(files = [{}]) { +export async function createMockTestDirectory(files: FileDesc[] = [{}]): + Promise<FakeFileSystemDirectoryHandle> { const directory = new FakeFileSystemDirectoryHandle(); - for (const /** !FileDesc */ file of files) { + for (const file of files) { const fileBlob = file.arrayBuffer !== undefined ? new Blob([await file.arrayBuffer()]) : new Blob(); @@ -340,81 +317,69 @@ /** * Creates a mock LaunchParams object from the provided `files`. - * @param {!Array<!FileSystemHandle>} files - * @return {!LaunchParams} */ -export function handlesToLaunchParams(files) { - return /** @type{!LaunchParams} */ ({files}); +export function handlesToLaunchParams(files: FileSystemHandle[]): LaunchParams { + return {files}; } /** * Helper to "launch" with the given `directoryContents`. Populates a fake * directory containing those handles, then launches the app. The focus file is * either the first file in `multiSelectionFiles`, or the first directory entry. - * @param {!Array<!FakeFileSystemFileHandle>} directoryContents - * @param {!Array<!FakeFileSystemFileHandle>=} multiSelectionFiles If provided, + * @param multiSelectionFiles If provided, * holds additional files selected in the files app at launch time. - * @return {!Promise<!FakeFileSystemDirectoryHandle>} */ export async function launchWithHandles( - directoryContents, multiSelectionFiles = []) { + directoryContents: FakeFileSystemFileHandle[], + multiSelectionFiles: FakeFileSystemFileHandle[] = + []): Promise<FakeFileSystemDirectoryHandle> { await testMessageHandlersReady; - /** @type {?FakeFileSystemFileHandle} */ let focusFile = multiSelectionFiles[0]; if (!focusFile) { - focusFile = directoryContents[0]; + focusFile = directoryContents[0]!; } multiSelectionFiles = multiSelectionFiles.slice(1); const directory = new FakeFileSystemDirectoryHandle(); for (const handle of directoryContents) { directory.addFileHandleForTest(handle); } - const files = [directory, focusFile, ...multiSelectionFiles]; + const files: FileSystemHandle[] = + [directory, focusFile, ...multiSelectionFiles]; await launchConsumer(handlesToLaunchParams(files)); return directory; } /** * Wraps a file in a FakeFileSystemFileHandle. - * @param {!File} file - * @return {!FakeFileSystemFileHandle} */ -export function fileToFileHandle(file) { +export function fileToFileHandle(file: File): FakeFileSystemFileHandle { return new FakeFileSystemFileHandle( file.name, file.type, file.lastModified, file); } /** * Helper to invoke launchWithHandles after wrapping `files` in fake handles. - * @param {!Array<!File>} files - * @param {!Array<number>=} selectedIndexes - * @return {!Promise<!FakeFileSystemDirectoryHandle>} */ -export async function launchWithFiles(files, selectedIndexes = []) { +export async function launchWithFiles( + files: File[], + selectedIndexes: number[] = []): Promise<FakeFileSystemDirectoryHandle> { const fileHandles = files.map(fileToFileHandle); - const selection = - selectedIndexes.map((/** @type {number} */ i) => fileHandles[i]); + const selection = selectedIndexes.map(i => fileHandles[i]!); return launchWithHandles(fileHandles, selection); } /** * Creates an `Error` with the name field set. - * @param {string} name - * @param {string} msg - * @return {!Error} */ -export function createNamedError(name, msg) { +export function createNamedError(name: string, msg: string): Error { const error = new Error(msg); error.name = name; return error; } -/** - * @param {!FileSystemDirectoryHandle} directory - * @param {!File} file - */ -export async function loadFilesWithoutSendingToGuest(directory, file) { +export async function loadFilesWithoutSendingToGuest( + directory: FileSystemDirectoryHandle, file: File) { const handle = await directory.getFileHandle(file.name); const launchNumber = incrementLaunchNumber(); setCurrentDirectory(directory, {file, handle}); @@ -424,20 +389,18 @@ /** * Checks that the `currentFiles` array maintained by launch.js has the same * sequence of files as `expectedFiles`. - * @param {!Array<!File>} expectedFiles - * @param {string=} testCase */ -export function assertFilesToBe(expectedFiles, testCase = undefined) { - assertFilenamesToBe(expectedFiles.map(f => f.name).join(), testCase); +export function assertFilesToBe( + expectedFiles: Array<undefined|{name: string}>, testCase?: string) { + assertFilenamesToBe(expectedFiles.map(f => f!.name).join(), testCase); } /** * Checks that the `currentFiles` array maintained by launch.js has the same * sequence of filenames as `expectedFilenames`. - * @param {string} expectedFilenames - * @param {string=} testCase */ -export function assertFilenamesToBe(expectedFilenames, testCase = undefined) { +export function assertFilenamesToBe( + expectedFilenames: string, testCase?: string) { // Use filenames as an approximation of file uniqueness. const currentFilenames = currentFiles.map(d => d.handle.name).join(); chai.assert.equal( @@ -448,25 +411,25 @@ /** * Wraps `chai.assert.match` allowing tests to use `assertMatch`. - * @param {string} string the string to match - * @param {string} regex an escaped regex compatible string - * @param {string=} opt_message logged if the assertion fails + * @param string the string to match + * @param regex an escaped regex compatible string + * @param message logged if the assertion fails */ -export function assertMatch(string, regex, opt_message = undefined) { - chai.assert.match(string, new RegExp(regex), opt_message); +export function assertMatch(string: string, regex: string, message?: string) { + chai.assert.match(string, new RegExp(regex), message); } /** * Returns the files loaded in the most recent call to `loadFiles()`. - * @return {!Promise<?Array<!FileSnapshot>>} */ -export async function getLoadedFiles() { - const response = /** @type {!LastLoadedFilesResponse} */ ( - await guestMessagePipe.sendMessage('get-last-loaded-files')); +export async function getLoadedFiles(): Promise<FileSnapshot[]> { + const response: LastLoadedFilesResponse = + await guestMessagePipe.sendMessage('get-last-loaded-files'); if (response.fileList) { return response.fileList; } - return null; + // No callers currently want this to return null. + throw new Error('No last loaded files'); } /** @@ -478,31 +441,25 @@ setCurrentDirectoryHandle(null); } -/** - * @param {!FakeFileSystemDirectoryHandle} directory - * @return {{handle: !FakeFileSystemFileHandle, file: !File}} - */ -export function launchWithFocusFile(directory) { +export function launchWithFocusFile(directory: FakeFileSystemDirectoryHandle): + {handle: FakeFileSystemFileHandle, file: File} { + const firstFile = assertCast(directory.files[0]); const focusFile = { - /** @type {!FakeFileSystemFileHandle} */ - handle: directory.files[0], - file: directory.files[0].getFileSync(), + handle: firstFile, + file: firstFile.getFileSync(), }; incrementLaunchNumber(); setCurrentDirectory(directory, focusFile); return focusFile; } -/** - * @param {!FakeFileSystemDirectoryHandle} directory - * @param {number} totalFiles - */ -export async function assertSingleFileLaunch(directory, totalFiles) { +export async function assertSingleFileLaunch( + directory: FakeFileSystemDirectoryHandle, totalFiles: number) { chai.assert.equal(1, currentFiles.length); await sendFilesToGuest(); - const loadedFiles = assertCast(await getLoadedFiles()); + const loadedFiles = await getLoadedFiles(); // The untrusted context only loads the first file. chai.assert.equal(1, loadedFiles.length); // All files are in the `FileSystemDirectoryHandle`. @@ -512,16 +469,14 @@ /** * Check files loaded in the trusted context `currentFiles` against the working * directory and the untrusted context. - * @param {!FakeFileSystemDirectoryHandle} directory - * @param {!Array<string>} fileNames - * @param {string=} testCase */ export async function assertFilesLoaded( - directory, fileNames, testCase = undefined) { + directory: FakeFileSystemDirectoryHandle, fileNames: string[], + testCase?: string) { chai.assert.equal(fileNames.length, directory.files.length); chai.assert.equal(fileNames.length, currentFiles.length); - const loadedFiles = /** @type {!Array<!File>} */ (await getLoadedFiles()); + const loadedFiles = await getLoadedFiles(); chai.assert.equal(fileNames.length, loadedFiles.length); // Check `currentFiles` in the trusted context matches up with files sent
diff --git a/ash/webui/media_app_ui/test/driver_api.js b/ash/webui/media_app_ui/test/driver_api.js deleted file mode 100644 index 3af142d..0000000 --- a/ash/webui/media_app_ui/test/driver_api.js +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Reply to test messages. Contents depend on the test message sent. - * @typedef {{ - * testQueryResult: string, - * testQueryResultData: (!Object|undefined) - * }} - */ -let TestMessageResponseData; - -/** - * Object sent over postMessage to run a command or extract data. - * @typedef {{ - * deleteLastFile: (boolean|undefined), - * getFileErrors: (boolean|undefined), - * navigate: ({direction: string, token: number}|undefined), - * openFile: (boolean|undefined), - * overwriteLastFile: (string|undefined), - * rethrow: (boolean|undefined), - * pathToRoot: (!Array<string>|undefined), - * property: (string|undefined), - * renameLastFile: (string|undefined), - * requestFullscreen: (boolean|undefined), - * requestSaveFile: (boolean|undefined), - * saveAs: (string|undefined), - * simple: (string|undefined), - * simpleArgs: (Object|undefined), - * suppressCrashReports: (boolean|undefined), - * testQuery: string, - * }} - */ -let TestMessageQueryData; - -/** @typedef {{testCase: string}} */ -let TestMessageRunTestCase; - -/** - * Subset of mediaApp.AbstractFile that can be serialized. The fields - * `hasDelete` and `hasRename` indicate whether the methods are defined. - * @typedef {{ - * blob: !Blob, - * name: string, - * size: number, - * mimeType: string, - * fromClipboard: (boolean|undefined), - * error: (string|undefined), - * token: (number|undefined), - * lastModified: number, - * hasDelete: boolean, - * hasRename: boolean, - * }} - */ -let FileSnapshot; - -/** - * Return type of `get-last-loaded-files` used to spy on the files sent to the - * guest app using `loadFiles()`. - * @typedef {{fileList: ?Array<!FileSnapshot>}} - */ -let LastLoadedFilesResponse;
diff --git a/ash/webui/media_app_ui/test/driver_api.ts b/ash/webui/media_app_ui/test/driver_api.ts new file mode 100644 index 0000000..85fd11a9 --- /dev/null +++ b/ash/webui/media_app_ui/test/driver_api.ts
@@ -0,0 +1,62 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Reply to test messages. Contents depend on the test message sent. + */ +export interface TestMessageResponseData { + testQueryResult: string; + testQueryResultData?: any; +} + +/** + * Object sent over postMessage to run a command or extract data. + */ +export interface TestMessageQueryData { + deleteLastFile?: boolean; + getFileErrors?: boolean; + navigate?: {direction?: string, token?: number}; + openFile?: boolean; + overwriteLastFile?: string; + rethrow?: boolean; + pathToRoot?: string[]; + property?: string; + renameLastFile?: string; + requestFullscreen?: boolean; + requestSaveFile?: boolean; + saveAs?: string; + simple?: string; + simpleArgs?: any; + suppressCrashReports?: boolean; + testQuery: string; +} + +export interface TestMessageRunTestCase { + testCase: string; +} + +/** + * Subset of mediaApp.AbstractFile that can be serialized. The fields + * `hasDelete` and `hasRename` indicate whether the methods are defined. + */ +export interface FileSnapshot { + blob: Blob; + name: string; + size: number; + mimeType: string; + fromClipboard?: boolean; + error?: string; + token?: number; + lastModified: number; + hasDelete: boolean; + hasRename: boolean; +} + +/** + * Return type of `get-last-loaded-files` used to spy on the files sent to the + * guest app using `loadFiles()`. + */ +export interface LastLoadedFilesResponse { + fileList: FileSnapshot[]; +}
diff --git a/ash/webui/media_app_ui/test/guest_query_receiver.d.ts b/ash/webui/media_app_ui/test/guest_query_receiver.d.ts deleted file mode 100644 index 371b7cc..0000000 --- a/ash/webui/media_app_ui/test/guest_query_receiver.d.ts +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview - * Temporary export until guest_query_receiver.js is converted to TS. The - * generated .d.ts doesn't work due to an undefined/void mismatch. - */ -// eslint-disable-next-line @typescript-eslint/naming-convention -export function GUEST_TEST( - testName: string, testCase: () => void|Promise<void>): void;
diff --git a/ash/webui/media_app_ui/test/guest_query_receiver.js b/ash/webui/media_app_ui/test/guest_query_receiver.ts similarity index 72% rename from ash/webui/media_app_ui/test/guest_query_receiver.js rename to ash/webui/media_app_ui/test/guest_query_receiver.ts index 35bf0e6..3b8b241 100644 --- a/ash/webui/media_app_ui/test/guest_query_receiver.js +++ b/ash/webui/media_app_ui/test/guest_query_receiver.ts
@@ -2,40 +2,42 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Note we can only import from 'receiver.js': other modules are rolled-up into -// it, and already loaded. -import {TEST_ONLY} from './receiver.js'; +/// <reference path="media_app.d.ts" /> -/** - * @typedef {{ - * name: string, - * message: string, - * stack: string, - * }} - */ -let GenericErrorResponse; +import {FileSnapshot, LastLoadedFilesResponse, TestMessageQueryData, TestMessageResponseData, TestMessageRunTestCase} from './driver_api.js'; +import {ReceivedFileList, TEST_ONLY} from './receiver.js'; + +interface GenericErrorResponse { + name: string; + message: string; + stack: string; +} const { RenameResult, DELEGATE, - assertCast, parentMessagePipe, loadFiles, setLoadFiles, } = TEST_ONLY; /** - * The last file list loaded into the guest, updated via a spy on loadFiles(). - * TODO(b/185734620): This should be type {ReceivedFileList} but closure fails - * to resolve it properly. See b/185734620 for details. + * TODO(b/314827247): Remove this when imports are converted to TypeScript. This + * is needed because the generated .d.ts doesn't capture non-nullability. */ -let lastLoadedFileList = null; +function assertCast<A>(arg: A): NonNullable<A> { + return TEST_ONLY.assertCast(arg)!; +} + +/** + * The last file list loaded into the guest, updated via a spy on loadFiles(). + */ +let lastLoadedFileList: ReceivedFileList|null = null; /** * Test cases registered by GUEST_TEST. - * @type {!Map<string, function(): (!Promise<undefined>|undefined)>} */ -const guestTestCases = new Map(); +const guestTestCases = new Map<string, () => unknown>(); /** * Returns the last file list passed to the guest context over the message pipe. @@ -47,7 +49,7 @@ * the received file list on `window.customLaunchData.files`. Support either. * This only affects tests: `launchConsumer` cannot be awaited in the real app. */ -function assertLastReceivedFileList() { +function assertLastReceivedFileList(): ReceivedFileList { if (lastLoadedFileList) { return lastLoadedFileList; } @@ -55,34 +57,27 @@ throw new Error('No file list received.'); } console.log('Note: app not loaded. Returning customLaunchData.files.'); - return window.customLaunchData.files; + return window.customLaunchData.files as ReceivedFileList; } -/** - * @return {!Array<!mediaApp.AbstractFile>} - */ -function assertLastReceivedFileArray() { +function assertLastReceivedFileArray(): AbstractFile[] { const fileList = assertLastReceivedFileList(); - return Array.from({length: fileList.length}, (v, k) => fileList.item(k)); + return Array.from({length: fileList.length}, (_, k) => fileList.item(k)) as + AbstractFile[]; } -/** - * @return {!mediaApp.AbstractFile} - */ -function currentFile() { +function currentFile(): AbstractFile { const fileList = assertLastReceivedFileList(); - return assertCast(fileList.item(fileList.currentFileIndex)); + return assertCast(fileList.item(fileList.currentFileIndex))!; } /** * Flatten out primitives from the file object for transfer over message pipe. - * @param {!mediaApp.AbstractFile} file - * @return {!FileSnapshot} */ -function flattenFile(file) { +function flattenFile(file: AbstractFile): FileSnapshot { const hasDelete = !!file.deleteOriginalFile; const hasRename = !!file.renameOriginalFile; - const lastModified = /** @type{!File} */ (file.blob).lastModified; + const lastModified = (file.blob as File).lastModified; const {blob, name, size, mimeType, fromClipboard, error, token} = file; return { blob, @@ -98,13 +93,14 @@ }; } +type QueryHandler = (data: TestMessageQueryData, arg: any) => + Promise<string>|string; + /** * Handlers for simple tests run in the guest that return a string result. - * @type{!Object<string, function(!TestMessageQueryData, !Object): - * Promise<string>>} */ -const SIMPLE_TEST_QUERIES = { - requestSaveFile: async (data, resultData) => { +const SIMPLE_TEST_QUERIES: {[key: string]: QueryHandler} = { + requestSaveFile: async (data, _resultData) => { // Call requestSaveFile on the delegate. const existingFile = assertLastReceivedFileList().item(0); if (!existingFile) { @@ -115,44 +111,45 @@ data.simpleArgs ? data.simpleArgs.accept : []); return assertCast(pickedFile.token).toString(); }, - getExportFile: async (data, resultData) => { + getExportFile: async (data, _resultData) => { const existingFile = assertLastReceivedFileList().item(0); if (!existingFile) { return 'getExportFile failed, no file loaded'; } - const pickedFile = await existingFile.getExportFile(data.simpleArgs.accept); - return pickedFile.token.toString(); + const pickedFile = + await existingFile.getExportFile!(data.simpleArgs.accept); + return pickedFile.token!.toString(); }, - getLastFile: async (data, resultData) => { + getLastFile: async (_data, resultData) => { Object.assign(resultData, flattenFile(currentFile())); return resultData.name; }, - getAllFiles: async (data, resultData) => { + getAllFiles: async (_data, resultData) => { Object.assign(resultData, assertLastReceivedFileArray().map(flattenFile)); return `${resultData.length}`; }, - notifyCurrentFile: (data, resultData) => { + notifyCurrentFile: (data, _resultData) => { DELEGATE.notifyCurrentFile(data.simpleArgs.name, data.simpleArgs.type); + return 'notified'; }, - openFileAtIndex: async (data, resultData) => { + openFileAtIndex: async (data, _resultData) => { const handle = assertLastReceivedFileList().item(data.simpleArgs.index); - const domFile = await handle.openFile(); - handle.updateFile(domFile, domFile.name); + const domFile = await handle!.openFile(); + // Cast to any to access private method. + (handle as any).updateFile(domFile, domFile.name); return 'opened and updated'; }, - openFilesWithFilePicker: async (data, resultData) => { - /** - * @typedef {{ - * acceptTypeKeys: !Array<string>, - * explicitToken: (number|undefined), - * singleFile: ?boolean, - * }} - */ - let Args; - const args = /** @type {Args} */ (data.simpleArgs); - let existingFile = assertLastReceivedFileList().item(0) || null; + openFilesWithFilePicker: async (data, _resultData) => { + interface Args { + acceptTypeKeys: string[]; + explicitToken?: number; + singleFile?: boolean; + } + const args: Args = data.simpleArgs; + let existingFile: AbstractFile|undefined = + assertLastReceivedFileList().item(0) || undefined; if (args.explicitToken) { - existingFile = {token: args.explicitToken}; + existingFile = {token: args.explicitToken} as AbstractFile; } await assertLastReceivedFileList().openFilesWithFilePicker( args.acceptTypeKeys, existingFile, args.singleFile); @@ -162,10 +159,9 @@ /** * Acts on received TestMessageQueryData. - * @param {!TestMessageQueryData} data - * @return {!Promise<!TestMessageResponseData>} */ -async function runTestQuery(data) { +async function runTestQuery(data: TestMessageQueryData): + Promise<TestMessageResponseData> { let result = 'no result'; let extraResultData = {}; if (data.testQuery) { @@ -173,24 +169,24 @@ result = element.tagName; if (data.property) { - result = JSON.stringify(element[data.property]); + result = JSON.stringify((element as any)[data.property]); } else if (data.requestFullscreen) { try { await element.requestFullscreen(); result = 'hooray'; - } catch (/** @type {!TypeError} */ typeError) { + } catch (typeError: any) { result = typeError.message; } } } else if (data.simple !== undefined && data.simple in SIMPLE_TEST_QUERIES) { - result = await SIMPLE_TEST_QUERIES[data.simple](data, extraResultData); + result = await SIMPLE_TEST_QUERIES[data.simple]!(data, extraResultData); } else if (data.navigate !== undefined) { // Simulate a user navigating to the next/prev file. if (data.navigate.direction === 'next') { - await assertLastReceivedFileList().loadNext(data.navigate.token); + await assertLastReceivedFileList().loadNext(data.navigate.token!); result = 'loadNext called'; } else if (data.navigate.direction === 'prev') { - await assertLastReceivedFileList().loadPrev(data.navigate.token); + await assertLastReceivedFileList().loadPrev(data.navigate.token!); result = 'loadPrev called'; } else { result = 'nothing called'; @@ -202,7 +198,7 @@ try { await assertCast(file.overwriteOriginal).call(file, testBlob); result = 'overwriteOriginal resolved'; - } catch (/** @type{!Error} */ error) { + } catch (error: unknown) { result = `overwriteOriginal failed Error: ${error}`; if (data.rethrow) { throw error; @@ -217,7 +213,7 @@ try { await assertCast(currentFile().deleteOriginalFile).call(currentFile()); result = 'deleteOriginalFile resolved success'; - } catch (/** @type{!Error} */ error) { + } catch (error: unknown) { result = `deleteOriginalFile failed Error: ${error}`; } } else if (data.renameLastFile) { @@ -235,7 +231,7 @@ } else { result = 'renameOriginalFile resolved success'; } - } catch (/** @type{!Error} */ error) { + } catch (error: unknown) { result = `renameOriginalFile failed Error: ${error}`; } } else if (data.saveAs) { @@ -254,7 +250,7 @@ await assertCast(file.saveAs).call(file, testBlob, assertCast(token)); result = file.name; extraResultData = {blobText: await file.blob.text()}; - } catch (/** @type{!Error} */ error) { + } catch (error: unknown) { result = `saveAs failed Error: ${error}`; extraResultData = {filename: file.name}; } @@ -268,8 +264,9 @@ // Remove the implementation of reportError so test code // can safely check that the right errors are being thrown without // triggering a crash. - if (chrome) { - chrome.crashReportPrivate.reportError = () => {}; + const chromeWindow = window as unknown as {chrome: any}; + if (chromeWindow.chrome) { + chromeWindow.chrome.crashReportPrivate.reportError = () => {}; } } @@ -278,10 +275,9 @@ /** * Acts on TestMessageRunTestCase. - * @param {!TestMessageRunTestCase} data - * @return {!Promise<!TestMessageResponseData>} */ -async function runTestCase(data) { +async function runTestCase(data: TestMessageRunTestCase): + Promise<TestMessageResponseData> { const testCase = guestTestCases.get(data.testCase); if (!testCase) { throw new Error(`Unknown test case: '${data.testCase}'`); @@ -293,10 +289,9 @@ /** * Registers a test that runs in the guest context. To indicate failure, the * test throws an exception (e.g. via assertEquals). - * @param {string} testName - * @param {function(): (!Promise<undefined>|undefined)} testCase */ -export function GUEST_TEST(testName, testCase) { +// eslint-disable-next-line @typescript-eslint/naming-convention +export function GUEST_TEST(testName: string, testCase: () => unknown) { guestTestCases.set(testName, testCase); } @@ -317,7 +312,8 @@ await new Promise(resolve => setTimeout(resolve, 100)); await parentMessagePipe.sendMessage('test-handlers-ready', {}); return; - } catch (/** @type {!GenericErrorResponse} */ e) { + } catch (error: unknown) { + const e = error as GenericErrorResponse; if (!EXPECTED_ERROR.test(e.message)) { console.error('Unexpected error in signalTestHandlersReady', e); return; @@ -329,22 +325,25 @@ /** Installs the MessagePipe handlers for receiving test queries. */ function installTestHandlers() { - parentMessagePipe.registerHandler('test', (data) => { - return runTestQuery(/** @type {!TestMessageQueryData} */ (data)); + parentMessagePipe.registerHandler('test', (data: TestMessageQueryData) => { + return runTestQuery(data); }); // Turn off error rethrowing for tests so the test runner doesn't mark // our error handling tests as failed. parentMessagePipe.rethrowErrors = false; - parentMessagePipe.registerHandler('run-test-case', (data) => { - return runTestCase(/** @type{!TestMessageRunTestCase} */ (data)); - }); + parentMessagePipe.registerHandler( + 'run-test-case', (data: TestMessageRunTestCase) => { + return runTestCase(data); + }); parentMessagePipe.registerHandler('get-last-loaded-files', () => { // Note: the `ReceivedFileList` has methods stripped since it gets sent // over a pipe so just send the underlying files. - return /** @type {!LastLoadedFilesResponse} */ ( - {fileList: assertLastReceivedFileList().files.map(flattenFile)}); + const response: LastLoadedFilesResponse = { + fileList: assertLastReceivedFileList().files.map(flattenFile), + }; + return response; }); // Log errors, rather than send them to console.error. This allows the error @@ -355,11 +354,7 @@ // Install spies. const realLoadFiles = loadFiles; - /** - * @param {*} fileList - * @return {!Promise<undefined>} - */ - async function watchLoadFiles(fileList) { + async function watchLoadFiles(fileList: ReceivedFileList) { lastLoadedFileList = fileList; return realLoadFiles(fileList); }
diff --git a/ash/webui/media_app_ui/test/media_app_ui_browsertest.js b/ash/webui/media_app_ui/test/media_app_ui_browsertest.ts similarity index 79% rename from ash/webui/media_app_ui/test/media_app_ui_browsertest.js rename to ash/webui/media_app_ui/test/media_app_ui_browsertest.ts index f77a1ed..e7215d1 100644 --- a/ash/webui/media_app_ui/test/media_app_ui_browsertest.js +++ b/ash/webui/media_app_ui/test/media_app_ui_browsertest.ts
@@ -3,7 +3,9 @@ // found in the LICENSE file. import {assertFilenamesToBe, assertFilesLoaded, assertFilesToBe, assertMatch, assertSingleFileLaunch, createMockTestDirectory, FakeFileSystemFileHandle, fileToFileHandle, getFileErrors, getLoadedFiles, GuestDriver, launchWithFiles, launchWithFocusFile, launchWithHandles, loadFilesWithoutSendingToGuest, runTestInGuest, sendTestMessage, simulateLosingAccessToDirectory} from './driver.js'; +import {FileSnapshot} from './driver_api.js'; import {TEST_ONLY} from './launch.js'; +import type {LoadFilesMessage} from './message_types.js'; const { Message, @@ -37,14 +39,13 @@ */ const GENERIC_ERROR_MESSAGE_REGEX = '^".*[A-Za-z].*"$'; -/** @type {!GuestDriver} */ const driver = new GuestDriver(); /** * Runs a CSS selector until it detects the "error" UX being loaded. - * @return {!Promise<string>} alt= text of the element showing the error. + * @return alt= text of the element showing the error. */ -function waitForErrorUX() { +function waitForErrorUX(): Promise<string> { const ERROR_UX_SELECTOR = 'img[alt^="Unable to decode"]'; return driver.waitForElementInGuest(ERROR_UX_SELECTOR, 'alt'); } @@ -52,10 +53,9 @@ /** * Runs a CSS selector that waits for an image to load with the given alt= text * and returns its width. - * @param {string} altText - * @return {!Promise<string>} The value of the width attribute. + * @return The value of the width attribute. */ -function waitForImageAndGetWidth(altText) { +function waitForImageAndGetWidth(altText: string): Promise<string> { return driver.waitForElementInGuest(`img[alt="${altText}"]`, 'naturalWidth'); } @@ -65,68 +65,62 @@ const TEST_IMAGE_HEIGHT = 456; /** - * @param {number=} width - * @param {number=} height - * @param {string=} name - * @param {number=} lastModified - * @return {!Promise<!File>} A {width}x{height} transparent encoded image/png. + * Returns A {width}x{height} transparent encoded image/png. */ async function createTestImageFile( width = TEST_IMAGE_WIDTH, height = TEST_IMAGE_HEIGHT, - name = 'test_file.png', lastModified = 0) { + name = 'test_file.png', lastModified = 0): Promise<File> { const canvas = new OffscreenCanvas(width, height); canvas.getContext('2d'); // convertToBlob fails without a rendering context. const blob = await canvas.convertToBlob(); return new File([blob], name, {type: 'image/png', lastModified}); } -/** - * @param {!Array<string>} filenames - * @return {!Promise<!Array<!File>>} - */ -async function createMultipleImageFiles(filenames) { - const filePromise = name => createTestImageFile(1, 1, `${name}.png`); +async function createMultipleImageFiles(filenames: unknown[]): Promise<File[]> { + const filePromise = (name: unknown) => + createTestImageFile(1, 1, `${name}.png`); const files = await Promise.all(filenames.map(filePromise)); return files; } -/** @return {!HTMLIFrameElement} */ function queryIFrame() { - return /** @type{!HTMLIFrameElement} */ (document.querySelector('iframe')); + return document.querySelector('iframe')!; } -/** @return {!HTMLTitleElement} */ function getTitle() { - return /** @type{!HTMLTitleElement} */ (document.querySelector('title')); + return document.querySelector('title')!; } -/** @return {!HTMLLinkElement} */ function getIcon() { - return /** @type{!HTMLLinkElement} */ ( - document.querySelector('link[rel=icon]')); + return document.querySelector<HTMLLinkElement>('link[rel=icon]')!; } /** * Sets up a FakeFileSystemFileHandle to behave like a file which has been * deleted or moved to a directory to which we do not have access. - * @param {!FakeFileSystemFileHandle} handle */ -function makeFileNotFound(handle) { +function makeFileNotFound(handle?: FakeFileSystemFileHandle) { // Mimic the exception that would be thrown when attempting to call getFile on // a file which has been moved or deleted. - handle.getFileSync = () => { + handle!.getFileSync = () => { throw new DOMException('File not found', 'NotFoundError'); }; } -/** @struct */ -const MediaAppUIBrowserTest = { - /** @type function(string): !Promise<undefined> */ - runTestInGuest, +interface TestSuite { + [testName: string]: () => unknown; + runTestInGuest: (testName?: string) => unknown; +} + +const MediaAppUIBrowserTest: TestSuite = { + // runTestInGuest takes a compulsory string arg, which isn't compatible with + // the TestSuite index signature, so cast it here. + runTestInGuest: runTestInGuest as () => unknown, }; // Expose an export for tests run through `isolatedTestRunner`. -window['MediaAppUiBrowserTest'] = MediaAppUIBrowserTest; +(window as unknown as {MediaAppUiBrowserTest: {}})['MediaAppUiBrowserTest'] = + MediaAppUIBrowserTest; // Tests that chrome://media-app is allowed to frame // chrome-untrusted://media-app. The URL is set in the html. If that URL can't @@ -135,7 +129,7 @@ // chrome-untrusted://media-app/". This test also fails if the guest renderer is // terminated, e.g., due to webui performing bad IPC such as network requests // (failure detected in content/public/test/no_renderer_crashes_assertion.cc). -MediaAppUIBrowserTest.GuestCanLoad = async () => { +MediaAppUIBrowserTest['GuestCanLoad'] = async () => { const guest = queryIFrame(); const app = await driver.waitForElementInGuest('backlight-app', 'tagName'); @@ -145,18 +139,18 @@ }; // Tests that we have localized information in the HTML like title and lang. -MediaAppUIBrowserTest.HasTitleAndLang = async () => { +MediaAppUIBrowserTest['HasTitleAndLang'] = async () => { assertEquals(document.documentElement.lang, 'en'); assertEquals(document.title, 'Gallery'); }; // Tests that regular launch for an image succeeds. -MediaAppUIBrowserTest.LaunchFile = async () => { +MediaAppUIBrowserTest['LaunchFile'] = async () => { await launchWithFiles([await createTestImageFile()]); const result = await driver.waitForElementInGuest('img[src^="blob:"]', 'naturalWidth'); const receivedFiles = await getLoadedFiles(); - const file = receivedFiles[0]; + const file = receivedFiles[0]!; assertEquals(`${TEST_IMAGE_WIDTH}`, result); assertEquals(currentFiles.length, 1); @@ -173,16 +167,22 @@ // the first arguments. // Note: unhandledrejection & onerror tests throw JS Errors regardless and are // tested in media_app_integration_browsertest.cc. -MediaAppUIBrowserTest.ReportsErrorsFromTrustedContext = async () => { +MediaAppUIBrowserTest['ReportsErrorsFromTrustedContext'] = async () => { const originalConsoleError = console.error; - const reportedErrors = []; + // chrome.crashReportPrivate.ErrorInfo. + interface ErrorInfo { + message: string; + stackTrace?: string; + } + const reportedErrors: ErrorInfo[] = []; /** * In tests stub out `chrome.crashReportPrivate.reportError`, check *`reportedErrors` to make sure they are "sent" to the crash reporter. */ function suppressConsoleErrorsForErrorTesting() { - chrome.crashReportPrivate.reportError = function(e) { + (window as any as {chrome: any}).chrome.crashReportPrivate.reportError = + function(e: ErrorInfo) { // Everything should have a non-empty stack. assertEquals(!!e.stackTrace, true); reportedErrors.push(e); @@ -200,12 +200,10 @@ error.name = 'yikes error'; const extraData = {b: 'b'}; - const loop = {}; + const loop: {loop?: {}} = {}; loop.loop = loop; class MySpecialException { - constructor() { - this.loop = loop; - } + aLoop = loop; } console.error('a'); @@ -219,34 +217,34 @@ assertEquals(8, reportedErrors.length); // Test handles console.error(string). - assertEquals('Unexpected: "a", (from console)', reportedErrors[0].message); + assertEquals('Unexpected: "a", (from console)', reportedErrors[0]!.message); // Test handles console.error(Error). assertEquals( 'Error: [yikes error] yikes message, (from console)', - reportedErrors[1].message); + reportedErrors[1]!.message); // Test handles console.error(string, Object). assertEquals( - 'Unexpected: "b"\n{"b":"b"}, (from console)', reportedErrors[2].message); + 'Unexpected: "b"\n{"b":"b"}, (from console)', reportedErrors[2]!.message); // Test handles console.error(Object, Object, Object). assertEquals( 'Object: Unexpected: {"b":"b"}\n{"b":"b"}\n{"b":"b"}, (from console)', - reportedErrors[3].message); + reportedErrors[3]!.message); // Test handles console.error(string, Object, Error, Object). assertEquals( 'Error: [yikes error] yikes message, foo\n{"b":"b"}\n' + '{"e":{"name":"yikes error"}}, (from console)', - reportedErrors[4].message); + reportedErrors[4]!.message); // Test arbitrary classes. assertEquals( 'MySpecialException: Unexpected: <object loop?><object loop?>, ' + '(from console)', - reportedErrors[5].message); + reportedErrors[5]!.message); // Test non-objects. assertEquals( - 'Unexpected: 1\n2\n3\n4\n5, (from console)', reportedErrors[6].message); + 'Unexpected: 1\n2\n3\n4\n5, (from console)', reportedErrors[6]!.message); assertEquals( 'Unexpected: null\nnull\nnull, (from console)', - reportedErrors[7].message); + reportedErrors[7]!.message); // Note: This is not needed i.e. tests pass without this but it is good // practice to reset it since we stub it out for this test. @@ -257,7 +255,7 @@ // interact with it by invoking IPC (deletion) that doesn't re-launch the // MediaApp i.e. doesn't call `launchWithDirectory`, then the rest of the files // in the current directory are loaded in. -MediaAppUIBrowserTest.NonLaunchableIpcAfterFastLoad = async () => { +MediaAppUIBrowserTest['NonLaunchableIpcAfterFastLoad'] = async () => { setSortOrder(SortOrder.A_FIRST); const files = await createMultipleImageFiles(['file1', 'file2', 'file3', 'file4']); @@ -292,7 +290,7 @@ // Tests that we can launch the MediaApp with the selected (first) file, // and re-launch it before all files from the first launch are loaded in. -MediaAppUIBrowserTest.ReLaunchableAfterFastLoad = async () => { +MediaAppUIBrowserTest['ReLaunchableAfterFastLoad'] = async () => { setSortOrder(SortOrder.A_FIRST); const files = await createMultipleImageFiles(['file1', 'file2', 'file3', 'file4']); @@ -308,9 +306,9 @@ await assertSingleFileLaunch(directory, files.length); // Mutate the second file. - directory.files[1].name = 'changed.png'; + directory.files[1]!.name = 'changed.png'; // Relaunch the app with the second file. - await launchWithDirectory(directory, directory.files[1]); + await launchWithDirectory(directory, directory.files[1]!); // Ensure second launch incremented the `globalLaunchNumber`. assertEquals(1, getGlobalLaunchNumber()); @@ -339,32 +337,32 @@ // Focus file (file that the directory was launched with) stays index 0. const lastLoadedFiles = await getLoadedFiles(); - assertEquals('changed.png', lastLoadedFiles[0].name); - assertEquals(loadedFilesSecondLaunch[0].name, lastLoadedFiles[0].name); + assertEquals('changed.png', lastLoadedFiles[0]!.name); + assertEquals(loadedFilesSecondLaunch[0]!.name, lastLoadedFiles[0]!.name); // Focus file in the `FileSystemDirectoryHandle` is at index 1. - assertEquals(directory.files[1].name, lastLoadedFiles[0].name); + assertEquals(directory.files[1]!.name, lastLoadedFiles[0]!.name); }; // Tests that a regular // launch for multiple images succeeds, and the files get // distinct token mappings. -MediaAppUIBrowserTest.MultipleFilesHaveTokens = async () => { +MediaAppUIBrowserTest['MultipleFilesHaveTokens'] = async () => { const directory = await launchWithFiles([ await createTestImageFile(1, 1, 'file1.png'), await createTestImageFile(1, 1, 'file2.png'), ]); assertEquals(currentFiles.length, 2); - assertGE(currentFiles[0].token, 0); - assertGE(currentFiles[1].token, 0); - assertNotEquals(currentFiles[0].token, currentFiles[1].token); - assertEquals(fileHandleForToken(currentFiles[0].token), directory.files[0]); - assertEquals(fileHandleForToken(currentFiles[1].token), directory.files[1]); + assertGE(currentFiles[0]!.token, 0); + assertGE(currentFiles[1]!.token, 0); + assertNotEquals(currentFiles[0]!.token, currentFiles[1]!.token); + assertEquals(fileHandleForToken(currentFiles[0]!.token), directory.files[0]); + assertEquals(fileHandleForToken(currentFiles[1]!.token), directory.files[1]); }; // Tests that a launch with a single audio file selected in the files app loads // only that audio file and not the directory. -MediaAppUIBrowserTest.SingleAudioLaunch = async () => { +MediaAppUIBrowserTest['SingleAudioLaunch'] = async () => { await launchWithFiles([ // Zero-byte audio. It won't load, but should still be added to DOM. new File([], 'audio1.wav', {type: 'audio/wav'}), @@ -376,10 +374,10 @@ // Tests that a launch with multiple files selected in the files app loads only // the files selected. -MediaAppUIBrowserTest.MultipleSelectionLaunch = async () => { +MediaAppUIBrowserTest['MultipleSelectionLaunch'] = async () => { const directoryContents = await createMultipleImageFiles([0, 1, 2, 3]); const selectedIndexes = [1, 3]; - const directory = await launchWithFiles(directoryContents, selectedIndexes); + await launchWithFiles(directoryContents, selectedIndexes); // Expect filenames to be sorted in the default lexicographical order. assertEquals(TEST_ONLY.sortOrder, SortOrder.A_FIRST); @@ -387,7 +385,7 @@ }; // Test that each file type has an icon in light mode. -MediaAppUIBrowserTest.NotifyCurrentFileLight = async () => { +MediaAppUIBrowserTest['NotifyCurrentFileLight'] = async () => { const imageFile = new File([], 'image.png', {type: 'image/png'}); const audioFile = new File([], 'audio.wav', {type: 'audio/wav'}); const videoFile = new File([], 'video.mp4', {type: 'video/mp4'}); @@ -415,7 +413,7 @@ }; // Test that each file type has a corresponding dark icon. -MediaAppUIBrowserTest.NotifyCurrentFileDark = async () => { +MediaAppUIBrowserTest['NotifyCurrentFileDark'] = async () => { const imageFile = new File([], 'image.png', {type: 'image/png'}); const audioFile = new File([], 'audio.wav', {type: 'audio/wav'}); const videoFile = new File([], 'video.mp4', {type: 'video/mp4'}); @@ -441,7 +439,7 @@ }; // Test that the Gallery app icon does not have a dark variant. -MediaAppUIBrowserTest.NotifyCurrentFileAppIconDark = async () => { +MediaAppUIBrowserTest['NotifyCurrentFileAppIconDark'] = async () => { await sendTestMessage({ simple: 'notifyCurrentFile', simpleArgs: {name: undefined, type: undefined}, @@ -452,7 +450,7 @@ }; // Tests that we show error UX when trying to launch an unopenable file. -MediaAppUIBrowserTest.LaunchUnopenableFile = async () => { +MediaAppUIBrowserTest['LaunchUnopenableFile'] = async () => { const mockFileHandle = new FakeFileSystemFileHandle('not_allowed.png', 'image/png'); mockFileHandle.getFileSync = () => { @@ -469,7 +467,7 @@ // Tests that directories that are not navigable do not generate crash reports, // and the focus file still loads. -MediaAppUIBrowserTest.LaunchUnnavigableDirectory = async () => { +MediaAppUIBrowserTest['LaunchUnnavigableDirectory'] = async () => { const focus = new FakeFileSystemFileHandle('focus.png', 'image/png'); const mine = new FakeFileSystemFileHandle('mine.png', 'image/png'); mine.errorToFireOnIterate = new DOMException('boom', 'NotFoundError'); @@ -481,7 +479,7 @@ // Tests that a file that becomes inaccessible after the initial app launch is // ignored on navigation, and shows an error when navigated to itself. -MediaAppUIBrowserTest.NavigateWithUnopenableSibling = async () => { +MediaAppUIBrowserTest['NavigateWithUnopenableSibling'] = async () => { setSortOrder(SortOrder.A_FIRST); const handles = [ fileToFileHandle(await createTestImageFile(111 /* width */, 10, '1.png')), @@ -499,8 +497,8 @@ // Note that if the file is non-null, no "reopen" occurs: launch.js does not // open files a second time after examining siblings for relevance to the // focus file. - assertEquals(currentFiles[2].file, null); - handles[2].getFileSync = () => { + assertEquals(currentFiles[2]!.file, null); + handles[2]!.getFileSync = () => { throw new DOMException( 'Fake NotAllowedError for NavigateToUnopenableSibling test.', 'NotAllowedError'); @@ -536,7 +534,7 @@ // Tests a hypothetical scenario where a file may be deleted and replaced with // an openable directory with the same name while the app is running. -MediaAppUIBrowserTest.FileThatBecomesDirectory = async () => { +MediaAppUIBrowserTest['FileThatBecomesDirectory'] = async () => { await sendTestMessage({suppressCrashReports: true}); const handles = [ fileToFileHandle(await createTestImageFile(111 /* width */, 10, '1.png')), @@ -547,8 +545,8 @@ let result = await waitForImageAndGetWidth('1.png'); assertEquals(await getFileErrors(), ','); - handles[1].kind = 'directory'; - handles[1].getFileSync = () => { + (handles[1] as {kind: string}).kind = 'directory'; + handles[1]!.getFileSync = () => { throw new Error( '(in test) FileThatBecomesDirectory: getFileSync should not be called'); }; @@ -562,14 +560,14 @@ // Tests that chrome://media-app can successfully send a request to open the // feedback dialog and receive a response. -MediaAppUIBrowserTest.CanOpenFeedbackDialog = async () => { +MediaAppUIBrowserTest['CanOpenFeedbackDialog'] = async () => { const result = await mediaAppPageHandler.openFeedbackDialog(); assertEquals(result.errorMessage, null); }; // Tests that video elements in the guest can be full-screened. -MediaAppUIBrowserTest.CanFullscreenVideo = async () => { +MediaAppUIBrowserTest['CanFullscreenVideo'] = async () => { // Remove `overflow: hidden` to work around a spurious DCHECK in Blink // layout. See crbug.com/1052791. Oddly, even though the video is in the guest // iframe document (which also has these styles on its body), it is necessary @@ -593,15 +591,15 @@ // Tests that associated subtitles get not just a handle but a valid open File // upon initial file load. -MediaAppUIBrowserTest.LoadVideoWithSubtitles = async () => { +MediaAppUIBrowserTest['LoadVideoWithSubtitles'] = async () => { // Mock the send message call to prevent actual loading. We just want to see // what would be sent. - let secondMessageSent; - const messageSent = new Promise(resolve => { - guestMessagePipe.sendMessage = (messageId, data) => { + let secondMessageSent!: Promise<{messageId: number, data: {}}>; + const messageSent = new Promise<{messageId: number, data: {}}>(resolve => { + guestMessagePipe.sendMessage = (messageId: number, data: {}) => { resolve({messageId, data}); secondMessageSent = new Promise(resolveAgain => { - guestMessagePipe.sendMessage = (messageId, data) => { + guestMessagePipe.sendMessage = (messageId: number, data: {}) => { resolveAgain({messageId, data}); return Promise.resolve(); }; @@ -625,30 +623,30 @@ // on messge_types.js directly because it's rolled up into launch.js. We // *should* be able to re-export LoadFilesMessage, but that confuses closure // too much. See b/185734620. - let data = /** !LoadFilesMessage */ (message.data); + let data = message.data as LoadFilesMessage; assertEquals(data.files.length, 2); - assertEquals(data.files[0].name, 'zero_byte_video.webm'); - assertNotEquals(data.files[0].file, null); - assertEquals(data.files[1].name, 'zero_byte_video.vtt'); - assertNotEquals(data.files[1].file, null); + assertEquals(data.files[0]!.name, 'zero_byte_video.webm'); + assertNotEquals(data.files[0]!.file, null); + assertEquals(data.files[1]!.name, 'zero_byte_video.vtt'); + assertNotEquals(data.files[1]!.file, null); // The extra files message shouldn't include any of the old files. And the new // file should have a null ref. const secondMessage = await secondMessageSent; assertEquals(secondMessage.messageId, Message.LOAD_EXTRA_FILES); - data = /** !LoadFilesMessage */ (secondMessage.data); + data = secondMessage.data as LoadFilesMessage; assertEquals(data.files.length, 1); - assertEquals(data.files[0].name, 'extra_video.webm'); - assertEquals(data.files[0].file, null); + assertEquals(data.files[0]!.name, 'extra_video.webm'); + assertEquals(data.files[0]!.file, null); }; // Tests the IPC behind the implementation of ReceivedFile.overwriteOriginal() // in the untrusted context. Ensures it correctly updates the file handle owned // by the privileged context. -MediaAppUIBrowserTest.OverwriteOriginalIPC = async () => { +MediaAppUIBrowserTest['OverwriteOriginalIPC'] = async () => { const directory = await launchWithFiles([await createTestImageFile()]); - const handle = directory.files[0]; + const handle = directory.files[0]!; // Write should not be called initially. assertEquals(handle.lastWritable.writes.length, 0); @@ -659,8 +657,8 @@ assertEquals(testResponse.testQueryResult, 'overwriteOriginal resolved'); assertEquals( - testResponse.testQueryResultData['receiverFileName'], 'test_file.png'); - assertEquals(testResponse.testQueryResultData['receiverErrorName'], ''); + testResponse.testQueryResultData!['receiverFileName'], 'test_file.png'); + assertEquals(testResponse.testQueryResultData!['receiverErrorName'], ''); assertEquals(await writeResult.text(), 'Foo'); assertEquals(handle.lastWritable.writes.length, 1); assertDeepEquals( @@ -671,12 +669,12 @@ // check that it's defined and is strictly positive. const loadedFiles = await getLoadedFiles(); assertEquals(loadedFiles.length, 1); - assertGE(loadedFiles[0].lastModified, 1); + assertGE(loadedFiles[0]!.lastModified, 1); }; -MediaAppUIBrowserTest.RejectZeroByteWrites = async () => { +MediaAppUIBrowserTest['RejectZeroByteWrites'] = async () => { const directory = await launchWithFiles([await createTestImageFile()]); - const handle = directory.files[0]; + const handle = directory.files[0]!; const EMPTY_DATA = ''; const message = {overwriteLastFile: EMPTY_DATA}; @@ -692,14 +690,14 @@ // Tests that OverwriteOriginal shows a file picker (and writes to that file) if // the write attempt to the original file fails. -MediaAppUIBrowserTest.OverwriteOriginalPickerFallback = async () => { +MediaAppUIBrowserTest['OverwriteOriginalPickerFallback'] = async () => { const directory = await launchWithFiles([await createTestImageFile()]); - directory.files[0].nextCreateWritableError = + directory.files[0]!.nextCreateWritableError = new DOMException('Fake exception to trigger file picker', 'FakeError'); const pickedFile = new FakeFileSystemFileHandle('pickme.png'); - window.showSaveFilePicker = options => Promise.resolve(pickedFile); + window.showSaveFilePicker = () => Promise.resolve(pickedFile); const message = {overwriteLastFile: 'Foo'}; const testResponse = await sendTestMessage(message); @@ -718,21 +716,21 @@ // Tests that extensions in the `accept` option passed to showSaveFilePicker is // correctly configured when only a MIME type is provided. -MediaAppUIBrowserTest.FilePickerValidateExtension = async () => { +MediaAppUIBrowserTest['FilePickerValidateExtension'] = async () => { const JPG_EXTENSIONS = ['.jpg', '.jpeg', '.jpe', '.jfif', '.jif', '.jfi', '.pjpeg', '.pjp']; - function pick(mimeType) { + function pick(mimeType: string) { return new Promise(resolve => { window.showSaveFilePicker = options => { if (options.types) { assertEquals(!!options.excludeAcceptAllOption, true); - resolve(options.types.map(t => Object.values(t.accept || {}))); + resolve(options.types.map((t: any) => Object.values(t.accept || {}))); } else { assertEquals(!!options.excludeAcceptAllOption, false); resolve(null); } - // The handle is unused in the test, but needed to keep closure happy. - return Promise.resolve(/** @type {!FileSystemFileHandle}*/ (null)); + // The handle is unused in the test, but needed to keep types happy. + return Promise.resolve(null as unknown as FileSystemFileHandle); }; pickWritableFile('foo.foo', mimeType, 0, []); }); @@ -747,9 +745,10 @@ }; // Tests `MessagePipe.sendMessage()` properly propagates errors. -MediaAppUIBrowserTest.CrossContextErrors = async () => { +MediaAppUIBrowserTest['CrossContextErrors'] = async () => { // Prevent the trusted context throwing errors resulting JS errors. - guestMessagePipe.logClientError = error => console.log(JSON.stringify(error)); + guestMessagePipe.logClientError = (error: {}) => + console.log(JSON.stringify(error)); guestMessagePipe.rethrowErrors = false; const directory = await launchWithFiles([await createTestImageFile()]); @@ -761,17 +760,17 @@ error.name = 'NotAllowedError'; const pickedFile = new FakeFileSystemFileHandle(); pickedFile.nextCreateWritableError = error; - window.showSaveFilePicker = options => Promise.resolve(pickedFile); + window.showSaveFilePicker = () => Promise.resolve(pickedFile); - directory.files[0].nextCreateWritableError = + directory.files[0]!.nextCreateWritableError = new DOMException('Fake exception to trigger file picker', 'FakeError'); - let caughtError = {}; + let caughtError!: Error; try { const message = {overwriteLastFile: 'Foo', rethrow: true}; await sendTestMessage(message); - } catch (e) { + } catch (e: any) { caughtError = e; } @@ -781,7 +780,7 @@ // Tests the IPC behind the implementation of ReceivedFile.deleteOriginalFile() // in the untrusted context. -MediaAppUIBrowserTest.DeleteOriginalIPC = async () => { +MediaAppUIBrowserTest['DeleteOriginalIPC'] = async () => { let directory = await launchWithFiles( [await createTestImageFile(1, 1, 'first_file_name.png')]); const testHandle = directory.files[0]; @@ -822,7 +821,8 @@ assertEquals(1, directory.files.length); // Prevent the trusted context throwing errors resulting JS errors. - guestMessagePipe.logClientError = error => console.log(JSON.stringify(error)); + guestMessagePipe.logClientError = (error: {}) => + console.log(JSON.stringify(error)); guestMessagePipe.rethrowErrors = false; // Test it throws an error by simulating a failed directory change. simulateLosingAccessToDirectory(); @@ -838,7 +838,7 @@ // Tests when a file is deleted, the app tries to open the next available file // and reloads with those files. -MediaAppUIBrowserTest.DeletionOpensNextFile = async () => { +MediaAppUIBrowserTest['DeletionOpensNextFile'] = async () => { setSortOrder(SortOrder.A_FIRST); const testFiles = [ await createTestImageFile(1, 1, 'test_file_1.png'), @@ -854,9 +854,9 @@ // Check the app loads all 3 files. let lastLoadedFiles = await getLoadedFiles(); assertEquals(3, lastLoadedFiles.length); - assertEquals('test_file_1.png', lastLoadedFiles[0].name); - assertEquals('test_file_2.png', lastLoadedFiles[1].name); - assertEquals('test_file_3.png', lastLoadedFiles[2].name); + assertEquals('test_file_1.png', lastLoadedFiles[0]!.name); + assertEquals('test_file_2.png', lastLoadedFiles[1]!.name); + assertEquals('test_file_3.png', lastLoadedFiles[2]!.name); // Delete the first file. const messageDelete = {deleteLastFile: true}; @@ -870,11 +870,11 @@ // Check the app reloads the file list with the remaining two files. lastLoadedFiles = await getLoadedFiles(); assertEquals(2, lastLoadedFiles.length); - assertEquals('test_file_2.png', lastLoadedFiles[0].name); - assertEquals('test_file_3.png', lastLoadedFiles[1].name); + assertEquals('test_file_2.png', lastLoadedFiles[0]!.name); + assertEquals('test_file_3.png', lastLoadedFiles[1]!.name); // Navigate to the last file (originally the third file) and delete it - const token = currentFiles[getEntryIndex()].token; + const token = currentFiles[getEntryIndex()]!.token; await sendTestMessage({navigate: {direction: 'next', token}}); testResponse = await sendTestMessage(messageDelete); @@ -887,7 +887,7 @@ // (originally the second file). lastLoadedFiles = await getLoadedFiles(); assertEquals(1, lastLoadedFiles.length); - assertEquals(testFiles[1].name, lastLoadedFiles[0].name); + assertEquals(testFiles[1]!.name, lastLoadedFiles[0]!.name); // Delete the last file, should lead to zero state. testResponse = await sendTestMessage(messageDelete); @@ -901,7 +901,7 @@ // Tests that the app gracefully handles a delete request on a file that's // been deleted or moved. -MediaAppUIBrowserTest.DeleteMissingFile = async () => { +MediaAppUIBrowserTest['DeleteMissingFile'] = async () => { const directory = await launchWithFiles( [await createTestImageFile(1, 1, 'first_file_name.png')]); makeFileNotFound(directory.files[0]); @@ -917,7 +917,7 @@ // Tests that the app gracefully handles a rename request on a file that's // been deleted or moved. -MediaAppUIBrowserTest.RenameMissingFile = async () => { +MediaAppUIBrowserTest['RenameMissingFile'] = async () => { const directory = await launchWithFiles([await createTestImageFile(1, 1, 'file_name.png')]); makeFileNotFound(directory.files[0]); @@ -932,38 +932,36 @@ // Tests the IPC behind the AbstractFile.openFile function to open a file from a // file handle token previously communicated to the untrusted context. -MediaAppUIBrowserTest.OpenAllowedFileIPC = async () => { +MediaAppUIBrowserTest['OpenAllowedFileIPC'] = async () => { await launchWithFiles( [await createTestImageFile(), await createTestImageFile()]); let testResponse = await sendTestMessage({simple: 'getAllFiles'}); - let clientFiles = - /** @type{!Array<!FileSnapshot>} */ (testResponse.testQueryResultData); + let clientFiles: FileSnapshot[] = testResponse.testQueryResultData; // Second file should be a placeholder with zero size. const IMAGE_FILE_SIZE = 1605; - assertEquals(clientFiles[0].size, IMAGE_FILE_SIZE); - assertEquals(clientFiles[1].size, 0); + assertEquals(clientFiles[0]!.size, IMAGE_FILE_SIZE); + assertEquals(clientFiles[1]!.size, 0); testResponse = await sendTestMessage( {simple: 'openFileAtIndex', simpleArgs: {index: 1}}); assertEquals(testResponse.testQueryResult, 'opened and updated'); testResponse = await sendTestMessage({simple: 'getAllFiles'}); - clientFiles = - /** @type{!Array<!FileSnapshot>} */ (testResponse.testQueryResultData); + clientFiles = testResponse.testQueryResultData; // Second file should now be opened and have a valid size. - assertEquals(clientFiles[0].size, IMAGE_FILE_SIZE); - assertEquals(clientFiles[1].size, IMAGE_FILE_SIZE); + assertEquals(clientFiles[0]!.size, IMAGE_FILE_SIZE); + assertEquals(clientFiles[1]!.size, IMAGE_FILE_SIZE); }; // Tests the IPC behind the loadNext and loadPrev functions on the received file // list in the untrusted context. -MediaAppUIBrowserTest.NavigateIPC = async () => { +MediaAppUIBrowserTest['NavigateIPC'] = async () => { await launchWithFiles( [await createTestImageFile(), await createTestImageFile()]); - const fileOneToken = currentFiles[0].token; - const fileTwoToken = currentFiles[1].token; + const fileOneToken = currentFiles[0]!.token; + const fileTwoToken = currentFiles[1]!.token; assertEquals(getEntryIndex(), 0); let result = await sendTestMessage( @@ -985,11 +983,11 @@ // Tests the loadNext and loadPrev functions on the received file list correctly // navigate when they are working with a out of date file list. // Regression test for b/163662946 -MediaAppUIBrowserTest.NavigateOutOfSync = async () => { +MediaAppUIBrowserTest['NavigateOutOfSync'] = async () => { await launchWithFiles( [await createTestImageFile(), await createTestImageFile()]); - const fileOneToken = currentFiles[0].token; - const fileTwoToken = currentFiles[1].token; + const fileOneToken = currentFiles[0]!.token; + const fileTwoToken = currentFiles[1]!.token; // Simulate some operation updating getEntryIndex() without reloading the // media app. @@ -1021,7 +1019,7 @@ // in the untrusted context. This test is integration-y making sure we rename // the focus file and that gets inserted in the right place in `currentFiles` // preserving navigation order. -MediaAppUIBrowserTest.RenameOriginalIPC = async () => { +MediaAppUIBrowserTest['RenameOriginalIPC'] = async () => { const directory = await launchWithFiles([ await createTestImageFile(1, 1, 'file1.png'), await createTestImageFile(1, 1, 'file2.png'), @@ -1034,9 +1032,9 @@ await advance(1); // Test normal rename flow. - const file2Handle = directory.files[getEntryIndex()]; + const file2Handle = directory.files[getEntryIndex()]!; const file2File = file2Handle.getFileSync(); - const file2Token = currentFiles[getEntryIndex()].token; + const file2Token = currentFiles[getEntryIndex()]!.token; let messageRename = {renameLastFile: 'new_file_name.png'}; let testResponse; @@ -1048,38 +1046,38 @@ assertEquals(file2Handle, directory.lastDeleted); // The new file has the right name in the trusted context. assertEquals(directory.files.length, 2); - assertEquals(directory.files[getEntryIndex()].name, 'new_file_name.png'); - assertEquals(currentFiles[getEntryIndex()].handle.name, 'new_file_name.png'); + assertEquals(directory.files[getEntryIndex()]!.name, 'new_file_name.png'); + assertEquals(currentFiles[getEntryIndex()]!.handle.name, 'new_file_name.png'); // The file doesn't need to be opened yet. Wait for a navigation. - assertEquals(currentFiles[getEntryIndex()].file, null); + assertEquals(currentFiles[getEntryIndex()]!.file, null); // The new file has the right name in the untrusted context. testResponse = await sendTestMessage({simple: 'getLastFile'}); - const result = /** @type{!FileSnapshot} */ (testResponse.testQueryResultData); + const result: FileSnapshot = testResponse.testQueryResultData; assertEquals(result.name, 'new_file_name.png'); // The new file uses the same token as the old file. - assertEquals(currentFiles[getEntryIndex()].token, file2Token); + assertEquals(currentFiles[getEntryIndex()]!.token, file2Token); // Check the new file written has the correct data. - const renamedHandle = directory.files[getEntryIndex()]; + const renamedHandle = directory.files[getEntryIndex()]!; const renamedFile = await renamedHandle.getFile(); assertEquals(renamedFile.size, file2File.size); assertEquals(await renamedFile.text(), await file2File.text()); // Check the internal representation (token map & currentFiles) is updated. assertEquals(tokenMap.get(file2Token), renamedHandle); - assertEquals(currentFiles[getEntryIndex()].handle, renamedHandle); + assertEquals(currentFiles[getEntryIndex()]!.handle, renamedHandle); // Check navigation order is preserved. assertEquals(getEntryIndex(), 1); - assertEquals(currentFiles[getEntryIndex()].handle.name, 'new_file_name.png'); - assertEquals(currentFiles[0].handle.name, 'file1.png'); + assertEquals(currentFiles[getEntryIndex()]!.handle.name, 'new_file_name.png'); + assertEquals(currentFiles[0]!.handle.name, 'file1.png'); // Advancing wraps around back to the first file. await advance(1); assertEquals(getEntryIndex(), 0); - assertEquals(currentFiles[getEntryIndex()].handle.name, 'file1.png'); - assertEquals(currentFiles[1].handle.name, 'new_file_name.png'); + assertEquals(currentFiles[getEntryIndex()]!.handle.name, 'file1.png'); + assertEquals(currentFiles[1]!.handle.name, 'new_file_name.png'); // Test renaming when a file with the new name already exists, tries to rename // `file1.png` to `new_file_name.png` which already exists. @@ -1090,13 +1088,13 @@ testResponse.testQueryResult, 'renameOriginalFile resolved file exists'); // No change to the existing file. assertEquals(directory.files.length, 2); - assertEquals(directory.files[getEntryIndex()].name, 'file1.png'); - assertEquals(directory.files[1].name, 'new_file_name.png'); + assertEquals(directory.files[getEntryIndex()]!.name, 'file1.png'); + assertEquals(directory.files[1]!.name, 'new_file_name.png'); // Test renaming when something is out of sync with `currentFiles` and has an // expired token. const expiredToken = tokenGenerator.next().value; - currentFiles[getEntryIndex()].token = expiredToken; + currentFiles[getEntryIndex()]!.token = expiredToken; messageRename = {renameLastFile: 'another_name.png'}; @@ -1106,7 +1104,7 @@ assertEquals( testResponse.testQueryResult, 'renameOriginalFile resolved FILE_NO_LONGER_IN_LAST_OPENED_DIRECTORY'); - assertEquals(currentFiles[getEntryIndex()].handle.name, 'file1.png'); + assertEquals(currentFiles[getEntryIndex()]!.handle.name, 'file1.png'); assertEquals(currentFiles.length, 2); assertEquals(directory.files.length, 2); @@ -1114,7 +1112,8 @@ simulateLosingAccessToDirectory(); // Prevent the trusted context throwing errors resulting JS errors. - guestMessagePipe.logClientError = error => console.log(JSON.stringify(error)); + guestMessagePipe.logClientError = (error: {}) => + console.log(JSON.stringify(error)); guestMessagePipe.rethrowErrors = false; const messageRenameNoOp = {renameLastFile: 'new_file_name_2.png'}; @@ -1130,7 +1129,7 @@ // via trusted user gestures. function mockShowSaveFilePicker() { const newFileHandle = new FakeFileSystemFileHandle(); - const chooseEntries = new Promise(resolve => { + const chooseEntries = new Promise<FilePickerOptions>(resolve => { window.showSaveFilePicker = options => { resolve(options); return Promise.resolve(newFileHandle); @@ -1140,38 +1139,38 @@ } // Tests the IPC behind the requestSaveFile delegate function. -MediaAppUIBrowserTest.RequestSaveFileIPC = async () => { +MediaAppUIBrowserTest['RequestSaveFileIPC'] = async () => { let chooseEntries = mockShowSaveFilePicker(); await launchWithFiles([await createTestImageFile(10, 10)]); // Initially test with accept `empty`. let result = await sendTestMessage({simple: 'requestSaveFile'}); let options = await chooseEntries; - let lastToken = [...tokenMap.keys()].slice(-1)[0]; + let lastToken = `${[...tokenMap.keys()].slice(-1)[0]}`; // Check the token matches to confirm the ReceivedFile returned represents the // new file created on disk. assertMatch(result.testQueryResult, lastToken); assertEquals(options.types.length, 1); - assertEquals(options.types[0].description, 'PNG'); - assertDeepEquals(options.types[0].accept['image/png'], ['.png']); + assertEquals(options.types[0]!.description, 'PNG'); + assertDeepEquals(options.types[0]!.accept['image/png'], ['.png']); chooseEntries = mockShowSaveFilePicker(); result = await sendTestMessage( {simple: 'requestSaveFile', simpleArgs: {accept: ['PDF', 'PNG']}}); options = await chooseEntries; - lastToken = [...tokenMap.keys()].slice(-1)[0]; + lastToken = `${[...tokenMap.keys()].slice(-1)[0]}`; assertMatch(result.testQueryResult, lastToken); assertEquals(options.types.length, 2); - assertEquals(options.types[0].description, 'PDF'); - assertDeepEquals(options.types[0].accept['application/pdf'], ['.pdf']); - assertEquals(options.types[1].description, 'PNG'); - assertDeepEquals(options.types[1].accept['image/png'], ['.png']); + assertEquals(options.types[0]!.description, 'PDF'); + assertDeepEquals(options.types[0]!.accept['application/pdf'], ['.pdf']); + assertEquals(options.types[1]!.description, 'PNG'); + assertDeepEquals(options.types[1]!.accept['image/png'], ['.png']); }; // Tests the IPC behind the getExportFile method. -MediaAppUIBrowserTest.GetExportFileIPC = async () => { +MediaAppUIBrowserTest['GetExportFileIPC'] = async () => { const chooseEntries = mockShowSaveFilePicker(); const directory = await launchWithFiles([await createTestImageFile(10, 10)]); @@ -1181,27 +1180,27 @@ }; const result = await sendTestMessage(message); const options = await chooseEntries; - const lastToken = [...tokenMap.keys()].slice(-1)[0]; + const lastToken = `${[...tokenMap.keys()].slice(-1)[0]}`; assertMatch(result.testQueryResult, lastToken); assertEquals(options.types.length, 3); // Contents and order of the `types` array should correspond. - assertEquals(options.types[0].description, 'PNG'); - assertEquals(options.types[1].description, 'JPG'); - assertEquals(options.types[2].description, 'WEBP'); - assertDeepEquals(options.types[0].accept['image/png'], ['.png']); - assertDeepEquals(options.types[2].accept['image/webp'], ['.webp']); + assertEquals(options.types[0]!.description, 'PNG'); + assertEquals(options.types[1]!.description, 'JPG'); + assertEquals(options.types[2]!.description, 'WEBP'); + assertDeepEquals(options.types[0]!.accept['image/png'], ['.png']); + assertDeepEquals(options.types[2]!.accept['image/webp'], ['.webp']); // jpg has a bunch of extensions. - assertEquals(options.types[1].accept['image/jpeg'].length, 8); + assertEquals(options.types[1]!.accept['image/jpeg']!.length, 8); // The startIn option should be set to the opened file. assertEquals(options.startIn, directory.files[0]); }; // Tests the IPC behind the saveAs function on received files. -MediaAppUIBrowserTest.SaveAsIPC = async () => { +MediaAppUIBrowserTest['SaveAsIPC'] = async () => { // Mock out choose file system entries since it can only be interacted with // via trusted user gestures. const newFileHandle = new FakeFileSystemFileHandle('new_file.jpg'); @@ -1210,7 +1209,7 @@ const directory = await launchWithFiles( [await createTestImageFile(10, 10, 'original_file.jpg')]); - const originalFileToken = currentFiles[0].token; + const originalFileToken = currentFiles[0]!.token; assertEquals(getEntryIndex(), 0); const receivedFilesBefore = await getLoadedFiles(); @@ -1226,33 +1225,34 @@ // Make sure we have created a new file descriptor, and that // the original file is still available. assertEquals(getEntryIndex(), 1); - assertEquals(currentFiles[0].handle, directory.files[0]); - assertEquals(currentFiles[0].handle.name, 'original_file.jpg'); - assertNotEquals(currentFiles[0].token, originalFileToken); - assertEquals(currentFiles[1].handle, newFileHandle); - assertEquals(currentFiles[1].handle.name, 'new_file.jpg'); - assertEquals(currentFiles[1].token, originalFileToken); - assertEquals(tokenMap.get(currentFiles[0].token), currentFiles[0].handle); - assertEquals(tokenMap.get(currentFiles[1].token), currentFiles[1].handle); + assertEquals(currentFiles[0]!.handle, directory.files[0]); + assertEquals(currentFiles[0]!.handle.name, 'original_file.jpg'); + assertNotEquals(currentFiles[0]!.token, originalFileToken); + assertEquals(currentFiles[1]!.handle, newFileHandle); + assertEquals(currentFiles[1]!.handle.name, 'new_file.jpg'); + assertEquals(currentFiles[1]!.token, originalFileToken); + assertEquals(tokenMap.get(currentFiles[0]!.token), currentFiles[0]!.handle); + assertEquals(tokenMap.get(currentFiles[1]!.token), currentFiles[1]!.handle); // Currently, files obtained from a file picker can not be deleted or renamed. // TODO(b/163285659): Try to support delete/rename in this case. For now, we // check that the methods go away so that the UI updates to disable buttons. - assertEquals(receivedFilesBefore[0].hasRename, true); - assertEquals(receivedFilesBefore[0].hasDelete, true); - assertEquals(receivedFilesAfter[0].hasRename, false); - assertEquals(receivedFilesAfter[0].hasDelete, false); + assertEquals(receivedFilesBefore[0]!.hasRename, true); + assertEquals(receivedFilesBefore[0]!.hasDelete, true); + assertEquals(receivedFilesAfter[0]!.hasRename, false); + assertEquals(receivedFilesAfter[0]!.hasDelete, false); // Ensure there's a last modified property on the file after swapping in the // picked file. - assertGE(receivedFilesAfter[0].lastModified, 1); + assertGE(receivedFilesAfter[0]!.lastModified, 1); }; // Tests the error handling behind the saveAs function on received files. -MediaAppUIBrowserTest.SaveAsErrorHandling = async () => { +MediaAppUIBrowserTest['SaveAsErrorHandling'] = async () => { // Prevent the trusted context from throwing errors which cause the test to // fail. - guestMessagePipe.logClientError = error => console.log(JSON.stringify(error)); + guestMessagePipe.logClientError = (error: {}) => + console.log(JSON.stringify(error)); guestMessagePipe.rethrowErrors = false; const newFileHandle = new FakeFileSystemFileHandle('new_file.jpg'); newFileHandle.nextCreateWritableError = @@ -1260,7 +1260,7 @@ window.showSaveFilePicker = () => Promise.resolve(newFileHandle); const directory = await launchWithFiles( [await createTestImageFile(10, 10, 'original_file.jpg')]); - const originalFileToken = currentFiles[0].token; + const originalFileToken = currentFiles[0]!.token; const result = await sendTestMessage({saveAs: 'foo'}); @@ -1268,24 +1268,23 @@ assertEquals( result.testQueryResult, 'saveAs failed Error: FakeError: save-as: Fake exception'); - assertEquals(result.testQueryResultData['filename'], 'original_file.jpg'); + assertEquals(result.testQueryResultData!['filename'], 'original_file.jpg'); assertEquals(getEntryIndex(), 0); assertEquals(currentFiles.length, 1); - assertEquals(currentFiles[0].handle, directory.files[0]); - assertEquals(currentFiles[0].handle.name, 'original_file.jpg'); - assertEquals(currentFiles[0].token, originalFileToken); - assertEquals(tokenMap.get(currentFiles[0].token), currentFiles[0].handle); + assertEquals(currentFiles[0]!.handle, directory.files[0]); + assertEquals(currentFiles[0]!.handle.name, 'original_file.jpg'); + assertEquals(currentFiles[0]!.token, originalFileToken); + assertEquals(tokenMap.get(currentFiles[0]!.token), currentFiles[0]!.handle); }; // Tests the IPC behind the AbstractFileList.openFilesWithFilePicker function to // relaunch the app with a new selection of files from a file picker. -MediaAppUIBrowserTest.OpenFilesWithFilePickerIPC = async () => { +MediaAppUIBrowserTest['OpenFilesWithFilePickerIPC'] = async () => { const pickedFileHandles = [ new FakeFileSystemFileHandle('picked_file1.jpg'), new FakeFileSystemFileHandle('picked_file2.jpg'), ]; - /** @type {!OpenFilePickerOptions|!DraftFilePickerOptions|undefined} */ - let lastPickerOptions; + let lastPickerOptions!: OpenFilePickerOptions; window.showOpenFilePicker = (pickerOptions) => { lastPickerOptions = pickerOptions; return Promise.resolve(pickedFileHandles); @@ -1293,7 +1292,7 @@ const directory = await launchWithFiles( [await createTestImageFile(10, 10, 'original_file.jpg')]); - const simpleArgs = {acceptTypeKeys: ['VIDEO', 'IMAGE']}; + const simpleArgs: any = {acceptTypeKeys: ['VIDEO', 'IMAGE']}; async function openFilesWithFilePickerWithSimpleArgs() { const response = await sendTestMessage({simple: 'openFilesWithFilePicker', simpleArgs}); @@ -1309,16 +1308,15 @@ assertEquals(startIn, directory.files[0]); assertEquals(excludeAcceptAllOption, true); assertEquals(types.length, 2); - assertEquals(types[0].description, 'Video Files'); - assertEquals(types[1].description, 'Image Files'); + assertEquals(types[0]!.description, 'Video Files'); + assertEquals(types[1]!.description, 'Image Files'); testResponse = await sendTestMessage({simple: 'getAllFiles'}); console.log(JSON.stringify(testResponse)); - const clientFiles = - /** @type{!Array<!FileSnapshot>} */ (testResponse.testQueryResultData); + const clientFiles: FileSnapshot[] = testResponse.testQueryResultData; - assertEquals(clientFiles[0].name, 'picked_file1.jpg'); - assertEquals(clientFiles[1].name, 'picked_file2.jpg'); + assertEquals(clientFiles[0]!.name, 'picked_file1.jpg'); + assertEquals(clientFiles[1]!.name, 'picked_file2.jpg'); // Test to handle invalid tokens (b/209342852). These should leave the // `startIn` option unspecified. @@ -1338,9 +1336,9 @@ // Spot-check the ALL_EX_TEXT filter key, which groups all extensions. simpleArgs.acceptTypeKeys = ['ALL_EX_TEXT']; await openFilesWithFilePickerWithSimpleArgs(); - const extensions = lastPickerOptions.types[0].accept['*/*']; + const extensions = lastPickerOptions.types[0]!.accept['*/*']!; assertEquals(lastPickerOptions.types.length, 1); - assertEquals(lastPickerOptions.types[0].description, 'All'); + assertEquals(lastPickerOptions.types[0]!.description, 'All'); assertEquals(extensions.includes('.pdf'), true); assertEquals(extensions.includes('.jpeg'), true); assertEquals(extensions.includes('.avi'), true); @@ -1348,7 +1346,7 @@ assertEquals(extensions.includes('.zip'), false); }; -MediaAppUIBrowserTest.RelatedFiles = async () => { +MediaAppUIBrowserTest['RelatedFiles'] = async () => { setSortOrder(SortOrder.A_FIRST); // These files all have a last modified time of 0 so the order they end up in // is their lexicographical order i.e. `jaypeg.jpg, jiff.gif, matroska.mkv, @@ -1373,32 +1371,32 @@ ]; const directory = await createMockTestDirectory(testFiles); const files = directory.getFilesSync(); - const [html, jpg, gif, emkv, mkv, MKV, ext, other, vtt, txt] = files; + const [html, jpg, gif, _emkv, mkv, MKV, ext, other, vtt, txt] = files; const [webm, avi, y3gp, mpg] = files.slice(10); - await loadFilesWithoutSendingToGuest(directory, mkv); + await loadFilesWithoutSendingToGuest(directory, mkv!); assertFilesToBe([mkv, MKV, vtt, webm, avi, y3gp, mpg, jpg, gif], 'mkv'); - await loadFilesWithoutSendingToGuest(directory, jpg); + await loadFilesWithoutSendingToGuest(directory, jpg!); assertFilesToBe([jpg, gif, mkv, MKV, vtt, webm, avi, y3gp, mpg], 'jpg'); - await loadFilesWithoutSendingToGuest(directory, gif); + await loadFilesWithoutSendingToGuest(directory, gif!); assertFilesToBe([gif, mkv, MKV, vtt, webm, avi, y3gp, mpg, jpg], 'gif'); - await loadFilesWithoutSendingToGuest(directory, webm); + await loadFilesWithoutSendingToGuest(directory, webm!); assertFilesToBe([webm, avi, y3gp, mpg, jpg, gif, mkv, MKV, vtt], 'webm'); - await loadFilesWithoutSendingToGuest(directory, txt); + await loadFilesWithoutSendingToGuest(directory, txt!); assertFilesToBe([txt, other], 'txt'); - await loadFilesWithoutSendingToGuest(directory, html); + await loadFilesWithoutSendingToGuest(directory, html!); assertFilesToBe([html], 'html'); - await loadFilesWithoutSendingToGuest(directory, ext); + await loadFilesWithoutSendingToGuest(directory, ext!); assertFilesToBe([ext], 'ext'); }; -MediaAppUIBrowserTest.SortedFilesByTime = async () => { +MediaAppUIBrowserTest['SortedFilesByTime'] = async () => { setSortOrder(SortOrder.NEWEST_FIRST); // We want the more recent (i.e. higher timestamp) files first. In the case of // equal timestamp, it should sort lexicographically by filename. @@ -1413,14 +1411,14 @@ ]); const files = [...filesInModifiedOrder]; // Mix up files so that we can check they get sorted correctly. - [files[4], files[2], files[3]] = [files[2], files[3], files[4]]; + [files[4], files[2], files[3]] = [files[2]!, files[3]!, files[4]!]; await launchWithFiles(files); assertFilesToBe(filesInModifiedOrder); }; -MediaAppUIBrowserTest.SortedFilesByName = async () => { +MediaAppUIBrowserTest['SortedFilesByName'] = async () => { // A_FIRST should be the default. assertEquals(TEST_ONLY.sortOrder, SortOrder.A_FIRST); // Establish some sample files that match the naming style from the Camera app @@ -1437,7 +1435,7 @@ ]); const files = [...filesInLexicographicOrder]; // Mix up files so that we can check they get sorted correctly. - [files[4], files[2], files[3]] = [files[2], files[3], files[4]]; + [files[4], files[2], files[3]] = [files[2]!, files[3]!, files[4]!]; await launchWithFiles(files); @@ -1447,17 +1445,18 @@ // Tests that getFile is not called on all files in a directory on launch with // default sort order. This is to avoid a series of slow file system api calls // due to b/172529567. -MediaAppUIBrowserTest.GetFileNotCalledOnAllFiles = async () => { +MediaAppUIBrowserTest['GetFileNotCalledOnAllFiles'] = async () => { const handles = [ fileToFileHandle(await createTestImageFile(1, 1, '1.png')), fileToFileHandle(await createTestImageFile(1, 1, '2.png')), fileToFileHandle(await createTestImageFile(1, 1, '3.png')), fileToFileHandle(await createTestImageFile(1, 1, '4.png')), ]; - const getFileCalls = []; + const getFileCalls: string[] = []; for (const handle of handles) { handle.getFileSync = () => { getFileCalls.push(handle.name); + return undefined as unknown as File; // unused. }; } @@ -1472,7 +1471,7 @@ }; // Tests that the guest gets focus automatically on start up. -MediaAppUIBrowserTest.GuestHasFocus = async () => { +MediaAppUIBrowserTest['GuestHasFocus'] = async () => { const guest = queryIFrame(); // By the time this tests runs the iframe should already have been loaded. @@ -1480,7 +1479,7 @@ }; // Check the body element's background color when it is light mode. -MediaAppUIBrowserTest.BodyHasCorrectBackgroundColorInLightMode = () => { +MediaAppUIBrowserTest['BodyHasCorrectBackgroundColorInLightMode'] = () => { const actualBackgroundColor = getComputedStyle(document.body).backgroundColor; assertEquals(actualBackgroundColor, 'rgb(255, 255, 255)'); // White. };
diff --git a/ash/webui/media_app_ui/test/test_api.d.ts b/ash/webui/media_app_ui/test/test_api.d.ts index 8527d8e..e7b7463 100644 --- a/ash/webui/media_app_ui/test/test_api.d.ts +++ b/ash/webui/media_app_ui/test/test_api.d.ts
@@ -19,6 +19,8 @@ interface ChaiJsAsserts { isTrue(value: any): void; isDefined(value: any): void; + equal(lhs: any, rhs: any, message?: string): void; + match(string: string, regex: RegExp, message?: string): void; } interface ChaiJs { @@ -27,3 +29,6 @@ } declare const chai: ChaiJs; + +// Things that become available when dom_testing_helpers.js is injected. +declare function waitForNode(query: string, path?: string[]): Promise<Element>;
diff --git a/ash/webui/media_app_ui/test/test_worker.js b/ash/webui/media_app_ui/test/test_worker.ts similarity index 100% rename from ash/webui/media_app_ui/test/test_worker.js rename to ash/webui/media_app_ui/test/test_worker.ts
diff --git a/base/android/jank_metric_uma_recorder.cc b/base/android/jank_metric_uma_recorder.cc index 5fce95ad..58a2ce46 100644 --- a/base/android/jank_metric_uma_recorder.cc +++ b/base/android/jank_metric_uma_recorder.cc
@@ -31,65 +31,88 @@ const char* GetPerScrollHistogramName(JankScenario scenario, int num_frames, - PerScrollHistogramType type) { + PerScrollHistogramType type, + bool with_scroll_size_suffix) { #define HISTOGRAM_NAME(hist_scenario, hist_type, length) \ "Android.FrameTimelineJank." #hist_scenario "." #hist_type \ "." \ - "PerScroll." #length + "PerScroll" #length if (scenario == JankScenario::WEBVIEW_SCROLLING) { if (type == PerScrollHistogramType::kPercentage) { + if (!with_scroll_size_suffix) { + return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, + /*no suffix*/); + } if (num_frames <= 16) { - return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, Small); + return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, + .Small); } else if (num_frames <= 64) { return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, - Medium); + .Medium); } else { - return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, Large); + return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, + .Large); } } else if (type == PerScrollHistogramType::kMax) { + if (!with_scroll_size_suffix) { + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, /*no suffix*/); + } if (num_frames <= 16) { - return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, Small); + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, .Small); } else if (num_frames <= 64) { - return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, Medium); + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, .Medium); } else { - return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, Large); + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, .Large); } } else { DCHECK_EQ(type, PerScrollHistogramType::kSum); + if (!with_scroll_size_suffix) { + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, /*no suffix*/); + } if (num_frames <= 16) { - return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, Small); + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, .Small); } else if (num_frames <= 64) { - return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, Medium); + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, .Medium); } else { - return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, Large); + return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, .Large); } } } else { DCHECK_EQ(scenario, JankScenario::FEED_SCROLLING); if (type == PerScrollHistogramType::kPercentage) { + if (!with_scroll_size_suffix) { + return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, + /*no suffix*/); + } if (num_frames <= 16) { - return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, Small); + return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, .Small); } else if (num_frames <= 64) { - return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, Medium); + return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, .Medium); } else { - return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, Large); + return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, .Large); } } else if (type == PerScrollHistogramType::kMax) { + if (!with_scroll_size_suffix) { + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, /*no suffix*/); + } if (num_frames <= 16) { - return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, Small); + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, .Small); } else if (num_frames <= 64) { - return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, Medium); + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, .Medium); } else { - return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, Large); + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, .Large); } } else { DCHECK_EQ(type, PerScrollHistogramType::kSum); + if (!with_scroll_size_suffix) { + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, /*no suffix*/); + } if (num_frames <= 16) { - return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, Small); + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, .Small); } else if (num_frames <= 64) { - return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, Medium); + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, .Medium); } else { - return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, Large); + return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, .Large); } } } @@ -133,17 +156,39 @@ scenario != JankScenario::FEED_SCROLLING) { return; } + // Emit non-bucketed per scroll metrics. base::UmaHistogramPercentage( GetPerScrollHistogramName(scenario, num_presented_frames, - PerScrollHistogramType::kPercentage), + PerScrollHistogramType::kPercentage, + /*with_scroll_size_suffix=*/false), delayed_frames_percentage); base::UmaHistogramCustomCounts( GetPerScrollHistogramName(scenario, num_presented_frames, - PerScrollHistogramType::kMax), + PerScrollHistogramType::kMax, + /*with_scroll_size_suffix=*/false), missed_vsyncs_max, kVsyncCountsMin, kVsyncCountsMax, kVsyncCountsBuckets); base::UmaHistogramCustomCounts( GetPerScrollHistogramName(scenario, num_presented_frames, - PerScrollHistogramType::kSum), + PerScrollHistogramType::kSum, + /*with_scroll_size_suffix=*/false), + missed_vsyncs_sum, kVsyncCountsMin, kVsyncCountsMax, kVsyncCountsBuckets); + + // Emit bucketed per scroll metrics where scrolls are divided into three + // buckets Small, Medium, Large. + base::UmaHistogramPercentage( + GetPerScrollHistogramName(scenario, num_presented_frames, + PerScrollHistogramType::kPercentage, + /*with_scroll_size_suffix=*/true), + delayed_frames_percentage); + base::UmaHistogramCustomCounts( + GetPerScrollHistogramName(scenario, num_presented_frames, + PerScrollHistogramType::kMax, + /*with_scroll_size_suffix=*/true), + missed_vsyncs_max, kVsyncCountsMin, kVsyncCountsMax, kVsyncCountsBuckets); + base::UmaHistogramCustomCounts( + GetPerScrollHistogramName(scenario, num_presented_frames, + PerScrollHistogramType::kSum, + /*with_scroll_size_suffix=*/true), missed_vsyncs_sum, kVsyncCountsMin, kVsyncCountsMax, kVsyncCountsBuckets); }
diff --git a/base/android/jank_metric_uma_recorder_unittest.cc b/base/android/jank_metric_uma_recorder_unittest.cc index deb263d..5f4d6e7e 100644 --- a/base/android/jank_metric_uma_recorder_unittest.cc +++ b/base/android/jank_metric_uma_recorder_unittest.cc
@@ -145,17 +145,17 @@ JankMetricUMARecorderPerScrollTests, testing::ValuesIn<ScrollTestCase>({ {JankScenario::WEBVIEW_SCROLLING, "EmitsSmallScrollHistogramInWebview", - 10, "Small"}, + 10, ".Small"}, {JankScenario::WEBVIEW_SCROLLING, "EmitsMediumScrollHistogramInWebview", - 50, "Medium"}, + 50, ".Medium"}, {JankScenario::WEBVIEW_SCROLLING, "EmitsLargeScrollHistogramInWebview", - 65, "Large"}, + 65, ".Large"}, {JankScenario::FEED_SCROLLING, "EmitsSmallScrollHistogramInFeed", 10, - "Small"}, + ".Small"}, {JankScenario::FEED_SCROLLING, "EmitsMediumScrollHistogramInFeed", 50, - "Medium"}, + ".Medium"}, {JankScenario::FEED_SCROLLING, "EmitsLargeScrollHistogramInFeed", 65, - "Large"}, + ".Large"}, }), [](const testing::TestParamInfo< JankMetricUMARecorderPerScrollTests::ParamType>& info) { @@ -202,24 +202,31 @@ std::string delayed_frames_histogram = "Android.FrameTimelineJank." + scenario_name + ".DelayedFramesPercentage." - "PerScroll." + - params.suffix; + "PerScroll"; std::string missed_vsyncs_max_histogram = "Android.FrameTimelineJank." + scenario_name + ".MissedVsyncsMax." - "PerScroll." + - params.suffix; + "PerScroll"; std::string missed_vsyncs_sum_histogram = "Android.FrameTimelineJank." + scenario_name + ".MissedVsyncsSum." - "PerScroll." + - params.suffix; + "PerScroll"; + // Should emit non-bucketed scroll histograms. histogram_tester.ExpectUniqueSample(delayed_frames_histogram, expected_delayed_frames_percentage, 1); histogram_tester.ExpectUniqueSample(missed_vsyncs_max_histogram, expected_vsyncs_max, 1); histogram_tester.ExpectUniqueSample(missed_vsyncs_sum_histogram, expected_vsyncs_sum, 1); + + // Should emit bucketed scroll histograms, suffixed with scroll size like + // Small, Medium, Large. + histogram_tester.ExpectUniqueSample(delayed_frames_histogram + params.suffix, + expected_delayed_frames_percentage, 1); + histogram_tester.ExpectUniqueSample( + missed_vsyncs_max_histogram + params.suffix, expected_vsyncs_max, 1); + histogram_tester.ExpectUniqueSample( + missed_vsyncs_sum_histogram + params.suffix, expected_vsyncs_sum, 1); } } // namespace base::android
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index 25c39ac6..903f93f4 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -1405,10 +1405,10 @@ // For now only run on SkiaRenderer-based compositors. INSTANTIATE_TEST_SUITE_P(, MixedFilterZoomAndOffsetTest, - ::testing::ValuesIn(viz::GetRendererTypesSkiaOnly()), + ::testing::ValuesIn(viz::GetGpuRendererTypes()), ::testing::PrintToStringParamName()); -// viz::GetRendererTypesSkiaOnly() can return an empty list on some platforms. +// viz::GetGpuRendererTypes() can return an empty list on some platforms. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MixedFilterZoomAndOffsetTest); TEST_P(MixedFilterZoomAndOffsetTest, StandardDpi) {
diff --git a/chrome/VERSION b/chrome/VERSION index 347c080..27a82d9 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=122 MINOR=0 -BUILD=6193 +BUILD=6194 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java index dba3bf2a..6989211 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -48,7 +48,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.util.AndroidTaskUtils; import org.chromium.chrome.browser.webapps.WebappLauncherActivity; -import org.chromium.components.browser_ui.media.MediaNotificationUma; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.ui.widget.Toast; @@ -128,8 +127,6 @@ if (mIntent != null && BrowserIntentUtils.getStartupRealtimeMillis(mIntent) == -1) { BrowserIntentUtils.addStartupTimestampsToIntent(mIntent); } - - recordIntentMetrics(); } /** @@ -511,11 +508,6 @@ || !TextUtils.isEmpty(getClientPackageNameFromIdentitySharing()); } - /** Records metrics gleaned from the Intent. */ - private void recordIntentMetrics() { - MediaNotificationUma.recordClickSource(mIntent); - } - private static boolean clearTopIntentsForCustomTabsEnabled(Intent intent) { // The new behavior is important for TWAs, but could potentially affect other clients. // For now we expose this risky change only to TWAs.
diff --git a/chrome/android/profiles/arm.newest.txt b/chrome/android/profiles/arm.newest.txt index 218d550d..3bb3a8e 100644 --- a/chrome/android/profiles/arm.newest.txt +++ b/chrome/android/profiles/arm.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-122.0.6190.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-arm-122.0.6191.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index b9308767..9fca194 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-122.0.6190.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-122.0.6191.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 3f06ff7..6d1937f 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -344,6 +344,10 @@ #include "ui/views/views_switches.h" #endif // defined(TOOLKIT_VIEWS) +#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) +#include "components/unexportable_keys/features.h" // nogncheck +#endif + using flags_ui::FeatureEntry; using flags_ui::kDeprecated; using flags_ui::kOsAndroid; @@ -2548,26 +2552,6 @@ std::size(kAddToHomescreen_UseMessage), nullptr}}; #endif -#if BUILDFLAG(IS_ANDROID) -const FeatureEntry::FeatureParam - kAutofillUseMobileLabelDisambiguationShowAll[] = { - {autofill::features::kAutofillUseMobileLabelDisambiguationParameterName, - autofill::features:: - kAutofillUseMobileLabelDisambiguationParameterShowAll}}; -const FeatureEntry::FeatureParam - kAutofillUseMobileLabelDisambiguationShowOne[] = { - {autofill::features::kAutofillUseMobileLabelDisambiguationParameterName, - autofill::features:: - kAutofillUseMobileLabelDisambiguationParameterShowOne}}; - -const FeatureEntry::FeatureVariation - kAutofillUseMobileLabelDisambiguationVariations[] = { - {"(show all)", kAutofillUseMobileLabelDisambiguationShowAll, - std::size(kAutofillUseMobileLabelDisambiguationShowAll), nullptr}, - {"(show one)", kAutofillUseMobileLabelDisambiguationShowOne, - std::size(kAutofillUseMobileLabelDisambiguationShowOne), nullptr}}; -#endif // BUILDFLAG(IS_ANDROID) - constexpr FeatureEntry::FeatureParam kStorageAccessAPI_WithPrompt[] = { {"storage_access_api_auto_deny_outside_fps", "false"}}; @@ -6405,9 +6389,6 @@ flag_descriptions::kHandwritingLegacyRecognitionName, flag_descriptions::kHandwritingLegacyRecognitionDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kHandwritingLegacyRecognition)}, - {"handwriting-library-dlc", flag_descriptions::kHandwritingLibraryDlcName, - flag_descriptions::kHandwritingLibraryDlcDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kHandwritingLibraryDlc)}, {"language-packs-in-settings", flag_descriptions::kLanguagePacksInSettingsName, flag_descriptions::kLanguagePacksInSettingsDescription, kOsCrOS, @@ -7473,13 +7454,6 @@ flag_descriptions::kAvifGainmapHdrImagesDescription, kOsAll, FEATURE_VALUE_TYPE(blink::features::kAvifGainmapHdrImages)}, - {"autofill-use-improved-label-disambiguation", - flag_descriptions::kAutofillUseImprovedLabelDisambiguationName, - flag_descriptions::kAutofillUseImprovedLabelDisambiguationDescription, - kOsAll, - FEATURE_VALUE_TYPE( - autofill::features::kAutofillUseImprovedLabelDisambiguation)}, - {"file-handling-icons", flag_descriptions::kFileHandlingIconsName, flag_descriptions::kFileHandlingIconsDescription, kOsDesktop, FEATURE_VALUE_TYPE(blink::features::kFileHandlingIcons)}, @@ -7760,17 +7734,6 @@ flag_descriptions::kWebGpuDeveloperFeaturesDescription, kOsAll, SINGLE_VALUE_TYPE(switches::kEnableWebGPUDeveloperFeatures)}, -#if BUILDFLAG(IS_ANDROID) - {"autofill-use-mobile-label-disambiguation", - flag_descriptions::kAutofillUseMobileLabelDisambiguationName, - flag_descriptions::kAutofillUseMobileLabelDisambiguationDescription, - kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE( - autofill::features::kAutofillUseMobileLabelDisambiguation, - kAutofillUseMobileLabelDisambiguationVariations, - "AutofillUseMobileLabelDisambiguation")}, -#endif // BUILDFLAG(IS_ANDROID) - #if BUILDFLAG(IS_CHROMEOS_ASH) {"gesture-properties-dbus-service", flag_descriptions::kEnableGesturePropertiesDBusServiceName, @@ -10783,6 +10746,15 @@ FEATURE_WITH_PARAMS_VALUE_TYPE(switches::kEnableBoundSessionCredentials, kEnableBoundSessionCredentialsVariations, "EnableBoundSessionCredentials")}, + {"enable-bound-session-credentials-software-keys-for-manual-testing", + flag_descriptions:: + kEnableBoundSessionCredentialsSoftwareKeysForManualTestingName, + flag_descriptions:: + kEnableBoundSessionCredentialsSoftwareKeysForManualTestingDescription, + kOsMac | kOsWin | kOsLinux, + FEATURE_VALUE_TYPE( + unexportable_keys:: + kEnableBoundSessionCredentialsSoftwareKeysForManualTesting)}, #endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/accessibility/live_caption/live_caption_automatic_language_download_browsertest.cc b/chrome/browser/accessibility/live_caption/live_caption_automatic_language_download_browsertest.cc index a19cd35..68f89840 100644 --- a/chrome/browser/accessibility/live_caption/live_caption_automatic_language_download_browsertest.cc +++ b/chrome/browser/accessibility/live_caption/live_caption_automatic_language_download_browsertest.cc
@@ -92,20 +92,20 @@ frame_host, "de-de", media::mojom::ConfidenceLevel::kHighlyConfident, media::mojom::AsrSwitchResult::kDefaultNoSwitch); OnLanguageIdentificationEvent( - frame_host, "fr-fr", media::mojom::ConfidenceLevel::kHighlyConfident, + frame_host, "es-es", media::mojom::ConfidenceLevel::kHighlyConfident, media::mojom::AsrSwitchResult::kDefaultNoSwitch); OnLanguageIdentificationEvent( - frame_host, "fr-fr", media::mojom::ConfidenceLevel::kHighlyConfident, + frame_host, "es-es", media::mojom::ConfidenceLevel::kHighlyConfident, media::mojom::AsrSwitchResult::kDefaultNoSwitch); OnLanguageIdentificationEvent( - frame_host, "es-us", media::mojom::ConfidenceLevel::kHighlyConfident, + frame_host, "fr-fr", media::mojom::ConfidenceLevel::kHighlyConfident, media::mojom::AsrSwitchResult::kDefaultNoSwitch); OnLanguageIdentificationEvent( - frame_host, "es-us", media::mojom::ConfidenceLevel::kHighlyConfident, + frame_host, "fr-fr", media::mojom::ConfidenceLevel::kHighlyConfident, media::mojom::AsrSwitchResult::kDefaultNoSwitch); OnLanguageIdentificationEvent( - frame_host, "es-us", media::mojom::ConfidenceLevel::kHighlyConfident, + frame_host, "fr-fr", media::mojom::ConfidenceLevel::kHighlyConfident, media::mojom::AsrSwitchResult::kDefaultNoSwitch); size_t expected_language_pack_count = 2u; @@ -113,10 +113,10 @@ std::set<speech::LanguageCode> installed_languages = GetInstalledLanguages(); ASSERT_EQ(expected_language_pack_count, installed_languages.size()); - // The en-US language pack is downloaded by default. Only the es-ES language + // The en-US language pack is downloaded by default. Only the fr-FR language // pack should be automatically downloaded. ASSERT_TRUE(base::Contains(installed_languages, speech::LanguageCode::kEnUs)); - ASSERT_TRUE(base::Contains(installed_languages, speech::LanguageCode::kEsEs)); + ASSERT_TRUE(base::Contains(installed_languages, speech::LanguageCode::kFrFr)); } } // namespace captions
diff --git a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc index b7cb952..f30baff 100644 --- a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc +++ b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc
@@ -329,8 +329,7 @@ if (language_identification_event_count_ == kLanguageIdentificationEventCountThreshold) { std::optional<speech::SodaLanguagePackComponentConfig> language_config = - speech::GetLanguageComponentConfigMatchingLanguageSubtag( - event->language); + speech::GetLanguageComponentConfig(event->language); if (language_config.has_value() && IsLanguageInstallable(language_config.value().language_name)) {
diff --git a/chrome/browser/apps/link_capturing/DIR_METADATA b/chrome/browser/apps/link_capturing/DIR_METADATA new file mode 100644 index 0000000..2bb73c4 --- /dev/null +++ b/chrome/browser/apps/link_capturing/DIR_METADATA
@@ -0,0 +1,5 @@ +monorail: { + # Use WebAppInstalls as a catch-all component. + # ChromeOS-specific issues should be triaged to Platform>Apps>Foundation. + component: "UI>Browser>WebAppInstalls" +}
diff --git a/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc b/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc index 6d119f3..de47382 100644 --- a/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc +++ b/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc
@@ -63,6 +63,13 @@ #include "content/public/test/test_utils.h" #include "net/http/http_status_code.h" +// TODO(https://crbug.com/1512521): Failing on ASan/Lsan builder on Linux. +#if defined(ADDRESS_SANITIZER) && BUILDFLAG(IS_LINUX) +#define MAYBE_ASAN(x) DISABLED_##x +#else +#define MAYBE_ASAN(x) x +#endif + namespace ash { namespace { @@ -925,7 +932,8 @@ } // FRE explicitly required in VPD, but the state keys are missing. -IN_PROC_BROWSER_TEST_F(AutoEnrollmentNoStateKeys, FREExplicitlyRequired) { +IN_PROC_BROWSER_TEST_F(AutoEnrollmentNoStateKeys, + MAYBE_ASAN(FREExplicitlyRequired)) { SetFRERequiredKey("1"); host()->StartWizard(AutoEnrollmentCheckScreenView::kScreenId); WaitForOobeUI(); @@ -938,7 +946,7 @@ // FRE explicitly required when kCheckEnrollmentKey is set to an invalid value. IN_PROC_BROWSER_TEST_F(AutoEnrollmentNoStateKeys, - FREExplicitlyRequiredInvalid) { + MAYBE_ASAN(FREExplicitlyRequiredInvalid)) { SetFRERequiredKey("anything"); host()->StartWizard(AutoEnrollmentCheckScreenView::kScreenId); WaitForOobeUI(); @@ -958,7 +966,8 @@ // FRE explicitly not required in VPD, so it should not even contact the policy // server. -IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, ExplicitlyNotRequired) { +IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, + MAYBE_ASAN(ExplicitlyNotRequired)) { SetFRERequiredKey("0"); // Should be ignored. @@ -986,7 +995,8 @@ } // FRE is required when VPD is valid and activate date is there. -IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, MachineActivated) { +IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, + MAYBE_ASAN(MachineActivated)) { SetActivateDate("1970-01"); EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse( @@ -1000,7 +1010,7 @@ } // FRE is required when VPD in invalid state. -IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, CorruptedVPD) { +IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, MAYBE_ASAN(CorruptedVPD)) { SetVPDCorrupted(); EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
diff --git a/chrome/browser/ash/login/password_change_browsertest.cc b/chrome/browser/ash/login/password_change_browsertest.cc index 3ccd149..c5bac3e 100644 --- a/chrome/browser/ash/login/password_change_browsertest.cc +++ b/chrome/browser/ash/login/password_change_browsertest.cc
@@ -74,6 +74,11 @@ using AuthOp = FakeUserDataAuthClient::Operation; +bool HasPasswordConfirmationPage() { + return !base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit); +} + } // namespace class PasswordChangeTestBase : public LoginManagerTest { @@ -179,6 +184,12 @@ test_user_info_.auth_config.online_password); test::PasswordChangedSubmitOldPassword(); + if (HasPasswordConfirmationPage()) { + test::CreatePasswordUpdateNoticePageWaiter()->Wait(); + test::PasswordUpdateNoticeExpectDone(); + test::PasswordUpdateNoticeDoneAction(); + } + // User session should start, and whole OOBE screen is expected to be hidden. OobeWindowVisibilityWaiter(false).Wait(); @@ -204,6 +215,12 @@ nullptr, ui::VKEY_RETURN, false /* control */, false /* shift */, false /* alt */, false /* command */)); + if (HasPasswordConfirmationPage()) { + test::CreatePasswordUpdateNoticePageWaiter()->Wait(); + test::PasswordUpdateNoticeExpectDone(); + test::PasswordUpdateNoticeDoneAction(); + } + // User session should start, and whole OOBE screen is expected to be hidden, OobeWindowVisibilityWaiter(false).Wait(); EXPECT_TRUE( @@ -234,6 +251,12 @@ test_user_info_.auth_config.online_password); test::PasswordChangedSubmitOldPassword(); + if (HasPasswordConfirmationPage()) { + test::CreatePasswordUpdateNoticePageWaiter()->Wait(); + test::PasswordUpdateNoticeExpectDone(); + test::PasswordUpdateNoticeDoneAction(); + } + // User session should start, and whole OOBE screen is expected to be hidden. OobeWindowVisibilityWaiter(false).Wait(); login_mixin_.WaitForActiveSession(); @@ -253,10 +276,10 @@ test::LocalDataLossWarningPageWaiter()->Wait(); test::LocalDataLossWarningPageExpectGoBack(); - test::LocalDataLossWarningPageExpectProceed(); + test::LocalDataLossWarningPageExpectRemove(); // Click "Proceed anyway". - test::LocalDataLossWarningPageProceedAction(); + test::LocalDataLossWarningPageRemoveAction(); // With cryptohome recovery we re-create session and re-run onboarding. OobeWindowVisibilityWaiter(true).Wait(); @@ -277,7 +300,8 @@ test::LocalDataLossWarningPageWaiter()->Wait(); test::LocalDataLossWarningPageExpectGoBack(); - test::LocalDataLossWarningPageExpectProceed(); + test::LocalDataLossWarningPageExpectRemove(); + // Go back to old password input by clicking Try Again. test::LocalDataLossWarningPageGoBackAction(); @@ -289,6 +313,12 @@ test_user_info_.auth_config.online_password); test::PasswordChangedSubmitOldPassword(); + if (HasPasswordConfirmationPage()) { + test::CreatePasswordUpdateNoticePageWaiter()->Wait(); + test::PasswordUpdateNoticeExpectDone(); + test::PasswordUpdateNoticeDoneAction(); + } + // User session should start, and whole OOBE screen is expected to be hidden, OobeWindowVisibilityWaiter(false).Wait(); EXPECT_TRUE( @@ -320,8 +350,7 @@ OpenGaiaDialog(test_account_id_); SetGaiaScreenCredentials(test_account_id_, test::kNewPassword); - OobeWindowVisibilityWaiter(true).Wait(); - OobeScreenWaiter(GaiaPasswordChangedView::kScreenId).Wait(); + test::CreateOldPasswordEnterPageWaiter()->Wait(); } class PasswordChangeTokenCheck : public PasswordChangeTest {
diff --git a/chrome/browser/ash/login/screens/osauth/apply_online_password_screen.cc b/chrome/browser/ash/login/screens/osauth/apply_online_password_screen.cc index 7ecdca0..0d16f8c0 100644 --- a/chrome/browser/ash/login/screens/osauth/apply_online_password_screen.cc +++ b/chrome/browser/ash/login/screens/osauth/apply_online_password_screen.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ash/login/screens/osauth/apply_online_password_screen.h" #include "ash/constants/ash_features.h" +#include "base/check.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ash/login/quick_unlock/quick_unlock_factory.h" @@ -64,14 +65,14 @@ } bool ApplyOnlinePasswordScreen::MaybeSkip(WizardContext& wizard_context) { - CHECK(features::AreLocalPasswordsEnabledForConsumers()); return false; } void ApplyOnlinePasswordScreen::InspectContext(UserContext* user_context) { if (!user_context) { LOG(ERROR) << "Session expired while waiting for user's decision"; - exit_callback_.Run(Result::kSuccess); + context()->osauth_error = WizardContext::OSAuthErrorKind::kFatal; + exit_callback_.Run(Result::kError); return; } CHECK(user_context->HasAuthFactorsConfiguration()); @@ -90,10 +91,22 @@ quick_unlock::QuickUnlockFactory::GetDelegate(), g_browser_process->local_state()); - password_factor_editor.SetOnlinePassword( - GetToken(), online_password_.value().value(), - base::BindOnce(&ApplyOnlinePasswordScreen::OnOnlinePasswordSet, - weak_ptr_factory_.GetWeakPtr())); + if (context()->knowledge_factor_setup.auth_setup_flow == + WizardContext::AuthChangeFlow::kInitialSetup) { + CHECK(!auth_factors_config_.HasConfiguredFactor( + cryptohome::AuthFactorType::kPassword)); + password_factor_editor.SetOnlinePassword( + GetToken(), online_password_.value().value(), + base::BindOnce(&ApplyOnlinePasswordScreen::OnOnlinePasswordSet, + weak_ptr_factory_.GetWeakPtr())); + } else { + CHECK(auth_factors_config_.HasConfiguredFactor( + cryptohome::AuthFactorType::kPassword)); + password_factor_editor.UpdateOnlinePassword( + GetToken(), online_password_.value().value(), + base::BindOnce(&ApplyOnlinePasswordScreen::OnOnlinePasswordSet, + weak_ptr_factory_.GetWeakPtr())); + } } void ApplyOnlinePasswordScreen::OnOnlinePasswordSet( @@ -103,6 +116,8 @@ exit_callback_.Run(Result::kError); LOG(ERROR) << "Could not set online password"; } else { + context()->knowledge_factor_setup.modified_factors.Put( + AshAuthFactor::kGaiaPassword); exit_callback_.Run(Result::kSuccess); } }
diff --git a/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.cc b/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.cc index 83eaa66..df04f7c 100644 --- a/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.cc +++ b/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.h" #include "ash/constants/ash_features.h" +#include "base/check.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ash/login/reauth_stats.h" #include "chrome/browser/ash/login/wizard_context.h" @@ -12,6 +13,10 @@ #include "chrome/browser/ui/webui/ash/login/cryptohome_recovery_screen_handler.h" #include "chromeos/ash/components/cryptohome/cryptohome_parameters.h" #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h" +#include "chromeos/ash/components/login/auth/public/auth_factors_configuration.h" +#include "chromeos/ash/components/login/auth/public/user_context.h" +#include "chromeos/ash/components/osauth/public/auth_session_storage.h" +#include "chromeos/ash/services/auth_factor_config/auth_factor_config_utils.h" #include "components/user_manager/user_manager.h" namespace { @@ -31,20 +36,26 @@ // static std::string CryptohomeRecoveryScreen::GetResultString(Result result) { switch (result) { - case Result::kSucceeded: + case Result::kObsoleteSucceeded: return "Succeeded"; case Result::kGaiaLogin: return "GaiaLogin"; - case Result::kManualRecovery: + case Result::kObsoleteManualRecovery: return "ManualRecovery"; - case Result::kRetry: + case Result::kObsoleteRetry: return "Retry"; - case Result::kNoRecoveryFactor: + case Result::kObsoleteNoRecoveryFactor: return "NoRecoveryFactor"; - case Result::kNotApplicable: - return BaseScreen::kNotApplicable; - case Result::kTimeout: + case Result::kObsoleteTimeout: return "Timeout"; + case Result::kAuthenticated: + return "Authenticated"; + case Result::kError: + return "Error"; + case Result::kFallbackLocal: + return "FallbackLocal"; + case Result::kFallbackOnline: + return "FallbackOnline"; } } @@ -77,15 +88,15 @@ void CryptohomeRecoveryScreen::OnUserAction(const base::Value::List& args) { const std::string& action_id = args[0].GetString(); if (action_id == kUserActionDone) { - exit_callback_.Run(Result::kSucceeded); + exit_callback_.Run(Result::kObsoleteSucceeded); } else if (action_id == kUserActionRetry) { // TODO(b/257073746): We probably want to differentiate between retry with // or without login. RecordReauthReason(context()->user_context->GetAccountId(), ReauthReason::kCryptohomeRecovery); - exit_callback_.Run(Result::kRetry); + exit_callback_.Run(Result::kObsoleteRetry); } else if (action_id == kUserActionEnterOldPassword) { - exit_callback_.Run(Result::kManualRecovery); + exit_callback_.Run(Result::kObsoleteManualRecovery); } else if (action_id == kUserActionReauth) { exit_callback_.Run(Result::kGaiaLogin); } else { @@ -100,7 +111,13 @@ LOG(ERROR) << "Failed to get auth factors configuration, code " << error->get_cryptohome_code(); context()->user_context = std::move(user_context); - view_->OnRecoveryFailed(); + if (base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit)) { + view_->OnRecoveryFailed(); + return; + } + context()->osauth_error = WizardContext::OSAuthErrorKind::kFatal; + exit_callback_.Run(Result::kError); return; } @@ -109,20 +126,28 @@ config.HasConfiguredFactor(cryptohome::AuthFactorType::kRecovery); if (is_configured) { if (user_context->GetReauthProofToken().empty()) { + auto account_id = user_context->GetAccountId(); + context()->user_context = std::move(user_context); if (was_reauth_proof_token_missing_) { LOG(ERROR) << "Reauth proof token is still missing after the second attempt"; - view_->OnRecoveryFailed(); + if (base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit)) { + view_->OnRecoveryFailed(); + return; + } + context()->osauth_error = WizardContext::OSAuthErrorKind::kFatal; + exit_callback_.Run(Result::kError); + return; } else { LOG(WARNING) << "Reauth proof token is not present"; was_reauth_proof_token_missing_ = true; - RecordReauthReason(user_context->GetAccountId(), - ReauthReason::kCryptohomeRecovery); + RecordReauthReason(account_id, ReauthReason::kCryptohomeRecovery); view_->ShowReauthNotification(); + return; } - context()->user_context = std::move(user_context); - return; } + CHECK(user_context->HasAuthFactorsConfiguration()); recovery_performer_ = std::make_unique<CryptohomeRecoveryPerformer>( UserDataAuthClient::Get(), g_browser_process->shared_url_loader_factory()); @@ -131,8 +156,27 @@ base::BindOnce(&CryptohomeRecoveryScreen::OnAuthenticateWithRecovery, weak_ptr_factory_.GetWeakPtr())); } else { + if (base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit)) { + context()->user_context = std::move(user_context); + exit_callback_.Run(Result::kObsoleteNoRecoveryFactor); + return; + } + CHECK(user_context->HasAuthFactorsConfiguration()); + const auto& auth_config = user_context->GetAuthFactorsConfiguration(); + + bool has_online_password = false; + if (auth_config.HasConfiguredFactor( + cryptohome::AuthFactorType::kPassword)) { + has_online_password = auth::IsGaiaPassword( + *auth_config.FindFactorByType(cryptohome::AuthFactorType::kPassword)); + } context()->user_context = std::move(user_context); - exit_callback_.Run(Result::kNoRecoveryFactor); + if (has_online_password) { + exit_callback_.Run(Result::kFallbackOnline); + } else { + exit_callback_.Run(Result::kFallbackLocal); + } } } @@ -143,7 +187,14 @@ LOG(ERROR) << "Failed to authenticate with recovery, " << error->ToDebugString(); context()->user_context = std::move(user_context); - view_->OnRecoveryFailed(); + if (base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit)) { + view_->OnRecoveryFailed(); + return; + } + context()->osauth_error = + WizardContext::OSAuthErrorKind::kRecoveryAuthenticationFailed; + exit_callback_.Run(Result::kError); return; } @@ -159,7 +210,23 @@ if (error.has_value()) { LOG(ERROR) << "Failed to rotate recovery factor, code " << error->get_cryptohome_code(); - // TODO(b/289472295): handle failure scenario. + context()->extra_factors_token = + ash::AuthSessionStorage::Get()->Store(std::move(user_context)); + context()->osauth_error = + WizardContext::OSAuthErrorKind::kRecoveryRotationFailed; + exit_callback_.Run(Result::kError); + return; + } + + if (!base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit)) { + // Get AuthFactorsConfiguration again, as it was cleared after + // rotation. + auth_factor_editor_.GetAuthFactorsConfiguration( + std::move(user_context), + base::BindOnce(&CryptohomeRecoveryScreen::OnRefreshFactorsConfiguration, + weak_ptr_factory_.GetWeakPtr())); + return; } std::string key_label; @@ -184,6 +251,22 @@ weak_ptr_factory_.GetWeakPtr())); } +void CryptohomeRecoveryScreen::OnRefreshFactorsConfiguration( + std::unique_ptr<UserContext> user_context, + absl::optional<AuthenticationError> error) { + if (error.has_value()) { + LOG(ERROR) << "Failed to get auth factors configuration, code " + << error->get_cryptohome_code(); + context()->user_context = std::move(user_context); + context()->osauth_error = WizardContext::OSAuthErrorKind::kFatal; + exit_callback_.Run(Result::kError); + return; + } + context()->extra_factors_token = + ash::AuthSessionStorage::Get()->Store(std::move(user_context)); + exit_callback_.Run(Result::kAuthenticated); +} + void CryptohomeRecoveryScreen::OnReplaceContextKey( std::unique_ptr<UserContext> user_context, std::optional<AuthenticationError> error) { @@ -210,7 +293,7 @@ void CryptohomeRecoveryScreen::OnAuthSessionExpired() { LOG(WARNING) << "Exiting due to expired Auth Session."; - exit_callback_.Run(Result::kTimeout); + exit_callback_.Run(Result::kObsoleteTimeout); } } // namespace ash
diff --git a/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.h b/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.h index 1e3efec7..aebf6bec 100644 --- a/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.h +++ b/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_ASH_LOGIN_SCREENS_OSAUTH_CRYPTOHOME_RECOVERY_SCREEN_H_ #define CHROME_BROWSER_ASH_LOGIN_SCREENS_OSAUTH_CRYPTOHOME_RECOVERY_SCREEN_H_ +#include <memory> + #include "base/functional/callback.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" @@ -13,6 +15,7 @@ #include "chromeos/ash/components/login/auth/public/user_context.h" #include "chromeos/ash/components/login/auth/recovery/cryptohome_recovery_performer.h" #include "components/account_id/account_id.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace ash { @@ -23,13 +26,17 @@ public: using TView = CryptohomeRecoveryScreenView; enum class Result { - kSucceeded, + kObsoleteSucceeded, + kObsoleteManualRecovery, + kObsoleteRetry, + kObsoleteNoRecoveryFactor, + kObsoleteTimeout, + kGaiaLogin, - kManualRecovery, - kRetry, - kNoRecoveryFactor, - kNotApplicable, - kTimeout, + kAuthenticated, + kError, + kFallbackOnline, + kFallbackLocal }; static std::string GetResultString(Result result); using ScreenExitCallback = base::RepeatingCallback<void(Result result)>; @@ -66,6 +73,9 @@ std::optional<AuthenticationError> error); void OnAuthSessionExpired(); + void OnRefreshFactorsConfiguration(std::unique_ptr<UserContext> user_context, + absl::optional<AuthenticationError> error); + std::unique_ptr<base::OneShotTimer> expiration_timer_; AuthFactorEditor auth_factor_editor_; std::unique_ptr<CryptohomeRecoveryPerformer> recovery_performer_;
diff --git a/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen_browsertest.cc b/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen_browsertest.cc index 558755a..0b56422d 100644 --- a/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen_browsertest.cc
@@ -4,9 +4,11 @@ #include "chrome/browser/ash/login/screens/osauth/cryptohome_recovery_setup_screen.h" +#include "ash/constants/ash_features.h" #include "ash/public/cpp/login_screen_test_api.h" #include "base/run_loop.h" #include "base/test/test_future.h" +#include "chrome/browser/ash/login/test/auth_ui_utils.h" #include "chrome/browser/ash/login/test/cryptohome_mixin.h" #include "chrome/browser/ash/login/test/fake_recovery_service_mixin.h" #include "chrome/browser/ash/login/test/login_manager_mixin.h" @@ -17,6 +19,7 @@ #include "chrome/browser/ash/login/ui/login_display_host.h" #include "chrome/browser/ash/login/wizard_controller.h" #include "chrome/browser/ui/webui/ash/login/cryptohome_recovery_screen_handler.h" +#include "chrome/browser/ui/webui/ash/login/enter_old_password_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/gaia_password_changed_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/gaia_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h" @@ -30,17 +33,17 @@ namespace { -const test::UIPath kSuccessStep = {"cryptohome-recovery", "successDialog"}; -const test::UIPath kErrorStep = {"cryptohome-recovery", "errorDialog"}; const test::UIPath kReauthNotificationStep = {"cryptohome-recovery", "reauthNotificationDialog"}; -const test::UIPath kDoneButton = {"cryptohome-recovery", "doneButton"}; -const test::UIPath kManualRecoveryButton = {"cryptohome-recovery", - "manualRecoveryButton"}; const test::UIPath kRetryButton = {"cryptohome-recovery", "retryButton"}; const test::UIPath kReauthButton = {"cryptohome-recovery", "reauthButton"}; const char kNewPassword[] = "new user password"; + +bool IsOldFlow() { + return base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit); +} } // namespace class CryptohomeRecoveryScreenTestBase : public OobeBaseTest { @@ -202,12 +205,20 @@ SetUpExitCallback(); SetGaiaScreenCredentials(test_user_.account_id, kNewPassword); - OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kSuccessStep)->Wait(); - test::OobeJS().ClickOnPath(kDoneButton); + if (!IsOldFlow()) { + WaitForScreenExit(); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kAuthenticated); + } - WaitForScreenExit(); - EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kSucceeded); + test::RecoveryPasswordUpdatedPageWaiter()->Wait(); + test::RecoveryPasswordUpdatedProceedAction(); + + if (IsOldFlow()) { + WaitForScreenExit(); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteSucceeded); + } OobeWindowVisibilityWaiter(false).Wait(); login_manager_mixin_.WaitForActiveSession(); @@ -232,9 +243,15 @@ OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); WaitForScreenExit(); - EXPECT_EQ(result_.value(), - CryptohomeRecoveryScreen::Result::kNoRecoveryFactor); - OobeScreenWaiter(GaiaPasswordChangedView::kScreenId).Wait(); + if (IsOldFlow()) { + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteNoRecoveryFactor); + OobeScreenWaiter(GaiaPasswordChangedView::kScreenId).Wait(); + } else { + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kFallbackOnline); + OobeScreenWaiter(EnterOldPasswordScreenView::kScreenId).Wait(); + } EXPECT_FALSE(IsMounted()); } @@ -249,18 +266,30 @@ SetUpExitCallback(); SetGaiaScreenCredentials(test_user_.account_id, kNewPassword); - OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kErrorStep)->Wait(); - test::OobeJS().ClickOnPath(kManualRecoveryButton); + if (IsOldFlow()) { + test::RecoveryErrorPageWaiter()->Wait(); + test::RecoveryErrorExpectFallback(); + test::RecoveryErrorFallbackAction(); - WaitForScreenExit(); - EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kManualRecovery); - OobeScreenWaiter(GaiaPasswordChangedView::kScreenId).Wait(); + WaitForScreenExit(); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteManualRecovery); + } else { + WaitForScreenExit(); + EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kError); + } + test::CreateOldPasswordEnterPageWaiter()->Wait(); EXPECT_FALSE(IsMounted()); } // Verifies that we could retry when there is error during recovery. IN_PROC_BROWSER_TEST_F(CryptohomeRecoveryScreenTest, RetryAfterError) { + // Ignore this test after Recovery screen split, it became responsibility + // of another screen. + if (!IsOldFlow()) { + return; + } + SetupFakeGaia(test_user_); fake_recovery_service_.SetErrorResponse("/v1/cryptorecovery", net::HTTP_BAD_REQUEST); @@ -269,24 +298,23 @@ SetUpExitCallback(); SetGaiaScreenCredentials(test_user_.account_id, kNewPassword); - OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kErrorStep)->Wait(); + test::RecoveryErrorPageWaiter()->Wait(); test::OobeJS().ClickOnPath(kRetryButton); WaitForScreenExit(); - EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kRetry); + EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kObsoleteRetry); fake_recovery_service_.SetErrorResponse("/v1/cryptorecovery", net::HTTP_OK); OobeScreenWaiter(GaiaView::kScreenId).Wait(); SetGaiaScreenCredentials(test_user_.account_id, kNewPassword); - OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kSuccessStep)->Wait(); - test::OobeJS().ClickOnPath(kDoneButton); + test::RecoveryPasswordUpdatedPageWaiter()->Wait(); + test::RecoveryPasswordUpdatedProceedAction(); WaitForScreenExit(); - EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kSucceeded); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteSucceeded); OobeWindowVisibilityWaiter(false).Wait(); login_manager_mixin_.WaitForActiveSession(); @@ -297,6 +325,11 @@ // when password change is detected. IN_PROC_BROWSER_TEST_F(CryptohomeRecoveryScreenTest, MissingReauthTokenDuringRecovery) { + // Ignore this test after Recovery screen split, logic responsibility + // of another test. + if (!IsOldFlow()) { + return; + } SetupFakeGaia(test_user_); // Entering the add person flow with an existing account. Reauth token was not @@ -319,12 +352,12 @@ OobeScreenWaiter(GaiaView::kScreenId).Wait(); SetGaiaScreenCredentials(test_user_.account_id, kNewPassword); - OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kSuccessStep)->Wait(); - test::OobeJS().ClickOnPath(kDoneButton); + test::RecoveryPasswordUpdatedPageWaiter()->Wait(); + test::RecoveryPasswordUpdatedProceedAction(); WaitForScreenExit(); - EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kSucceeded); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteSucceeded); OobeWindowVisibilityWaiter(false).Wait(); login_manager_mixin_.WaitForActiveSession(); @@ -333,6 +366,11 @@ // Recovery is cancelled after timeout. IN_PROC_BROWSER_TEST_F(CryptohomeRecoveryScreenTest, CancelledOnTimeout) { + // Ignore this test after Recovery screen split, it became responsibility + // of another screen. + if (!IsOldFlow()) { + return; + } SetupFakeGaia(test_user_); OpenGaiaDialog(test_user_.account_id); @@ -343,12 +381,12 @@ SetUpExitCallback(); SetGaiaScreenCredentials(test_user_.account_id, kNewPassword); - OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kSuccessStep)->Wait(); + test::RecoveryPasswordUpdatedPageWaiter()->Wait(); ASSERT_TRUE(FireExpirationTimer()); WaitForScreenExit(); - EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kTimeout); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteTimeout); EXPECT_FALSE(LoginScreenTestApi::IsOobeDialogVisible()); EXPECT_FALSE(IsMounted()); } @@ -403,12 +441,20 @@ SetUpExitCallback(); SetGaiaScreenCredentials(test_user_.account_id, kNewPassword); - OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kSuccessStep)->Wait(); - test::OobeJS().ClickOnPath(kDoneButton); + if (!IsOldFlow()) { + WaitForScreenExit(); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kAuthenticated); + } - WaitForScreenExit(); - EXPECT_EQ(result_.value(), CryptohomeRecoveryScreen::Result::kSucceeded); + test::RecoveryPasswordUpdatedPageWaiter()->Wait(); + test::RecoveryPasswordUpdatedProceedAction(); + + if (IsOldFlow()) { + WaitForScreenExit(); + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteSucceeded); + } OobeWindowVisibilityWaiter(false).Wait(); login_manager_mixin_.WaitForActiveSession(); @@ -432,9 +478,15 @@ OobeScreenWaiter(CryptohomeRecoveryScreenView::kScreenId).Wait(); WaitForScreenExit(); - EXPECT_EQ(result_.value(), - CryptohomeRecoveryScreen::Result::kNoRecoveryFactor); - OobeScreenWaiter(GaiaPasswordChangedView::kScreenId).Wait(); + if (IsOldFlow()) { + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kObsoleteNoRecoveryFactor); + OobeScreenWaiter(GaiaPasswordChangedView::kScreenId).Wait(); + } else { + EXPECT_EQ(result_.value(), + CryptohomeRecoveryScreen::Result::kFallbackOnline); + OobeScreenWaiter(EnterOldPasswordScreenView::kScreenId).Wait(); + } } } // namespace ash
diff --git a/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.cc b/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.cc index bf8d4ec..339f644 100644 --- a/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.cc +++ b/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.cc
@@ -34,8 +34,6 @@ return "CryptohomeError"; case Result::kAuthenticated: return "Authenticated"; - case Result::kNotApplicable: - return BaseScreen::kNotApplicable; } } @@ -89,13 +87,14 @@ std::unique_ptr<UserContext> user_context, std::optional<AuthenticationError> error) { if (error.has_value()) { + context()->user_context = std::move(user_context); if (cryptohome::ErrorMatches( error->get_cryptohome_code(), user_data_auth::CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED)) { - context()->user_context = std::move(user_context); view_->ShowWrongPasswordError(); return; } + context()->osauth_error = WizardContext::OSAuthErrorKind::kFatal; exit_callback_.Run(Result::kCryptohomeError); return; }
diff --git a/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.h b/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.h index f973eca..c945f4a6 100644 --- a/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.h +++ b/chrome/browser/ash/login/screens/osauth/enter_old_password_screen.h
@@ -27,7 +27,6 @@ kForgotOldPassword, kCryptohomeError, kAuthenticated, - kNotApplicable, }; static std::string GetResultString(Result result);
diff --git a/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.cc b/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.cc index a3f70f9e..b486603 100644 --- a/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.cc +++ b/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.cc
@@ -40,7 +40,9 @@ switch (result) { case Result::kRemoveUser: return "removeUser"; - case Result::kBack: + case Result::kBackToLocalAuth: + return "Back"; + case Result::kBackToOnlineAuth: return "Back"; case Result::kCryptohomeError: return "CryptohomeError"; @@ -61,8 +63,11 @@ LocalDataLossWarningScreen::~LocalDataLossWarningScreen() = default; void LocalDataLossWarningScreen::ShowImpl() { + bool can_go_back = context()->knowledge_factor_setup.data_loss_back_option != + WizardContext::DataLossBackOptions::kNone; view_->Show(isOwner(context()->user_context->GetAccountId()), - context()->user_context->GetAccountId().GetUserEmail(), true); + context()->user_context->GetAccountId().GetUserEmail(), + can_go_back); } void LocalDataLossWarningScreen::OnUserAction(const base::Value::List& args) { @@ -81,8 +86,17 @@ SessionManagerClient::Get()->StartDeviceWipe(base::DoNothing()); return; } else if (action_id == kUserActionBack) { - exit_callback_.Run(Result::kBack); - return; + switch (context()->knowledge_factor_setup.data_loss_back_option) { + case WizardContext::DataLossBackOptions::kNone: + NOTREACHED() << "Back button should not be shown"; + return; + case WizardContext::DataLossBackOptions::kBackToOnlineAuth: + exit_callback_.Run(Result::kBackToOnlineAuth); + return; + case WizardContext::DataLossBackOptions::kBackToLocalAuth: + exit_callback_.Run(Result::kBackToLocalAuth); + return; + } } else if (action_id == kUserActionCancel) { exit_callback_.Run(Result::kCancel); return; @@ -96,7 +110,7 @@ context()->user_context = std::move(user_context); if (error.has_value()) { LOGIN_LOG(ERROR) << "Failed to remove user home directory"; - // TODO(b/239420684): Send an error to the UI. + context()->osauth_error = WizardContext::OSAuthErrorKind::kFatal; exit_callback_.Run(Result::kCryptohomeError); return; } @@ -113,9 +127,12 @@ // related to cryptohome state. context()->user_context->ResetAuthSessionIds(); context()->user_context->ClearAuthFactorsConfiguration(); + // Move online password back so that it can be used as key. // See `ShowImpl()` to see where it was stored. - context()->user_context->ReuseReplacementKey(); + if (context()->user_context->HasReplacementKey()) { + context()->user_context->ReuseReplacementKey(); + } exit_callback_.Run(Result::kRemoveUser); }
diff --git a/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.h b/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.h index 4e27908..6f95ddb0 100644 --- a/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.h +++ b/chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.h
@@ -24,7 +24,8 @@ enum class Result { kRemoveUser, - kBack, + kBackToOnlineAuth, + kBackToLocalAuth, kCryptohomeError, kCancel, };
diff --git a/chrome/browser/ash/login/screens/osauth/osauth_error_screen.cc b/chrome/browser/ash/login/screens/osauth/osauth_error_screen.cc index 29ab937..de4cc58 100644 --- a/chrome/browser/ash/login/screens/osauth/osauth_error_screen.cc +++ b/chrome/browser/ash/login/screens/osauth/osauth_error_screen.cc
@@ -16,7 +16,10 @@ #include "chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.h" #include "chrome/browser/ash/login/wizard_context.h" #include "chrome/browser/ui/webui/ash/login/osauth/osauth_error_screen_handler.h" +#include "chromeos/ash/components/login/auth/public/auth_factors_configuration.h" +#include "chromeos/ash/components/login/auth/public/user_context.h" #include "chromeos/ash/components/osauth/public/auth_session_storage.h" +#include "chromeos/ash/services/auth_factor_config/auth_factor_config_utils.h" namespace ash { namespace { @@ -30,6 +33,12 @@ switch (result) { case Result::kAbortSignin: return "AbortSignin"; + case Result::kFallbackOnline: + return "FallbackOnline"; + case Result::kFallbackLocal: + return "FallbackLocal"; + case Result::kProceedAuthenticated: + return "ProceedAuthenticated"; } } @@ -47,6 +56,35 @@ return; } CHECK(context()->osauth_error.has_value()); + if (context()->osauth_error.value() == + WizardContext::OSAuthErrorKind::kRecoveryRotationFailed) { + // We don't have UI strings now, so just exit. + exit_callback_.Run(Result::kProceedAuthenticated); + return; + } + if (context()->osauth_error.value() == + WizardContext::OSAuthErrorKind::kRecoveryAuthenticationFailed) { + // We don't have UI strings now, so just pick right factor and exit. + CHECK(context()->user_context); + CHECK(context()->user_context->HasAuthFactorsConfiguration()); + const auto& auth_config = + context()->user_context->GetAuthFactorsConfiguration(); + + bool has_online_password = false; + if (auth_config.HasConfiguredFactor( + cryptohome::AuthFactorType::kPassword)) { + has_online_password = auth::IsGaiaPassword( + *auth_config.FindFactorByType(cryptohome::AuthFactorType::kPassword)); + } + if (has_online_password) { + exit_callback_.Run(Result::kFallbackOnline); + } else { + exit_callback_.Run(Result::kFallbackLocal); + } + return; + } + CHECK_EQ(context()->osauth_error.value(), + WizardContext::OSAuthErrorKind::kFatal); view_->Show(); } @@ -54,6 +92,9 @@ CHECK_GE(args.size(), 1u); const std::string& action_id = args[0].GetString(); if (action_id == kUserActionCanel) { + if (context()->user_context) { + context()->user_context.reset(); + } if (context()->extra_factors_token.has_value()) { AuthSessionStorage::Get()->Invalidate( GetToken(), base::BindOnce(&OSAuthErrorScreen::OnTokenInvalidated,
diff --git a/chrome/browser/ash/login/screens/osauth/osauth_error_screen.h b/chrome/browser/ash/login/screens/osauth/osauth_error_screen.h index eb9930bf..2e7b2bb7 100644 --- a/chrome/browser/ash/login/screens/osauth/osauth_error_screen.h +++ b/chrome/browser/ash/login/screens/osauth/osauth_error_screen.h
@@ -23,6 +23,9 @@ using TView = OSAuthErrorScreenView; enum class Result { kAbortSignin, + kFallbackOnline, + kFallbackLocal, + kProceedAuthenticated, }; static std::string GetResultString(Result result);
diff --git a/chrome/browser/ash/login/test/auth_ui_utils.cc b/chrome/browser/ash/login/test/auth_ui_utils.cc index 1470860..7410806 100644 --- a/chrome/browser/ash/login/test/auth_ui_utils.cc +++ b/chrome/browser/ash/login/test/auth_ui_utils.cc
@@ -13,7 +13,12 @@ #include "chrome/browser/ash/login/test/oobe_screen_waiter.h" #include "chrome/browser/ash/login/test/oobe_window_visibility_waiter.h" #include "chrome/browser/ash/login/test/test_condition_waiter.h" +#include "chrome/browser/ui/webui/ash/login/cryptohome_recovery_screen_handler.h" +#include "chrome/browser/ui/webui/ash/login/enter_old_password_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/gaia_password_changed_screen_handler.h" +#include "chrome/browser/ui/webui/ash/login/osauth/factor_setup_success_screen_handler.h" +#include "chrome/browser/ui/webui/ash/login/osauth/local_data_loss_warning_screen_handler.h" +#include "chrome/browser/ui/webui/ash/login/osauth/osauth_error_screen_handler.h" namespace ash::test { @@ -24,65 +29,229 @@ const UIPath kForgotPasswordButton = {"gaia-password-changed", "forgotPasswordButton"}; +const UIPath kEnterOldPasswordInputStep = {"enter-old-password", + "passwordStep"}; +const UIPath kEnterOldPasswordInput = {"enter-old-password", + "oldPasswordInput"}; +const UIPath kEnterOldPasswordProceedButton = {"enter-old-password", "next"}; +const UIPath kEnterOldPasswordForgotButton = {"enter-old-password", + "forgotPasswordButton"}; + const UIPath kForgotPasswordStep = {"gaia-password-changed", "forgotPassword"}; const UIPath kForgotCancel = {"gaia-password-changed", "cancelForgot"}; const UIPath kTryAgainRecovery = {"gaia-password-changed", "backButton"}; const UIPath kProceedAnyway = {"gaia-password-changed", "proceedAnyway"}; + +const UIPath kDataLossWarningElement = {"local-data-loss-warning"}; +// TODO: why don't we have it? +const UIPath kDataLossWarningCancel = {"local-data-loss-warning", "cancel"}; + +const UIPath kDataLossWarningBack = {"local-data-loss-warning", "backButton"}; +const UIPath kDataLossWarningRemove = {"local-data-loss-warning", + "proceedRemove"}; +const UIPath kDataLossWarningReset = {"local-data-loss-warning", "powerwash"}; + +const test::UIPath kRecoverySuccessStep = {"cryptohome-recovery", + "successDialog"}; +const test::UIPath kRecoveryDoneButton = {"cryptohome-recovery", "doneButton"}; +const test::UIPath kRecoveryErrorStep = {"cryptohome-recovery", "errorDialog"}; +const test::UIPath kRecoveryManualRecoveryButton = {"cryptohome-recovery", + "manualRecoveryButton"}; + +const UIPath kFactorSetupSuccessElement = {"factor-setup-success"}; +const UIPath kFactorSetupSuccessDoneButton = {"factor-setup-success", + "doneButton"}; +const UIPath kFactorSetupSuccessNextButton = {"factor-setup-success", + "nextButton"}; + +bool IsOldFlow() { + return base::FeatureList::IsEnabled( + ash::features::kCryptohomeRecoveryBeforeFlowSplit); +} + } // namespace // Password change scenario std::unique_ptr<test::TestConditionWaiter> CreateOldPasswordEnterPageWaiter() { + if (IsOldFlow()) { + return std::make_unique<CompositeWaiter>( + std::make_unique<OobeWindowVisibilityWaiter>(true), + std::make_unique<OobeScreenWaiter>(GaiaPasswordChangedView::kScreenId), + OobeJS().CreateVisibilityWaiter(true, kPasswordStep)); + } return std::make_unique<CompositeWaiter>( std::make_unique<OobeWindowVisibilityWaiter>(true), - std::make_unique<OobeScreenWaiter>(GaiaPasswordChangedView::kScreenId), - OobeJS().CreateVisibilityWaiter(true, kPasswordStep)); + std::make_unique<OobeScreenWaiter>( + ash::EnterOldPasswordScreenView::kScreenId), + OobeJS().CreateVisibilityWaiter(true, kEnterOldPasswordInputStep)); } void PasswordChangedTypeOldPassword(const std::string& text) { - test::OobeJS().TypeIntoPath(text, kOldPasswordInput); + if (IsOldFlow()) { + test::OobeJS().TypeIntoPath(text, kOldPasswordInput); + return; + } + test::OobeJS().TypeIntoPath(text, kEnterOldPasswordInput); } void PasswordChangedSubmitOldPassword() { - test::OobeJS().ClickOnPath(kSendPasswordButton); + if (IsOldFlow()) { + test::OobeJS().ClickOnPath(kSendPasswordButton); + return; + } + test::OobeJS().ClickOnPath(kEnterOldPasswordProceedButton); } std::unique_ptr<test::TestConditionWaiter> PasswordChangedInvalidPasswordFeedback() { + if (IsOldFlow()) { + return test::OobeJS().CreateWaiter( + test::GetOobeElementPath(kOldPasswordInput) + ".invalid"); + } return test::OobeJS().CreateWaiter( - test::GetOobeElementPath(kOldPasswordInput) + ".invalid"); + test::GetOobeElementPath(kEnterOldPasswordInput) + ".invalid"); } void PasswordChangedForgotPasswordAction() { - test::OobeJS().ClickOnPath(kForgotPasswordButton); + if (IsOldFlow()) { + test::OobeJS().ClickOnPath(kForgotPasswordButton); + return; + } + test::OobeJS().ClickOnPath(kEnterOldPasswordForgotButton); } std::unique_ptr<test::TestConditionWaiter> LocalDataLossWarningPageWaiter() { + if (IsOldFlow()) { + return std::make_unique<CompositeWaiter>( + std::make_unique<OobeWindowVisibilityWaiter>(true), + std::make_unique<OobeScreenWaiter>(GaiaPasswordChangedView::kScreenId), + OobeJS().CreateVisibilityWaiter(true, kForgotPasswordStep)); + } return std::make_unique<CompositeWaiter>( std::make_unique<OobeWindowVisibilityWaiter>(true), - std::make_unique<OobeScreenWaiter>(GaiaPasswordChangedView::kScreenId), - OobeJS().CreateVisibilityWaiter(true, kForgotPasswordStep)); + std::make_unique<OobeScreenWaiter>( + LocalDataLossWarningScreenView::kScreenId), + OobeJS().CreateVisibilityWaiter(true, kDataLossWarningElement)); } void LocalDataLossWarningPageCancelAction() { - test::OobeJS().ClickOnPath(kForgotCancel); + if (IsOldFlow()) { + test::OobeJS().ClickOnPath(kForgotCancel); + return; + } + test::OobeJS().ClickOnPath(kDataLossWarningCancel); } void LocalDataLossWarningPageGoBackAction() { - test::OobeJS().ClickOnPath(kTryAgainRecovery); + if (IsOldFlow()) { + test::OobeJS().ClickOnPath(kTryAgainRecovery); + return; + } + test::OobeJS().ClickOnPath(kDataLossWarningBack); } -void LocalDataLossWarningPageProceedAction() { - test::OobeJS().ClickOnPath(kProceedAnyway); +void LocalDataLossWarningPageRemoveAction() { + if (IsOldFlow()) { + test::OobeJS().ClickOnPath(kProceedAnyway); + return; + } + test::OobeJS().ClickOnPath(kDataLossWarningRemove); +} + +void LocalDataLossWarningPageResetAction() { + test::OobeJS().ClickOnPath(kDataLossWarningReset); } void LocalDataLossWarningPageExpectGoBack() { - test::OobeJS().ExpectVisiblePath(kTryAgainRecovery); + if (IsOldFlow()) { + test::OobeJS().ExpectVisiblePath(kTryAgainRecovery); + return; + } + test::OobeJS().ExpectVisiblePath(kDataLossWarningBack); } -void LocalDataLossWarningPageExpectProceed() { - test::OobeJS().ExpectVisiblePath(kProceedAnyway); +void LocalDataLossWarningPageExpectRemove() { + if (IsOldFlow()) { + test::OobeJS().ExpectVisiblePath(kProceedAnyway); + return; + } + test::OobeJS().ExpectVisiblePath(kDataLossWarningRemove); +} + +void LocalDataLossWarningPageExpectReset() { + test::OobeJS().ExpectVisiblePath(kDataLossWarningReset); +} + +std::unique_ptr<test::TestConditionWaiter> +CreatePasswordUpdateNoticePageWaiter() { + return std::make_unique<CompositeWaiter>( + std::make_unique<OobeWindowVisibilityWaiter>(true), + std::make_unique<OobeScreenWaiter>( + ash::FactorSetupSuccessScreenView::kScreenId), + OobeJS().CreateVisibilityWaiter(true, kFactorSetupSuccessElement)); +} + +void PasswordUpdateNoticeExpectNext() { + test::OobeJS().ExpectVisiblePath(kFactorSetupSuccessNextButton); +} + +void PasswordUpdateNoticeNextAction() { + test::OobeJS().ClickOnPath(kFactorSetupSuccessNextButton); +} + +void PasswordUpdateNoticeExpectDone() { + test::OobeJS().ExpectVisiblePath(kFactorSetupSuccessDoneButton); +} + +void PasswordUpdateNoticeDoneAction() { + test::OobeJS().ClickOnPath(kFactorSetupSuccessDoneButton); +} + +std::unique_ptr<test::TestConditionWaiter> RecoveryPasswordUpdatedPageWaiter() { + if (IsOldFlow()) { + return std::make_unique<CompositeWaiter>( + std::make_unique<OobeWindowVisibilityWaiter>(true), + std::make_unique<OobeScreenWaiter>( + CryptohomeRecoveryScreenView::kScreenId), + OobeJS().CreateVisibilityWaiter(true, kRecoverySuccessStep)); + } + return CreatePasswordUpdateNoticePageWaiter(); +} + +void RecoveryPasswordUpdatedProceedAction() { + if (IsOldFlow()) { + test::OobeJS().ClickOnPath(kRecoveryDoneButton); + return; + } + PasswordUpdateNoticeDoneAction(); +} + +std::unique_ptr<test::TestConditionWaiter> RecoveryErrorPageWaiter() { + if (IsOldFlow()) { + return std::make_unique<CompositeWaiter>( + std::make_unique<OobeWindowVisibilityWaiter>(true), + std::make_unique<OobeScreenWaiter>( + CryptohomeRecoveryScreenView::kScreenId), + OobeJS().CreateVisibilityWaiter(true, kRecoveryErrorStep)); + } + return std::make_unique<CompositeWaiter>( + std::make_unique<OobeWindowVisibilityWaiter>(true), + std::make_unique<OobeScreenWaiter>( + ash::OSAuthErrorScreenView::kScreenId)); +} + +void RecoveryErrorExpectFallback() { + CHECK(IsOldFlow()); + test::OobeJS().ExpectVisiblePath(kRecoveryManualRecoveryButton); + return; +} + +void RecoveryErrorFallbackAction() { + CHECK(IsOldFlow()); + test::OobeJS().ClickOnPath(kRecoveryManualRecoveryButton); + return; } } // namespace ash::test
diff --git a/chrome/browser/ash/login/test/auth_ui_utils.h b/chrome/browser/ash/login/test/auth_ui_utils.h index 9682be3..a7acd6e 100644 --- a/chrome/browser/ash/login/test/auth_ui_utils.h +++ b/chrome/browser/ash/login/test/auth_ui_utils.h
@@ -25,10 +25,26 @@ std::unique_ptr<test::TestConditionWaiter> LocalDataLossWarningPageWaiter(); void LocalDataLossWarningPageCancelAction(); void LocalDataLossWarningPageGoBackAction(); -void LocalDataLossWarningPageProceedAction(); +void LocalDataLossWarningPageRemoveAction(); +void LocalDataLossWarningPageResetAction(); void LocalDataLossWarningPageExpectGoBack(); -void LocalDataLossWarningPageExpectProceed(); +void LocalDataLossWarningPageExpectRemove(); +void LocalDataLossWarningPageExpectReset(); + +std::unique_ptr<test::TestConditionWaiter> +CreatePasswordUpdateNoticePageWaiter(); +void PasswordUpdateNoticeExpectNext(); +void PasswordUpdateNoticeNextAction(); +void PasswordUpdateNoticeExpectDone(); +void PasswordUpdateNoticeDoneAction(); + +std::unique_ptr<test::TestConditionWaiter> RecoveryPasswordUpdatedPageWaiter(); +void RecoveryPasswordUpdatedProceedAction(); + +std::unique_ptr<test::TestConditionWaiter> RecoveryErrorPageWaiter(); +void RecoveryErrorExpectFallback(); +void RecoveryErrorFallbackAction(); } // namespace ash::test
diff --git a/chrome/browser/ash/login/ui/login_display_host_mojo.cc b/chrome/browser/ash/login/ui/login_display_host_mojo.cc index cc650b3f..d45e790 100644 --- a/chrome/browser/ash/login/ui/login_display_host_mojo.cc +++ b/chrome/browser/ash/login/ui/login_display_host_mojo.cc
@@ -356,6 +356,8 @@ bool success, std::unique_ptr<UserContext> user_context) { if (!success) { + // TODO: pass flow to WizardController, suggest to + // remove & re-create user in case of Recovery flow. existing_user_controller_->OnLocalAuthenticationCancelled(); // While dialog itself is already hidden, this call should // correctly reset all associated data.
diff --git a/chrome/browser/ash/login/wizard_context.h b/chrome/browser/ash/login/wizard_context.h index f4cd201..572bcf96 100644 --- a/chrome/browser/ash/login/wizard_context.h +++ b/chrome/browser/ash/login/wizard_context.h
@@ -80,18 +80,31 @@ // part of recovery flow, or it it just an reauthentication flow. enum class AuthChangeFlow { kInitialSetup, kReauthentication, kRecovery }; + // Indicates the flow path that lead to Data Loss warning screen, + // allowing screen to correctly display/handle Back button. + enum class DataLossBackOptions { kNone, kBackToOnlineAuth, kBackToLocalAuth }; + struct KnowledgeFactorSetup { // Whether usage of local password is forced. bool local_password_forced = false; AuthChangeFlow auth_setup_flow = AuthChangeFlow::kInitialSetup; + DataLossBackOptions data_loss_back_option = DataLossBackOptions::kNone; + AuthFactorsSet modified_factors; }; enum class OSAuthErrorKind { // Most of the errors kFatal, + // User is already authenticated, but cryptohome failed to rotate the key. + // It is more of a warning. + kRecoveryRotationFailed, + // There were problems using the recovery key, but it is still + // possible to proceed using knowledge-based keys. + kRecoveryAuthenticationFailed, + }; // Configuration for automating OOBE screen actions, e.g. during device
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc index 9bc3334..4921e016 100644 --- a/chrome/browser/ash/login/wizard_controller.cc +++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -228,6 +228,7 @@ #include "chromeos/ash/components/language_packs/language_pack_manager.h" #include "chromeos/ash/components/network/network_state.h" #include "chromeos/ash/components/network/network_state_handler.h" +#include "chromeos/ash/components/osauth/public/auth_session_storage.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/cros_settings_provider.h" #include "chromeos/ash/components/settings/timezone_settings.h" @@ -913,17 +914,17 @@ weak_factory_.GetWeakPtr()))); } + append(std::make_unique<PasswordSelectionScreen>( + oobe_ui->GetView<PasswordSelectionScreenHandler>()->AsWeakPtr(), + base::BindRepeating(&WizardController::OnPasswordSelectionScreenExit, + weak_factory_.GetWeakPtr()))); + + append(std::make_unique<ApplyOnlinePasswordScreen>( + oobe_ui->GetView<ApplyOnlinePasswordScreenHandler>()->AsWeakPtr(), + base::BindRepeating(&WizardController::OnApplyOnlinePasswordScreenExit, + weak_factory_.GetWeakPtr()))); + if (features::AreLocalPasswordsEnabledForConsumers()) { - append(std::make_unique<PasswordSelectionScreen>( - oobe_ui->GetView<PasswordSelectionScreenHandler>()->AsWeakPtr(), - base::BindRepeating(&WizardController::OnPasswordSelectionScreenExit, - weak_factory_.GetWeakPtr()))); - - append(std::make_unique<ApplyOnlinePasswordScreen>( - oobe_ui->GetView<ApplyOnlinePasswordScreenHandler>()->AsWeakPtr(), - base::BindRepeating(&WizardController::OnApplyOnlinePasswordScreenExit, - weak_factory_.GetWeakPtr()))); - append(std::make_unique<LocalPasswordSetupScreen>( oobe_ui->GetView<LocalPasswordSetupHandler>()->AsWeakPtr(), base::BindRepeating(&WizardController::OnLocalPasswordSetupScreenExit, @@ -932,11 +933,13 @@ append(std::make_unique<LocalDataLossWarningScreen>( oobe_ui->GetView<LocalDataLossWarningScreenHandler>()->AsWeakPtr(), - base::DoNothing())); + base::BindRepeating(&WizardController::OnLocalDataLossWarningScreenExit, + weak_factory_.GetWeakPtr()))); append(std::make_unique<EnterOldPasswordScreen>( oobe_ui->GetView<EnterOldPasswordScreenHandler>()->AsWeakPtr(), - base::DoNothing())); + base::BindRepeating(&WizardController::OnEnterOldPasswordScreenExit, + weak_factory_.GetWeakPtr()))); append(std::make_unique<OSAuthErrorScreen>( oobe_ui->GetView<OSAuthErrorScreenHandler>()->AsWeakPtr(), @@ -1034,6 +1037,14 @@ SetCurrentScreen(GetScreen(ApplyOnlinePasswordScreenView::kScreenId)); } +void WizardController::ShowLocalDataLossWarningScreen() { + SetCurrentScreen(GetScreen(LocalDataLossWarningScreenView::kScreenId)); +} + +void WizardController::ShowEnterOldPasswordScreen() { + SetCurrentScreen(GetScreen(EnterOldPasswordScreenView::kScreenId)); +} + void WizardController::ShowEnrollmentScreen() { // Update the enrollment configuration and start the screen. GetLoginDisplayHost()->GetOobeMetricsHelper()->RecordEnrollingUserType(); @@ -1694,27 +1705,117 @@ OnScreenExit(CryptohomeRecoveryScreenView::kScreenId, CryptohomeRecoveryScreen::GetResultString(result)); switch (result) { - case CryptohomeRecoveryScreen::Result::kSucceeded: - ash::LoginDisplayHost::default_host() - ->GetExistingUserController() - ->LoginAuthenticated(std::move(wizard_context_->user_context)); + case CryptohomeRecoveryScreen::Result::kObsoleteSucceeded: + LoginAuthenticatedWithContext(std::move(wizard_context_->user_context)); break; + case CryptohomeRecoveryScreen::Result::kAuthenticated: { + switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) { + case WizardContext::AuthChangeFlow::kInitialSetup: + NOTREACHED() << "Recovery can not be used during initial setup."; + return; + case WizardContext::AuthChangeFlow::kRecovery: + ShowPasswordSelectionScreen(); + return; + case WizardContext::AuthChangeFlow::kReauthentication: + // Proceed with login + ObtainContextAndLoginAuthenticated(); + return; + } + } case CryptohomeRecoveryScreen::Result::kGaiaLogin: - case CryptohomeRecoveryScreen::Result::kRetry: + case CryptohomeRecoveryScreen::Result::kObsoleteRetry: // TODO(b/257073746): We probably want to differentiate between retry with // or without login. wizard_context_->gaia_config.prefilled_account = wizard_context_->user_context->GetAccountId(); AdvanceToScreen(GaiaView::kScreenId); break; - case CryptohomeRecoveryScreen::Result::kManualRecovery: - case CryptohomeRecoveryScreen::Result::kNoRecoveryFactor: - case CryptohomeRecoveryScreen::Result::kNotApplicable: + case CryptohomeRecoveryScreen::Result::kObsoleteManualRecovery: + case CryptohomeRecoveryScreen::Result::kObsoleteNoRecoveryFactor: ShowGaiaPasswordChangedScreen(std::move(wizard_context_->user_context)); break; - case CryptohomeRecoveryScreen::Result::kTimeout: + case CryptohomeRecoveryScreen::Result::kFallbackOnline: + ShowEnterOldPasswordScreen(); + break; + case CryptohomeRecoveryScreen::Result::kFallbackLocal: { + switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) { + case WizardContext::AuthChangeFlow::kInitialSetup: + NOTREACHED() << "Recovery is not used during initial setup"; + return; + case WizardContext::AuthChangeFlow::kReauthentication: + AttemptLocalAuthenticationWithContext( + std::move(wizard_context_->user_context)); + return; + case WizardContext::AuthChangeFlow::kRecovery: + // Recovery flow indicates that user does not remember + // their local password, so there is no step to retry. + wizard_context_->knowledge_factor_setup.data_loss_back_option = + WizardContext::DataLossBackOptions::kNone; + ShowLocalDataLossWarningScreen(); + return; + } + } + case CryptohomeRecoveryScreen::Result::kObsoleteTimeout: ShowLoginScreen(); break; + case CryptohomeRecoveryScreen::Result::kError: + ShowOSAuthErrorScreen(); + break; + } +} + +void WizardController::OnLocalDataLossWarningScreenExit( + LocalDataLossWarningScreen::Result result) { + OnScreenExit(LocalDataLossWarningScreenView::kScreenId, + LocalDataLossWarningScreen::GetResultString(result)); + switch (result) { + case LocalDataLossWarningScreen::Result::kRemoveUser: { + std::unique_ptr<UserContext> context = + std::move(wizard_context_->user_context); + ash::LoginDisplayHost::default_host()->CompleteLogin(*context); + break; + } + case LocalDataLossWarningScreen::Result::kCryptohomeError: + ShowOSAuthErrorScreen(); + break; + case LocalDataLossWarningScreen::Result::kCancel: + ShowLoginScreen(); + break; + case LocalDataLossWarningScreen::Result::kBackToOnlineAuth: + ShowEnterOldPasswordScreen(); + break; + case LocalDataLossWarningScreen::Result::kBackToLocalAuth: + AttemptLocalAuthenticationWithContext( + std::move(wizard_context_->user_context)); + break; + } +} + +void WizardController::OnEnterOldPasswordScreenExit( + EnterOldPasswordScreen::Result result) { + OnScreenExit(EnterOldPasswordScreenView::kScreenId, + EnterOldPasswordScreen::GetResultString(result)); + switch (result) { + case EnterOldPasswordScreen::Result::kForgotOldPassword: + wizard_context_->knowledge_factor_setup.data_loss_back_option = + WizardContext::DataLossBackOptions::kBackToOnlineAuth; + ShowLocalDataLossWarningScreen(); + break; + case EnterOldPasswordScreen::Result::kCryptohomeError: + ShowOSAuthErrorScreen(); + break; + case EnterOldPasswordScreen::Result::kAuthenticated: { + switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) { + case WizardContext::AuthChangeFlow::kInitialSetup: + NOTREACHED() << "Old password is not used during initial setup"; + break; + case WizardContext::AuthChangeFlow::kRecovery: + case WizardContext::AuthChangeFlow::kReauthentication: + ShowApplyOnlinePasswordScreen(); + return; + } + break; + } } } @@ -2022,7 +2123,8 @@ OobeMetricsHelper::CompletedPreLoginOobeFlowType::kAutoEnrollment); // Restart to make the login page pick up the policy changes resulting from - // enrollment recovery. (Not pretty, but this codepath is rarely exercised.) + // enrollment recovery. (Not pretty, but this codepath is rarely + // exercised.) if (prescribed_enrollment_config_.mode == policy::EnrollmentConfig::MODE_RECOVERY) { LOG(WARNING) << "Restart Chrome to pick up the policy changes"; @@ -2249,8 +2351,19 @@ ShowOSAuthErrorScreen(); return; case ApplyOnlinePasswordScreen::Result::kSuccess: - case ApplyOnlinePasswordScreen::Result::kNotApplicable: - ShowFingerprintSetupScreen(); + case ApplyOnlinePasswordScreen::Result::kNotApplicable: { + switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) { + case WizardContext::AuthChangeFlow::kInitialSetup: + ShowFingerprintSetupScreen(); + return; + case WizardContext::AuthChangeFlow::kRecovery: + ShowFactorSetupSuccessScreen(); + return; + case WizardContext::AuthChangeFlow::kReauthentication: + NOTREACHED() << "Reauthentication should have been switched to " + "Recovery if there was password update"; + } + } return; } } @@ -2260,6 +2373,39 @@ OnScreenExit(OSAuthErrorScreenView::kScreenId, OSAuthErrorScreen::GetResultString(result)); switch (result) { + case OSAuthErrorScreen::Result::kFallbackOnline: + ShowEnterOldPasswordScreen(); + break; + case OSAuthErrorScreen::Result::kFallbackLocal: { + switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) { + case WizardContext::AuthChangeFlow::kInitialSetup: + NOTREACHED() << "Recovery is not used during initial setup"; + return; + case WizardContext::AuthChangeFlow::kReauthentication: + AttemptLocalAuthenticationWithContext( + std::move(wizard_context_->user_context)); + return; + case WizardContext::AuthChangeFlow::kRecovery: + // Recovery flow means that the user forgot their + // local password. It does not make sense to ask for it. + ShowLocalDataLossWarningScreen(); + return; + } + } + + case OSAuthErrorScreen::Result::kProceedAuthenticated: { + switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) { + case WizardContext::AuthChangeFlow::kInitialSetup: + case WizardContext::AuthChangeFlow::kRecovery: + ShowPasswordSelectionScreen(); + return; + case WizardContext::AuthChangeFlow::kReauthentication: + // Proceed with login + ObtainContextAndLoginAuthenticated(); + return; + } + } + return; case OSAuthErrorScreen::Result::kAbortSignin: ShowLoginScreen(); return; @@ -2272,9 +2418,18 @@ FactorSetupSuccessScreen::GetResultString(result)); switch (result) { case FactorSetupSuccessScreen::Result::kNotApplicable: - case FactorSetupSuccessScreen::Result::kProceed: - ShowFingerprintSetupScreen(); - break; + case FactorSetupSuccessScreen::Result::kProceed: { + switch (wizard_context_->knowledge_factor_setup.auth_setup_flow) { + case WizardContext::AuthChangeFlow::kInitialSetup: + ShowFingerprintSetupScreen(); + return; + case WizardContext::AuthChangeFlow::kRecovery: + case WizardContext::AuthChangeFlow::kReauthentication: + // Proceed with login + ObtainContextAndLoginAuthenticated(); + return; + } + } case FactorSetupSuccessScreen::Result::kTimedOut: ShowLoginScreen(); return; @@ -2294,6 +2449,47 @@ FinishAuthFactorsSetup(); } +void WizardController::ObtainContextAndLoginAuthenticated() { + CHECK(wizard_context_->extra_factors_token); + auto token = std::move(wizard_context_->extra_factors_token); + wizard_context_->extra_factors_token = absl::nullopt; + + ash::AuthSessionStorage::Get()->Withdraw( + *token, base::BindOnce(&WizardController::LoginAuthenticatedWithContext, + weak_factory_.GetWeakPtr())); +} + +void WizardController::ObtainContextAndAttemptLocalAuthentication() { + CHECK(wizard_context_->extra_factors_token); + auto token = std::move(wizard_context_->extra_factors_token); + wizard_context_->extra_factors_token = absl::nullopt; + + ash::AuthSessionStorage::Get()->Withdraw( + *token, + base::BindOnce(&WizardController::AttemptLocalAuthenticationWithContext, + weak_factory_.GetWeakPtr())); +} + +void WizardController::LoginAuthenticatedWithContext( + std::unique_ptr<UserContext> context) { + if (!context) { + // Session has expired. + LOG(ERROR) << "Session expired before login could proceed."; + wizard_context_->osauth_error = WizardContext::OSAuthErrorKind::kFatal; + ShowOSAuthErrorScreen(); + return; + } + ash::LoginDisplayHost::default_host() + ->GetExistingUserController() + ->LoginAuthenticated(std::move(context)); +} + +void WizardController::AttemptLocalAuthenticationWithContext( + std::unique_ptr<UserContext> context) { + ash::LoginDisplayHost::default_host()->GetSigninUI()->RunLocalAuthentication( + std::move(context)); +} + void WizardController::FinishAuthFactorsSetup() { // TODO(b/238606050): Ensure that AuthSession is terminated after this step. ShowRecommendAppsScreen(); @@ -2625,9 +2821,9 @@ !wizard_context_->is_cloud_ready_update_flow && wizard_context_->screen_after_managed_tos != ash::OOBE_SCREEN_UNKNOWN) { - // If screen_after_managed_tos == SCREEN_UNKNOWN means that the onboarding - // has already been finished by the user and we don't need to save the - // state here. + // If screen_after_managed_tos == SCREEN_UNKNOWN means that the + // onboarding has already been finished by the user and we don't need to + // save the state here. user_manager::KnownUser(GetLocalState()) .SetPendingOnboardingScreen( user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(), @@ -2646,8 +2842,9 @@ void WizardController::UpdateStatusAreaVisibilityForScreen( OobeScreenId screen_id) { if (screen_id == WelcomeView::kScreenId) { - // Hide the status area initially; it only appears after OOBE first animates - // in. Keep it visible if the user goes back to the existing welcome screen. + // Hide the status area initially; it only appears after OOBE first + // animates in. Keep it visible if the user goes back to the existing + // welcome screen. GetLoginDisplayHost()->SetStatusAreaVisible( screen_manager_->HasScreen(WelcomeView::kScreenId)); } else { @@ -2686,9 +2883,9 @@ policy::EnrollmentRequisitionManager::SetDeviceRequisition( *requisition_value); } else if (policy::EnrollmentRequisitionManager::IsMeetDevice()) { - VLOG(1) - << "Using default Device Requisition value for CFM build configuration" - << policy::EnrollmentRequisitionManager::kRemoraRequisition; + VLOG(1) << "Using default Device Requisition value for CFM build " + "configuration" + << policy::EnrollmentRequisitionManager::kRemoraRequisition; policy::EnrollmentRequisitionManager::SetDeviceRequisition( policy::EnrollmentRequisitionManager::kRemoraRequisition); } @@ -2911,8 +3108,8 @@ } if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { - // If the `cros_settings_` are permanently untrusted, show an error message - // and refuse to auto-launch the kiosk app. + // If the `cros_settings_` are permanently untrusted, show an error + // message and refuse to auto-launch the kiosk app. AdvanceToScreen(LocalStateErrorScreenView::kScreenId); return; } @@ -3102,7 +3299,8 @@ // Determine the effective enrollment configuration. If there is a valid // prescribed configuration, use that. If not, figure out which variant of // manual enrollment is taking place. - // If OOBE Configuration exits, it might also affect enrollment configuration. + // If OOBE Configuration exits, it might also affect enrollment + // configuration. policy::EnrollmentConfig effective_config = prescribed_enrollment_config_; if (!effective_config.should_enroll() || (force_interactive && !effective_config.should_enroll_interactively())) {
diff --git a/chrome/browser/ash/login/wizard_controller.h b/chrome/browser/ash/login/wizard_controller.h index 51ff7d7..a1b0496c 100644 --- a/chrome/browser/ash/login/wizard_controller.h +++ b/chrome/browser/ash/login/wizard_controller.h
@@ -58,9 +58,11 @@ #include "chrome/browser/ash/login/screens/osauth/apply_online_password_screen.h" #include "chrome/browser/ash/login/screens/osauth/cryptohome_recovery_screen.h" #include "chrome/browser/ash/login/screens/osauth/cryptohome_recovery_setup_screen.h" +#include "chrome/browser/ash/login/screens/osauth/enter_old_password_screen.h" #include "chrome/browser/ash/login/screens/osauth/factor_setup_success_screen.h" #include "chrome/browser/ash/login/screens/osauth/gaia_password_changed_screen.h" #include "chrome/browser/ash/login/screens/osauth/gaia_password_changed_screen_legacy.h" +#include "chrome/browser/ash/login/screens/osauth/local_data_loss_warning_screen.h" #include "chrome/browser/ash/login/screens/osauth/local_password_setup_screen.h" #include "chrome/browser/ash/login/screens/osauth/osauth_error_screen.h" #include "chrome/browser/ash/login/screens/osauth/password_selection_screen.h" @@ -346,6 +348,8 @@ void ShowLocalPasswordSetupScreen(); void ShowApplyOnlinePasswordScreen(); void ShowOSAuthErrorScreen(); + void ShowEnterOldPasswordScreen(); + void ShowLocalDataLossWarningScreen(); void ShowFactorSetupSuccessScreen(); // Shows images login screen. @@ -397,12 +401,23 @@ void OnTermsOfServiceScreenExit(TermsOfServiceScreen::Result result); void OnSyncConsentScreenExit(SyncConsentScreen::Result result); // Start of Local authentication setup sub-group + // Authentication part + void OnCryptohomeRecoveryScreenExit(CryptohomeRecoveryScreen::Result result); + void OnEnterOldPasswordScreenExit(EnterOldPasswordScreen::Result result); + void OnLocalDataLossWarningScreenExit( + LocalDataLossWarningScreen::Result result); + // Factor setup part void StartAuthFactorsSetup(); void OnCryptohomeRecoverySetupScreenExit( CryptohomeRecoverySetupScreen::Result result); void OnPasswordSelectionScreenExit(PasswordSelectionScreen::Result result); void OnFingerprintSetupScreenExit(FingerprintSetupScreen::Result result); void OnPinSetupScreenExit(PinSetupScreen::Result result); + void ObtainContextAndLoginAuthenticated(); + void LoginAuthenticatedWithContext(std::unique_ptr<UserContext> user_context); + void ObtainContextAndAttemptLocalAuthentication(); + void AttemptLocalAuthenticationWithContext( + std::unique_ptr<UserContext> user_context); void FinishAuthFactorsSetup(); // End of Local authentication setup sub-group void OnRecommendAppsScreenExit(RecommendAppsScreen::Result result); @@ -438,7 +453,6 @@ void OnSmartPrivacyProtectionScreenExit( SmartPrivacyProtectionScreen::Result result); void OnThemeSelectionScreenExit(ThemeSelectionScreen::Result result); - void OnCryptohomeRecoveryScreenExit(CryptohomeRecoveryScreen::Result result); void OnChoobeScreenExit(ChoobeScreen::Result result); void OnTouchpadScreenExit(TouchpadScrollScreen::Result result); void OnDisplaySizeScreenExit(DisplaySizeScreen::Result result);
diff --git a/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller.cc b/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller.cc index 6c9d31a..6a118d04 100644 --- a/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller.cc +++ b/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller.cc
@@ -634,9 +634,10 @@ void CrdAdminSessionController::OnHostStopped( ExtendedStartCrdSessionResultCode result, const std::string& message) { - CRD_VLOG(3) << "Destroying CRD host session asynchronously"; - - DeleteSoon(std::move(active_session_)); + if (active_session_) { + CRD_VLOG(3) << "Destroying CRD host session asynchronously"; + DeleteSoon(std::move(active_session_)); + } } void CrdAdminSessionController::TryToReconnect(
diff --git a/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller_unittest.cc b/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller_unittest.cc index f404c736..5fe7c92 100644 --- a/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller_unittest.cc +++ b/chrome/browser/ash/policy/remote_commands/crd/crd_admin_session_controller_unittest.cc
@@ -250,10 +250,10 @@ RemotingServiceMock& remoting_service() { return remoting_service_; } CrdAdminSessionController& session_controller() { - return session_controller_; + return *session_controller_; } StartCrdSessionJobDelegate& delegate() { - return session_controller_.GetDelegate(); + return session_controller_->GetDelegate(); } auto success_callback() { @@ -323,8 +323,10 @@ } void InitWithNoReconnectableSession(CrdAdminSessionController& controller) { - EXPECT_CALL(remoting_service(), GetReconnectableSessionId) - .WillOnce(ReplyWithSessionId(std::nullopt)); + if (base::FeatureList::IsEnabled(kEnableCrdAdminRemoteAccessV2)) { + EXPECT_CALL(remoting_service(), GetReconnectableSessionId) + .WillOnce(ReplyWithSessionId(std::nullopt)); + } Init(controller); @@ -341,17 +343,12 @@ ASSERT_TRUE(delegate().HasActiveSession()); } + // UI elements (like the remote activity notification) can only be shown once + // the login screen is visible. void SimulateLoginScreenIsVisible() { - // Notifies the observers that the login screen is visible and ensure the - // `RemoteActivityNotificationController::Init()` is called. session_manager().NotifyLoginOrLockScreenVisible(); } - void SimulateRestart() { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kFirstExecAfterBoot); - } - const aura::Window& GetLockScreenContainersContainer() { return CHECK_DEREF(ash::Shell::Get()->GetPrimaryRootWindow()->GetChildById( ash::kShellWindowId_LockScreenContainersContainer)); @@ -407,26 +404,42 @@ mojo::Remote<SupportHostObserver>& observer_remote() { return observer_; } - private: + void RecreateSessionController() { + // It's possible the old session controller has an outstanding delete of + // its previously active session (which are deleted asynchronously), so + // give this outstanding delete a chance to finish before we delete + // the controller itself. + if (session_controller_.has_value()) { + base::RunLoop().RunUntilIdle(); + } + + session_controller_.emplace( + std::make_unique<RemotingServiceWrapper>(&remoting_service_)); + result_.Clear(); + session_finish_result_.Clear(); + } + + protected: void SetUp() override { AshTestBase::SetUp(); + RecreateSessionController(); session_controller().SetOAuthTokenForTesting("test-oauth-token"); } void TearDown() override { - session_controller_.Shutdown(); + session_controller_->Shutdown(); AshTestBase::TearDown(); } + private: ScopedTestingLocalState local_state_; - testing::StrictMock<ash::MockLoginDisplayHost> mock_login_display_host_; + testing::NiceMock<ash::MockLoginDisplayHost> mock_login_display_host_; TestFuture<Response> result_; TestFuture<base::TimeDelta> session_finish_result_; mojo::Remote<SupportHostObserver> observer_; testing::StrictMock<RemotingServiceMock> remoting_service_; SecurityCurtainControllerFake curtain_controller_fake_; - CrdAdminSessionController session_controller_{ - std::make_unique<RemotingServiceWrapper>(&remoting_service_)}; + std::optional<CrdAdminSessionController> session_controller_; base::test::ScopedFeatureList feature_; }; @@ -781,127 +794,6 @@ } TEST_F(CrdAdminSessionControllerTest, - ShouldNotShowActivityNotificationIfDisabledByFeature) { - DisableFeature(kEnableCrdAdminRemoteAccessV2); - Init(session_controller()); - - SessionParameters parameters; - parameters.curtain_local_user_session = true; - SupportHostObserver& observer = StartCrdHostAndBindObserver(parameters); - observer.OnHostStateConnected(kTestUserName); - FlushForTesting(observer); - - EXPECT_NO_CALLS(login_display_host(), ShowRemoteActivityNotificationScreen()); - - SimulateLoginScreenIsVisible(); -} - -TEST_F(CrdAdminSessionControllerTest, - ShouldShowActivityNotificationIfThePreviousSessionWasCurtained) { - EnableFeature(kEnableCrdAdminRemoteAccessV2); - InitWithNoReconnectableSession(session_controller()); - - SessionParameters parameters; - parameters.curtain_local_user_session = true; - SupportHostObserver& observer = StartCrdHostAndBindObserver(parameters); - observer.OnHostStateConnected(kTestUserName); - FlushForTesting(observer); - - EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen()) - .Times(1); - - SimulateLoginScreenIsVisible(); -} - -TEST_F(CrdAdminSessionControllerTest, - ShouldNotShowActivityNotificationIfThePreviousSessionWasNotCurtained) { - EnableFeature(kEnableCrdAdminRemoteAccessV2); - InitWithNoReconnectableSession(session_controller()); - - SessionParameters parameters; - parameters.curtain_local_user_session = false; - SupportHostObserver& observer = StartCrdHostAndBindObserver(parameters); - observer.OnHostStateConnected(kTestUserName); - FlushForTesting(observer); - - EXPECT_NO_CALLS(login_display_host(), ShowRemoteActivityNotificationScreen()); - - SimulateLoginScreenIsVisible(); -} - -TEST_F(CrdAdminSessionControllerTest, - ShouldShowActivityNotificationAgainIfUserDidNotDismissIt) { - EnableFeature(kEnableCrdAdminRemoteAccessV2); - InitWithNoReconnectableSession(session_controller()); - - SessionParameters parameters; - parameters.curtain_local_user_session = true; - SupportHostObserver& observer = StartCrdHostAndBindObserver(parameters); - observer.OnHostStateConnected(kTestUserName); - FlushForTesting(observer); - - // The first time the notification is displayed. - EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen()) - .Times(1); - SimulateLoginScreenIsVisible(); - - SimulateRestart(); - - EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen()) - .Times(1); - SimulateLoginScreenIsVisible(); -} - -TEST_F(CrdAdminSessionControllerTest, - ShouldNotShowActivityNotificationAgainIfUserDismissedIt) { - EnableFeature(kEnableCrdAdminRemoteAccessV2); - InitWithNoReconnectableSession(session_controller()); - - SessionParameters parameters; - parameters.curtain_local_user_session = true; - SupportHostObserver& observer = StartCrdHostAndBindObserver(parameters); - observer.OnHostStateConnected(kTestUserName); - FlushForTesting(observer); - TerminateActiveSession(); - - // The first time the notification is displayed. - EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen()) - .Times(1); - SimulateLoginScreenIsVisible(); - - DismissNotification(); - SimulateRestart(); - - EXPECT_NO_CALLS(login_display_host(), ShowRemoteActivityNotificationScreen()); - - SimulateLoginScreenIsVisible(); -} - -TEST_F( - CrdAdminSessionControllerTest, - ShouldShowActivityNotificationAgainIfUserDismissedItDuringACurtainedSession) { - EnableFeature(kEnableCrdAdminRemoteAccessV2); - InitWithNoReconnectableSession(session_controller()); - - SessionParameters parameters; - parameters.curtain_local_user_session = true; - SupportHostObserver& observer = StartCrdHostAndBindObserver(parameters); - SimulateClientConnects(observer); - - // The first time the notification is displayed. - EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen()) - .Times(1); - SimulateLoginScreenIsVisible(); - - DismissNotification(); - SimulateRestart(); - - EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen()) - .Times(1); - SimulateLoginScreenIsVisible(); -} - -TEST_F(CrdAdminSessionControllerTest, ShouldUmaLogErrorWhenRemotingServiceReportsStateError) { const std::tuple<ErrorCode, ExtendedStartCrdSessionResultCode> test_cases[] = {{ErrorCode::OK, ExtendedStartCrdSessionResultCode::kSuccess}, @@ -1187,6 +1079,123 @@ EXPECT_EQ(GetSessionControllerClient()->request_sign_out_count(), 1); } +class CrdAdminSessionControllerTestNotification + : public CrdAdminSessionControllerReconnectTest { + public: + void SetUp() override { + EnableFeature(kEnableCrdAdminRemoteAccessV2); + + CrdAdminSessionControllerReconnectTest::SetUp(); + + InitWithNoReconnectableSession(session_controller()); + } + + void SimulateChromeRestart() { + RecreateSessionController(); + observer_remote().reset(); + InitWithNoReconnectableSession(session_controller()); + session_controller().SetOAuthTokenForTesting("fake-oauth-token"); + SimulateLoginScreenIsVisible(); + } + + void StartCrdHost(bool is_curtained) { + SessionParameters parameters; + parameters.curtain_local_user_session = is_curtained; + StartCrdHostAndBindObserver(parameters); + } + + void SimulateCrdClientConnects() { + observer_remote()->OnHostStateConnecting(); + observer_remote()->OnHostStateConnected(kTestUserName); + FlushForTesting(*observer_remote()); + } + + void SimulateCrdClientDisconnects() { + observer_remote()->OnHostStateDisconnected(std::nullopt); + FlushForTesting(*observer_remote()); + } + + void SimulateCrdSessionWithClient(bool is_curtained) { + StartCrdHost(is_curtained); + SimulateCrdClientConnects(); + SimulateCrdClientDisconnects(); + } +}; + +TEST_F(CrdAdminSessionControllerTestNotification, + ShouldNotShowActivityNotificationIfDisabledByFeature) { + DisableFeature(kEnableCrdAdminRemoteAccessV2); + // Ensure disabling the feature takes effect. + SimulateChromeRestart(); + + SimulateCrdSessionWithClient(/*is_curtained=*/true); + + EXPECT_NO_CALLS(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); +} + +TEST_F(CrdAdminSessionControllerTestNotification, + ShouldShowActivityNotificationIfThePreviousSessionWasCurtained) { + SimulateCrdSessionWithClient(/*is_curtained=*/true); + + EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); +} + +TEST_F(CrdAdminSessionControllerTestNotification, + ShouldNotShowActivityNotificationIfThePreviousSessionWasNotCurtained) { + SimulateCrdSessionWithClient(/*is_curtained=*/false); + + EXPECT_NO_CALLS(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); +} + +TEST_F(CrdAdminSessionControllerTestNotification, + ShouldShowActivityNotificationAgainIfUserDidNotDismissIt) { + SimulateCrdSessionWithClient(/*is_curtained=*/true); + + // The first time the notification is displayed. + EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); + + // And it is shown again after restarting without dismissing the notification. + EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); +} + +TEST_F(CrdAdminSessionControllerTestNotification, + ShouldNotShowActivityNotificationAgainIfUserDidNotDismissIt) { + SimulateCrdSessionWithClient(/*is_curtained=*/true); + + // The first time the notification is displayed. + EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); + + // It is *not* shown again after dismissing the notification. + DismissNotification(); + + EXPECT_NO_CALLS(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); +} + +TEST_F(CrdAdminSessionControllerTestNotification, + ShouldHideActivityNotificationDuringACurtainedCrdSession) { + SimulateCrdSessionWithClient(/*is_curtained=*/true); + + // The first time the notification is displayed. + EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateChromeRestart(); + + StartCrdHost(/*is_curtained=*/true); + + EXPECT_CALL(login_display_host(), HideOobeDialog); + SimulateCrdClientConnects(); + + // It should be shown again after the CRD session ends. + EXPECT_CALL(login_display_host(), ShowRemoteActivityNotificationScreen); + SimulateCrdClientDisconnects(); +} + INSTANTIATE_TEST_SUITE_P(CrdAdminSessionControllerTestWithBoolParams, CrdAdminSessionControllerTestWithBoolParams, testing::Bool());
diff --git a/chrome/browser/ash/policy/remote_commands/crd/crd_session_observer.h b/chrome/browser/ash/policy/remote_commands/crd/crd_session_observer.h index 7368c0a..9a2f6088 100644 --- a/chrome/browser/ash/policy/remote_commands/crd/crd_session_observer.h +++ b/chrome/browser/ash/policy/remote_commands/crd/crd_session_observer.h
@@ -27,6 +27,7 @@ // Invoked when the remote admin used the access code to actually start a // CRD connection. + virtual void OnClientConnecting() {} virtual void OnClientConnected() {} // Invoked when the remote admin disconnects.
diff --git a/chrome/browser/ash/policy/remote_commands/crd/crd_support_host_observer_proxy.cc b/chrome/browser/ash/policy/remote_commands/crd/crd_support_host_observer_proxy.cc index bcc4560..67e038a 100644 --- a/chrome/browser/ash/policy/remote_commands/crd/crd_support_host_observer_proxy.cc +++ b/chrome/browser/ash/policy/remote_commands/crd/crd_support_host_observer_proxy.cc
@@ -64,6 +64,10 @@ void SupportHostObserverProxy::OnHostStateConnecting() { CRD_VLOG(3) << __func__; + + for (auto& observer : observers_) { + observer.OnClientConnecting(); + } } void SupportHostObserverProxy::OnHostStateConnected(
diff --git a/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.cc b/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.cc index dc87a12..e6245b4 100644 --- a/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.cc +++ b/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.cc
@@ -32,10 +32,21 @@ RemoteActivityNotificationController::~RemoteActivityNotificationController() = default; -// We only can display UI elements (like the notification) after the login -// screen is properly initialized. +// Buttons (like the one on the notification) do not correctly respond to +// on-click events if they are created before the login screen is properly +// initialized, so only create the notification once that's the case. void RemoteActivityNotificationController::OnLoginOrLockScreenVisible() { - Init(); + if (remote_admin_was_present_.GetValue()) { + notification_.Show(); + } +} + +void RemoteActivityNotificationController::OnClientConnecting() { + // The notification is meant for a local user not for the remote admin, so + // hide it during a CRD connection so we don't annoy them. This also prevents + // the notification from showing when the remote admin auto-reconnects after + // a Chrome crash/restart. + notification_.Hide(); } void RemoteActivityNotificationController::OnClientConnected() { @@ -44,25 +55,45 @@ } } -void RemoteActivityNotificationController::Init() { +void RemoteActivityNotificationController::OnClientDisconnected() { + // Show the notification once the remote admin disconnects. if (remote_admin_was_present_.GetValue()) { - ShowNotification(); + notification_.Show(); } } -void RemoteActivityNotificationController::ShowNotification() { - CHECK_DEREF(ash::LoginDisplayHost::default_host()) - .ShowRemoteActivityNotificationScreen(); -} - void RemoteActivityNotificationController:: OnRemoteAdminWasPresentPrefChanged() { - if (is_current_session_curtained_.Run() && - !remote_admin_was_present_.GetValue()) { + if (!remote_admin_was_present_.GetValue()) { + // Remember the notification was dismissed by the user. + notification_.Hide(); + } + + if (is_current_session_curtained_.Run()) { // When the notification is dismissed from inside a curtained session // we must ensure the notification is shown again the next time. remote_admin_was_present_.SetValue(true); } } +void RemoteActivityNotificationController::Notification::Show() { + if (!is_showing_) { + auto* default_host = ash::LoginDisplayHost::default_host(); + if (default_host) { + default_host->ShowRemoteActivityNotificationScreen(); + is_showing_ = true; + } + } +} + +void RemoteActivityNotificationController::Notification::Hide() { + if (is_showing_) { + auto* default_host = ash::LoginDisplayHost::default_host(); + if (default_host) { + default_host->HideOobeDialog(); + is_showing_ = false; + } + } +} + } // namespace policy
diff --git a/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.h b/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.h index 677d6fb..21d875c 100644 --- a/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.h +++ b/chrome/browser/ash/policy/remote_commands/crd/remote_activity_notification_controller.h
@@ -34,12 +34,22 @@ void OnLoginOrLockScreenVisible() override; // `CrdSessionObserver` implementation: + void OnClientConnecting() override; void OnClientConnected() override; + void OnClientDisconnected() override; private: - void Init(); + class Notification { + public: + void Show(); + void Hide(); - void ShowNotification(); + private: + // Unfortunately the `LocalHost` has no API to query if the notification + // screen is showing, so this must manually be tracked to prevent + // dismissing other OOBE screens when trying to hide the notification. + bool is_showing_ = false; + }; void OnRemoteAdminWasPresentPrefChanged(); @@ -48,6 +58,7 @@ session_manager::SessionManagerObserver> observation_{this}; BooleanPrefMember remote_admin_was_present_; + Notification notification_; base::WeakPtrFactory<RemoteActivityNotificationController> weak_ptr_factory_{ this};
diff --git a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc index 240d826..2c35858 100644 --- a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
@@ -216,7 +216,7 @@ // the "Enter CVC" dialog will pop up for card autofill. bool is_credit_card_field = triggered_field_type.has_value() && - GroupTypeOfServerFieldType(triggered_field_type.value()) == + GroupTypeOfFieldType(triggered_field_type.value()) == FieldTypeGroup::kCreditCard; bool should_cvc_dialog_pop_up = is_credit_card_field && cvc;
diff --git a/chrome/browser/devtools/protocol/autofill_handler.cc b/chrome/browser/devtools/protocol/autofill_handler.cc index f19a758..7cd6e57 100644 --- a/chrome/browser/devtools/protocol/autofill_handler.cc +++ b/chrome/browser/devtools/protocol/autofill_handler.cc
@@ -34,7 +34,7 @@ using autofill::FieldGlobalId; using autofill::FormData; using autofill::FormFieldData; -using autofill::HtmlFieldTypeToBestCorrespondingServerFieldType; +using autofill::HtmlFieldTypeToBestCorrespondingFieldType; using autofill::mojom::HtmlFieldType; using protocol::Maybe; using protocol::Response; @@ -259,7 +259,7 @@ bool autofill_inferred = autofill_field->html_type() == HtmlFieldType::kUnspecified || autofill_field->html_type() == HtmlFieldType::kUnrecognized || - HtmlFieldTypeToBestCorrespondingServerFieldType( + HtmlFieldTypeToBestCorrespondingFieldType( autofill_field->html_type()) != autofill_field->Type().GetStorableType(); filled_fields_to_be_sent_to_devtools->push_back( @@ -287,7 +287,7 @@ const std::string locale = "en-US"; autofill::GetAddressComponents( base::UTF16ToUTF8(profile_used_to_fill_form->GetInfo( - autofill::ServerFieldType::ADDRESS_HOME_COUNTRY, locale)), + autofill::FieldType::ADDRESS_HOME_COUNTRY, locale)), locale, /*include_literals=*/false, &components, nullptr);
diff --git a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc index fc4a779d..8324989 100644 --- a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc +++ b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc
@@ -274,12 +274,12 @@ .GetPersonalDataManager() ->test_addresses(); ASSERT_EQ(res.size(), 2u); - ASSERT_EQ(res[0].GetAddress().GetRawInfo( - autofill::ServerFieldType::ADDRESS_HOME_LINE1), - u"Erika-mann"); - ASSERT_EQ(res[1].GetAddress().GetRawInfo( - autofill::ServerFieldType::ADDRESS_HOME_LINE2), - u"Faria lima"); + ASSERT_EQ( + res[0].GetAddress().GetRawInfo(autofill::FieldType::ADDRESS_HOME_LINE1), + u"Erika-mann"); + ASSERT_EQ( + res[1].GetAddress().GetRawInfo(autofill::FieldType::ADDRESS_HOME_LINE2), + u"Faria lima"); } IN_PROC_BROWSER_TEST_F(DevToolsAutofillTest, TriggerCreditCard) {
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc index 8ea70a5..e46a227 100644 --- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc +++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -527,9 +527,11 @@ features.Append(GenerateFeatureFlag( "autocorrectparamstuning", base::FeatureList::IsEnabled(ash::features::kAutocorrectParamsTuning))); - features.Append(GenerateFeatureFlag( - "handwritinglibrarydlc", - base::FeatureList::IsEnabled(ash::features::kHandwritingLibraryDlc))); + + // TODO(b/316429185): Remove "handwritinglibrarydlc" when no longer referenced + // in CrOS virtual keyboard's internal code base. + features.Append(GenerateFeatureFlag("handwritinglibrarydlc", true)); + features.Append( GenerateFeatureFlag("jelly", chromeos::features::IsJellyEnabled())); features.Append(GenerateFeatureFlag(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 03c12b6b..1c7eb7b 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2151,6 +2151,11 @@ "expiry_milestone": 125 }, { + "name": "enable-bound-session-credentials-software-keys-for-manual-testing", + "owners": [ "alexilin@chromium.org", "msalama@chromium.org", "chrome-signin-team@google.com" ], + "expiry_milestone": 125 + }, + { "name": "enable-builtin-hls", "owners": ["tmathmeyer@chromium.org", "videostack-eng@google.com"], "expiry_milestone": 123 @@ -4540,11 +4545,6 @@ "expiry_milestone": 118 }, { - "name": "handwriting-library-dlc", - "owners": [ "shend@google.com", "essential-inputs-team@google.com" ], - "expiry_milestone": 118 - }, - { "name": "happiness-tracking-surveys-for-desktop-demo", "owners": [ "//chrome/browser/ui/hats/OWNERS" ], // A debugging and demo flag to allow UI/dev/testing team to always show the UI @@ -6312,7 +6312,7 @@ { "name": "password-suggestion-bottom-sheet-v2", "owners": ["atsvirchkova@google.com", "vasilii@chromium.org", "derinel@google.com"], - "expiry_milestone": 122 + "expiry_milestone": 125 }, { "name": "pcie-billboard-notification",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index a6914a98..8e1ef13 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -652,12 +652,6 @@ "When enabled, Chrome Settings link directs to GPay Web rather than " "Payments Center for payment methods management."; -const char kAutofillUseImprovedLabelDisambiguationName[] = - "Autofill Uses Improved Label Disambiguation"; -const char kAutofillUseImprovedLabelDisambiguationDescription[] = - "When enabled, the Autofill dropdown's suggestions' labels are displayed " - "using the improved disambiguation format."; - const char kAutofillVirtualCardsOnTouchToFillAndroidName[] = "Enable virtual cards on Touch To Fill bottomsheet for credit cards"; const char kAutofillVirtualCardsOnTouchToFillAndroidDescription[] = @@ -1955,12 +1949,6 @@ const char kHandwritingLegacyRecognitionDescription[] = "Enables new on-device recognition for handwriting legacy paths."; -const char kHandwritingLibraryDlcName[] = - "Handwriting recognition with library from DLC"; -const char kHandwritingLibraryDlcDescription[] = - "Enables new on-device recognition with the handwriting library installed " - "from DLC"; - const char kHardwareMediaKeyHandling[] = "Hardware Media Key Handling"; const char kHardwareMediaKeyHandlingDescription[] = "Enables using media keys to control the active media session. This " @@ -3866,12 +3854,6 @@ "Image drag on Android is available when flag touch-drag-and-context-menu " "is enabled."; -const char kAutofillUseMobileLabelDisambiguationName[] = - "Autofill Uses Mobile Label Disambiguation"; -const char kAutofillUseMobileLabelDisambiguationDescription[] = - "When enabled, Autofill suggestions' labels are displayed using a " - "mobile-friendly format."; - const char kArchiveTabServiceName[] = "Enable archive tab service"; const char kArchiveTabServiceDescription[] = "Archives suggested tabs for the user that haven't been used beyond a " @@ -7783,6 +7765,14 @@ "Enables Google session credentials binding to cryptographic keys that are " "practically impossible to extract from the user device. This will mostly " "prevent the usage of bound credentials outside of the user device."; + +const char kEnableBoundSessionCredentialsSoftwareKeysForManualTestingName[] = + "Device Bound Session Credentials with software keys"; +const char + kEnableBoundSessionCredentialsSoftwareKeysForManualTestingDescription[] = + "Enables mock software-backed cryptographic keys for Google session " + "credentials binding (not secure). This is intented to be used for " + "manual testing only."; #endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) #if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 4a8ba80..92c6410 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -376,9 +376,6 @@ extern const char kAutofillMoreProminentPopupName[]; extern const char kAutofillMoreProminentPopupDescription[]; -extern const char kAutofillUseImprovedLabelDisambiguationName[]; -extern const char kAutofillUseImprovedLabelDisambiguationDescription[]; - extern const char kAutofillVirtualCardsOnTouchToFillAndroidName[]; extern const char kAutofillVirtualCardsOnTouchToFillAndroidDescription[]; @@ -1095,9 +1092,6 @@ extern const char kHandwritingLegacyRecognitionName[]; extern const char kHandwritingLegacyRecognitionDescription[]; -extern const char kHandwritingLibraryDlcName[]; -extern const char kHandwritingLibraryDlcDescription[]; - extern const char kHardwareMediaKeyHandling[]; extern const char kHardwareMediaKeyHandlingDescription[]; @@ -2238,9 +2232,6 @@ extern const char kArchiveTabServiceName[]; extern const char kArchiveTabServiceDescription[]; -extern const char kAutofillUseMobileLabelDisambiguationName[]; -extern const char kAutofillUseMobileLabelDisambiguationDescription[]; - extern const char kBackGestureActivityTabProviderName[]; extern const char kBackGestureActivityTabProviderDescription[]; @@ -4506,6 +4497,11 @@ #if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) extern const char kEnableBoundSessionCredentialsName[]; extern const char kEnableBoundSessionCredentialsDescription[]; + +extern const char + kEnableBoundSessionCredentialsSoftwareKeysForManualTestingName[]; +extern const char + kEnableBoundSessionCredentialsSoftwareKeysForManualTestingDescription[]; #endif // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS) #if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
diff --git a/chrome/browser/privacy_budget/encountered_surface_tracker.cc b/chrome/browser/privacy_budget/encountered_surface_tracker.cc index d384ae4..14121956 100644 --- a/chrome/browser/privacy_budget/encountered_surface_tracker.cc +++ b/chrome/browser/privacy_budget/encountered_surface_tracker.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/privacy_budget/encountered_surface_tracker.h" +#include <set> #include <vector> #include "base/rand_util.h" @@ -11,24 +12,8 @@ #include "chrome/browser/privacy_budget/identifiability_study_state.h" #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" -namespace { - -uint64_t hash(uint64_t x) { - // This is should be a reasonable and fast reversible hash. - // Based a bit on https://naml.us/post/inverse-of-a-hash-function/ - x = x * 88388617; // calculate as (x<<23)+(x<<3)+x - x = x ^ (x >> 31); - x = x * 257; // calculate as (x<<8)+x - x = x ^ (x >> 13); - x = x * 769; // calculate as (x<<9)+(x<<8)+x - x = x ^ (x >> 23); - x = x * 127; // calculate as (x<<7)-x - return x; -} - -} // namespace - const unsigned EncounteredSurfaceTracker::kMaxTrackedSurfaces; +const unsigned EncounteredSurfaceTracker::kMaxTrackedSources; EncounteredSurfaceTracker::EncounteredSurfaceTracker() { Reset(); @@ -37,7 +22,6 @@ EncounteredSurfaceTracker::~EncounteredSurfaceTracker() = default; void EncounteredSurfaceTracker::Reset() { - seed_ = base::RandUint64(); surfaces_.clear(); } @@ -47,24 +31,24 @@ blink::IdentifiableSurface::Type::kReservedInternal) return false; - HashKey key = hash(surface ^ seed_); - auto it = surfaces_.find(key); + auto it = surfaces_.find(surface); if (it == surfaces_.end()) { - if (surfaces_.size() >= kMaxTrackedSurfaces && - key <= surfaces_.begin()->first) { - return false; - } // We need to add an entry for this surface, possibly bumping an entry out. - surfaces_.insert(std::make_pair(key, base::flat_set<uint64_t>{source_id})); + surfaces_.insert(std::make_pair(surface, std::set<uint64_t>{source_id})); if (surfaces_.size() > kMaxTrackedSurfaces) { - // Remove the smallest - surfaces_.erase(surfaces_.begin()); + // Remove a random one. + surfaces_.erase(base::RandInt(0, kMaxTrackedSurfaces)); } return true; } if (it->second.contains(source_id)) return false; + it->second.insert(source_id); + if (it->second.size() > kMaxTrackedSources) { + // Remove a random one. + it->second.erase(base::RandInt(0, kMaxTrackedSources)); + } return true; }
diff --git a/chrome/browser/privacy_budget/encountered_surface_tracker.h b/chrome/browser/privacy_budget/encountered_surface_tracker.h index 32d0ac6..1e0cf54b 100644 --- a/chrome/browser/privacy_budget/encountered_surface_tracker.h +++ b/chrome/browser/privacy_budget/encountered_surface_tracker.h
@@ -8,8 +8,7 @@ #include <stdint.h> #include <map> - -#include "base/containers/flat_set.h" +#include <set> class EncounteredSurfaceTracker { public: @@ -17,6 +16,10 @@ // memory growth. static constexpr unsigned kMaxTrackedSurfaces = 1000; + // Maximum number of sources that every surface can track. Prevents unbounded + // memory growth. + static constexpr unsigned kMaxTrackedSources = 1000; + EncounteredSurfaceTracker(); ~EncounteredSurfaceTracker(); @@ -25,10 +28,9 @@ void Reset(); private: - using HashKey = uint64_t; - // We use std::map since it makes it fast to remove the minimum. - std::map<HashKey, base::flat_set<uint64_t>> surfaces_; - uint64_t seed_; + // We use std::map and std::set since these containers are small and we need + // to insert and erase frequently. + std::map<uint64_t, std::set<uint64_t>> surfaces_; }; #endif // CHROME_BROWSER_PRIVACY_BUDGET_ENCOUNTERED_SURFACE_TRACKER_H_
diff --git a/chrome/browser/privacy_budget/encountered_surface_tracker_unittest.cc b/chrome/browser/privacy_budget/encountered_surface_tracker_unittest.cc index c5bb4da..41c3b55 100644 --- a/chrome/browser/privacy_budget/encountered_surface_tracker_unittest.cc +++ b/chrome/browser/privacy_budget/encountered_surface_tracker_unittest.cc
@@ -4,11 +4,13 @@ #include "chrome/browser/privacy_budget/encountered_surface_tracker.h" +#include "base/containers/flat_set.h" +#include "base/rand_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" namespace { -uint64_t metric(int i) { +uint64_t metric(uint64_t i) { return blink::IdentifiableSurface::FromTypeAndToken( blink::IdentifiableSurface::Type::kWebFeature, i) .ToUkmMetricHash(); @@ -22,6 +24,34 @@ EXPECT_TRUE(t.IsNewEncounter(1, metric(1))); } +TEST(EncounteredSurfaceTrackerTest, NeverDropsNewSurface) { + EncounteredSurfaceTracker t; + std::set<uint64_t> rand_numbers; + for (uint64_t i = 0; i < 10000; ++i) { + uint64_t new_rand_number; + bool inserted; + do { + new_rand_number = base::RandUint64(); + inserted = rand_numbers.insert(new_rand_number).second; + } while (!inserted); + EXPECT_TRUE(t.IsNewEncounter(0, metric(new_rand_number))); + } +} + +TEST(EncounteredSurfaceTrackerTest, NeverDropsNewSource) { + EncounteredSurfaceTracker t; + std::set<uint64_t> rand_numbers; + for (uint64_t i = 0; i < 10000; ++i) { + uint64_t new_rand_number; + bool inserted; + do { + new_rand_number = base::RandUint64(); + inserted = rand_numbers.insert(new_rand_number).second; + } while (!inserted); + EXPECT_TRUE(t.IsNewEncounter(new_rand_number, metric(0))); + } +} + TEST(EncounteredSurfaceTrackerTest, SizeLimit) { EncounteredSurfaceTracker t; for (uint64_t i = 0; i < EncounteredSurfaceTracker::kMaxTrackedSurfaces; @@ -36,16 +66,8 @@ } // Add an extra one. This should bump one of the surfaces out. - t.IsNewEncounter(0, EncounteredSurfaceTracker::kMaxTrackedSurfaces + 1); - - // We expect only kMaxTrackedSurfaces to return true for a new surface. - unsigned num_true = 0; - for (uint64_t i = 0; i < EncounteredSurfaceTracker::kMaxTrackedSurfaces + 1; - i++) { - if (t.IsNewEncounter(2, metric(i))) - num_true++; - } - EXPECT_EQ(EncounteredSurfaceTracker::kMaxTrackedSurfaces, num_true); + EXPECT_TRUE( + t.IsNewEncounter(0, EncounteredSurfaceTracker::kMaxTrackedSurfaces + 1)); } TEST(EncounteredSurfaceTrackerTest, Reset) {
diff --git a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_dialog.ts b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_dialog.ts index f25a8ac..0648b588 100644 --- a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_dialog.ts +++ b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_dialog.ts
@@ -17,9 +17,10 @@ import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {castExists} from '../assert_extras.js'; -import {GeolocationAccessLevel} from './privacy_hub_geolocation_subpage.js'; import {getTemplate} from './privacy_hub_geolocation_dialog.html.js'; +import {GEOLOCATION_ACCESS_LEVEL_ENUM_SIZE, GeolocationAccessLevel} from './privacy_hub_geolocation_subpage.js'; +import {LOCATION_PERMISSION_CHANGE_FROM_DIALOG_HISTOGRAM_NAME} from './privacy_hub_metrics_util.js'; const PrivacyHubGeolocationDialogBase = PrefsMixin(PolymerElement); @@ -42,6 +43,11 @@ this.setPrefValue( 'ash.user.geolocation_access_level', GeolocationAccessLevel.ONLY_ALLOWED_FOR_SYSTEM); + chrome.metricsPrivate.recordEnumerationValue( + LOCATION_PERMISSION_CHANGE_FROM_DIALOG_HISTOGRAM_NAME, + GeolocationAccessLevel.ONLY_ALLOWED_FOR_SYSTEM, + GEOLOCATION_ACCESS_LEVEL_ENUM_SIZE); + this.getDialog_().close(); }
diff --git a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.html b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.html index 4221ad9..171a004 100644 --- a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.html +++ b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.html
@@ -6,11 +6,13 @@ <div - id="geolocationDropdownMenu" + id="geolocationDropdownDiv" class="settings-box first"> <settings-dropdown-menu + id="geolocationDropdown" label="Label here" menu-options="[[geolocationMapTargets_]]" + on-settings-control-change="recordMetric_" pref="{{prefs.ash.user.geolocation_access_level}}"> </settings-dropdown-menu> </div>
diff --git a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts index bb00735..62c096f 100644 --- a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts +++ b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_geolocation_subpage.ts
@@ -8,11 +8,13 @@ * the state of the system geolocation access. */ -import {DropdownMenuOptionList} from '/shared/settings/controls/settings_dropdown_menu.js'; +import {DropdownMenuOptionList, SettingsDropdownMenuElement} from '/shared/settings/controls/settings_dropdown_menu.js'; +import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js'; import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './privacy_hub_geolocation_subpage.html.js'; +import {LOCATION_PERMISSION_CHANGE_FROM_SETTINGS_HISTOGRAM_NAME} from './privacy_hub_metrics_util.js'; /** * Geolocation access levels for the ChromeOS system. @@ -25,7 +27,17 @@ ONLY_ALLOWED_FOR_SYSTEM = 2, } -const SettingsPrivacyHubGeolocationSubpageBase = I18nMixin(PolymerElement); +export const GEOLOCATION_ACCESS_LEVEL_ENUM_SIZE = + Object.keys(GeolocationAccessLevel).length; + +export interface SettingsPrivacyHubGeolocationSubpage { + $: { + geolocationDropdown: SettingsDropdownMenuElement, + }; +} + +const SettingsPrivacyHubGeolocationSubpageBase = + PrefsMixin(I18nMixin(PolymerElement)); export class SettingsPrivacyHubGeolocationSubpage extends SettingsPrivacyHubGeolocationSubpageBase { @@ -62,6 +74,14 @@ } private geolocationMapTargets_: DropdownMenuOptionList; + + private recordMetric_(): void { + const accessLevel = this.$.geolocationDropdown.pref!.value; + + chrome.metricsPrivate.recordEnumerationValue( + LOCATION_PERMISSION_CHANGE_FROM_SETTINGS_HISTOGRAM_NAME, accessLevel, + GEOLOCATION_ACCESS_LEVEL_ENUM_SIZE); + } } declare global {
diff --git a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_metrics_util.ts b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_metrics_util.ts index 233dc647..d493800 100644 --- a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_metrics_util.ts +++ b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_metrics_util.ts
@@ -8,6 +8,14 @@ 'ChromeOS.PrivacyHub.MicrophoneSubpage.UserAction'; export const LOCATION_SUBPAGE_USER_ACTION_HISTOGRAM_NAME = 'ChromeOS.PrivacyHub.LocationSubpage.UserAction'; + +export const LOCATION_PERMISSION_CHANGE_FROM_SETTINGS_HISTOGRAM_NAME = + 'ChromeOS.PrivacyHub.Geolocation.AccessLevelChanged.SystemSettings'; +export const LOCATION_PERMISSION_CHANGE_FROM_DIALOG_HISTOGRAM_NAME = + 'ChromeOS.PrivacyHub.Geolocation.AccessLevelChanged.GeolocationDialog'; +export const LOCATION_PERMISSION_CHANGE_FROM_NOTIFICATION_HISTOGRAM_NAME = + 'ChromeOS.PrivacyHub.Geolocation.AccessLevelChanged.' + + 'LocationPermissionNotification'; /** * Enumeration of the user actions that can be taken on the Privacy Hub sensor * subpages.
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index a26861f..139441d3 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -22,7 +22,7 @@ # chromevox scripts. # # TS files to compile. -ts_modules = [ "background/input/keyboard_handler.ts" ] +ts_modules = [] # TS files needed from ../common/. common_ts_modules = [ @@ -107,6 +107,7 @@ "background/input/command_handler_interface.js", "background/input/gesture_command_handler.js", "background/input/gesture_interface.js", + "background/input/keyboard_handler.js", "background/input/smart_sticky_mode.js", "background/live_regions.js", "background/logging/event_stream_logger.js", @@ -151,6 +152,7 @@ "common/key_map.js", "common/key_sequence.js", "common/key_util.js", + "common/keyboard_handler.js", "common/learn_mode_bridge.js", "common/locale_output_helper.js", "common/log_types.js", @@ -206,23 +208,8 @@ ts_library("ts_build") { root_dir = "../" out_dir = tsc_out_dir - - definitions = [ - "../definitions/tts.d.ts", - "//tools/typescript/definitions/metrics_private.d.ts", - "//tools/typescript/definitions/context_menus.d.ts", - "../definitions/automation.d.ts", - "../definitions/extensions.d.ts", - "../definitions/runtime.d.ts", - "../definitions/i18n.d.ts", - "../definitions/tabs.d.ts", - "../definitions/accessibility_private_mv2.d.ts", - "../definitions/settings_private_mv2.d.ts", - "../definitions/storage_mv2.d.ts", - "../definitions/clipboard_mv2.d.ts", - "../definitions/extension_types.d.ts", - "//tools/typescript/definitions/windows.d.ts", - ] + deps = [ "../common:ts_build" ] + definitions = [] in_files = [] foreach(_js_file, js_deps) { @@ -231,8 +218,6 @@ foreach(_ts_file, ts_modules) { in_files += [ "chromevox/" + _ts_file ] } - - tsconfig_base = "../tsconfig.base.json" } group("build") { @@ -259,10 +244,7 @@ run_jsbundler("chromevox_copied_files") { mode = "copy" dest_dir = chromevox_out_dir - deps = [ - ":ts_build", - "../common:ts_build", - ] + deps = [ "../common:ts_build" ] sources = [ "background/background.html", "earcons/chromevox_loaded.ogg",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler.ts b/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler.js similarity index 69% rename from chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler.ts rename to chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler.js index 87144ea..f7055982 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler.ts +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler.js
@@ -6,6 +6,7 @@ * @fileoverview ChromeVox keyboard handler. */ import {KeyCode} from '../../../common/key_code.js'; +import {EarconId} from '../../common/earcon_id.js'; import {EventSourceType} from '../../common/event_source_type.js'; import {ChromeVoxKbHandler} from '../../common/keyboard_handler.js'; import {Msgs} from '../../common/msgs.js'; @@ -19,35 +20,36 @@ import {ChromeVoxPrefs} from '../prefs.js'; /** + * @enum {string} * Internal pass through mode state (see usage below). + * @private */ -enum KeyboardPassThroughState { +const KeyboardPassThroughState_ = { // No pass through is in progress. - NO_PASS_THROUGH = 'no_pass_through', + NO_PASS_THROUGH: 'no_pass_through', // The pass through shortcut command has been pressed (keydowns), waiting for // user to release (keyups) all the shortcut keys. - PENDING_PASS_THROUGH_SHORTCUT_KEYUPS = 'pending_pass_through_keyups', + PENDING_PASS_THROUGH_SHORTCUT_KEYUPS: 'pending_pass_through_keyups', // The pass through shortcut command has been pressed and released, waiting // for the user to press/release a shortcut to be passed through. - PENDING_SHORTCUT_KEYUPS = 'pending_shortcut_keyups', -} - -class InternalKeyEvent extends KeyboardEvent { - stickyMode?: boolean; -} + PENDING_SHORTCUT_KEYUPS: 'pending_shortcut_keyups', +}; export class BackgroundKeyboardHandler { - static instance?: BackgroundKeyboardHandler; - private static passThroughModeEnabled_: boolean = false; - private eatenKeyDowns_: Set<number>; - private passThroughState_: KeyboardPassThroughState; - private passedThroughKeyDowns_: Set<number>; - - private constructor() { + /** @private */ + constructor() { + /** @private {Set} */ this.eatenKeyDowns_ = new Set(); - this.passThroughState_ = KeyboardPassThroughState.NO_PASS_THROUGH; + + /** @private {boolean} */ + this.passThroughModeEnabled_ = false; + + /** @private {!KeyboardPassThroughState_} */ + this.passThroughState_ = KeyboardPassThroughState_.NO_PASS_THROUGH; + + /** @private {Set} */ this.passedThroughKeyDowns_ = new Set(); document.addEventListener( @@ -58,24 +60,25 @@ true, ChromeVoxPrefs.isStickyPrefOn); } - static init(): void { + static init() { if (BackgroundKeyboardHandler.instance) { throw 'Error: trying to create two instances of singleton BackgroundKeyboardHandler.'; } BackgroundKeyboardHandler.instance = new BackgroundKeyboardHandler(); } - static enablePassThroughMode(): void { + static enablePassThroughMode() { ChromeVox.tts.speak(Msgs.getMsg('pass_through_key'), QueueMode.QUEUE); - BackgroundKeyboardHandler.passThroughModeEnabled_ = true; + BackgroundKeyboardHandler.instance.passThroughModeEnabled_ = true; } /** * Handles key down events. - * The return value has no effect since we ignore it in + * @param {Event} evt The key down event to process. + * @return {boolean} This value has no effect since we ignore it in * SpokenFeedbackEventRewriterDelegate::HandleKeyboardEvent. */ - onKeyDown(evt: InternalKeyEvent): boolean { + onKeyDown(evt) { EventSource.set(EventSourceType.STANDARD_KEYBOARD); evt.stickyMode = ChromeVoxPrefs.isStickyModeOn(); @@ -87,7 +90,7 @@ this.passedThroughKeyDowns_.clear(); } - if (BackgroundKeyboardHandler.passThroughModeEnabled_) { + if (this.passThroughModeEnabled_) { this.passedThroughKeyDowns_.add(evt.keyCode); return false; } @@ -99,9 +102,9 @@ if (!this.callOnKeyDownHandlers_(evt) || this.shouldConsumeSearchKey_(evt)) { - if (BackgroundKeyboardHandler.passThroughModeEnabled_) { + if (this.passThroughModeEnabled_) { this.passThroughState_ = - KeyboardPassThroughState.PENDING_PASS_THROUGH_SHORTCUT_KEYUPS; + KeyboardPassThroughState_.PENDING_PASS_THROUGH_SHORTCUT_KEYUPS; } evt.preventDefault(); evt.stopPropagation(); @@ -111,7 +114,12 @@ return false; } - private callOnKeyDownHandlers_(evt: Event): boolean { + /** + * @param {Event} evt The key down event to process. + * @return {boolean} Whether the event should continue propagating. + * @private + */ + callOnKeyDownHandlers_(evt) { // Defer first to the math handler, if it exists, then ordinary keyboard // commands. if (!MathHandler.onKeyDown(evt)) { @@ -126,7 +134,12 @@ return ChromeVoxKbHandler.basicKeyDownActionsListener(evt); } - private shouldConsumeSearchKey_(evt: InternalKeyEvent): boolean { + /** + * @param {Event} evt The key down event to evaluate. + * @return {boolean} Whether the event should be consumed. + * @private + */ + shouldConsumeSearchKey_(evt) { // We natively always capture Search, so we have to be very careful to // either eat it here or re-inject it; otherwise, some components, like // ARC++ with TalkBack never get it. We only want to re-inject when @@ -135,44 +148,49 @@ return false; } - return Boolean(evt.metaKey) || evt.keyCode === KeyCode['SEARCH']; + return Boolean(evt.metaKey) || evt.keyCode === KeyCode.SEARCH; } /** - * The return value has no effect since we ignore it in + * Handles key up events. + * @param {Event} evt The key up event to process. + * @return {boolean} This value has no effect since we ignore it in * SpokenFeedbackEventRewriterDelegate::HandleKeyboardEvent. */ - onKeyUp(evt: InternalKeyEvent): boolean { + onKeyUp(evt) { if (this.eatenKeyDowns_.has(evt.keyCode)) { evt.preventDefault(); evt.stopPropagation(); this.eatenKeyDowns_.delete(evt.keyCode); } - if (BackgroundKeyboardHandler.passThroughModeEnabled_) { + if (this.passThroughModeEnabled_) { this.passedThroughKeyDowns_.delete(evt.keyCode); // Assuming we have no keys held (detected by held modifiers + keys we've // eaten in key down), we can start pass through for the next keys. if (this.passThroughState_ === - KeyboardPassThroughState.PENDING_PASS_THROUGH_SHORTCUT_KEYUPS && + KeyboardPassThroughState_.PENDING_PASS_THROUGH_SHORTCUT_KEYUPS && !evt.altKey && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && this.eatenKeyDowns_.size === 0) { // All keys of the pass through shortcut command have been released. // Ready to pass through the next shortcut. this.passThroughState_ = - KeyboardPassThroughState.PENDING_SHORTCUT_KEYUPS; + KeyboardPassThroughState_.PENDING_SHORTCUT_KEYUPS; } else if ( this.passThroughState_ === - KeyboardPassThroughState.PENDING_SHORTCUT_KEYUPS && + KeyboardPassThroughState_.PENDING_SHORTCUT_KEYUPS && this.passedThroughKeyDowns_.size === 0) { // All keys of the passed through shortcut have been released. Ready to // go back to normal processing (aka no pass through). - BackgroundKeyboardHandler.passThroughModeEnabled_ = false; - this.passThroughState_ = KeyboardPassThroughState.NO_PASS_THROUGH; + this.passThroughModeEnabled_ = false; + this.passThroughState_ = KeyboardPassThroughState_.NO_PASS_THROUGH; } } return false; } } + +/** @type {BackgroundKeyboardHandler} */ +BackgroundKeyboardHandler.instance;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler_test.js index 0149195..f693f04 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/keyboard_handler_test.js
@@ -57,7 +57,7 @@ 'ChromeVoxBackgroundKeyboardHandlerTest', 'PassThroughMode', async function() { await this.runWithLoadedTree('<p>test</p>'); - assertFalse(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertFalse(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); assertEquals('no_pass_through', keyboardHandler.passThroughState_); assertEquals(0, keyboardHandler.eatenKeyDowns_.size); assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); @@ -69,7 +69,7 @@ assertEquals(1, keyboardHandler.eatenKeyDowns_.size); assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); assertEquals('no_pass_through', keyboardHandler.passThroughState_); - assertFalse(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertFalse(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); const searchShift = TestUtils.createMockKeyEvent( KeyCode.SHIFT, {metaKey: true, shiftKey: true}); @@ -77,7 +77,7 @@ assertEquals(2, keyboardHandler.eatenKeyDowns_.size); assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); assertEquals('no_pass_through', keyboardHandler.passThroughState_); - assertFalse(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertFalse(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); const searchShiftEsc = TestUtils.createMockKeyEvent( KeyCode.ESCAPE, {metaKey: true, shiftKey: true}); @@ -86,14 +86,14 @@ assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_pass_through_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); keyboardHandler.onKeyUp(searchShiftEsc); assertEquals(2, keyboardHandler.eatenKeyDowns_.size); assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_pass_through_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); const searchShiftUp = TestUtils.createMockKeyEvent( KeyCode.SHIFT, {metaKey: true, shiftKey: false}); @@ -102,7 +102,7 @@ assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_pass_through_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); const searchUp = TestUtils.createMockKeyEvent(KeyCode.SEARCH, {metaKey: false}); @@ -111,7 +111,7 @@ assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_shortcut_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); // Now, the next series of key downs should be passed through. // Try Search+Ctrl+M. @@ -120,7 +120,7 @@ assertEquals(1, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_shortcut_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); const searchCtrl = TestUtils.createMockKeyEvent( KeyCode.CONTROL, {metaKey: true, ctrlKey: true}); @@ -129,7 +129,7 @@ assertEquals(2, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_shortcut_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); const searchCtrlM = TestUtils.createMockKeyEvent( KeyCode.M, {metaKey: true, ctrlKey: true}); @@ -138,27 +138,27 @@ assertEquals(3, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_shortcut_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); keyboardHandler.onKeyUp(searchCtrlM); assertEquals(0, keyboardHandler.eatenKeyDowns_.size); assertEquals(2, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_shortcut_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); keyboardHandler.onKeyUp(searchCtrl); assertEquals(0, keyboardHandler.eatenKeyDowns_.size); assertEquals(1, keyboardHandler.passedThroughKeyDowns_.size); assertEquals( 'pending_shortcut_keyups', keyboardHandler.passThroughState_); - assertTrue(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertTrue(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); keyboardHandler.onKeyUp(search); assertEquals(0, keyboardHandler.eatenKeyDowns_.size); assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); assertEquals('no_pass_through', keyboardHandler.passThroughState_); - assertFalse(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertFalse(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); }); AX_TEST_F( @@ -166,7 +166,7 @@ async function() { await this.runWithLoadedTree('<p>test</p>'); function assertNoPassThrough() { - assertFalse(BackgroundKeyboardHandler.passThroughModeEnabled_); + assertFalse(BackgroundKeyboardHandler.instance.passThroughModeEnabled_); assertEquals('no_pass_through', keyboardHandler.passThroughState_); assertEquals(0, keyboardHandler.passedThroughKeyDowns_.size); } @@ -246,7 +246,7 @@ 'UnexpectedKeyDownUpPairsPassThrough', async function() { await this.runWithLoadedTree('<p>test</p>'); // Force pass through mode. - BackgroundKeyboardHandler.passThroughModeEnabled_ = true; + BackgroundKeyboardHandler.instance.passThroughModeEnabled_ = true; // Send a few key downs (which are passed through). const search =
diff --git a/chrome/browser/resources/chromeos/login/login.gni b/chrome/browser/resources/chromeos/login/login.gni index a9cfea16..58416083 100644 --- a/chrome/browser/resources/chromeos/login/login.gni +++ b/chrome/browser/resources/chromeos/login/login.gni
@@ -95,7 +95,7 @@ "screens/oobe/auto_enrollment_check.js", "screens/oobe/consumer_update.js", "screens/oobe/demo_preferences.ts", - "screens/oobe/demo_setup.js", + "screens/oobe/demo_setup.ts", "screens/oobe/enable_debugging.js", "screens/oobe/enterprise_enrollment.js", "screens/oobe/hid_detection.js",
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn index 70b4460e..fad95fb 100644 --- a/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/screens/oobe/BUILD.gn
@@ -19,7 +19,6 @@ deps = [ ":auto_enrollment_check", ":consumer_update", - ":demo_setup", ":enable_debugging", ":enterprise_enrollment", ":hid_detection", @@ -58,20 +57,6 @@ extra_deps = [ ":web_components" ] } -js_library("demo_setup") { - sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/oobe/demo_setup.js" ] - deps = [ - "../../components:progress_list_item", - "../../components/behaviors:login_screen_behavior", - "../../components/behaviors:multi_step_behavior", - "../../components/behaviors:oobe_dialog_host_behavior", - "../../components/behaviors:oobe_i18n_behavior", - "../../components/dialogs:oobe_adaptive_dialog", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] - extra_deps = [ ":web_components" ] -} - js_library("enable_debugging") { sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/oobe/enable_debugging.js" ] deps = [
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/demo_setup.js b/chrome/browser/resources/chromeos/login/screens/oobe/demo_setup.js deleted file mode 100644 index 89489154..0000000 --- a/chrome/browser/resources/chromeos/login/screens/oobe/demo_setup.js +++ /dev/null
@@ -1,230 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Polymer element for displaying material design Demo Setup - * screen. - */ - -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; -import '../../components/oobe_icons.html.js'; -import '../../components/buttons/oobe_back_button.js'; -import '../../components/buttons/oobe_text_button.js'; -import '../../components/common_styles/oobe_common_styles.css.js'; -import '../../components/common_styles/oobe_dialog_host_styles.css.js'; -import '../../components/dialogs/oobe_adaptive_dialog.js'; -import '../../components/progress_list_item.js'; - -import {loadTimeData} from '//resources/ash/common/load_time_data.m.js'; -import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {LoginScreenBehavior, LoginScreenBehaviorInterface} from '../../components/behaviors/login_screen_behavior.js'; -import {MultiStepBehavior, MultiStepBehaviorInterface} from '../../components/behaviors/multi_step_behavior.js'; -import {OobeDialogHostBehavior} from '../../components/behaviors/oobe_dialog_host_behavior.js'; -import {OobeI18nBehavior, OobeI18nBehaviorInterface} from '../../components/behaviors/oobe_i18n_behavior.js'; - -import {getTemplate} from './demo_setup.html.js'; - - -/** - * UI mode for the dialog. - * @enum {string} - */ -const DemoSetupUIState = { - PROGRESS: 'progress', - ERROR: 'error', -}; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {LoginScreenBehaviorInterface} - * @implements {MultiStepBehaviorInterface} - * @implements {OobeI18nBehaviorInterface} - */ -const DemoSetupScreenBase = mixinBehaviors( - [ - OobeI18nBehavior, - OobeDialogHostBehavior, - LoginScreenBehavior, - MultiStepBehavior, - ], - PolymerElement); - -/** - * @polymer - */ -class DemoSetupScreen extends DemoSetupScreenBase { - static get is() { - return 'demo-setup-element'; - } - - static get template() { - return getTemplate(); - } - - static get properties() { - return { - /** Object mapping step strings to step indices */ - setupSteps_: { - type: Object, - value() { - return /** @type {!Object} */ ( - loadTimeData.getValue('demoSetupSteps')); - }, - }, - - /** Which step index is currently running in Demo Mode setup. */ - currentStepIndex_: { - type: Number, - value: -1, - }, - - /** Error message displayed on demoSetupErrorDialog screen. */ - errorMessage_: { - type: String, - value: '', - }, - - /** Whether powerwash is required in case of a setup error. */ - isPowerwashRequired_: { - type: Boolean, - value: false, - }, - }; - } - - constructor() { - super(); - } - - /** @override */ - ready() { - super.ready(); - this.initializeLoginScreen('DemoSetupScreen'); - } - - defaultUIStep() { - return DemoSetupUIState.PROGRESS; - } - - get UI_STEPS() { - return DemoSetupUIState; - } - - /** Overridden from LoginScreenBehavior. */ - // clang-format off - get EXTERNAL_API() { - return ['setCurrentSetupStep', - 'onSetupSucceeded', - 'onSetupFailed']; - } - // clang-format on - - - onBeforeShow() { - this.reset(); - } - - /** Resets demo setup flow to the initial screen and starts setup. */ - reset() { - this.setUIStep(DemoSetupUIState.PROGRESS); - this.userActed('start-setup'); - } - - /** Called after resources are updated. */ - updateLocalizedContent() { - this.i18nUpdateLocale(); - } - - /** - * Called at the beginning of a setup step. - * @param {string} currentStep The new step name. - */ - setCurrentSetupStep(currentStep) { - // If new step index not specified, remain unchanged. - if (this.setupSteps_.hasOwnProperty(currentStep)) { - this.currentStepIndex_ = this.setupSteps_[currentStep]; - } - } - - /** Called when demo mode setup succeeded. */ - onSetupSucceeded() { - this.errorMessage_ = ''; - } - - /** - * Called when demo mode setup failed. - * @param {string} message Error message to be displayed to the user. - * @param {boolean} isPowerwashRequired Whether powerwash is required to - * recover from the error. - */ - onSetupFailed(message, isPowerwashRequired) { - this.errorMessage_ = message; - this.isPowerwashRequired_ = isPowerwashRequired; - this.setUIStep(DemoSetupUIState.ERROR); - } - - /** - * Retry button click handler. - * @private - */ - onRetryClicked_() { - this.reset(); - } - - /** - * Powerwash button click handler. - * @private - */ - onPowerwashClicked_() { - this.userActed('powerwash'); - } - - /** - * Close button click handler. - * @private - */ - onCloseClicked_() { - // TODO(wzang): Remove this after crbug.com/900640 is fixed. - if (this.isPowerwashRequired_) { - return; - } - this.userActed('close-setup'); - } - - /** - * Whether a given step should be rendered on the UI. - * @param {string} stepName The name of the step (from the enum). - * @param {!Object} setupSteps - * @private - */ - shouldShowStep_(stepName, setupSteps) { - return setupSteps.hasOwnProperty(stepName); - } - - /** - * Whether a given step is active. - * @param {string} stepName The name of the step (from the enum). - * @param {!Object} setupSteps - * @param {number} currentStepIndex - * @private - */ - stepIsActive_(stepName, setupSteps, currentStepIndex) { - return currentStepIndex === setupSteps[stepName]; - } - - /** - * Whether a given step is completed. - * @param {string} stepName The name of the step (from the enum). - * @param {!Object} setupSteps - * @param {number} currentStepIndex - * @private - */ - stepIsCompleted_(stepName, setupSteps, currentStepIndex) { - return currentStepIndex > setupSteps[stepName]; - } -} - -customElements.define(DemoSetupScreen.is, DemoSetupScreen);
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/demo_setup.ts b/chrome/browser/resources/chromeos/login/screens/oobe/demo_setup.ts new file mode 100644 index 0000000..c9350478 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/screens/oobe/demo_setup.ts
@@ -0,0 +1,221 @@ +// Copyright 2017 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Polymer element for displaying material design Demo Setup + * screen. + */ + +import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import '../../components/oobe_icons.html.js'; +import '../../components/buttons/oobe_back_button.js'; +import '../../components/buttons/oobe_text_button.js'; +import '../../components/common_styles/oobe_common_styles.css.js'; +import '../../components/common_styles/oobe_dialog_host_styles.css.js'; +import '../../components/dialogs/oobe_adaptive_dialog.js'; +import '../../components/progress_list_item.js'; + +import {loadTimeData} from '//resources/js/load_time_data.js'; +import {PolymerElementProperties} from '//resources/polymer/v3_0/polymer/interfaces.js'; +import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {LoginScreenBehavior, LoginScreenBehaviorInterface} from '../../components/behaviors/login_screen_behavior.js'; +import {MultiStepBehavior, MultiStepBehaviorInterface} from '../../components/behaviors/multi_step_behavior.js'; +import {OobeDialogHostBehavior, OobeDialogHostBehaviorInterface} from '../../components/behaviors/oobe_dialog_host_behavior.js'; +import {OobeI18nBehavior, OobeI18nBehaviorInterface} from '../../components/behaviors/oobe_i18n_behavior.js'; + +import {getTemplate} from './demo_setup.html.js'; + +/** + * UI mode for the dialog. + */ +enum DemoSetupUiState { + PROGRESS = 'progress', + ERROR = 'error', +} + +export const DemoSetupScreenBase = mixinBehaviors( + [ + OobeI18nBehavior, + OobeDialogHostBehavior, + LoginScreenBehavior, + MultiStepBehavior, + ], + PolymerElement) as { + new (): PolymerElement & OobeI18nBehaviorInterface & + OobeDialogHostBehaviorInterface & LoginScreenBehaviorInterface & + MultiStepBehaviorInterface, +}; + +class DemoSetupScreen extends DemoSetupScreenBase { + static get is() { + return 'demo-setup-element' as const; + } + + static get template(): HTMLTemplateElement { + return getTemplate(); + } + + static get properties(): PolymerElementProperties { + return { + /** Object mapping step strings to step indices */ + setupSteps_: { + type: Object, + value() { + return loadTimeData.getValue('demoSetupSteps'); + }, + }, + + /** Which step index is currently running in Demo Mode setup. */ + currentStepIndex_: { + type: Number, + value: -1, + }, + + /** Error message displayed on demoSetupErrorDialog screen. */ + errorMessage_: { + type: String, + value: '', + }, + + /** Whether powerwash is required in case of a setup error. */ + isPowerwashRequired_: { + type: Boolean, + value: false, + }, + }; + } + + private setupSteps_: Record<string, number>; + private currentStepIndex_: number; + private errorMessage_: string; + private isPowerwashRequired_: boolean; + + constructor() { + super(); + } + + override ready(): void { + super.ready(); + this.initializeLoginScreen('DemoSetupScreen'); + } + + // eslint-disable-next-line @typescript-eslint/naming-convention + override defaultUIStep() { + return DemoSetupUiState.PROGRESS; + } + + override get UI_STEPS() { + return DemoSetupUiState; + } + + /** Overridden from LoginScreenBehavior. */ + override get EXTERNAL_API(): string[] { + return ['setCurrentSetupStep', 'onSetupSucceeded', 'onSetupFailed']; + } + + override onBeforeShow(): void { + this.reset(); + } + + /** Resets demo setup flow to the initial screen and starts setup. */ + reset(): void { + this.setUIStep(DemoSetupUiState.PROGRESS); + this.userActed('start-setup'); + } + + /** Called after resources are updated. */ + override updateLocalizedContent(): void { + this.i18nUpdateLocale(); + } + + /** + * Called at the beginning of a setup step. + * @param currentStep The new step name. + */ + setCurrentSetupStep(currentStep: string): void { + // If new step index not specified, remain unchanged. + if (this.setupSteps_.hasOwnProperty(currentStep)) { + this.currentStepIndex_ = this.setupSteps_[currentStep]; + } + } + + /** Called when demo mode setup succeeded. */ + onSetupSucceeded(): void { + this.errorMessage_ = ''; + } + + /** + * Called when demo mode setup failed. + * @param message Error message to be displayed to the user. + * @param isPowerwashRequired Whether powerwash is required to + * recover from the error. + */ + onSetupFailed(message: string, isPowerwashRequired: boolean): void { + this.errorMessage_ = message; + this.isPowerwashRequired_ = isPowerwashRequired; + this.setUIStep(DemoSetupUiState.ERROR); + } + + /** + * Retry button click handler. + */ + private onRetryClicked_(): void { + this.reset(); + } + + /** + * Powerwash button click handler. + */ + private onPowerwashClicked_(): void { + this.userActed('powerwash'); + } + + /** + * Close button click handler. + */ + private onCloseClicked_(): void { + // TODO(wzang): Remove this after crbug.com/900640 is fixed. + if (this.isPowerwashRequired_) { + return; + } + this.userActed('close-setup'); + } + + /** + * Whether a given step should be rendered on the UI. + * @param stepName The name of the step (from the enum). + */ + private shouldShowStep_(stepName: string, setupSteps: Object): boolean { + return setupSteps.hasOwnProperty(stepName); + } + + /** + * Whether a given step is active. + * @param stepName The name of the step (from the enum). + */ + private stepIsActive_( + stepName: string, setupSteps: Record<string, number>, + currentStepIndex: number): boolean { + return currentStepIndex === setupSteps[stepName]; + } + + /** + * Whether a given step is completed. + * @param stepName The name of the step (from the enum). + */ + private stepIsCompleted_( + stepName: string, setupSteps: Record<string, number>, + currentStepIndex: number): boolean { + return currentStepIndex > setupSteps[stepName]; + } +} + +declare global { + interface HTMLElementTagNameMap { + [DemoSetupScreen.is]: DemoSetupScreen; + } +} + +customElements.define(DemoSetupScreen.is, DemoSetupScreen);
diff --git a/chrome/browser/resources/chromeos/login/screens/osauth/local_data_loss_warning.html b/chrome/browser/resources/chromeos/login/screens/osauth/local_data_loss_warning.html index 32b6f71..8ca37310 100644 --- a/chrome/browser/resources/chromeos/login/screens/osauth/local_data_loss_warning.html +++ b/chrome/browser/resources/chromeos/login/screens/osauth/local_data_loss_warning.html
@@ -43,7 +43,7 @@ </oobe-back-button> </div> <div slot="bottom-buttons"> - <oobe-text-button hidden="[[isOwner]]" id="proceedAnyway" + <oobe-text-button hidden="[[isOwner]]" id="proceedRemove" on-click="onProceedClicked_" text-key="continueAnywayButtonLabel"> </oobe-text-button> <oobe-text-button hidden= "[[!isOwner]]" id="powerwash"
diff --git a/chrome/browser/resources/search_engine_choice/app.html b/chrome/browser/resources/search_engine_choice/app.html index e40a217c..7fc1c928 100644 --- a/chrome/browser/resources/search_engine_choice/app.html +++ b/chrome/browser/resources/search_engine_choice/app.html
@@ -8,6 +8,7 @@ --search-engine-omnibox-shadow-color: var(--google-grey-300); --scrollbar-height: 116px; --action-button-margins: 40px; + --omnibox-width: 252px; color: var(--cr-primary-text-color); } @@ -72,7 +73,7 @@ flex-direction: row; gap: 12px; padding: var(--dummy-omnibox-vertical-padding) 0; - width: 230px; + width: var(--omnibox-width); } /* We modify the bottom and transform parameters so that the @@ -92,7 +93,7 @@ opacity: 0; position: absolute; transform: translateY(var(--search-engine-omnibox-bottom-value)); - width: 234px; + width: var(--omnibox-width); } .fade-in-animation { @@ -145,7 +146,7 @@ .omnibox-text, .choice-title { font-family: Roboto, Arial; - font-size: 0.875rem; + font-size: 0.8125rem; font-weight: 400; line-height: 20px; text-align: start; @@ -276,12 +277,6 @@ transform: rotate(5deg); } - /* To add a bouncing effect. */ - 90% { - top: -9%; - transform: translateY(0); - } - 100% { opacity: 1; top: 0;
diff --git a/chrome/browser/sync/test/integration/ash_trusted_vault_keys_sharing_sync_test.cc b/chrome/browser/sync/test/integration/ash_trusted_vault_keys_sharing_sync_test.cc index d0e0cb7..f1bd1ab9 100644 --- a/chrome/browser/sync/test/integration/ash_trusted_vault_keys_sharing_sync_test.cc +++ b/chrome/browser/sync/test/integration/ash_trusted_vault_keys_sharing_sync_test.cc
@@ -2,29 +2,95 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <ostream> + #include "base/files/file_path.h" +#include "base/notreached.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/sync/sync_error_notifier.h" +#include "chrome/browser/ash/sync/sync_error_notifier_factory.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/sync/test/integration/encryption_helper.h" #include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/trusted_vault/trusted_vault_service_factory.h" +#include "chrome/browser/ui/webui/trusted_vault/trusted_vault_dialog_delegate.h" +#include "chrome/grit/generated_resources.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "chromeos/ash/components/standalone_browser/standalone_browser_features.h" #include "chromeos/crosapi/mojom/trusted_vault.mojom.h" #include "components/sync/service/sync_service_impl.h" +#include "components/sync/test/fake_server_nigori_helper.h" +#include "components/sync/test/nigori_test_utils.h" #include "components/trusted_vault/features.h" #include "components/trusted_vault/trusted_vault_client.h" #include "components/trusted_vault/trusted_vault_server_constants.h" #include "components/trusted_vault/trusted_vault_service.h" #include "content/public/test/browser_test.h" +#include "google_apis/gaia/gaia_switches.h" #include "mojo/public/cpp/bindings/remote.h" #include "testing/gmock/include/gmock/gmock.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/test/widget_test.h" +#include "ui/views/widget/any_widget_observer.h" namespace { +using testing::ElementsAre; using testing::Eq; +using testing::IsEmpty; using testing::NotNull; +class TrustedVaultStateNotifiedToCrosapiObserverChecker + : public StatusChangeChecker, + public crosapi::mojom::TrustedVaultBackendObserver { + public: + enum class ExpectedNotification { kKeysChanged, kRecoverabilityStateChanged }; + + TrustedVaultStateNotifiedToCrosapiObserverChecker( + mojo::Remote<crosapi::mojom::TrustedVaultBackend>* backend_remote, + ExpectedNotification expected_notification) + : expected_notification_(expected_notification) { + CHECK(backend_remote); + backend_remote->get()->AddObserver(receiver_.BindNewPipeAndPassRemote()); + backend_remote->FlushForTesting(); + } + + // crosapi::mojom::TrustedVaultBackendObserver overrides. + void OnTrustedVaultKeysChanged() override { + keys_changed_notified_ = true; + CheckExitCondition(); + } + + void OnTrustedVaultRecoverabilityChanged() override { + recoverability_state_changed_notified_ = true; + CheckExitCondition(); + } + + // StatusChangeChecker overrides. + bool IsExitConditionSatisfied(std::ostream* os) override { + switch (expected_notification_) { + case ExpectedNotification::kKeysChanged: + *os << "Waiting for OnTrustedVaultKeysChanged() call for crosapi " + "observer."; + return keys_changed_notified_; + case ExpectedNotification::kRecoverabilityStateChanged: + *os << "Waiting for OnTrustedVaultRecoverabilityChanged() call for " + "crosapi observer."; + return recoverability_state_changed_notified_; + } + NOTREACHED_NORETURN(); + } + + private: + bool keys_changed_notified_ = false; + bool recoverability_state_changed_notified_ = false; + + ExpectedNotification expected_notification_; + mojo::Receiver<crosapi::mojom::TrustedVaultBackendObserver> receiver_{this}; +}; + class AshTrustedVaultKeysSharingSyncTest : public SyncTest { public: AshTrustedVaultKeysSharingSyncTest() : SyncTest(SINGLE_CLIENT) { @@ -49,6 +115,22 @@ ash::BrowserContextHelper::kTestUserBrowserContextDirName); } + void SetUpCommandLine(base::CommandLine* command_line) override { + SyncTest::SetUpCommandLine(command_line); + + ASSERT_TRUE(embedded_https_test_server().InitializeAndListen()); + const GURL& base_url = embedded_https_test_server().base_url(); + command_line->AppendSwitchASCII(switches::kGaiaUrl, base_url.spec()); + } + + void SetUpOnMainThread() override { + SyncTest::SetUpOnMainThread(); + trusted_vault_widget_shown_waiter_ = + std::make_unique<views::NamedWidgetShownWaiter>( + views::test::AnyWidgetTestPasskey{}, + TrustedVaultDialogDelegate::kWidgetName); + } + void SetupCrosapi() { ASSERT_TRUE(crosapi::browser_util::IsLacrosEnabled()); @@ -60,6 +142,20 @@ trusted_vault_backend_remote_.BindNewPipeAndPassReceiver()); } + bool SetupSyncAndTrustedVaultFakes() { + if (!SetupSync()) { + return false; + } + + encryption_helper::SetupFakeTrustedVaultPages( + GetSyncService(0)->GetAccountInfo().gaia, kTestTrustedVaultKey, + /*trusted_vault_key_version=*/1, + /*recovery_method_public_key=*/{}, &embedded_https_test_server()); + embedded_https_test_server().StartAcceptingConnections(); + + return true; + } + trusted_vault::TrustedVaultClient& GetAshSyncTrustedVaultClient() { trusted_vault::TrustedVaultService* trusted_vault_service = TrustedVaultServiceFactory::GetForProfile(GetProfile(0)); @@ -83,6 +179,14 @@ return fetched_keys_future.Take(); } + TrustedVaultStateNotifiedToCrosapiObserverChecker + CreateTrustedVaultStateNotifiedToCrosapiObserverChecker( + TrustedVaultStateNotifiedToCrosapiObserverChecker::ExpectedNotification + expected_notification) { + return TrustedVaultStateNotifiedToCrosapiObserverChecker( + &trusted_vault_backend_remote_, expected_notification); + } + CoreAccountInfo GetSyncingUserAccountInfo() { return GetSyncService(0)->GetAccountInfo(); } @@ -94,26 +198,94 @@ return account_key; } + bool WaitForTrustedVaultReauthCompletion() { + CHECK(trusted_vault_widget_shown_waiter_); + views::Widget* trusted_vault_widged = + trusted_vault_widget_shown_waiter_->WaitIfNeededAndGet(); + views::test::WidgetDestroyedWaiter(trusted_vault_widged).Wait(); + return true; + } + + protected: + const std::vector<uint8_t> kTestTrustedVaultKey = {1, 2, 3}; + private: base::test::ScopedFeatureList feature_list_; + std::unique_ptr<views::NamedWidgetShownWaiter> + trusted_vault_widget_shown_waiter_; + mojo::Remote<crosapi::mojom::TrustedVaultBackend> trusted_vault_backend_remote_; }; IN_PROC_BROWSER_TEST_F(AshTrustedVaultKeysSharingSyncTest, ShouldFetchStoredKeysThroughCrosapi) { - ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(SetupSyncAndTrustedVaultFakes()); // Mimic that Ash already has trusted vault key. - std::vector<std::vector<uint8_t>> trusted_vault_keys = {{1, 2, 3}}; GetAshSyncTrustedVaultClient().StoreKeys(GetSyncingUserAccountInfo().gaia, - trusted_vault_keys, + {kTestTrustedVaultKey}, /*last_key_version*/ 1); // Mimic that Lacros starts and attempts to fetch keys, it should succeed. SetupCrosapi(); - EXPECT_THAT(FetchKeysThroughCrosapi(), Eq(trusted_vault_keys)); + EXPECT_THAT(FetchKeysThroughCrosapi(), ElementsAre(kTestTrustedVaultKey)); +} + +IN_PROC_BROWSER_TEST_F(AshTrustedVaultKeysSharingSyncTest, + ShouldAcceptKeysFromTheWebAndFetchThemThroughCrosapi) { + // Mimic the account being already using a trusted vault passphrase. + SetNigoriInFakeServer( + syncer::BuildTrustedVaultNigoriSpecifics({kTestTrustedVaultKey}), + GetFakeServer()); + + // Need to create `display_service` before key missing notification is shown + // (it will be shown during SetupSyncAndTrustedVaultFakes()). + ASSERT_TRUE(SetupClients()); + NotificationDisplayServiceTester display_service(GetProfile(0)); + + ASSERT_TRUE(SetupSyncAndTrustedVaultFakes()); + SetupCrosapi(); + + // No keys yet available in Ash, Lacros will fetch empty keys. + EXPECT_THAT(FetchKeysThroughCrosapi(), IsEmpty()); + + EXPECT_TRUE(GetSyncService(0) + ->GetUserSettings() + ->IsTrustedVaultKeyRequiredForPreferredDataTypes()); + // Key missing notification should be displayed. + const std::string notification_id = + ash::SyncErrorNotifierFactory::GetForProfile(GetProfile(0)) + ->GetNotificationIdForTesting(); + absl::optional<message_center::Notification> notification = + display_service.GetNotification(notification_id); + ASSERT_TRUE(notification); + EXPECT_THAT(notification->title(), + Eq(l10n_util::GetStringUTF16( + IDS_SYNC_ERROR_PASSWORDS_BUBBLE_VIEW_TITLE))); + EXPECT_THAT( + notification->message(), + Eq(l10n_util::GetStringUTF16( + IDS_SYNC_NEEDS_KEYS_FOR_PASSWORDS_ERROR_BUBBLE_VIEW_MESSAGE))); + + auto keys_changed_notified_checker = + CreateTrustedVaultStateNotifiedToCrosapiObserverChecker( + TrustedVaultStateNotifiedToCrosapiObserverChecker:: + ExpectedNotification::kKeysChanged); + // Mimic the user going through key retrieval: + // 1. User clicks on the notification. + // 2. It opens reauth page (note that no actual reauth happens in this test, + // page closes automatically as if user did the reauth). + // 3. Reauth page supplies Ash with kTestTrustedVaultKey. + display_service.SimulateClick(NotificationHandler::Type::TRANSIENT, + notification_id, /*action_index=*/absl::nullopt, + /*reply=*/absl::nullopt); + EXPECT_TRUE(WaitForTrustedVaultReauthCompletion()); + + // Now Lacros should be able to fetch keys. + EXPECT_TRUE(keys_changed_notified_checker.Wait()); + EXPECT_THAT(FetchKeysThroughCrosapi(), ElementsAre(kTestTrustedVaultKey)); } } // namespace
diff --git a/chrome/browser/sync/test/integration/encryption_helper.cc b/chrome/browser/sync/test/integration/encryption_helper.cc index 0e5bfee..da4a67f 100644 --- a/chrome/browser/sync/test/integration/encryption_helper.cc +++ b/chrome/browser/sync/test/integration/encryption_helper.cc
@@ -7,12 +7,97 @@ #include <string> #include <vector> +#include "base/base64.h" #include "base/functional/bind.h" +#include "base/strings/stringprintf.h" #include "components/sync/base/passphrase_enums.h" #include "components/sync/service/sync_client.h" #include "components/sync/service/sync_service_impl.h" +#include "google_apis/gaia/gaia_urls.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_response.h" #include "testing/gtest/include/gtest/gtest.h" +namespace encryption_helper { + +namespace { + +GURL GetFakeTrustedVaultRetrievalURL( + const net::test_server::EmbeddedTestServer& test_server, + const std::string& gaia_id, + const std::vector<uint8_t>& encryption_key, + int encryption_key_version) { + // encryption_keys_retrieval.html would populate encryption key to + // TrustedVaultService service upon loading. Key is provided as part of URL + // and needs to be encoded with Base64, because it is binary. + const std::string base64_encoded_key = base::Base64Encode(encryption_key); + return test_server.GetURL(base::StringPrintf( + "/sync/encryption_keys_retrieval.html?gaia=%s&key=%s&key_version=%d", + gaia_id.c_str(), base64_encoded_key.c_str(), encryption_key_version)); +} + +GURL GetFakeTrustedVaultRecoverabilityURL( + const net::test_server::EmbeddedTestServer& test_server, + const std::string& gaia_id, + const std::vector<uint8_t>& public_key) { + // encryption_keys_recoverability.html would populate `public_key` to + // TrustedVaultService upon loading. Key is provided as part of URL and needs + // to be encoded with Base64, because it is binary. + const std::string base64_encoded_public_key = base::Base64Encode(public_key); + return test_server.GetURL( + base::StringPrintf("/sync/encryption_keys_recoverability.html?%s#%s", + gaia_id.c_str(), base64_encoded_public_key.c_str())); +} + +// Helper function to install server redirects in the test HTTP server. +std::unique_ptr<net::test_server::HttpResponse> HttpServerRedirect( + const GURL& from_prefix, + const GURL& to, + const net::test_server::HttpRequest& request) { + if (!base::StartsWith(request.GetURL().spec(), from_prefix.spec())) { + return nullptr; + } + auto http_response = std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HTTP_MOVED_PERMANENTLY); + http_response->AddCustomHeader("Location", to.spec()); + http_response->set_content_type("text/html"); + http_response->set_content(base::StringPrintf( + "<html><head></head><body>Redirecting to %s</body></html>", + to.spec().c_str())); + return http_response; +} + +} // namespace + +void SetupFakeTrustedVaultPages( + const std::string& gaia_id, + const std::vector<uint8_t>& trusted_vault_key, + int trusted_vault_key_version, + const std::vector<uint8_t>& recovery_method_public_key, + net::test_server::EmbeddedTestServer* test_server) { + CHECK(test_server); + // Note that this needs to be installed before the analogous below for + // retrieval, because they share prefix. + const GURL recoverability_url = GetFakeTrustedVaultRecoverabilityURL( + *test_server, gaia_id, recovery_method_public_key); + test_server->RegisterRequestHandler(base::BindRepeating( + &HttpServerRedirect, + /*from_prefix=*/ + GaiaUrls::GetInstance() + ->signin_chrome_sync_keys_recoverability_degraded_url(), + /*to=*/recoverability_url)); + + const GURL retrieval_url = GetFakeTrustedVaultRetrievalURL( + *test_server, gaia_id, trusted_vault_key, trusted_vault_key_version); + test_server->RegisterRequestHandler(base::BindRepeating( + &HttpServerRedirect, + /*from_prefix=*/ + GaiaUrls::GetInstance()->signin_chrome_sync_keys_retrieval_url(), + /*to=*/retrieval_url)); +} + +} // namespace encryption_helper + ServerPassphraseTypeChecker::ServerPassphraseTypeChecker( syncer::PassphraseType expected_passphrase_type) : expected_passphrase_type_(expected_passphrase_type) {}
diff --git a/chrome/browser/sync/test/integration/encryption_helper.h b/chrome/browser/sync/test/integration/encryption_helper.h index d31a7c37..c183863b 100644 --- a/chrome/browser/sync/test/integration/encryption_helper.h +++ b/chrome/browser/sync/test/integration/encryption_helper.h
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include <vector> #include "base/memory/raw_ptr.h" #include "base/test/scoped_feature_list.h" @@ -16,6 +17,25 @@ #include "components/sync/base/passphrase_enums.h" #include "components/sync/test/fake_server.h" #include "components/trusted_vault/trusted_vault_client.h" +#include "net/test/embedded_test_server/embedded_test_server.h" + +namespace encryption_helper { + +// Setups `test_server` in a way it will redirect from trusted vault URLs (key +// retrieval URL and degraded recoverability URL) to fake pages. These pages +// will populate parameters (`trusted_vault_key` and its version in case of key +// retrieval, `recovery_method_public_key` in case of degraded recoverability) +// to Chrome upon loading and will close themselves automatically. +// Must be called before `test_server` starts to accept connections. +// `test_server` must not be null. +void SetupFakeTrustedVaultPages( + const std::string& gaia_id, + const std::vector<uint8_t>& trusted_vault_key, + int trusted_vault_key_version, + const std::vector<uint8_t>& recovery_method_public_key, + net::test_server::EmbeddedTestServer* test_server); + +} // namespace encryption_helper // Checker used to block until a Nigori with a given passphrase type is // available on the server.
diff --git a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc index 909f2bf..dbb40d5 100644 --- a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
@@ -131,55 +131,12 @@ return true; } -GURL GetFakeTrustedVaultRetrievalURL( - const net::test_server::EmbeddedTestServer& test_server, - const std::vector<uint8_t>& encryption_key, - int encryption_key_version) { - // encryption_keys_retrieval.html would populate encryption key to sync - // service upon loading. Key is provided as part of URL and needs to be - // encoded with Base64, because |encryption_key| is binary. - const std::string base64_encoded_key = base::Base64Encode(encryption_key); - return test_server.GetURL(base::StringPrintf( - "/sync/encryption_keys_retrieval.html?gaia=%s&key=%s&key_version=%d", - kGaiaId, base64_encoded_key.c_str(), encryption_key_version)); -} - -GURL GetFakeTrustedVaultRecoverabilityURL( - const net::test_server::EmbeddedTestServer& test_server, - const std::vector<uint8_t>& public_key) { - // encryption_keys_recoverability.html would populate encryption key to sync - // service upon loading. Key is provided as part of URL and needs to be - // encoded with Base64, because |public_key| is binary. - const std::string base64_encoded_public_key = base::Base64Encode(public_key); - return test_server.GetURL( - base::StringPrintf("/sync/encryption_keys_recoverability.html?%s#%s", - kGaiaId, base64_encoded_public_key.c_str())); -} - std::string ComputeKeyName(const KeyParamsForTesting& key_params) { return syncer::Nigori::CreateByDerivation(key_params.derivation_params, key_params.password) ->GetKeyName(); } -// Helper function to install server redirects in the test HTTP server. -std::unique_ptr<net::test_server::HttpResponse> HttpServerRedirect( - const GURL& from_prefix, - const GURL& to, - const net::test_server::HttpRequest& request) { - if (!base::StartsWith(request.GetURL().spec(), from_prefix.spec())) { - return nullptr; - } - auto http_response = std::make_unique<net::test_server::BasicHttpResponse>(); - http_response->set_code(net::HTTP_MOVED_PERMANENTLY); - http_response->AddCustomHeader("Location", to.spec()); - http_response->set_content_type("text/html"); - http_response->set_content(base::StringPrintf( - "<html><head></head><body>Redirecting to %s</body></html>", - to.spec().c_str())); - return http_response; -} - class WifiConfigurationsSyncActiveChecker : public SingleClientStatusChangeChecker { public: @@ -950,30 +907,9 @@ &trusted_vault::FakeSecurityDomainsServer::HandleRequest, base::Unretained(security_domains_server_.get()))); - // Install a redirect from the actual degraded recoverability URL as - // determined by GaiaUrls to |recoverability_url|, which runs Javascript - // code to mimic adding recovery method with key - // |kTestRecoveryMethodPublicKey|. Note that this needs to be installed - // before the analogous below for retrieval, because they share prefix. - const GURL recoverability_url = GetFakeTrustedVaultRecoverabilityURL( - *embedded_test_server(), kTestRecoveryMethodPublicKey); - embedded_test_server()->RegisterRequestHandler(base::BindRepeating( - &HttpServerRedirect, - /*from_prefix=*/ - GaiaUrls::GetInstance() - ->signin_chrome_sync_keys_recoverability_degraded_url(), - /*to=*/recoverability_url)); - - // Install a redirect from the actual retrieval URL as determined by - // GaiaUrls to |retrieval_url|, which runs Javascript code to mimic - // retrieval of key |kTestEncryptionKey|. - const GURL retrieval_url = GetFakeTrustedVaultRetrievalURL( - *embedded_test_server(), kTestEncryptionKey, kTestEncryptionKeyVersion); - embedded_test_server()->RegisterRequestHandler(base::BindRepeating( - &HttpServerRedirect, - /*from_prefix=*/ - GaiaUrls::GetInstance()->signin_chrome_sync_keys_retrieval_url(), - /*to=*/retrieval_url)); + encryption_helper::SetupFakeTrustedVaultPages( + kGaiaId, kTestEncryptionKey, kTestEncryptionKeyVersion, + kTestRecoveryMethodPublicKey, embedded_test_server()); embedded_test_server()->StartAcceptingConnections(); }
diff --git a/chrome/browser/sync/test/lacros/trusted_vault_keys_sharing_lacros_browsertest.cc b/chrome/browser/sync/test/lacros/trusted_vault_keys_sharing_lacros_browsertest.cc index 6baef72..6d2f6c86 100644 --- a/chrome/browser/sync/test/lacros/trusted_vault_keys_sharing_lacros_browsertest.cc +++ b/chrome/browser/sync/test/lacros/trusted_vault_keys_sharing_lacros_browsertest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/base64.h" #include "base/files/file_path.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/sync/sync_ui_util.h" @@ -23,7 +22,6 @@ #include "content/public/browser/browser_main_parts.h" #include "content/public/test/browser_test.h" #include "google_apis/gaia/gaia_switches.h" -#include "google_apis/gaia/gaia_urls.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/views/test/widget_test.h" @@ -67,51 +65,6 @@ return true; } -GURL GetFakeTrustedVaultRetrievalURL( - const net::test_server::EmbeddedTestServer& test_server, - const std::string& gaia_id, - const std::vector<uint8_t>& encryption_key, - int encryption_key_version) { - // encryption_keys_retrieval.html would populate encryption key to sync - // service upon loading. Key is provided as part of URL and needs to be - // encoded with Base64, because `encryption_key` is binary. - const std::string base64_encoded_key = base::Base64Encode(encryption_key); - return test_server.GetURL(base::StringPrintf( - "/sync/encryption_keys_retrieval.html?gaia=%s&key=%s&key_version=%d", - gaia_id.c_str(), base64_encoded_key.c_str(), encryption_key_version)); -} - -GURL GetFakeTrustedVaultRecoverabilityURL( - const net::test_server::EmbeddedTestServer& test_server, - const std::string& gaia_id, - const std::vector<uint8_t>& public_key) { - // encryption_keys_recoverability.html would populate encryption key to sync - // service upon loading. Key is provided as part of URL and needs to be - // encoded with Base64, because |public_key| is binary. - const std::string base64_encoded_public_key = base::Base64Encode(public_key); - return test_server.GetURL( - base::StringPrintf("/sync/encryption_keys_recoverability.html?%s#%s", - gaia_id.c_str(), base64_encoded_public_key.c_str())); -} - -// Helper function to install server redirects in the test HTTP server. -std::unique_ptr<net::test_server::HttpResponse> HttpServerRedirect( - const GURL& from_prefix, - const GURL& to, - const net::test_server::HttpRequest& request) { - if (!base::StartsWith(request.GetURL().spec(), from_prefix.spec())) { - return nullptr; - } - auto http_response = std::make_unique<net::test_server::BasicHttpResponse>(); - http_response->set_code(net::HTTP_MOVED_PERMANENTLY); - http_response->AddCustomHeader("Location", to.spec()); - http_response->set_content_type("text/html"); - http_response->set_content(base::StringPrintf( - "<html><head></head><body>Redirecting to %s</body></html>", - to.spec().c_str())); - return http_response; -} - class TrustedVaultKeysSharingLacrosBrowserTest : public SyncTest { public: TrustedVaultKeysSharingLacrosBrowserTest() @@ -172,32 +125,10 @@ const CoreAccountInfo primary_account_info = GetSyncService(0)->GetAccountInfo(); - // Install a redirect from the actual degraded recoverability URL as - // determined by GaiaUrls to |recoverability_url|, which runs Javascript - // code to mimic adding recovery method with kTestRecoveryMethodPublicKey. - // Note that this needs to be installed before the analogous below for - // retrieval, because they share prefix. - const GURL recoverability_url = GetFakeTrustedVaultRecoverabilityURL( - *embedded_test_server(), primary_account_info.gaia, - kTestRecoveryMethodPublicKey); - embedded_test_server()->RegisterRequestHandler(base::BindRepeating( - &HttpServerRedirect, - /*from_prefix=*/ - GaiaUrls::GetInstance() - ->signin_chrome_sync_keys_recoverability_degraded_url(), - /*to=*/recoverability_url)); - - // Install a redirect from the actual retrieval URL as determined by - // GaiaUrls to `retrieval_url`, which runs Javascript code to mimic - // retrieval of key kTestTrustedVaultKey. - const GURL retrieval_url = GetFakeTrustedVaultRetrievalURL( - *embedded_test_server(), primary_account_info.gaia, - kTestTrustedVaultKey, /*encryption_key_version=*/1); - embedded_test_server()->RegisterRequestHandler(base::BindRepeating( - &HttpServerRedirect, - /*from_prefix=*/ - GaiaUrls::GetInstance()->signin_chrome_sync_keys_retrieval_url(), - /*to=*/retrieval_url)); + encryption_helper::SetupFakeTrustedVaultPages( + primary_account_info.gaia, kTestTrustedVaultKey, + /*trusted_vault_key_version=*/1, kTestRecoveryMethodPublicKey, + embedded_test_server()); embedded_test_server()->StartAcceptingConnections();
diff --git a/chrome/browser/ui/browser_focus_uitest.cc b/chrome/browser/ui/browser_focus_uitest.cc index 7ad8814..bb72b05 100644 --- a/chrome/browser/ui/browser_focus_uitest.cc +++ b/chrome/browser/ui/browser_focus_uitest.cc
@@ -51,6 +51,8 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "third_party/blink/public/common/switches.h" #include "ui/base/test/ui_controls.h" +#include "ui/views/focus/focus_manager.h" +#include "ui/views/widget/widget.h" #if BUILDFLAG(IS_MAC) #include "base/mac/mac_util.h" @@ -58,6 +60,68 @@ namespace { +constexpr char kGetFocusedElementJS[] = "getFocusedElement();"; + +// Listens to UI and DOM element focus changes. +class FocusChangeObserver : public views::FocusChangeListener, + public content::WebContentsObserver { + public: + FocusChangeObserver(views::FocusManager* focus_manager, + content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) { + obs_.Observe(focus_manager); + } + + void WaitForFocusChange() { run_loop_.Run(); } + + // FocusChangeListener: + void OnWillChangeFocus(views::View* focused_before, + views::View* focused_now) override {} + void OnDidChangeFocus(views::View* focused_before, + views::View* focused_now) override { + if (focused_now) { + SCOPED_TRACE(base::StrCat( + {"View with ID=", base::NumberToString(focused_now->GetID()), + " is focused now."})); + } + run_loop_.Quit(); + } + + // WebContentsObserver: + void OnFocusChangedInPage(content::FocusedNodeDetails* details) override { + SCOPED_TRACE(base::StrCat( + {"Page element with id=", + content::EvalJs(web_contents(), kGetFocusedElementJS).ExtractString(), + " is focused now."})); + run_loop_.Quit(); + } + + private: + base::ScopedObservation<views::FocusManager, FocusChangeObserver> obs_{this}; + base::RunLoop run_loop_; +}; + +} // namespace + +namespace base { + +template <> +struct ::base::ScopedObservationTraits<views::FocusManager, + FocusChangeObserver> { + static void AddObserver(views::FocusManager* source, + FocusChangeObserver* observer) { + source->AddFocusChangeListener(observer); + } + static void RemoveObserver(views::FocusManager* source, + FocusChangeObserver* observer) { + source->RemoveFocusChangeListener(observer); + } +}; + +} // namespace base + +namespace { + using content::RenderViewHost; using content::WebContents; @@ -90,105 +154,48 @@ void ClickOnView(ViewID vid) { ui_test_utils::ClickOnView(browser(), vid); } - void TestFocusTraversal(WebContents* tab, bool reverse) { - const char kGetFocusedElementJS[] = "getFocusedElement();"; - const char* kExpectedIDs[] = {"textEdit", "searchButton", "luckyButton", - "googleLink", "gmailLink", "gmapLink"}; - SCOPED_TRACE(base::StringPrintf("TestFocusTraversal: reverse=%d", reverse)); - ui::KeyboardCode key = ui::VKEY_TAB; -#if BUILDFLAG(IS_MAC) - // TODO(msw): Mac requires ui::VKEY_BACKTAB for reverse cycling. Sigh... - key = reverse ? ui::VKEY_BACKTAB : ui::VKEY_TAB; -#endif - - // Loop through the focus chain twice for good measure. - for (size_t i = 0; i < 2; ++i) { - SCOPED_TRACE(base::StringPrintf("focus outer loop: %" PRIuS, i)); - ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX)); - - // Mac requires an extra Tab key press to traverse the app menu button - // iff "Full Keyboard Access" is enabled. In reverse, four Tab key presses - // are required to traverse the back/forward buttons and the tab strip. -#if BUILDFLAG(IS_MAC) - constexpr int kFocusableElementsBeforeOmnibox = 4; - constexpr int kFocusableElementsAfterOmnibox = 1; - if (ui_controls::IsFullKeyboardAccessEnabled()) { - for (int j = 0; j < (reverse ? kFocusableElementsBeforeOmnibox - : kFocusableElementsAfterOmnibox); - ++j) { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - reverse, false, false)); - } - } -#endif - - if (reverse) { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - reverse, false, false)); - } - - // From the location icon we must traverse backwards one more time to - // traverse past the tab search caption button if present. - if (WindowFrameUtil::IsWindowsTabSearchCaptionButtonEnabled(browser()) && - reverse) { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, true, - false, false)); - } - - for (size_t j = 0; j < std::size(kExpectedIDs); ++j) { - SCOPED_TRACE(base::StringPrintf("focus inner loop %" PRIuS, j)); - const size_t index = reverse ? std::size(kExpectedIDs) - 1 - j : j; - // The details are the node's editable state, i.e. true for "textEdit". - bool is_editable_node = index == 0; - - // Press Tab (or Shift+Tab) and check the focused element id. - content::FocusChangedObserver observer(tab); - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - reverse, false, false)); - auto observed_details = observer.Wait(); - EXPECT_EQ(is_editable_node, observed_details.is_editable_node); - - EXPECT_EQ(kExpectedIDs[index], - content::EvalJs(tab, kGetFocusedElementJS)); - } - - // On the last Tab key press, focus returns to the browser. - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - reverse, false, false)); - - // Except on Mac, where extra tabs are once again required to traverse the - // other top chrome elements. -#if BUILDFLAG(IS_MAC) - if (ui_controls::IsFullKeyboardAccessEnabled()) { - for (int j = 0; j < (reverse ? kFocusableElementsAfterOmnibox - : kFocusableElementsBeforeOmnibox); - ++j) { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - reverse, false, false)); - } - } -#endif - - // Traverse over the tab search frame caption button if present. - if (WindowFrameUtil::IsWindowsTabSearchCaptionButtonEnabled(browser()) && - !reverse) { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - false, false, false)); - } - - ui_test_utils::WaitForViewFocus( - browser(), reverse ? VIEW_ID_OMNIBOX : VIEW_ID_LOCATION_ICON, true); - - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - reverse, false, false)); - ui_test_utils::WaitForViewFocus( - browser(), reverse ? VIEW_ID_LOCATION_ICON : VIEW_ID_OMNIBOX, true); - if (reverse) { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, - false, false, false)); - } - } + void FocusNextElement(bool reverse) { + FocusChangeObserver obs{ + GetFocusManager(), + browser()->tab_strip_model()->GetActiveWebContents()}; + ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_TAB, false, + reverse, false, false)); + obs.WaitForFocusChange(); } + + void TestFocusTraversal(bool reverse) { + SCOPED_TRACE(base::StrCat( + {"Started focus traversal, reverse=", base::ToString(reverse)})); + + // Move focus one element away from the omnibox. + ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX)); + FocusNextElement(reverse); + EXPECT_FALSE(IsViewFocused(VIEW_ID_OMNIBOX)); + + // Traverse the whole focus chain until the omnibox is focused again. + size_t c = 0; + while (!IsViewFocused(VIEW_ID_OMNIBOX) && c < kMaxIterations) { + FocusNextElement(reverse); + ++c; + } + EXPECT_TRUE(c <= kMaxIterations); + EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX)); + } + + views::FocusManager* GetFocusManager() { + BrowserWindow* browser_window = browser()->window(); + DCHECK(browser_window); + gfx::NativeWindow window = browser_window->GetNativeWindow(); + DCHECK(window); + views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); + DCHECK(widget); + views::FocusManager* focus_manager = widget->GetFocusManager(); + DCHECK(focus_manager); + return focus_manager; + } + + private: + constexpr static size_t kMaxIterations = 20; }; // Flaky on Mac (http://crbug.com/67301). @@ -420,17 +427,20 @@ } // Test forward and reverse focus traversal on a typical page. -// Flaky everywhere: https://crbug.com/1259721 -IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusTraversal) { +IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversal) { ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); const GURL url = embedded_test_server()->GetURL(kTypicalPage); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - EXPECT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); + FocusChangeObserver obs{GetFocusManager(), + browser()->tab_strip_model()->GetActiveWebContents()}; chrome::FocusLocationBar(browser()); - - WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_NO_FATAL_FAILURE(TestFocusTraversal(tab, false)); - EXPECT_NO_FATAL_FAILURE(TestFocusTraversal(tab, true)); + obs.WaitForFocusChange(); + ASSERT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX)); + // Loop through the focus chain twice in each direction for good measure. + TestFocusTraversal(false); + TestFocusTraversal(false); + TestFocusTraversal(true); + TestFocusTraversal(true); } // Test that find-in-page UI can request focus, even when it is already open.
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.cc index c676bb1..0e17f89 100644 --- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.cc +++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.cc
@@ -236,15 +236,11 @@ UpdateFrameHints(); } -void BrowserDesktopWindowTreeHostLacros::OnImmersiveModeChanged(bool enabled) { - DesktopWindowTreeHostLacros::OnImmersiveModeChanged(enabled); - // Update the browser UI, because some fullscreen mode UI updates depend on - // immersive mode state. Unlike ash-chrome, Lacros's immersive mode is set - // to the system asynchronously. - browser_view_->browser()->FullscreenTopUIStateChanged(); -} +void BrowserDesktopWindowTreeHostLacros::OnFullscreenTypeChanged( + ui::PlatformFullscreenType old_type, + ui::PlatformFullscreenType new_type) { + DesktopWindowTreeHostLacros::OnFullscreenTypeChanged(old_type, new_type); -void BrowserDesktopWindowTreeHostLacros::OnFullscreenModeChanged() { // Finalizing full screen mode transition after Ash has also asynchronously // entered the full screen mode state for this window. browser_view_->FullscreenStateChanged();
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.h b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.h index 7c2b9892..de8d94b3 100644 --- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.h +++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_lacros.h
@@ -59,8 +59,8 @@ void OnBoundsChanged(const BoundsChange& change) override; void OnWindowStateChanged(ui::PlatformWindowState old_state, ui::PlatformWindowState new_state) override; - void OnImmersiveModeChanged(bool enabled) override; - void OnFullscreenModeChanged() override; + void OnFullscreenTypeChanged(ui::PlatformFullscreenType old_type, + ui::PlatformFullscreenType new_type) override; void OnOverviewModeChanged(bool in_overview) override; const raw_ptr<BrowserView> browser_view_;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 2af30a6..536ff3d93 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -2589,6 +2589,8 @@ } void BrowserView::SynchronizeRenderWidgetHostVisualPropertiesForMainFrame() { +// TODO(crbug.com/1503145): Investigate and fix on MacOS. +#if !BUILDFLAG(IS_MAC) content::WebContents* web_contents = GetActiveWebContents(); if (!web_contents || !web_contents->GetPrimaryMainFrame()) { return; @@ -2598,6 +2600,7 @@ web_contents->GetPrimaryMainFrame()->GetRenderWidgetHost()) { render_widget_host->SynchronizeVisualProperties(); } +#endif } void BrowserView::OnWidgetSizeConstraintsChanged(views::Widget* widget) {
diff --git a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc index 917fec8..ab401b5 100644 --- a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc +++ b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
@@ -165,6 +165,24 @@ views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_PRIMARY)); } + void GetAccessibleNodeData(ui::AXNodeData* node_data) override { + if (!controller_) { + return; + } + + node_data->role = ax::mojom::Role::kListBoxOption; + node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, + controller_->edit_password_selected()); + node_data->SetNameChecked( + l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_EDIT_PASSWORD)); + const std::u16string help_text = l10n_util::GetStringFUTF16( + GetHelpTextMessageId(), + l10n_util::GetStringUTF16( + IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SYNCED_TO_ACCOUNT), + controller_->GetPrimaryAccountEmail()); + node_data->SetDescription(help_text); + } + private: void OnMouseEntered(const ui::MouseEvent& event) override { if (controller_) { @@ -314,11 +332,24 @@ node_data->SetNameChecked(base::JoinString( {controller_->SuggestedText(), controller_->password()}, u" ")); const std::u16string help_text = l10n_util::GetStringFUTF16( - IDS_PASSWORD_GENERATION_PROMPT_GOOGLE_PASSWORD_MANAGER, + GetHelpTextMessageId(), l10n_util::GetStringUTF16( IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SYNCED_TO_ACCOUNT), controller_->GetPrimaryAccountEmail()); + if (password_manager::features::kPasswordGenerationExperimentVariationParam + .Get() == PasswordGenerationVariation::kCrossDevice) { + const std::u16string description = base::JoinString( + {l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_BENEFITS), + l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_CROSS_DEVICE), + l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_SECURITY), + l10n_util::GetStringUTF16(IDS_PASSWORD_GENERATION_PROACTIVE_CHECK), + help_text}, + u", "); + node_data->SetDescription(description); + return; + } + node_data->SetDescription(help_text); }
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.cc b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.cc index cd048ad4..5d10b46 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.cc +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.cc
@@ -51,17 +51,12 @@ Browser* browser, base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate, base::TimeTicks permission_requested_time, - PermissionPromptStyle prompt_style, - std::u16string window_title, - std::u16string accessible_window_title, - std::optional<std::u16string> extra_text) + PermissionPromptStyle prompt_style) : PermissionPromptBaseView(browser, delegate), browser_(browser), delegate_(delegate), permission_requested_time_(permission_requested_time), - is_one_time_permission_(IsOneTimePermission(*delegate.get())), - accessible_window_title_(accessible_window_title), - window_title_(window_title) { + is_one_time_permission_(IsOneTimePermission(*delegate.get())) { // Note that browser_ may be null in unit tests. SetPromptStyle(prompt_style); @@ -73,18 +68,12 @@ set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); - if (extra_text.has_value()) { - auto* extra_text_label = - AddChildView(std::make_unique<views::Label>(extra_text.value())); - extra_text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - extra_text_label->SetMultiLine(true); - extra_text_label->SetID(permissions::PermissionPromptViewID:: - VIEW_ID_PERMISSION_PROMPT_EXTRA_TEXT); - if (features::IsChromeRefresh2023()) { - extra_text_label->SetTextStyle(views::style::STYLE_BODY_3); - extra_text_label->SetEnabledColorId(kColorPermissionPromptRequestText); - } - } + SetProperty(views::kElementIdentifierKey, kMainViewId); +} + +PermissionPromptBubbleBaseView::~PermissionPromptBubbleBaseView() = default; + +void PermissionPromptBubbleBaseView::CreatePermissionButtons() { if (is_one_time_permission_) { SetButtons(ui::DIALOG_BUTTON_NONE); @@ -161,11 +150,23 @@ SetButtonStyle(ui::DIALOG_BUTTON_CANCEL, ui::ButtonStyle::kTonal); } } - - SetProperty(views::kElementIdentifierKey, kMainViewId); } -PermissionPromptBubbleBaseView::~PermissionPromptBubbleBaseView() = default; +void PermissionPromptBubbleBaseView::CreateExtraTextLabel( + const std::u16string& extra_text) { + auto extra_text_label = views::Builder<views::Label>() + .SetText(extra_text) + .SetHorizontalAlignment(gfx::ALIGN_LEFT) + .SetMultiLine(true) + .SetID(permissions::PermissionPromptViewID:: + VIEW_ID_PERMISSION_PROMPT_EXTRA_TEXT) + .Build(); + if (features::IsChromeRefresh2023()) { + extra_text_label->SetTextStyle(views::style::STYLE_BODY_3); + extra_text_label->SetEnabledColorId(kColorPermissionPromptRequestText); + } + AddChildView(std::move(extra_text_label)); +} void PermissionPromptBubbleBaseView::Show() { CreateWidget(); @@ -244,15 +245,6 @@ return true; } -std::u16string PermissionPromptBubbleBaseView::GetWindowTitle() const { - return window_title_; -} - -std::u16string PermissionPromptBubbleBaseView::GetAccessibleWindowTitle() - const { - return accessible_window_title_; -} - void PermissionPromptBubbleBaseView::ClosingPermission() { DCHECK_EQ(prompt_style_, PermissionPromptStyle::kBubbleOnly); RecordDecision(permissions::PermissionAction::DISMISSED); @@ -282,10 +274,9 @@ std::u16string PermissionPromptBubbleBaseView::GetPermissionFragmentForTesting() const { - std::u16string origin = - PermissionPromptBaseView::GetUrlIdentity(browser_, *delegate_).name; - return accessible_window_title_.substr(accessible_window_title_.find(origin) + - origin.length()); + std::u16string origin = GetUrlIdentityObject().name; + return GetAccessibleWindowTitle().substr( + GetAccessibleWindowTitle().find(origin) + origin.length()); } // static
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.h b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.h index e0a8bf5..f562d38d 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.h +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.h
@@ -48,10 +48,7 @@ Browser* browser, base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate, base::TimeTicks permission_requested_time, - PermissionPromptStyle prompt_style, - std::u16string window_title, - std::u16string accessible_window_title_, - std::optional<std::u16string> extra_text); + PermissionPromptStyle prompt_style); PermissionPromptBubbleBaseView(const PermissionPromptBubbleBaseView&) = delete; PermissionPromptBubbleBaseView& operator=( @@ -74,14 +71,10 @@ void ShowWidget(); - void SetPromptStyle(PermissionPromptStyle prompt_style); - void ClosingPermission(); // views::BubbleDialogDelegateView: bool ShouldShowCloseButton() const override; - std::u16string GetAccessibleWindowTitle() const override; - std::u16string GetWindowTitle() const override; // PermissionPromptBaseView: void RunButtonCallback(int button_id) override; @@ -89,9 +82,12 @@ std::u16string GetPermissionFragmentForTesting() const; protected: + void CreatePermissionButtons(); + void CreateExtraTextLabel(const std::u16string& extra_text); + void CreateWidget(); - base::WeakPtr<permissions::PermissionPrompt::Delegate> GetDelegate() { + base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate() const { return delegate_; } @@ -102,6 +98,8 @@ permissions::PermissionPrompt::Delegate& delegate); private: + void SetPromptStyle(PermissionPromptStyle prompt_style); + // Record UMA Permissions.*.TimeToDecision.|action| metric. Can be // Permissions.Prompt.TimeToDecision.* or Permissions.Chip.TimeToDecision.*, // depending on which UI is used. @@ -124,8 +122,6 @@ PermissionPromptStyle prompt_style_; const bool is_one_time_permission_; - const std::u16string accessible_window_title_; - const std::u16string window_title_; }; #endif // CHROME_BROWSER_UI_VIEWS_PERMISSIONS_PERMISSION_PROMPT_BUBBLE_BASE_VIEW_H_
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_one_origin_view.cc b/chrome/browser/ui/views/permissions/permission_prompt_bubble_one_origin_view.cc index 92d3b9d2..c84a271 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_one_origin_view.cc +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_one_origin_view.cc
@@ -155,23 +155,27 @@ base::WeakPtr<permissions::PermissionPrompt::Delegate> delegate, base::TimeTicks permission_requested_time, PermissionPromptStyle prompt_style) - : PermissionPromptBubbleBaseView( - browser, - delegate, - permission_requested_time, - prompt_style, - l10n_util::GetStringFUTF16( - IDS_PERMISSIONS_BUBBLE_PROMPT, - PermissionPromptBaseView::GetUrlIdentity(browser, *delegate) - .name), - GetAccessibleWindowTitleInternal( - PermissionPromptBaseView::GetUrlIdentity(browser, *delegate).name, - GetVisibleRequests(*delegate.get())), - GetExtraText(*delegate.get())) { - bool has_camera_request = false; - bool has_mic_request = false; + : PermissionPromptBubbleBaseView(browser, + delegate, + permission_requested_time, + prompt_style) { std::vector<permissions::PermissionRequest*> visible_requests = GetVisibleRequests(*delegate.get()); + + SetAccessibleTitle(GetAccessibleWindowTitleInternal( + GetUrlIdentityObject().name, visible_requests)); + SetTitle(l10n_util::GetStringFUTF16(IDS_PERMISSIONS_BUBBLE_PROMPT, + GetUrlIdentityObject().name)); + + auto extra_text = GetExtraText(*delegate.get()); + if (extra_text.has_value()) { + CreateExtraTextLabel(extra_text.value()); + } + + CreatePermissionButtons(); + + bool has_camera_request = false; + bool has_mic_request = false; for (std::size_t i = 0; i < visible_requests.size(); i++) { AddRequestLine(visible_requests[i], i); if (visible_requests[i]->request_type() ==
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc b/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc index 3d0efc2..a53eeb9 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc
@@ -24,20 +24,6 @@ // so we can adjust this delay accordingly. constexpr int kMaxShowDelayMs = 200; -std::u16string GetWindowTitleTwoOrigin( - permissions::PermissionPrompt::Delegate& delegate) { - CHECK_GT(delegate.Requests().size(), 0u); - switch (delegate.Requests()[0]->request_type()) { - case permissions::RequestType::kStorageAccess: - return l10n_util::GetStringFUTF16( - IDS_STORAGE_ACCESS_PERMISSION_TWO_ORIGIN_PROMPT_TITLE, - url_formatter::FormatUrlForSecurityDisplay( - delegate.GetRequestingOrigin(), - url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); - default: - NOTREACHED_NORETURN(); - } -} std::optional<std::u16string> GetExtraTextTwoOrigin( permissions::PermissionPrompt::Delegate& delegate) { @@ -73,10 +59,16 @@ : PermissionPromptBubbleBaseView(browser, delegate, permission_requested_time, - prompt_style, - GetWindowTitleTwoOrigin(*delegate), - GetWindowTitleTwoOrigin(*delegate), - GetExtraTextTwoOrigin(*delegate)) { + prompt_style) { + SetTitle(CreateWindowTitle()); + + auto extra_text = GetExtraTextTwoOrigin(*delegate); + if (extra_text.has_value()) { + CreateExtraTextLabel(extra_text.value()); + } + + CreatePermissionButtons(); + // Only requests for Storage Access should use this prompt. CHECK(delegate); CHECK_GT(delegate->Requests().size(), 0u); @@ -162,6 +154,21 @@ base::Unretained(this))); } +std::u16string PermissionPromptBubbleTwoOriginsView::CreateWindowTitle() const { + CHECK_GT(delegate()->Requests().size(), 0u); + + switch (delegate()->Requests()[0]->request_type()) { + case permissions::RequestType::kStorageAccess: + return l10n_util::GetStringFUTF16( + IDS_STORAGE_ACCESS_PERMISSION_TWO_ORIGIN_PROMPT_TITLE, + url_formatter::FormatUrlForSecurityDisplay( + delegate()->GetRequestingOrigin(), + url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); + default: + NOTREACHED_NORETURN(); + } +} + void PermissionPromptBubbleTwoOriginsView::CreateFaviconRow() { // Getting default favicon. ui::ImageModel default_favicon_ = ui::ImageModel::FromVectorIcon( @@ -224,7 +231,7 @@ views::StyledLabel::RangeStyleInfo link_style; std::optional<std::u16string> link = GetLink(link_range, link_style); if (link.has_value()) { - size_t index = HasExtraText(*GetDelegate()) ? 1 : 0; + size_t index = HasExtraText(*delegate()) ? 1 : 0; auto* link_label = AddChildViewAt(std::make_unique<views::StyledLabel>(), index); link_label->SetText(link.value()); @@ -239,9 +246,8 @@ std::optional<std::u16string> PermissionPromptBubbleTwoOriginsView::GetLink( gfx::Range& link_range, views::StyledLabel::RangeStyleInfo& link_style) { - auto delegate = GetDelegate(); - CHECK_GT(delegate->Requests().size(), 0u); - switch (delegate->Requests()[0]->request_type()) { + CHECK_GT(delegate()->Requests().size(), 0u); + switch (delegate()->Requests()[0]->request_type()) { case permissions::RequestType::kStorageAccess: return GetLinkStorageAccess(link_range, link_style); default: @@ -266,8 +272,8 @@ void PermissionPromptBubbleTwoOriginsView::HelpCenterLinkClicked( const ui::Event& event) { - if (auto delegate = GetDelegate()) { - delegate->OpenHelpCenterLink(event); + if (delegate()) { + delegate()->OpenHelpCenterLink(event); } }
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.h b/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.h index f6215b0..b45b3e7 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.h +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.h
@@ -48,6 +48,7 @@ private: void CreateFaviconRow(); + std::u16string CreateWindowTitle() const; void OnEmbeddingOriginFaviconLoaded( const favicon_base::FaviconRawBitmapResult& favicon_result);
diff --git a/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.cc b/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.cc index 789ec724..61a2390e 100644 --- a/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.cc +++ b/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/ash/app_install/app_install_page_handler.h" +#include "base/metrics/user_metrics.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ui/webui/ash/app_install/app_install.mojom.h" @@ -21,7 +22,10 @@ dialog_args_{std::move(args)}, dialog_accepted_callback_{std::move(dialog_accepted_callback)}, receiver_{this, std::move(pending_page_handler)}, - close_dialog_callback_{std::move(close_dialog_callback)} {} + close_dialog_callback_{std::move(close_dialog_callback)} { + base::RecordAction( + base::UserMetricsAction("ChromeOS.AppInstallDialog.Shown")); +} AppInstallPageHandler::~AppInstallPageHandler() = default; @@ -32,8 +36,11 @@ void AppInstallPageHandler::CloseDialog() { if (dialog_accepted_callback_) { + base::RecordAction( + base::UserMetricsAction("ChromeOS.AppInstallDialog.Cancelled")); std::move(dialog_accepted_callback_).Run(false); } + // The callback could be null if the close button is clicked a second time // before the dialog closes. if (close_dialog_callback_) { @@ -42,6 +49,9 @@ } void AppInstallPageHandler::InstallApp(InstallAppCallback callback) { + base::RecordAction( + base::UserMetricsAction("ChromeOS.AppInstallDialog.Installed")); + install_app_callback_ = std::move(callback); std::move(dialog_accepted_callback_).Run(true); } @@ -50,6 +60,7 @@ if (app_id) { app_id_ = *app_id; } + if (install_app_callback_) { std::move(install_app_callback_).Run(/*success=*/app_id); } @@ -60,6 +71,8 @@ mojo::ReportBadMessage("Unable to launch app without an app_id."); return; } + base::RecordAction( + base::UserMetricsAction("ChromeOS.AppInstallDialog.AppLaunched")); apps::AppServiceProxyFactory::GetForProfile(profile_)->Launch( app_id_, ui::EF_NONE, apps::LaunchSource::kFromInstaller); }
diff --git a/chrome/browser/ui/webui/ash/login/oobe_ui.cc b/chrome/browser/ui/webui/ash/login/oobe_ui.cc index 33bfef2..4d37212d 100644 --- a/chrome/browser/ui/webui/ash/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/ash/login/oobe_ui.cc
@@ -484,10 +484,10 @@ AddScreenHandler(std::make_unique<FingerprintSetupScreenHandler>()); if (features::AreLocalPasswordsEnabledForConsumers()) { - AddScreenHandler(std::make_unique<PasswordSelectionScreenHandler>()); AddScreenHandler(std::make_unique<LocalPasswordSetupHandler>()); - AddScreenHandler(std::make_unique<ApplyOnlinePasswordScreenHandler>()); } + AddScreenHandler(std::make_unique<PasswordSelectionScreenHandler>()); + AddScreenHandler(std::make_unique<ApplyOnlinePasswordScreenHandler>()); AddScreenHandler(std::make_unique<LocalDataLossWarningScreenHandler>()); AddScreenHandler(std::make_unique<EnterOldPasswordScreenHandler>());
diff --git a/chrome/browser/web_applications/app_service/browser_shortcuts_unittest.cc b/chrome/browser/web_applications/app_service/browser_shortcuts_unittest.cc index bdfb29c..c6bd2f2e 100644 --- a/chrome/browser/web_applications/app_service/browser_shortcuts_unittest.cc +++ b/chrome/browser/web_applications/app_service/browser_shortcuts_unittest.cc
@@ -33,8 +33,10 @@ #include "ui/display/types/display_constants.h" namespace { + +using webapps::AppId; + const char kUrl[] = "https://example.com/"; -const char kIconUrl[] = "https://example.com/icon"; } namespace web_app { @@ -50,33 +52,13 @@ test::AwaitStartWebAppProviderAndSubsystems(profile()); } - std::string CreateShortcut(const std::string& shortcut_name, - bool with_icon = false) { - const GURL kAppUrl(kUrl); - - // Create a web app entry without scope, which would be recognised - // as ShortcutApp in the web app system. - auto web_app_info = std::make_unique<WebAppInstallInfo>(); - web_app_info->title = base::UTF8ToUTF16(shortcut_name); - web_app_info->start_url = kAppUrl; - - if (with_icon) { - const GeneratedIconsInfo icon_info( - IconPurpose::ANY, {web_app::icon_size::k32}, {SK_ColorBLACK}); - web_app::AddIconsToWebAppInstallInfo(web_app_info.get(), GURL(kIconUrl), - {icon_info}); - } - - std::string app_id = - test::InstallWebApp(profile(), std::move(web_app_info), - /*overwrite_existing_manifest_fields=*/true); - CHECK( - WebAppProvider::GetForTest(profile())->registrar_unsafe().IsShortcutApp( - app_id)); - return app_id; + AppId CreateShortcut(const std::string& shortcut_name, + bool with_icon = true) { + return test::InstallShortcut(profile(), shortcut_name, GURL(kUrl), + with_icon); } - std::string CreateWebApp(const std::string& app_name) { + AppId CreateWebApp(const std::string& app_name) { const GURL kAppUrl(kUrl); // Create a web app entry with scope, which would be recognised @@ -143,7 +125,11 @@ TEST_F(BrowserShortcutsTest, PublishExistingBrowserShortcut) { const std::string kShortcutName = "Shortcut"; - auto local_shortcut_id = CreateShortcut(kShortcutName); + // Does not create a default icon with this installation so that we can + // verify the icon effect is set to be correct. + // TODO(b/315263875): Add a specific test to test the different icon + // effect to make this clearer. + AppId local_shortcut_id = CreateShortcut(kShortcutName, /*with_icon =*/false); apps::ShortcutId expected_shortcut_id = apps::GenerateShortcutId(app_constants::kChromeAppId, local_shortcut_id); @@ -176,7 +162,7 @@ } TEST_F(BrowserShortcutsTest, WebAppNotPublishedAsShortcut) { - auto app_id = CreateWebApp("App"); + CreateWebApp("App"); InitializeBrowserShortcutPublisher(); @@ -185,7 +171,7 @@ ->ShortcutRegistryCache(); EXPECT_EQ(cache->GetAllShortcuts().size(), 0u); - auto new_app_id = CreateWebApp("NewApp"); + CreateWebApp("NewApp"); EXPECT_EQ(cache->GetAllShortcuts().size(), 0u); } @@ -198,7 +184,7 @@ const std::string kShortcutName = "Shortcut"; - auto local_shortcut_id = CreateShortcut(kShortcutName, /*with_icon = */ true); + AppId local_shortcut_id = CreateShortcut(kShortcutName); apps::ShortcutId expected_shortcut_id = apps::GenerateShortcutId(app_constants::kChromeAppId, local_shortcut_id); @@ -228,7 +214,7 @@ TEST_F(BrowserShortcutsTest, LaunchShortcut) { const std::string kShortcutName = "Shortcut"; - auto local_shortcut_id = CreateShortcut(kShortcutName); + AppId local_shortcut_id = CreateShortcut(kShortcutName); apps::ShortcutId expected_shortcut_id = apps::GenerateShortcutId(app_constants::kChromeAppId, local_shortcut_id); InitializeBrowserShortcutPublisher(); @@ -276,7 +262,7 @@ const std::string kShortcutName = "Shortcut"; - auto local_shortcut_id = CreateShortcut(kShortcutName); + AppId local_shortcut_id = CreateShortcut(kShortcutName); apps::ShortcutId expected_shortcut_id = apps::GenerateShortcutId(app_constants::kChromeAppId, local_shortcut_id); @@ -292,7 +278,7 @@ TEST_F(BrowserShortcutsTest, RemoveShortcut) { const std::string kShortcutName = "Shortcut"; - auto local_shortcut_id = CreateShortcut(kShortcutName); + AppId local_shortcut_id = CreateShortcut(kShortcutName); apps::ShortcutId shortcut_id = apps::GenerateShortcutId(app_constants::kChromeAppId, local_shortcut_id); InitializeBrowserShortcutPublisher(); @@ -319,7 +305,7 @@ TEST_F(BrowserShortcutsTest, GetCompressedShortcutIcon) { const std::string kShortcutName = "Shortcut"; - auto local_shortcut_id = CreateShortcut(kShortcutName); + AppId local_shortcut_id = CreateShortcut(kShortcutName); apps::ShortcutId shortcut_id = apps::GenerateShortcutId(app_constants::kChromeAppId, local_shortcut_id); InitializeBrowserShortcutPublisher(); @@ -372,7 +358,7 @@ ->AppRegistryCache(); ASSERT_EQ(shortcut_cache->GetAllShortcuts().size(), 0u); - auto web_app_id = CreateShortcut("Shortcut"); + AppId web_app_id = CreateShortcut("Shortcut"); EXPECT_TRUE(shortcut_cache->HasShortcut(apps::ShortcutId(web_app_id))); EXPECT_FALSE(app_cache.IsAppInstalled(web_app_id));
diff --git a/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller_unittest.cc b/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller_unittest.cc index 0126090..fc6d6cea 100644 --- a/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller_unittest.cc +++ b/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller_unittest.cc
@@ -32,6 +32,10 @@ #include "ui/display/types/display_constants.h" #include "url/gurl.h" +namespace { +using webapps::AppId; +} + namespace web_app { class FakeShortcutPublisher : public crosapi::mojom::AppShortcutPublisher { @@ -93,25 +97,11 @@ test::AwaitStartWebAppProviderAndSubsystems(profile()); } - std::string CreateWebAppBasedShortcut(const GURL& shortcut_url, - const std::u16string& shortcut_name, - bool with_icon = false) { - // Create web app based shortcut. - auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>(); - web_app_info->start_url = shortcut_url; - web_app_info->title = shortcut_name; - - if (with_icon) { - const GeneratedIconsInfo icon_info( - IconPurpose::ANY, {web_app::icon_size::k32}, {SK_ColorBLACK}); - web_app::AddIconsToWebAppInstallInfo( - web_app_info.get(), GURL(shortcut_url.spec() + "/icon"), {icon_info}); - } - - auto local_shortcut_id = web_app::test::InstallWebApp( - profile(), std::move(web_app_info), - /*overwrite_existing_manifest_fields=*/true); - return local_shortcut_id; + AppId CreateWebAppBasedShortcut(const GURL& shortcut_url, + const std::string& shortcut_name, + bool with_icon = true) { + return test::InstallShortcut(profile(), shortcut_name, shortcut_url, + with_icon); } std::string CreateWebApp(const GURL& app_url, @@ -153,8 +143,13 @@ }; TEST_F(LacrosBrowserShortcutsControllerTest, PublishShortcuts) { - auto local_id_1 = CreateWebAppBasedShortcut(GURL("https://www.example.com/"), - u"shortcut name"); + // Does not create a default icon with this shortcut so that we can + // verify the icon effect is set to be correct. + // TODO(b/315263875): Add a specific test to test the different icon + // effect to make this clearer. + AppId local_id_1 = + CreateWebAppBasedShortcut(GURL("https://www.example.com/"), + "shortcut name", /*with_icon = */ false); InitializeLacrosBrowserShortcutsController(); ASSERT_TRUE(fake_publisher()->controller_registered()); @@ -173,9 +168,8 @@ apps::IconEffects::kRoundCorners | apps::IconEffects::kCrOsStandardMask); EXPECT_TRUE(fake_publisher()->get_deltas().back()->allow_removal); - auto local_id_2 = CreateWebAppBasedShortcut( - GURL("https://www.another-example.com/"), u"another shortcut name", - /*with_icon = */ true); + AppId local_id_2 = CreateWebAppBasedShortcut( + GURL("https://www.another-example.com/"), "another shortcut name"); EXPECT_EQ(fake_publisher()->get_deltas().size(), 2U); EXPECT_EQ(fake_publisher()->get_deltas().back()->local_id, local_id_2); @@ -210,8 +204,8 @@ TEST_F(LacrosBrowserShortcutsControllerTest, LaunchShortcut) { InitializeLacrosBrowserShortcutsController(); - auto shortcut_id = CreateWebAppBasedShortcut(GURL("https://www.example.com/"), - u"shortcut name"); + AppId shortcut_id = CreateWebAppBasedShortcut( + GURL("https://www.example.com/"), "shortcut name"); base::RunLoop runloop; fake_publisher()->controller_->LaunchShortcut( @@ -223,8 +217,8 @@ TEST_F(LacrosBrowserShortcutsControllerTest, GetCompressedIcon) { InitializeLacrosBrowserShortcutsController(); - auto shortcut_id = CreateWebAppBasedShortcut(GURL("https://www.example.com/"), - u"shortcut name"); + AppId shortcut_id = CreateWebAppBasedShortcut( + GURL("https://www.example.com/"), "shortcut name"); const float scale1 = 1.0; const float scale2 = 2.0; const int kIconSize1 = 64 * scale1; @@ -259,8 +253,8 @@ TEST_F(LacrosBrowserShortcutsControllerTest, RemoveShortcut) { InitializeLacrosBrowserShortcutsController(); - auto shortcut_id = CreateWebAppBasedShortcut(GURL("https://www.example.com/"), - u"shortcut name"); + AppId shortcut_id = CreateWebAppBasedShortcut( + GURL("https://www.example.com/"), "shortcut name"); base::RunLoop runloop; fake_publisher()->controller_->RemoveShortcut(
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc index e6ce6256..da4ba8e1 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc
@@ -118,18 +118,7 @@ webapps::AppId CreateShortcut(const GURL& shortcut_url, const std::string& shortcut_name) { - // Create a web app entry without scope, which would be recognised - // as ShortcutApp in the web app system. - auto web_app_info = std::make_unique<WebAppInstallInfo>(); - web_app_info->title = base::UTF8ToUTF16(shortcut_name); - web_app_info->start_url = shortcut_url; - - webapps::AppId app_id = - test::InstallWebApp(profile(), std::move(web_app_info)); - CHECK( - WebAppProvider::GetForTest(profile())->registrar_unsafe().IsShortcutApp( - app_id)); - return app_id; + return test::InstallShortcut(profile(), shortcut_name, shortcut_url); } content::BrowserTaskEnvironment task_environment_;
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_unittest.cc b/chrome/browser/web_applications/app_service/web_app_publisher_unittest.cc index 895e91b..c960216 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_unittest.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_unittest.cc
@@ -52,20 +52,9 @@ test::AwaitStartWebAppProviderAndSubsystems(profile()); } - std::string CreateShortcut(const GURL& shortcut_url, - const std::string& shortcut_name) { - // Create a web app entry without scope, which would be recognised - // as ShortcutApp in the web app system. - auto web_app_info = std::make_unique<WebAppInstallInfo>(); - web_app_info->title = base::UTF8ToUTF16(shortcut_name); - web_app_info->start_url = shortcut_url; - - std::string app_id = - test::InstallWebApp(profile(), std::move(web_app_info)); - CHECK( - WebAppProvider::GetForTest(profile())->registrar_unsafe().IsShortcutApp( - app_id)); - return app_id; + webapps::AppId CreateShortcut(const GURL& shortcut_url, + const std::string& shortcut_name) { + return test::InstallShortcut(profile(), shortcut_name, shortcut_url); } std::string CreateWebApp(const GURL& app_url, const std::string& app_name) {
diff --git a/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc b/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc index b819d65..946b4946 100644 --- a/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc +++ b/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc
@@ -395,11 +395,8 @@ IN_PROC_BROWSER_TEST_F(LaunchWebAppCommandTest_Shortstand, ShortcutLaunchInTab) { const GURL kShortcutUrl("https://www.shortcut-example.com"); - auto web_app_info = std::make_unique<WebAppInstallInfo>(); - web_app_info->title = u"TestShortcut"; - web_app_info->start_url = kShortcutUrl; webapps::AppId web_shortcut_id = - test::InstallWebApp(profile(), std::move(web_app_info)); + test::InstallShortcut(profile(), "TestShortcut", kShortcutUrl); { apps::AppLaunchParams launch_params = CreateLaunchParams(
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.cc b/chrome/browser/web_applications/test/web_app_install_test_utils.cc index aa47286..7cc6bde 100644 --- a/chrome/browser/web_applications/test/web_app_install_test_utils.cc +++ b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
@@ -13,6 +13,7 @@ #include "build/build_config.h" #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h" #include "chrome/browser/web_applications/test/fake_web_app_provider.h" +#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h" #include "chrome/browser/web_applications/web_app_command_scheduler.h" #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/browser/web_applications/web_app_helpers.h" @@ -113,6 +114,50 @@ return app_id; } +webapps::AppId InstallShortcut(Profile* profile, + const std::string& shortcut_name, + const GURL& start_url, + bool create_default_icon) { + auto web_app_info = std::make_unique<WebAppInstallInfo>(); + + web_app_info->start_url = start_url; + web_app_info->title = base::UTF8ToUTF16(shortcut_name); + web_app_info->user_display_mode = mojom::UserDisplayMode::kBrowser; + if (create_default_icon) { + const GeneratedIconsInfo icon_info( + IconPurpose::ANY, {web_app::icon_size::k32}, {SK_ColorBLACK}); + web_app::AddIconsToWebAppInstallInfo(web_app_info.get(), start_url, + {icon_info}); + } + // The sync system requires that sync entity name is never empty. + if (web_app_info->title.empty()) { + web_app_info->title = u"WebAppInstallInfo Shortcut Name"; + } + + base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode> + future; + auto* provider = WebAppProvider::GetForTest(profile); + DCHECK(provider); + WaitUntilReady(provider); + // In unit tests, we do not have Browser or WebContents instances. Hence we + // use `InstallFromInfoCommand` instead of `FetchManifestAndInstallCommand` or + // `WebAppInstallCommand` to install the web app. + provider->scheduler().InstallFromInfo( + std::move(web_app_info), /*overwrite_existing_manifest_fields =*/true, + webapps::WebappInstallSource::MENU_CREATE_SHORTCUT, future.GetCallback()); + + webapps::AppId app_id = future.Get<0>(); + webapps::InstallResultCode code = future.Get<1>(); + + EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code); + + // Allow updates to be published to App Service listeners. + base::RunLoop().RunUntilIdle(); + + CHECK(provider->registrar_unsafe().IsShortcutApp(app_id)); + return app_id; +} + void UninstallWebApp(Profile* profile, const webapps::AppId& app_id) { WebAppProvider* const provider = WebAppProvider::GetForTest(profile); base::test::TestFuture<webapps::UninstallResultCode> future;
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.h b/chrome/browser/web_applications/test/web_app_install_test_utils.h index ded5b504..8f38f226 100644 --- a/chrome/browser/web_applications/test/web_app_install_test_utils.h +++ b/chrome/browser/web_applications/test/web_app_install_test_utils.h
@@ -57,6 +57,12 @@ webapps::WebappInstallSource install_source = webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON); +// Synchronously install a web-app-based shortcut for testing. +webapps::AppId InstallShortcut(Profile* profile, + const std::string& shortcut_name, + const GURL& start_url, + bool create_default_icon = true); + // Synchronously uninstall a web app. May be used in unit tests and browser // tests. void UninstallWebApp(Profile* profile, const webapps::AppId& app_id);
diff --git a/chrome/renderer/net/available_offline_content_helper.cc b/chrome/renderer/net/available_offline_content_helper.cc index 88f028e..02b46e7 100644 --- a/chrome/renderer/net/available_offline_content_helper.cc +++ b/chrome/renderer/net/available_offline_content_helper.cc
@@ -132,8 +132,6 @@ for (const AvailableOfflineContentPtr& item : fetched_content_) { if (item->id == id && item->name_space == name_space) { - UMA_HISTOGRAM_ENUMERATION("Net.ErrorPageCounts.SuggestionClicked", - item->content_type); RecordEvent(error_page::NETWORK_ERROR_PAGE_OFFLINE_SUGGESTION_CLICKED); provider_->LaunchItem(id, name_space); return;
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn index 76c4562..4efb1b2 100644 --- a/chrome/test/data/webui/settings/chromeos/BUILD.gn +++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -289,6 +289,7 @@ "os_privacy_page/privacy_hub_app_permission_test_util.ts", "os_privacy_page/privacy_hub_camera_subpage_test.ts", "os_privacy_page/privacy_hub_microphone_subpage_test.ts", + "os_privacy_page/privacy_hub_geolocation_subpage_test.ts", "os_privacy_page/privacy_hub_subpage_test.ts", "os_privacy_page/smart_privacy_subpage_test.ts", "os_privacy_page/test_metrics_consent_browser_proxy.ts",
diff --git a/chrome/test/data/webui/settings/chromeos/os_privacy_page/privacy_hub_geolocation_subpage_test.ts b/chrome/test/data/webui/settings/chromeos/os_privacy_page/privacy_hub_geolocation_subpage_test.ts new file mode 100644 index 0000000..3c96098 --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/os_privacy_page/privacy_hub_geolocation_subpage_test.ts
@@ -0,0 +1,122 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://os-settings/lazy_load.js'; + +import {SettingsPrivacyHubGeolocationSubpage} from 'chrome://os-settings/lazy_load.js'; +import {GeolocationAccessLevel, Router, routes} from 'chrome://os-settings/os_settings.js'; +import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {assertEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js'; + +import {FakeMetricsPrivate} from '../fake_metrics_private.js'; + +import {createFakeMetricsPrivate} from './privacy_hub_app_permission_test_util.js'; + + +suite('<settings-privacy-hub-geolocation-subpage>', () => { + let metrics: FakeMetricsPrivate; + let privacyHubGeolocationSubpage: SettingsPrivacyHubGeolocationSubpage; + + async function initPage() { + privacyHubGeolocationSubpage = + document.createElement('settings-privacy-hub-geolocation-subpage'); + const prefs = { + ash: { + user: { + geolocation_access_level: { + key: 'ash.user.geolocation_access_level', + type: chrome.settingsPrivate.PrefType.NUMBER, + value: GeolocationAccessLevel.ALLOWED, + }, + }, + }, + }; + privacyHubGeolocationSubpage.prefs = prefs; + document.body.appendChild(privacyHubGeolocationSubpage); + flush(); + } + + + setup(() => { + metrics = createFakeMetricsPrivate(); + Router.getInstance().navigateTo(routes.PRIVACY_HUB_GEOLOCATION); + }); + + teardown(() => { + privacyHubGeolocationSubpage.remove(); + Router.getInstance().resetRouteForTesting(); + }); + + function histogram(): string { + return 'ChromeOS.PrivacyHub.Geolocation.AccessLevelChanged.SystemSettings'; + } + + function setGeolocationAccessLevel(accessLevel: GeolocationAccessLevel) { + const dropdown = privacyHubGeolocationSubpage.shadowRoot! + .querySelector('settings-dropdown-menu')!.shadowRoot! + .querySelector<HTMLSelectElement>('#dropdownMenu')!; + assertTrue(!!dropdown); + + dropdown.value = accessLevel.toString(); + dropdown.dispatchEvent(new CustomEvent('change')); + flush(); + } + + function getGeolocationAccessLevel(): GeolocationAccessLevel { + const dropdown = privacyHubGeolocationSubpage.shadowRoot! + .querySelector('settings-dropdown-menu')!.shadowRoot! + .querySelector<HTMLSelectElement>('#dropdownMenu')!; + assertTrue(!!dropdown); + + switch (dropdown.value) { + case '0': + return GeolocationAccessLevel.DISALLOWED; + case '1': + return GeolocationAccessLevel.ALLOWED; + case '2': + return GeolocationAccessLevel.ONLY_ALLOWED_FOR_SYSTEM; + } + + assertNotReached('Invalid GeolocationAccessLevel value detected'); + } + + test('Metric recorded when clicked', async () => { + await initPage(); + + assertEquals( + 0, + metrics.countMetricValue( + histogram(), GeolocationAccessLevel.DISALLOWED)); + assertEquals( + 0, + metrics.countMetricValue(histogram(), GeolocationAccessLevel.ALLOWED)); + assertEquals( + 0, + metrics.countMetricValue( + histogram(), GeolocationAccessLevel.ONLY_ALLOWED_FOR_SYSTEM)); + + // Default access level should be ALLOWED. + assertEquals(GeolocationAccessLevel.ALLOWED, getGeolocationAccessLevel()); + + // Change dropdown and check the corresponding metric is recorded. + setGeolocationAccessLevel(GeolocationAccessLevel.DISALLOWED); + assertEquals( + 1, + metrics.countMetricValue( + histogram(), GeolocationAccessLevel.DISALLOWED)); + + // Change dropdown and check the corresponding metric is recorded. + setGeolocationAccessLevel(GeolocationAccessLevel.ONLY_ALLOWED_FOR_SYSTEM); + assertEquals( + 1, + metrics.countMetricValue( + histogram(), GeolocationAccessLevel.ONLY_ALLOWED_FOR_SYSTEM)); + + // Change dropdown and check the corresponding metric is recorded. + setGeolocationAccessLevel(GeolocationAccessLevel.ALLOWED); + assertEquals( + 1, + metrics.countMetricValue(histogram(), GeolocationAccessLevel.ALLOWED)); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js index 19005071..3ad2c959 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -1122,6 +1122,16 @@ }, ], [ + 'OsPrivacyPagePrivacyHubGeolocationSubpage', + 'os_privacy_page/privacy_hub_geolocation_subpage_test.js', + { + enabled: [ + 'ash::features::kCrosPrivacyHubV0', + 'ash::features::kCrosPrivacyHub', + ] + }, + ], + [ 'OsPrivacyPagePrivacyHubSubpage', 'os_privacy_page/privacy_hub_subpage_test.js', {enabled: ['ash::features::kCrosPrivacyHubV0']},
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index fa1ae43..f76666d 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -15711.0.0 \ No newline at end of file +15714.0.0 \ No newline at end of file
diff --git a/chromeos/ash/components/emoji/tools/.style.yapf b/chromeos/ash/components/emoji/tools/.style.yapf new file mode 100644 index 0000000..3d8b70f --- /dev/null +++ b/chromeos/ash/components/emoji/tools/.style.yapf
@@ -0,0 +1,2 @@ +[style] +based_on_style = pep8 \ No newline at end of file
diff --git a/chromeos/ash/components/emoji/tools/emoji_data.py b/chromeos/ash/components/emoji/tools/emoji_data.py index 904a72f..78b3941 100755 --- a/chromeos/ash/components/emoji/tools/emoji_data.py +++ b/chromeos/ash/components/emoji/tools/emoji_data.py
@@ -19,40 +19,40 @@ import action_helpers - # LINT.IfChange + # `MULTI_TONE` is not defined in ../types.ts because this script removes any # multi-tone values before being outputted. class Tone(enum.IntEnum): - LIGHT = 1 - MEDIUM_LIGHT = 2 - MEDIUM = 3 - MEDIUM_DARK = 4 - DARK = 5 - MULTI_TONE = 6 + LIGHT = 1 + MEDIUM_LIGHT = 2 + MEDIUM = 3 + MEDIUM_DARK = 4 + DARK = 5 + MULTI_TONE = 6 class Gender(enum.IntEnum): - WOMAN = 1 - MAN = 2 + WOMAN = 1 + MAN = 2 + # LINT.ThenChange(//chrome/browser/resources/chromeos/emoji_picker/types.ts) - # Codepoints for the range of skin tone modifiers from lightest to darkest. TONE_MODIFIERS = { - ord('🏻'): Tone.LIGHT, - ord('🏼'): Tone.MEDIUM_LIGHT, - ord('🏽'): Tone.MEDIUM, - ord('🏾'): Tone.MEDIUM_DARK, - ord('🏿'): Tone.DARK, + ord('🏻'): Tone.LIGHT, + ord('🏼'): Tone.MEDIUM_LIGHT, + ord('🏽'): Tone.MEDIUM, + ord('🏾'): Tone.MEDIUM_DARK, + ord('🏿'): Tone.DARK, } # Codepoints for the woman and man gender modifiers. GENDER_MODIFIERS = { - ord('♀'): Gender.WOMAN, - ord('♂'): Gender.MAN, + ord('♀'): Gender.WOMAN, + ord('♂'): Gender.MAN, } @@ -66,10 +66,10 @@ for tag in root.iterfind('./annotations/annotation'): cp = tag.attrib['cp'] if tag.attrib.get('type') == 'tts': - if tag.text.startswith("flag"): - names[cp] = tag.text.replace("flag:","flag of") + if tag.text.startswith('flag'): + names[cp] = tag.text.replace('flag:', 'flag of') else: - names[cp] = tag.text + names[cp] = tag.text else: keywords[cp] = tag.text.split(' | ') @@ -82,34 +82,33 @@ def get_tone(codepoints): - tone_matches = [ - codepoint - for codepoint in codepoints - if codepoint in TONE_MODIFIERS - ] + tone_matches = [ + codepoint for codepoint in codepoints if codepoint in TONE_MODIFIERS + ] - if len(tone_matches) == 0: - return None - elif len(tone_matches) == 1: - return TONE_MODIFIERS[tone_matches[0]] - else: - return Tone.MULTI_TONE + if len(tone_matches) == 0: + return None + elif len(tone_matches) == 1: + return TONE_MODIFIERS[tone_matches[0]] + else: + return Tone.MULTI_TONE def get_gender(codepoints): - for codepoint in codepoints: - if codepoint in GENDER_MODIFIERS: - return GENDER_MODIFIERS[codepoint] + for codepoint in codepoints: + if codepoint in GENDER_MODIFIERS: + return GENDER_MODIFIERS[codepoint] - return None + return None def transform_emoji_data(metadata, names, keywords, first_only): - def transform(codepoints, is_variant, emoticons = None, shortcodes = None): + + def transform(codepoints, is_variant, emoticons=None, shortcodes=None): if emoticons is None: - emoticons = [] + emoticons = [] if shortcodes is None: - shortcodes = [] + shortcodes = [] # transform array of codepoint values into unicode string. string = u''.join(chr(x) for x in codepoints) @@ -118,20 +117,21 @@ string = string.replace(u'\ufe0f', u'') # TODO(b/183440310): Better handle search for non-standard emoji. if string in names: - name = names[string] - keyword_list = keywords[string] + emoticons + shortcodes + name = names[string] + keyword_list = keywords[string] + emoticons + shortcodes else: - name = '' - keyword_list = emoticons + name = '' + keyword_list = emoticons if is_variant: - return {'string': string, 'name': name} + return {'string': string, 'name': name} else: - return {'string': string, 'name': name, 'keywords': keyword_list} + return {'string': string, 'name': name, 'keywords': keyword_list} + if first_only: - metadata = [metadata[0]] + metadata = [metadata[0]] else: - metadata = metadata[1:] + metadata = metadata[1:] # Create a new object for output since they keep adding extra properties to # the JSON (rather than just editing the input object). @@ -140,7 +140,8 @@ newGroup = [] for emoji in group['emoji']: newobj = { - 'base': transform( + 'base': + transform( emoji['base'], False, emoji['emoticons'], @@ -148,35 +149,35 @@ ), } if emoji['alternates']: - newobj['alternates'] = [] + newobj['alternates'] = [] - has_multi_tone = any( - get_tone(codepoints) == Tone.MULTI_TONE - for codepoints in emoji['alternates'] - ) + has_multi_tone = any( + get_tone(codepoints) == Tone.MULTI_TONE + for codepoints in emoji['alternates']) - for codepoints in emoji['alternates']: - variant = transform(codepoints, True) + for codepoints in emoji['alternates']: + variant = transform(codepoints, True) - # Multi-tone preferences are individual, so all tones are - # ignored if any variant is multi-tone. - tone = get_tone(codepoints) if not has_multi_tone else None - gender = get_gender(codepoints) + # Multi-tone preferences are individual, so all tones are + # ignored if any variant is multi-tone. + tone = get_tone(codepoints) if not has_multi_tone else None + gender = get_gender(codepoints) - if tone: - variant['tone'] = tone - newobj['groupedTone'] = True + if tone: + variant['tone'] = tone + newobj['groupedTone'] = True - if gender: - variant['gender'] = gender - newobj['groupedGender'] = True + if gender: + variant['gender'] = gender + newobj['groupedGender'] = True - newobj['alternates'].append(variant) + newobj['alternates'].append(variant) newGroup.append(newobj) out.append({'emoji': newGroup}) return out + def main(args): parser = argparse.ArgumentParser() parser.add_argument('--metadata', @@ -189,17 +190,17 @@ required=True, nargs='+', help='emoji keyword files as list of XML files') - parser.add_argument('--firstgroup', - required = True, - help='Only output the first group, otherwise output all groups' - ) + parser.add_argument( + '--firstgroup', + required=True, + help='Only output the first group, otherwise output all groups') options = parser.parse_args(args) metadata_file = options.metadata keyword_files = options.keywords output_file = options.output - first_group = options.firstgroup == "True" + first_group = options.firstgroup == 'True' # iterate through keyword files and combine them names = {}
diff --git a/chromeos/ash/components/emoji/tools/emoticon_data.py b/chromeos/ash/components/emoji/tools/emoticon_data.py index 7125702..3598a68 100644 --- a/chromeos/ash/components/emoji/tools/emoticon_data.py +++ b/chromeos/ash/components/emoji/tools/emoticon_data.py
@@ -14,7 +14,6 @@ import action_helpers - # Set of unicode characters that do not render with fonts available on ChromeOS # TODO(b:267370102) add font(s) such that there are no more invalid characters INVALID_CHARACTERS = set([ @@ -40,15 +39,15 @@ list(dict): list of readily used emoticon groups. """ return [{ - "group": - group["group"], - "emoji": [{ - "base": { - "string": emoticon["value"], - "name": emoticon["description"], + 'group': + group['group'], + 'emoji': [{ + 'base': { + 'string': emoticon['value'], + 'name': emoticon['description'], }, - } for emoticon in group["emoticon"] - if isValidEmoticon(emoticon["value"])] + } for emoticon in group['emoticon'] + if isValidEmoticon(emoticon['value'])] } for group in metadata]
diff --git a/chromeos/ash/components/emoji/tools/symbol_data.py b/chromeos/ash/components/emoji/tools/symbol_data.py index a0b678b..4057b4b 100755 --- a/chromeos/ash/components/emoji/tools/symbol_data.py +++ b/chromeos/ash/components/emoji/tools/symbol_data.py
@@ -24,7 +24,6 @@ logging.basicConfig(stream=sys.stdout, level=logging.ERROR) LOGGER = logging.getLogger(__name__) - # List of unicode ranges for each symbol group (ranges are inclusive). SYMBOLS_GROUPS = { 'Arrows': [ @@ -113,7 +112,6 @@ ], } - # Set of unicode symbols that do not render with fonts available on ChromeOS INVALID_SYMBOLS = set([ '\u2BBA', @@ -125,34 +123,33 @@ '\U0001F8B1', ]) - # Custom search keywords for symbols. # By default, symbols do not have search keywords. # These are "shortcut" style search keywords based off compose key to provide a # fast way to access common symbols. CUSTOM_KEYWORDS = { - '⅐':['17'], - '⅓':['13'], - '⅔':['23'], - '½':['12'], - '¼':['14'], - '¾':['34'], - '⅕':['15'], - '⅖':['25'], - '⅗':['35'], - '⅘':['45'], - '⅙':['16'], - '⅛':['18'], - '⅜':['38'], - '⅝':['58'], - '⅞':['78'], - '©':['oc', 'co'], - '®':['or', 'ro'], - '₠':['CE'], - '₡':['C/','/C'], - '₢':['Cr'], - '₣':['Fr'], - '¢':['|c', 'c|', 'c/', '/c'], + '⅐': ['17'], + '⅓': ['13'], + '⅔': ['23'], + '½': ['12'], + '¼': ['14'], + '¾': ['34'], + '⅕': ['15'], + '⅖': ['25'], + '⅗': ['35'], + '⅘': ['45'], + '⅙': ['16'], + '⅛': ['18'], + '⅜': ['38'], + '⅝': ['58'], + '⅞': ['78'], + '©': ['oc', 'co'], + '®': ['or', 'ro'], + '₠': ['CE'], + '₡': ['C/', '/C'], + '₢': ['Cr'], + '₣': ['Fr'], + '¢': ['|c', 'c|', 'c/', '/c'], '£': ['L-', '-L'], '₥': ['m/', '/m'], '₦': ['N=', '=N'], @@ -180,8 +177,7 @@ # Name of the unicode character. name: str # Search keywords related to the unicode character. - keywords: List[str] = dataclasses.field( - default_factory=list) + keywords: List[str] = dataclasses.field(default_factory=list) @dataclasses.dataclass @@ -190,8 +186,7 @@ # Base Emoji. base: EmojiPickerChar # Base Emoji's variants and alternative emojis. - alternates: List[EmojiPickerChar] = dataclasses.field( - default_factory=list) + alternates: List[EmojiPickerChar] = dataclasses.field(default_factory=list) @dataclasses.dataclass @@ -235,8 +230,7 @@ """ return { _convert_snake_case_to_camel_case(key): value - for (key, value) in data - if not isinstance(value, list) or value + for (key, value) in data if not isinstance(value, list) or value } @@ -286,9 +280,8 @@ LOGGER.info( 'generating EmojiPickerChar instances for ranges: [%s].', - ', '.join( - '(U+{:02x}, U+{:02x})'.format(*rng) - for rng in unicode_ranges)) + ', '.join('(U+{:02x}, U+{:02x})'.format(*rng) + for rng in unicode_ranges)) num_chars = 0 num_ignored = 0 @@ -297,9 +290,7 @@ for (start_code_point, end_code_point) in unicode_ranges: LOGGER.debug( 'generating EmojiPickerChar instances ' - 'for range (U+%02x to U+%02x).', - start_code_point, - end_code_point) + 'for range (U+%02x to U+%02x).', start_code_point, end_code_point) num_chars += end_code_point + 1 - start_code_point # Iterate over all code points in the range. @@ -319,18 +310,16 @@ raise else: num_ignored += 1 - LOGGER.warning( - 'invalid code point U+%02x.', code_point) + LOGGER.warning('invalid code point U+%02x.', code_point) - LOGGER.info( - 'stats: #returned instances: %d, #ignored code points: %d', - num_chars, - num_ignored) + LOGGER.info('stats: #returned instances: %d, #ignored code points: %d', + num_chars, num_ignored) def get_symbols_groups( group_unicode_ranges: Dict[str, List[Tuple[int, int]]], - search_only: bool = False, ignore_errors: bool = True, + search_only: bool = False, + ignore_errors: bool = True, filter_set: Optional[Set[str]] = None) -> List[EmojiPickerGroup]: """Creates symbols data from predefined groups and their unicode ranges. @@ -353,27 +342,29 @@ emoji_chars = _convert_unicode_ranges_to_emoji_chars( unicode_ranges, ignore_errors=ignore_errors) emoji = [ - EmojiPickerEmoji(base=emoji_char) - for emoji_char in emoji_chars - if filter_set is None or emoji_char.string not in filter_set] + EmojiPickerEmoji(base=emoji_char) for emoji_char in emoji_chars + if filter_set is None or emoji_char.string not in filter_set + ] - emoji_group = EmojiPickerGroup( - group=group_name, emoji=emoji, search_only=search_only) + emoji_group = EmojiPickerGroup(group=group_name, + emoji=emoji, + search_only=search_only) emoji_groups.append(emoji_group) return emoji_groups def main(argv: List[str]) -> None: parser = argparse.ArgumentParser() - parser.add_argument( - '--output', required=True, type=str, - help='Path to write the output JSON file.') - parser.add_argument( - '--verbose', required=False, default=False, - action='store_true', - help="Set the logging level to Debug.") - parser.add_argument( - '--filter-data-paths', action='append', nargs='+') + parser.add_argument('--output', + required=True, + type=str, + help='Path to write the output JSON file.') + parser.add_argument('--verbose', + required=False, + default=False, + action='store_true', + help='Set the logging level to Debug.') + parser.add_argument('--filter-data-paths', action='append', nargs='+') args = parser.parse_args(argv) @@ -395,35 +386,30 @@ filter_set |= INVALID_SYMBOLS # Add symbol groups. - symbols_groups = get_symbols_groups( - group_unicode_ranges=SYMBOLS_GROUPS, - filter_set=filter_set, - search_only=False) + symbols_groups = get_symbols_groups(group_unicode_ranges=SYMBOLS_GROUPS, + filter_set=filter_set, + search_only=False) # Add search-only symbol groups. symbols_groups.extend( - get_symbols_groups( - group_unicode_ranges=SEARCH_ONLY_SYMBOLS_GROUPS, - filter_set=filter_set, - search_only=True) - ) + get_symbols_groups(group_unicode_ranges=SEARCH_ONLY_SYMBOLS_GROUPS, + filter_set=filter_set, + search_only=True)) # Create the data and convert them to dict. symbols_groups_dicts = [] for symbol_group in symbols_groups: symbol_group_dict = dataclasses.asdict( - symbol_group, - dict_factory=_emoji_data_dict_factory) + symbol_group, dict_factory=_emoji_data_dict_factory) symbols_groups_dicts.append(symbol_group_dict) # Write the result to output path as json file. with action_helpers.atomic_output(args.output) as tmp_file: tmp_file.write( - json.dumps( - symbols_groups_dicts, - separators=(',', ':'), - ensure_ascii=False).encode('utf-8')) + json.dumps(symbols_groups_dicts, + separators=(',', ':'), + ensure_ascii=False).encode('utf-8')) -if __name__ == "__main__": +if __name__ == '__main__': main(sys.argv[1:])
diff --git a/chromeos/profiles/arm-exp.afdo.newest.txt b/chromeos/profiles/arm-exp.afdo.newest.txt index 7b84205..75bc69b 100644 --- a/chromeos/profiles/arm-exp.afdo.newest.txt +++ b/chromeos/profiles/arm-exp.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-exp-121-6167.9-1702295304-benchmark-122.0.6189.0-r1-redacted.afdo.xz +chromeos-chrome-arm-exp-121-6167.9-1702295304-benchmark-122.0.6191.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt index f383089..9b794e02 100644 --- a/chromeos/profiles/arm.afdo.newest.txt +++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-none-121-6154.0-1702299075-benchmark-122.0.6190.0-r1-redacted.afdo.xz +chromeos-chrome-arm-none-121-6154.0-1702299075-benchmark-122.0.6191.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index 742f5d598..6dc13c0 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-121-6167.9-1702295304-benchmark-122.0.6189.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-121-6167.9-1702295304-benchmark-122.0.6190.0-r1-redacted.afdo.xz
diff --git a/components/BUILD.gn b/components/BUILD.gn index 9a406f8..b5f2e19 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -483,6 +483,7 @@ "//components/services/paint_preview_compositor:unit_tests", "//components/services/storage:tests", "//components/session_proto_db:unit_tests", + "//components/subresource_filter/content/browser:unit_tests", "//components/subresource_filter/content/common:unit_tests", "//components/subresource_filter/content/renderer:unit_tests", "//components/tracing:unit_tests", @@ -569,7 +570,6 @@ "//components/site_isolation:unit_tests", "//components/spellcheck/browser:unit_tests", "//components/spellcheck/renderer:unit_tests", - "//components/subresource_filter/content/browser:unit_tests", ] if (!is_win) { #!iOS and!Windows
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index dab1077b..7a3dfd6 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -121,6 +121,8 @@ "data_model/address.h", "data_model/autofill_data_model.cc", "data_model/autofill_data_model.h", + "data_model/autofill_feature_guarded_address_component.cc", + "data_model/autofill_feature_guarded_address_component.h", "data_model/autofill_i18n_api.cc", "data_model/autofill_i18n_api.h", "data_model/autofill_i18n_formatting_expressions.h", @@ -482,29 +484,15 @@ "ui/accessory_sheet_enums.h", "ui/address_combobox_model.cc", "ui/address_combobox_model.h", - "ui/address_contact_form_label_formatter.cc", - "ui/address_contact_form_label_formatter.h", - "ui/address_email_form_label_formatter.cc", - "ui/address_email_form_label_formatter.h", - "ui/address_form_label_formatter.cc", - "ui/address_form_label_formatter.h", - "ui/address_phone_form_label_formatter.cc", - "ui/address_phone_form_label_formatter.h", "ui/autofill_image_fetcher_base.h", "ui/autofill_popup_delegate.h", "ui/autofill_resource_utils.cc", "ui/autofill_resource_utils.h", - "ui/contact_form_label_formatter.cc", - "ui/contact_form_label_formatter.h", "ui/country_combobox_model.cc", "ui/country_combobox_model.h", "ui/fast_checkout_client.h", "ui/fast_checkout_delegate.h", "ui/fast_checkout_enums.h", - "ui/label_formatter.cc", - "ui/label_formatter.h", - "ui/label_formatter_utils.cc", - "ui/label_formatter_utils.h", "ui/payments/autofill_error_dialog_controller.h", "ui/payments/bubble_show_options.cc", "ui/payments/bubble_show_options.h", @@ -528,6 +516,8 @@ "ui/touch_to_fill_delegate.h", "validation.cc", "validation.h", + "webdata/addresses/address_autofill_table.cc", + "webdata/addresses/address_autofill_table.h", "webdata/autocomplete_entry.cc", "webdata/autocomplete_entry.h", "webdata/autocomplete_sync_bridge.cc", @@ -598,8 +588,6 @@ "payments/autofill_virtual_card_enrollment_infobar_delegate_mobile.cc", "payments/autofill_virtual_card_enrollment_infobar_delegate_mobile.h", "payments/autofill_virtual_card_enrollment_infobar_mobile.h", - "ui/mobile_label_formatter.cc", - "ui/mobile_label_formatter.h", "ui/payments/card_expiration_date_fix_flow_controller.h", "ui/payments/card_expiration_date_fix_flow_controller_impl.cc", "ui/payments/card_expiration_date_fix_flow_controller_impl.h", @@ -1157,6 +1145,7 @@ "ui/payments/virtual_card_enroll_ui_model_unittest.cc", "ui/region_combobox_model_unittest.cc", "validation_unittest.cc", + "webdata/addresses/address_autofill_table_unittest.cc", "webdata/autocomplete_sync_bridge_unittest.cc", "webdata/autocomplete_table_unittest.cc", "webdata/autofill_profile_sync_bridge_unittest.cc", @@ -1181,7 +1170,6 @@ sources += [ "payments/autofill_save_card_delegate_unittest.cc", "payments/autofill_save_card_ui_info_unittest.cc", - "ui/mobile_label_formatter_unittest.cc", "ui/payments/card_expiration_date_fix_flow_controller_impl_unittest.cc", "ui/payments/card_name_fix_flow_controller_impl_unittest.cc", ] @@ -1212,13 +1200,6 @@ sources += [ "payments/local_card_migration_manager_unittest.cc", "server_prediction_overrides_unittest.cc", - "ui/address_contact_form_label_formatter_unittest.cc", - "ui/address_email_form_label_formatter_unittest.cc", - "ui/address_form_label_formatter_unittest.cc", - "ui/address_phone_form_label_formatter_unittest.cc", - "ui/contact_form_label_formatter_unittest.cc", - "ui/label_formatter_unittest.cc", - "ui/label_formatter_utils_unittest.cc", ] }
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/autofill_data_util.cc index 24a9af6..078b513 100644 --- a/components/autofill/core/browser/autofill_data_util.cc +++ b/components/autofill/core/browser/autofill_data_util.cc
@@ -273,7 +273,7 @@ } void AddGroupToBitmask(uint32_t* group_bitmask, FieldType type) { - const FieldTypeGroup group = GroupTypeOfServerFieldType(type); + const FieldTypeGroup group = GroupTypeOfFieldType(type); switch (group) { case autofill::FieldTypeGroup::kName: *group_bitmask |= kName;
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc index 3a9c1f08..15597900 100644 --- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc +++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -99,7 +99,7 @@ Suggestion CreateFieldByFieldFillingSuggestion(const std::string& guid, FieldType fbf_type_used) { Suggestion suggestion = test::CreateAutofillSuggestion( - GroupTypeOfServerFieldType(fbf_type_used) == FieldTypeGroup::kCreditCard + GroupTypeOfFieldType(fbf_type_used) == FieldTypeGroup::kCreditCard ? PopupItemId::kCreditCardFieldByFieldFilling : PopupItemId::kAddressFieldByFieldFilling, u"field by field", Suggestion::Guid(guid));
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc index 38bcaa05..a68921d 100644 --- a/components/autofill/core/browser/autofill_field.cc +++ b/components/autofill/core/browser/autofill_field.cc
@@ -276,7 +276,7 @@ } void AutofillField::add_possible_types_validities( - const ServerFieldTypeValidityStateMap& possible_types_validities) { + const FieldTypeValidityStateMap& possible_types_validities) { for (const auto& possible_type_validity : possible_types_validities) { possible_types_validities_[possible_type_validity.first].push_back( possible_type_validity.second); @@ -350,7 +350,7 @@ // If autocomplete=tel/tel-* and server confirms it really is a phone field, // we always use the server prediction as html types are not very reliable. if (GroupTypeOfHtmlFieldType(html_type_) == FieldTypeGroup::kPhone && - GroupTypeOfServerFieldType(server_type()) == FieldTypeGroup::kPhone) { + GroupTypeOfFieldType(server_type()) == FieldTypeGroup::kPhone) { return AutofillType(server_type()); } @@ -406,7 +406,7 @@ // Either way, retain a preference for the CVC heuristic over the // server's password predictions (http://crbug.com/469007) believe_server = - believe_server && !(GroupTypeOfServerFieldType(server_type()) == + believe_server && !(GroupTypeOfFieldType(server_type()) == FieldTypeGroup::kPasswordField && heuristic_type() == CREDIT_CARD_VERIFICATION_CODE); @@ -503,10 +503,8 @@ } bool AutofillField::IsCreditCardPrediction() const { - return GroupTypeOfServerFieldType(server_type()) == - FieldTypeGroup::kCreditCard || - GroupTypeOfServerFieldType(heuristic_type()) == - FieldTypeGroup::kCreditCard; + return GroupTypeOfFieldType(server_type()) == FieldTypeGroup::kCreditCard || + GroupTypeOfFieldType(heuristic_type()) == FieldTypeGroup::kCreditCard; } void AutofillField::AppendLogEventIfNotRepeated(
diff --git a/components/autofill/core/browser/autofill_field.h b/components/autofill/core/browser/autofill_field.h index c8c91f2..db6339b5 100644 --- a/components/autofill/core/browser/autofill_field.h +++ b/components/autofill/core/browser/autofill_field.h
@@ -27,10 +27,10 @@ namespace autofill { typedef std::map<FieldType, std::vector<AutofillDataModel::ValidityState>> - ServerFieldTypeValidityStatesMap; + FieldTypeValidityStatesMap; typedef std::map<FieldType, AutofillDataModel::ValidityState> - ServerFieldTypeValidityStateMap; + FieldTypeValidityStateMap; // Specifies if the Username First Flow vote has intermediate values. enum class IsMostRecentSingleUsernameCandidate { @@ -92,7 +92,7 @@ HtmlFieldType html_type() const { return html_type_; } HtmlFieldMode html_mode() const { return html_mode_; } const FieldTypeSet& possible_types() const { return possible_types_; } - const ServerFieldTypeValidityStatesMap& possible_types_validities() const { + const FieldTypeValidityStatesMap& possible_types_validities() const { return possible_types_validities_; } bool previously_autofilled() const { return previously_autofilled_; } @@ -103,7 +103,7 @@ // Setters for the detected types. void set_heuristic_type(HeuristicSource s, FieldType t); void add_possible_types_validities( - const ServerFieldTypeValidityStateMap& possible_types_validities); + const FieldTypeValidityStateMap& possible_types_validities); void set_server_predictions( std::vector<AutofillQueryResponse::FormSuggestion::FieldSuggestion:: FieldPrediction> predictions); @@ -116,7 +116,7 @@ possible_types_ = possible_types; } void set_possible_types_validities( - const ServerFieldTypeValidityStatesMap& possible_types_validities) { + const FieldTypeValidityStatesMap& possible_types_validities) { possible_types_validities_ = possible_types_validities; } std::vector<AutofillDataModel::ValidityState> @@ -406,7 +406,7 @@ FieldTypeSet possible_types_; // The set of possible types and their validity for this field. - ServerFieldTypeValidityStatesMap possible_types_validities_; + FieldTypeValidityStatesMap possible_types_validities_; // A low-entropy hash of the field's initial value before user-interactions or // automatic fillings. This field is used to detect static placeholders.
diff --git a/components/autofill/core/browser/autofill_granular_filling_utils.cc b/components/autofill/core/browser/autofill_granular_filling_utils.cc index dff9d580..6dd253e 100644 --- a/components/autofill/core/browser/autofill_granular_filling_utils.cc +++ b/components/autofill/core/browser/autofill_granular_filling_utils.cc
@@ -72,7 +72,7 @@ switch (GetFillingMethodFromTargetedFields(last_targeted_field_types)) { case AutofillFillingMethod::kGroupFilling: return GetServerFieldsForFieldGroup( - GroupTypeOfServerFieldType(triggering_field_type)); + GroupTypeOfFieldType(triggering_field_type)); case AutofillFillingMethod::kFullForm: return kAllFieldTypes; case AutofillFillingMethod::kFieldByFieldFilling:
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc index 8eabb475..97e36a5c 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -40,7 +40,6 @@ #include "components/autofill/core/browser/payments/autofill_offer_manager.h" #include "components/autofill/core/browser/payments/constants.h" #include "components/autofill/core/browser/personal_data_manager.h" -#include "components/autofill/core/browser/ui/label_formatter.h" #include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/common/autofill_clock.h" @@ -432,7 +431,7 @@ const std::string& app_locale, Suggestion& suggestion) { const FieldTypeGroup trigger_field_type_group = - GroupTypeOfServerFieldType(trigger_field_type); + GroupTypeOfFieldType(trigger_field_type); bool phone_number_suggestion_added = false; if (profile.HasInfo(PHONE_HOME_WHOLE_NUMBER)) { @@ -606,7 +605,7 @@ } const FieldTypeGroup trigger_field_type_group = - GroupTypeOfServerFieldType(trigger_field_type); + GroupTypeOfFieldType(trigger_field_type); // Lambda to return the expected `PopupItemId` when // `last_targeted_fields` matches one of the granular filling groups. @@ -703,7 +702,7 @@ std::vector<std::vector<std::u16string>> labels; labels.reserve(profiles.size()); for (const AutofillProfile* profile : profiles) { - switch (GroupTypeOfServerFieldType(triggering_field_type)) { + switch (GroupTypeOfFieldType(triggering_field_type)) { case FieldTypeGroup::kName: labels.push_back({l10n_util::GetStringUTF16( IDS_AUTOFILL_FILL_NAME_GROUP_POPUP_OPTION_SELECTED)}); @@ -751,7 +750,7 @@ !AreFieldsGranularFillingGroup(*last_targeted_fields)) { return {triggering_field_type}; } - switch (GroupTypeOfServerFieldType(triggering_field_type)) { + switch (GroupTypeOfFieldType(triggering_field_type)) { case FieldTypeGroup::kAddress: if (ShouldAddAddressLine1ToGranularFillingLabels(triggering_field_type)) { // In the case where the `ADDRESS_HOME_LINE1` was added to the granular @@ -790,34 +789,13 @@ FieldType trigger_field_type, std::optional<FieldTypeSet> last_targeted_fields, const std::string& app_locale) { - std::unique_ptr<LabelFormatter> formatter; - bool use_formatter; - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - use_formatter = base::FeatureList::IsEnabled( - features::kAutofillUseImprovedLabelDisambiguation); -#else - use_formatter = base::FeatureList::IsEnabled( - features::kAutofillUseMobileLabelDisambiguation); -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - - // The formatter stores a constant reference to |profiles|. - // This is safe since the formatter is destroyed when this function returns. - formatter = use_formatter - ? LabelFormatter::Create(profiles, app_locale, - trigger_field_type, field_types) - : nullptr; - // Generate disambiguating labels based on the list of matches. std::vector<std::u16string> differentiating_labels; - if (!IsAddressType(trigger_field_type) && base::FeatureList::IsEnabled( features::kAutofillForUnclassifiedFieldsAvailable)) { differentiating_labels = GetProfileSuggestionLabelForNonAddressField(profiles, app_locale); - } else if (formatter) { - differentiating_labels = formatter->GetLabels(); } else { AutofillProfile::CreateInferredLabels( profiles, field_types, @@ -825,12 +803,6 @@ trigger_field_type, last_targeted_fields), 1, app_locale, &differentiating_labels); } - - if (use_formatter && !profiles.empty()) { - AutofillMetrics::LogProfileSuggestionsMadeWithFormatter(formatter != - nullptr); - } - return differentiating_labels; } @@ -1032,8 +1004,7 @@ bool field_is_autofilled) { // Phones should do a substring match because they can be trimmed to remove // the first parts (e.g. country code or prefix). - if (GroupTypeOfServerFieldType(trigger_field_type) == - FieldTypeGroup::kPhone && + if (GroupTypeOfFieldType(trigger_field_type) == FieldTypeGroup::kPhone && suggestion_canon.find(field_contents_canon) != std::u16string::npos) { return true; } @@ -1073,7 +1044,7 @@ // entered into. std::u16string NormalizeForComparisonForType(const std::u16string& text, FieldType type) { - if (GroupTypeOfServerFieldType(type) == FieldTypeGroup::kEmail) { + if (GroupTypeOfFieldType(type) == FieldTypeGroup::kEmail) { // For emails, keep special characters so that if the user has two emails // `test@foo.xyz` and `test1@foo.xyz` saved, only the first one is suggested // upon entering `test@` into the email field. @@ -1215,8 +1186,7 @@ // This will be used to check if suggestions should be supported with icons. const bool contains_profile_related_fields = base::ranges::count_if(field_types, [](FieldType field_type) { - FieldTypeGroup field_type_group = - GroupTypeOfServerFieldType(field_type); + FieldTypeGroup field_type_group = GroupTypeOfFieldType(field_type); return field_type_group == FieldTypeGroup::kName || field_type_group == FieldTypeGroup::kAddress || field_type_group == FieldTypeGroup::kPhone || @@ -1224,7 +1194,7 @@ }) > 1; FieldTypeGroup trigger_field_type_group = - GroupTypeOfServerFieldType(trigger_field_type); + GroupTypeOfFieldType(trigger_field_type); for (const AutofillProfile* profile : profiles) { // Compute the main text to be displayed in the suggestion bubble. std::u16string main_text = @@ -1434,7 +1404,7 @@ const AutofillProfile& profile, Suggestion& suggestion) const { const FieldTypeGroup trigger_field_type_group = - GroupTypeOfServerFieldType(trigger_field_type); + GroupTypeOfFieldType(trigger_field_type); const std::string app_locale = personal_data_->app_locale(); AddNameChildSuggestions(trigger_field_type_group, profile, app_locale, suggestion); @@ -1456,8 +1426,7 @@ std::vector<Suggestion> suggestions; // Manual fallback entries are shown for all non credit card fields. const bool is_manual_fallback = - GroupTypeOfServerFieldType(trigger_field_type) != - FieldTypeGroup::kCreditCard; + GroupTypeOfFieldType(trigger_field_type) != FieldTypeGroup::kCreditCard; const std::string& app_locale = personal_data_->app_locale(); std::map<std::string, AutofillOfferData*> card_linked_offers_map = @@ -1780,8 +1749,7 @@ bool card_linked_offer_available) const { // Manual fallback entries are shown for all non credit card fields. const bool is_manual_fallback = - GroupTypeOfServerFieldType(trigger_field_type) != - FieldTypeGroup::kCreditCard; + GroupTypeOfFieldType(trigger_field_type) != FieldTypeGroup::kCreditCard; Suggestion suggestion; suggestion.icon = credit_card.CardIconForAutofillSuggestion();
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc index 4715dbc..a7ba444 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
@@ -28,7 +28,6 @@ #include "components/autofill/core/browser/personal_data_manager_test_base.h" #include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/test_personal_data_manager.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" #include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" @@ -58,15 +57,6 @@ using testing::IsEmpty; using testing::Matcher; -constexpr Suggestion::Icon kAddressEntryIcon = Suggestion::Icon::kAccount; - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -std::vector<std::vector<Suggestion::Text>> ConstructLabelLineMatrix( - const std::vector<std::u16string>& parts) { - return {{Suggestion::Text(ConstructLabelLine(parts))}}; -} -#endif - Matcher<Suggestion> EqualsSuggestion(PopupItemId id) { return Field(&Suggestion::popup_item_id, id); } @@ -756,11 +746,7 @@ } TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_PhoneSubstring_NoImprovedDisambiguation) { - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndDisableFeature( - features::kAutofillUseImprovedLabelDisambiguation); - + CreateSuggestionsFromProfiles_PhoneSubstring) { AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison", "johnwayne@me.xyz", "Fox", @@ -776,322 +762,6 @@ EXPECT_EQ(u"12345678910", suggestions[0].main_text.value); } -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_LogProfileSuggestionsMadeWithFormatter) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillUseImprovedLabelDisambiguation); - - base::HistogramTester histogram_tester; - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile}, - {NAME_FIRST, NAME_LAST, EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, NAME_FIRST, - /*trigger_field_max_length=*/0), - ElementsAre(testing::Field( - &Suggestion::main_text, - Suggestion::Text(u"Hoa", Suggestion::Text::IsPrimary(true))))); - histogram_tester.ExpectUniqueSample( - "Autofill.ProfileSuggestionsMadeWithFormatter", true, 1); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_ForContactForm) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillUseImprovedLabelDisambiguation); - - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile}, - {NAME_FIRST, NAME_LAST, EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, NAME_FIRST, - /*trigger_field_max_length=*/0), - ElementsAre(AllOf( - testing::Field(&Suggestion::labels, - ConstructLabelLineMatrix( - {u"(978) 674-4120", u"hoa.pham@comcast.net"})), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_AddressForm) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillUseImprovedLabelDisambiguation); - - EXPECT_THAT(suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile}, - {NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY, - ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP}, - /*last_targeted_fields=*/std::nullopt, NAME_FULL, - /*trigger_field_max_length=*/0), - ElementsAre(AllOf( - testing::Field(&Suggestion::labels, - ConstructLabelLineMatrix( - {u"401 Merrimack St, Lowell, MA 01852"})), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_AddressPhoneForm) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillUseImprovedLabelDisambiguation); - - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile}, - {NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, NAME_FULL, - /*trigger_field_max_length=*/0), - ElementsAre( - AllOf(testing::Field(&Suggestion::labels, - ConstructLabelLineMatrix( - {u"(978) 674-4120", u"401 Merrimack St"})), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_AddressEmailForm) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillUseImprovedLabelDisambiguation); - - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile}, {NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, EMAIL_ADDRESS}, - /*last_targeted_fields=*/std::nullopt, NAME_FULL, - /*trigger_field_max_length=*/0), - ElementsAre(AllOf( - testing::Field(&Suggestion::labels, - ConstructLabelLineMatrix( - {u"401 Merrimack St", u"hoa.pham@comcast.net"})), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_FormWithOneProfile) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillUseImprovedLabelDisambiguation); - - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile}, - {NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, EMAIL_ADDRESS, - PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, NAME_FULL, - /*trigger_field_max_length=*/0), - ElementsAre( - AllOf(testing::Field(&Suggestion::labels, - ConstructLabelLineMatrix({u"401 Merrimack St"})), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_AddressContactFormWithProfiles) { - base::test::ScopedFeatureList scoped_features; - scoped_features.InitWithFeatures( - /*enabled_features=*/{features:: - kAutofillEnableRankingFormulaAddressProfiles, - features::kAutofillUseImprovedLabelDisambiguation}, - /*disabled_features=*/{}); - - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Hoa", "", "Pham", "hp@aol.com", "", - "216 Broadway St", "", "Lowell", "MA", "01854", "US", - "19784523366"); - - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile1, &profile2}, - {NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, EMAIL_ADDRESS, - PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, NAME_FULL, - /*trigger_field_max_length=*/0), - ElementsAre( - AllOf(testing::Field(&Suggestion::labels, - ConstructLabelLineMatrix( - {u"401 Merrimack St", u"(978) 674-4120", - u"hoa.pham@comcast.net"})), - testing::Field(&Suggestion::icon, kAddressEntryIcon)), - AllOf(testing::Field(&Suggestion::labels, - ConstructLabelLineMatrix({u"216 Broadway St", - u"(978) 452-3366", - u"hp@aol.com"})), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_MobileShowOne) { - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - features::kAutofillUseMobileLabelDisambiguationParameterShowOne; - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "María", "", "Lòpez", "maria@aol.com", "", - "11 Elkins St", "", "Boston", "MA", "02127", "US", - "6172686862"); - - // Tests a form with name, email address, and phone number fields. - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile1, &profile2}, - {NAME_FIRST, NAME_LAST, EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, EMAIL_ADDRESS, - /*trigger_field_max_length=*/0), - ElementsAre( - AllOf(testing::Field(&Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(u"(978) 674-4120")}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)), - AllOf(testing::Field(&Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(u"(617) 268-6862")}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); - - // Tests a form with name, address, phone number, and email address fields. - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile1, &profile2}, - {NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY, - EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, EMAIL_ADDRESS, - /*trigger_field_max_length=*/0), - ElementsAre( - AllOf(testing::Field(&Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(u"401 Merrimack St")}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)), - AllOf(testing::Field(&Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(u"11 Elkins St")}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) - -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) -TEST_F(AutofillSuggestionGeneratorTest, - CreateSuggestionsFromProfiles_MobileShowAll) { - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - features::kAutofillUseMobileLabelDisambiguationParameterShowAll; - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Hoa", "", "Pham", "hoa.pham@comcast.net", "", - "401 Merrimack St", "", "Lowell", "MA", "01852", "US", - "19786744120"); - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "María", "", "Lòpez", "maria@aol.com", "", - "11 Elkins St", "", "Boston", "MA", "02127", "US", - "6172686862"); - - // Tests a form with name, email address, and phone number fields. - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile1, &profile2}, - {NAME_FIRST, NAME_LAST, EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, EMAIL_ADDRESS, - /*trigger_field_max_length=*/0), - ElementsAre( - AllOf(testing::Field(&Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(ConstructMobileLabelLine( - {u"Hoa", u"(978) 674-4120"}))}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)), - AllOf(testing::Field(&Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(ConstructMobileLabelLine( - {u"María", u"(617) 268-6862"}))}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); - - // Tests a form with name, address, phone number, and email address fields. - EXPECT_THAT( - suggestion_generator()->CreateSuggestionsFromProfiles( - {&profile1, &profile2}, - {NAME_FULL, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_CITY, - EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}, - /*last_targeted_fields=*/std::nullopt, EMAIL_ADDRESS, - /*trigger_field_max_length=*/0), - ElementsAre( - AllOf( - testing::Field( - &Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(ConstructMobileLabelLine( - {u"Hoa", u"401 Merrimack St", u"(978) 674-4120"}))}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)), - AllOf(testing::Field( - &Suggestion::labels, - std::vector<std::vector<Suggestion::Text>>{ - {Suggestion::Text(ConstructMobileLabelLine( - {u"María", u"11 Elkins St", u"(617) 268-6862"}))}}), - testing::Field(&Suggestion::icon, kAddressEntryIcon)))); -} -#endif // if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) - class AutofillChildrenSuggestionGeneratorTest : public AutofillSuggestionGeneratorTest { public:
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index 863793b2..bf31d8f 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -746,12 +746,11 @@ void InitializePossibleTypesAndValidities( std::vector<FieldTypeSet>& possible_field_types, - std::vector<ServerFieldTypeValidityStatesMap>& - possible_field_types_validities, + std::vector<FieldTypeValidityStatesMap>& possible_field_types_validities, const std::vector<FieldType>& possible_types, const std::vector<AutofillDataModel::ValidityState>& validity_states) { possible_field_types.push_back(FieldTypeSet()); - possible_field_types_validities.push_back(ServerFieldTypeValidityStatesMap()); + possible_field_types_validities.push_back(FieldTypeValidityStatesMap()); if (validity_states.empty()) { for (const auto& possible_type : possible_types) { @@ -916,7 +915,7 @@ return CreateFieldPrediction(type, FieldPrediction::SOURCE_UNSPECIFIED); } return CreateFieldPrediction( - type, GroupTypeOfServerFieldType(type) == FieldTypeGroup::kPasswordField + type, GroupTypeOfFieldType(type) == FieldTypeGroup::kPasswordField ? FieldPrediction::SOURCE_PASSWORDS_DEFAULT : FieldPrediction::SOURCE_AUTOFILL_DEFAULT); }
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h index a84dd93..ff99174 100644 --- a/components/autofill/core/browser/autofill_test_utils.h +++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -290,8 +290,7 @@ // corresponding |validity_state|. void InitializePossibleTypesAndValidities( std::vector<FieldTypeSet>& possible_field_types, - std::vector<ServerFieldTypeValidityStatesMap>& - possible_field_types_validities, + std::vector<FieldTypeValidityStatesMap>& possible_field_types_validities, const std::vector<FieldType>& possible_type, const std::vector<AutofillDataModel::ValidityState>& validity_state = {});
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc index 8d2fa82..f138765 100644 --- a/components/autofill/core/browser/autofill_type.cc +++ b/components/autofill/core/browser/autofill_type.cc
@@ -53,7 +53,7 @@ AutofillType::AutofillType(HtmlFieldType field_type) : html_type_(field_type) {} FieldTypeGroup AutofillType::group() const { - return server_type_ != UNKNOWN_TYPE ? GroupTypeOfServerFieldType(server_type_) + return server_type_ != UNKNOWN_TYPE ? GroupTypeOfFieldType(server_type_) : GroupTypeOfHtmlFieldType(html_type_); } @@ -66,7 +66,7 @@ FieldType AutofillType::GetStorableType() const { return server_type_ != UNKNOWN_TYPE ? server_type_ - : HtmlFieldTypeToBestCorrespondingServerFieldType(html_type_); + : HtmlFieldTypeToBestCorrespondingFieldType(html_type_); } std::string AutofillType::ToString() const {
diff --git a/components/autofill/core/browser/autofill_type_unittest.cc b/components/autofill/core/browser/autofill_type_unittest.cc index 87d4edb3..0289e20 100644 --- a/components/autofill/core/browser/autofill_type_unittest.cc +++ b/components/autofill/core/browser/autofill_type_unittest.cc
@@ -123,7 +123,7 @@ base::to_underlying(HtmlFieldType::kMaxValue))); TEST_P(AutofillTypeTestForHtmlFieldTypes, GroupsOfHtmlFieldTypes) { - if (HtmlFieldTypeToBestCorrespondingServerFieldType(html_field_type()) == + if (HtmlFieldTypeToBestCorrespondingFieldType(html_field_type()) == UNKNOWN_TYPE) { return; } @@ -132,7 +132,7 @@ << "html_field_type=" << FieldTypeToStringView(html_field_type()) << " " << "field_type=" << FieldTypeToStringView(t.GetStorableType())); - EXPECT_EQ(t.group(), GroupTypeOfServerFieldType(t.GetStorableType())); + EXPECT_EQ(t.group(), GroupTypeOfFieldType(t.GetStorableType())); } } // namespace
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index 6a1aa3d..13ec081f 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -199,14 +199,14 @@ const auto& old_types = field->possible_types(); for (FieldType type : old_types) { - FieldTypeGroup group = GroupTypeOfServerFieldType(type); + FieldTypeGroup group = GroupTypeOfFieldType(type); if ((is_credit_card && group == FieldTypeGroup::kCreditCard) || (!is_credit_card && group == FieldTypeGroup::kName)) { types_to_keep.insert(type); } } - ServerFieldTypeValidityStatesMap new_types_validities; + FieldTypeValidityStatesMap new_types_validities; // Since the disambiguation takes place when we up to four possible types, // here we can add up to three remaining types when only one is removed. for (auto type_to_keep : types_to_keep) { @@ -716,8 +716,7 @@ FieldType field_type = autofill_field ? autofill_field->Type().GetStorableType() : CREDIT_CARD_NUMBER; - DCHECK_EQ(FieldTypeGroup::kCreditCard, - GroupTypeOfServerFieldType(field_type)); + DCHECK_EQ(FieldTypeGroup::kCreditCard, GroupTypeOfFieldType(field_type)); bool should_display_gpay_logo = false; auto cards = GetCreditCardSuggestions(field_data, field_type, @@ -3052,7 +3051,7 @@ if (matching_types.empty()) { matching_types.insert(UNKNOWN_TYPE); - ServerFieldTypeValidityStateMap matching_types_validities; + FieldTypeValidityStateMap matching_types_validities; matching_types_validities[UNKNOWN_TYPE] = AutofillDataModel::UNVALIDATED; field->add_possible_types_validities(matching_types_validities); }
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc index 5edc50e..5b72bc5 100644 --- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc +++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -1407,84 +1407,30 @@ features::kAutofillParseAsync}; }; -class SuggestionMatchingTest - : public BrowserAutofillManagerTest, - public testing::WithParamInterface<std::tuple<bool, std::string, bool>> { +class SuggestionMatchingTest : public BrowserAutofillManagerTest, + public testing::WithParamInterface<bool> { protected: void SetUp() override { BrowserAutofillManagerTest::SetUp(); InitializeFeatures(); } - - bool IsMetadataEnabled() const { return std::get<2>(GetParam()); } - -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) + bool IsMetadataEnabled() const { return GetParam(); } void InitializeFeatures(); -#else - void InitializeFeatures(); -#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) - std::string MakeLabel(const std::vector<std::string>& parts); - std::string MakeMobileLabel(const std::vector<std::string>& parts); - - enum class EnabledFeature { kNone, kDesktop, kMobileShowAll, kMobileShowOne }; - EnabledFeature enabled_feature_; base::test::ScopedFeatureList features_; }; #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) -void SuggestionMatchingTest::InitializeFeatures() { - if (std::get<0>(GetParam())) { - std::string variant = std::get<1>(GetParam()); - - if (variant == - features::kAutofillUseMobileLabelDisambiguationParameterShowAll) { - enabled_feature_ = EnabledFeature::kMobileShowAll; - } else if (variant == - features:: - kAutofillUseMobileLabelDisambiguationParameterShowOne) { - enabled_feature_ = EnabledFeature::kMobileShowOne; - } else { - NOTREACHED(); - } - - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - variant; - features_.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - } else { - enabled_feature_ = EnabledFeature::kNone; - } -} +void SuggestionMatchingTest::InitializeFeatures() {} #else void SuggestionMatchingTest::InitializeFeatures() { - bool improved_label_feature = std::get<0>(GetParam()); - - enabled_feature_ = - improved_label_feature ? EnabledFeature::kDesktop : EnabledFeature::kNone; - features_.InitWithFeatureStates( - {{features::kAutofillUseImprovedLabelDisambiguation, - improved_label_feature}, - {features::kAutofillEnableVirtualCardMetadata, IsMetadataEnabled()}, + {{features::kAutofillEnableVirtualCardMetadata, IsMetadataEnabled()}, {features::kAutofillEnableCardProductName, IsMetadataEnabled()}, {features::kAutofillEnableCardArtImage, IsMetadataEnabled()}}); } #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) -std::string SuggestionMatchingTest::MakeLabel( - const std::vector<std::string>& parts) { - return base::JoinString( - parts, l10n_util::GetStringUTF8(IDS_AUTOFILL_SUGGESTION_LABEL_SEPARATOR)); -} - -std::string SuggestionMatchingTest::MakeMobileLabel( - const std::vector<std::string>& parts) { - return base::JoinString( - parts, l10n_util::GetStringUTF8(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR)); -} - // Credit card suggestion tests related with keyboard accessory. class CreditCardSuggestionTest : public BrowserAutofillManagerTest { protected: @@ -2013,39 +1959,12 @@ FormsSeen({form}); GetAutofillSuggestions(form, form.fields[0]); - - std::string label1; - std::string label2; - - switch (enabled_feature_) { - // 23456789012 is not formatted because it is invalid for the app locale. - // It has an extra digit. - case EnabledFeature::kDesktop: - label1 = MakeLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeLabel({"3734 Elvis Presley Blvd., Apt. 10", "(234) 567-8901", - "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowAll: - label1 = MakeMobileLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeMobileLabel({"3734 Elvis Presley Blvd., Apt. 10", - "(234) 567-8901", "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowOne: - label1 = "123 Apple St., unit 6"; - label2 = "3734 Elvis Presley Blvd., Apt. 10"; - break; - case EnabledFeature::kNone: - label1 = "123 Apple St."; - label2 = "3734 Elvis Presley Blvd."; - } // Test that we sent the right values to the external delegate. CheckSuggestions(form.fields[0].global_id(), - Suggestion("Charles", label1, kAddressEntryIcon, + Suggestion("Charles", "123 Apple St.", kAddressEntryIcon, PopupItemId::kAddressEntry), - Suggestion("Elvis", label2, kAddressEntryIcon, - PopupItemId::kAddressEntry)); + Suggestion("Elvis", "3734 Elvis Presley Blvd.", + kAddressEntryIcon, PopupItemId::kAddressEntry)); } // Test that we return only matching address profile suggestions when the @@ -2058,22 +1977,10 @@ FormFieldData field = CreateTestFormField("First Name", "firstname", "E", FormControlType::kInputText); GetAutofillSuggestions(form, field); - - std::string label; - - switch (enabled_feature_) { - case EnabledFeature::kDesktop: - case EnabledFeature::kMobileShowAll: - case EnabledFeature::kMobileShowOne: - label = "3734 Elvis Presley Blvd., Apt. 10"; - break; - case EnabledFeature::kNone: - label = "3734 Elvis Presley Blvd."; - } // Test that we sent the right values to the external delegate. CheckSuggestions(field.global_id(), - Suggestion("Elvis", label, kAddressEntryIcon, - PopupItemId::kAddressEntry)); + Suggestion("Elvis", "3734 Elvis Presley Blvd.", + kAddressEntryIcon, PopupItemId::kAddressEntry)); } // Tests that we return address profile suggestions values when the section @@ -2136,22 +2043,10 @@ FormFieldData field = CreateTestFormField("First Name", "firstname", "E", FormControlType::kInputText); GetAutofillSuggestions(form, field); - - std::string label; - - switch (enabled_feature_) { - case EnabledFeature::kDesktop: - case EnabledFeature::kMobileShowAll: - case EnabledFeature::kMobileShowOne: - label = "3734 Elvis Presley Blvd., Apt. 10"; - break; - case EnabledFeature::kNone: - label = "3734 Elvis Presley Blvd."; - } // Test that we sent the right values to the external delegate. CheckSuggestions(field.global_id(), - Suggestion("Elvis", label, kAddressEntryIcon, - PopupItemId::kAddressEntry)); + Suggestion("Elvis", "3734 Elvis Presley Blvd.", + kAddressEntryIcon, PopupItemId::kAddressEntry)); } // Test that we return no suggestions when the form has no relevant fields. @@ -2188,38 +2083,12 @@ GetAutofillSuggestions(form, form.fields[0]); - std::string label1; - std::string label2; - - switch (enabled_feature_) { - // 23456789012 is not formatted because it is invalid for the app locale. - // It has an extra digit. - case EnabledFeature::kDesktop: - label1 = MakeLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeLabel({"3734 Elvis Presley Blvd., Apt. 10", "(234) 567-8901", - "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowAll: - label1 = MakeMobileLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeMobileLabel({"3734 Elvis Presley Blvd., Apt. 10", - "(234) 567-8901", "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowOne: - label1 = "123 Apple St., unit 6"; - label2 = "3734 Elvis Presley Blvd., Apt. 10"; - break; - case EnabledFeature::kNone: - label1 = "123 Apple St."; - label2 = "3734 Elvis Presley Blvd."; - } // Test that we sent the right values to the external delegate. CheckSuggestions(form.fields[0].global_id(), - Suggestion("Charles", label1, kAddressEntryIcon, + Suggestion("Charles", "123 Apple St.", kAddressEntryIcon, PopupItemId::kAddressEntry), - Suggestion("Elvis", label2, kAddressEntryIcon, - PopupItemId::kAddressEntry)); + Suggestion("Elvis", "3734 Elvis Presley Blvd.", + kAddressEntryIcon, PopupItemId::kAddressEntry)); } // Test that we return no suggestions when autofill is disabled. @@ -2809,40 +2678,12 @@ FormsSeen({form}); GetAutofillSuggestions(form, form.fields[0]); - - std::string label1; - std::string label2; - - switch (enabled_feature_) { - case EnabledFeature::kDesktop: - // 23456789012 is not formatted because it is invalid for the app locale. - // It has an extra digit. - label1 = MakeLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeLabel({"3734 Elvis Presley Blvd., Apt. 10", "(234) 567-8901", - "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowAll: - label1 = MakeMobileLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeMobileLabel({"3734 Elvis Presley Blvd., Apt. 10", - "(234) 567-8901", "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowOne: - label1 = "123 Apple St., unit 6"; - label2 = "3734 Elvis Presley Blvd., Apt. 10"; - break; - case EnabledFeature::kNone: - label1 = "123 Apple St."; - label2 = "3734 Elvis Presley Blvd."; - } - // Test that we sent the right values to the external delegate. CheckSuggestions(form.fields[0].global_id(), - Suggestion("Charles", label1, kAddressEntryIcon, + Suggestion("Charles", "123 Apple St.", kAddressEntryIcon, PopupItemId::kAddressEntry), - Suggestion("Elvis", label2, kAddressEntryIcon, - PopupItemId::kAddressEntry)); + Suggestion("Elvis", "3734 Elvis Presley Blvd.", + kAddressEntryIcon, PopupItemId::kAddressEntry)); FormFieldData field = CreateTestFormField("Card Number", "cardnumber", "", FormControlType::kInputText); @@ -3556,39 +3397,12 @@ // Mark one of the fields as filled. form.fields[2].is_autofilled = true; GetAutofillSuggestions(form, form.fields[0]); - - std::string label1; - std::string label2; - - switch (enabled_feature_) { - // 23456789012 is not formatted because it is invalid for the app locale. - // It has an extra digit. - case EnabledFeature::kDesktop: - label1 = MakeLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeLabel({"3734 Elvis Presley Blvd., Apt. 10", "(234) 567-8901", - "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowAll: - label1 = MakeMobileLabel( - {"123 Apple St., unit 6", "23456789012", "buddy@gmail.com"}); - label2 = MakeMobileLabel({"3734 Elvis Presley Blvd., Apt. 10", - "(234) 567-8901", "theking@gmail.com"}); - break; - case EnabledFeature::kMobileShowOne: - label1 = "123 Apple St., unit 6"; - label2 = "3734 Elvis Presley Blvd., Apt. 10"; - break; - case EnabledFeature::kNone: - label1 = "123 Apple St."; - label2 = "3734 Elvis Presley Blvd."; - } // Test that we sent the right values to the external delegate. CheckSuggestions(form.fields[0].global_id(), - Suggestion("Charles", label1, kAddressEntryIcon, + Suggestion("Charles", "123 Apple St.", kAddressEntryIcon, PopupItemId::kAddressEntry), - Suggestion("Elvis", label2, kAddressEntryIcon, - PopupItemId::kAddressEntry)); + Suggestion("Elvis", "3734 Elvis Presley Blvd.", + kAddressEntryIcon, PopupItemId::kAddressEntry)); } // The method `AutofillSuggestionGenerator::GetPrefixMatchedProfiles` prevents @@ -3613,22 +3427,10 @@ field.is_autofilled = true; field.value = u"Elvis"; GetAutofillSuggestions(form, field); - - std::string label; - - switch (enabled_feature_) { - case EnabledFeature::kDesktop: - case EnabledFeature::kMobileShowAll: - case EnabledFeature::kMobileShowOne: - label = "3734 Elvis Presley Blvd., Apt. 10"; - break; - case EnabledFeature::kNone: - label = "3734 Elvis Presley Blvd."; - } // Test that we sent the right values to the external delegate. CheckSuggestions(field.global_id(), - Suggestion("Elvis", label, kAddressEntryIcon, - PopupItemId::kAddressEntry)); + Suggestion("Elvis", "3734 Elvis Presley Blvd.", + kAddressEntryIcon, PopupItemId::kAddressEntry)); } #endif @@ -10429,19 +10231,9 @@ INSTANTIATE_TEST_SUITE_P(All, OnFocusOnFormFieldTest, testing::Bool()); #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID) -INSTANTIATE_TEST_SUITE_P( - , - SuggestionMatchingTest, - testing::Values(std::make_tuple(0, "", false), - std::make_tuple(1, "show-all", false), - std::make_tuple(1, "show-one", false))); +INSTANTIATE_TEST_SUITE_P(, SuggestionMatchingTest, testing::Values(false)); #else -INSTANTIATE_TEST_SUITE_P(All, - SuggestionMatchingTest, - testing::Values(std::make_tuple(0, "", false), - std::make_tuple(0, "", true), - std::make_tuple(1, "", false), - std::make_tuple(1, "", true))); +INSTANTIATE_TEST_SUITE_P(All, SuggestionMatchingTest, testing::Bool()); #endif // BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID) struct ShareNicknameTestParam {
diff --git a/components/autofill/core/browser/data_model/address.cc b/components/autofill/core/browser/data_model/address.cc index 255877da..33113c01 100644 --- a/components/autofill/core/browser/data_model/address.cc +++ b/components/autofill/core/browser/data_model/address.cc
@@ -110,7 +110,7 @@ } std::u16string Address::GetRawInfo(FieldType type) const { - DCHECK_EQ(FieldTypeGroup::kAddress, GroupTypeOfServerFieldType(type)); + DCHECK_EQ(FieldTypeGroup::kAddress, GroupTypeOfFieldType(type)); return structured_address_->GetValueForType(type); } @@ -118,7 +118,7 @@ void Address::SetRawInfoWithVerificationStatus(FieldType type, const std::u16string& value, VerificationStatus status) { - DCHECK_EQ(FieldTypeGroup::kAddress, GroupTypeOfServerFieldType(type)); + DCHECK_EQ(FieldTypeGroup::kAddress, GroupTypeOfFieldType(type)); // The street address has a structure that may have already been set before // using the settings dialog. In case the settings dialog was used to change // the address to contain different tokens, the structure must be reset.
diff --git a/components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.cc b/components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.cc new file mode 100644 index 0000000..a10b82a --- /dev/null +++ b/components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.cc
@@ -0,0 +1,36 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.h" + +#include "base/feature_list.h" + +namespace autofill { + +FeatureGuardedAddressComponent::FeatureGuardedAddressComponent( + raw_ptr<const base::Feature> feature, + FieldType storage_type, + SubcomponentsList children, + unsigned int merge_mode) + : AddressComponent(storage_type, std::move(children), merge_mode), + feature_(feature) {} + +void FeatureGuardedAddressComponent::SetValue(std::u16string value, + VerificationStatus status) { + if (!base::FeatureList::IsEnabled(*feature_)) { + return; + } + AddressComponent::SetValue(value, status); +} + +void FeatureGuardedAddressComponent::GetTypes( + bool storable_only, + FieldTypeSet* supported_types) const { + if (!base::FeatureList::IsEnabled(*feature_)) { + return; + } + AddressComponent::GetTypes(storable_only, supported_types); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.h b/components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.h new file mode 100644 index 0000000..54c8a56 --- /dev/null +++ b/components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.h
@@ -0,0 +1,36 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_AUTOFILL_FEATURE_GUARDED_ADDRESS_COMPONENT_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_AUTOFILL_FEATURE_GUARDED_ADDRESS_COMPONENT_H_ + +#include "base/feature_list.h" +#include "components/autofill/core/browser/data_model/autofill_structured_address_component.h" +#include "components/autofill/core/browser/field_types.h" + +namespace autofill { + +// This class represents a type that is controlled by a feature flag. It +// overrides the SetValue method to prevent setting values to nodes for which +// the flag is turned off. It further prevents exposing disabled types as +// supported. +class FeatureGuardedAddressComponent : public AddressComponent { + public: + FeatureGuardedAddressComponent(raw_ptr<const base::Feature> feature, + FieldType storage_type, + SubcomponentsList children, + unsigned int merge_mode); + + // AddressComponent overrides: + void SetValue(std::u16string value, VerificationStatus status) override; + void GetTypes(bool storable_only, + FieldTypeSet* supported_types) const override; + + private: + // Feature guarding the rollout of this address component. + const raw_ptr<const base::Feature> feature_; +}; + +} // namespace autofill +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_AUTOFILL_FEATURE_GUARDED_ADDRESS_COMPONENT_H_
diff --git a/components/autofill/core/browser/data_model/autofill_i18n_api.cc b/components/autofill/core/browser/data_model/autofill_i18n_api.cc index 2a5c348..5c14a9a 100644 --- a/components/autofill/core/browser/data_model/autofill_i18n_api.cc +++ b/components/autofill/core/browser/data_model/autofill_i18n_api.cc
@@ -232,7 +232,7 @@ std::u16string GetFormattingExpression(FieldType field_type, AddressCountryCode country_code) { if (base::FeatureList::IsEnabled(features::kAutofillUseI18nAddressModel) && - GroupTypeOfServerFieldType(field_type) == FieldTypeGroup::kAddress) { + GroupTypeOfFieldType(field_type) == FieldTypeGroup::kAddress) { // If `country_code` is specified, return the corresponding formatting // expression if they exist. Note that it should not fallback to a legacy // expression, as these ones refer to a different hierarchy. @@ -262,7 +262,7 @@ std::string_view value, FieldType field_type, AddressCountryCode country_code) { - CHECK(GroupTypeOfServerFieldType(field_type) == FieldTypeGroup::kAddress); + CHECK(GroupTypeOfFieldType(field_type) == FieldTypeGroup::kAddress); // If `country_code` is specified, attempt to parse the `value` using a // custom parsing structure (if exist). // Otherwise try using a legacy parsing expression (if exist).
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc index 60187f8..1a66ee4 100644 --- a/components/autofill/core/browser/data_model/autofill_profile.cc +++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -88,11 +88,11 @@ // similarly. FieldType GetStorableTypeCollapsingGroups(FieldType type) { FieldType storable_type = AutofillType(type).GetStorableType(); - if (GroupTypeOfServerFieldType(storable_type) == FieldTypeGroup::kName) { + if (GroupTypeOfFieldType(storable_type) == FieldTypeGroup::kName) { return NAME_FULL; } - if (GroupTypeOfServerFieldType(storable_type) == FieldTypeGroup::kPhone) { + if (GroupTypeOfFieldType(storable_type) == FieldTypeGroup::kPhone) { return PHONE_HOME_WHOLE_NUMBER; } @@ -463,7 +463,7 @@ } FieldType AutofillProfile::GetStorableTypeOf(FieldType type) const { - const FieldTypeGroup group = GroupTypeOfServerFieldType(type); + const FieldTypeGroup group = GroupTypeOfFieldType(type); if (group == FieldTypeGroup::kAddress) { return address_.GetStructuredAddress().GetStorableTypeOf(type).value_or( type); @@ -1211,13 +1211,8 @@ bool AutofillProfile::FinalizeAfterImport() { bool success = true; - if (!name_.FinalizeAfterImport()) { - success = false; - } - if (!address_.FinalizeAfterImport()) { - success = false; - } - + success &= name_.FinalizeAfterImport(); + success &= address_.FinalizeAfterImport(); return success; }
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address.cc b/components/autofill/core/browser/data_model/autofill_structured_address.cc index 125ca19..119453a 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address.cc
@@ -33,31 +33,6 @@ /*keep_white_space=*/true); } -FeatureGuardedAddressComponent::FeatureGuardedAddressComponent( - raw_ptr<const base::Feature> feature, - FieldType storage_type, - SubcomponentsList children, - unsigned int merge_mode) - : AddressComponent(storage_type, std::move(children), merge_mode), - feature_(feature) {} - -void FeatureGuardedAddressComponent::SetValue(std::u16string value, - VerificationStatus status) { - if (!base::FeatureList::IsEnabled(*feature_)) { - return; - } - AddressComponent::SetValue(value, status); -} - -void FeatureGuardedAddressComponent::GetTypes( - bool storable_only, - FieldTypeSet* supported_types) const { - if (!base::FeatureList::IsEnabled(*feature_)) { - return; - } - AddressComponent::GetTypes(storable_only, supported_types); -} - StreetNameNode::StreetNameNode(SubcomponentsList children) : AddressComponent(ADDRESS_HOME_STREET_NAME, std::move(children),
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address.h b/components/autofill/core/browser/data_model/autofill_structured_address.h index 808b97a0..cbfddd7 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address.h +++ b/components/autofill/core/browser/data_model/autofill_structured_address.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/feature_list.h" +#include "components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.h" #include "components/autofill/core/browser/data_model/autofill_structured_address_component.h" #include "components/autofill/core/browser/field_types.h" @@ -28,27 +29,6 @@ const AddressComponent& other) const override; }; -// This class represents a type that is controlled by a feature flag. It -// overrides the SetValue method to prevent setting values to nodes for which -// the flag is turned off. It further prevents exposing disabled types as -// supported. -class FeatureGuardedAddressComponent : public AddressComponent { - public: - FeatureGuardedAddressComponent(raw_ptr<const base::Feature> feature, - FieldType storage_type, - SubcomponentsList children, - unsigned int merge_mode); - - // AddressComponent overrides: - void SetValue(std::u16string value, VerificationStatus status) override; - void GetTypes(bool storable_only, - FieldTypeSet* supported_types) const override; - - private: - // Feature guarding the rollout of this address component. - const raw_ptr<const base::Feature> feature_; -}; - // The name of the street. class StreetNameNode : public AddressComponent { public:
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component.cc b/components/autofill/core/browser/data_model/autofill_structured_address_component.cc index 0218ba6..3028fc2 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_component.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address_component.cc
@@ -462,8 +462,7 @@ bool parsing_successful = base::FeatureList::IsEnabled(features::kAutofillUseI18nAddressModel) && - GroupTypeOfServerFieldType(GetStorageType()) == - FieldTypeGroup::kAddress + GroupTypeOfFieldType(GetStorageType()) == FieldTypeGroup::kAddress ? ParseValueAndAssignSubcomponentsByI18nParsingRules() : ParseValueAndAssignSubcomponentsByRegularExpressions(); @@ -505,8 +504,7 @@ void AddressComponent:: TryParseValueAndAssignSubcomponentsRespectingSetValues() { if (base::FeatureList::IsEnabled(features::kAutofillUseI18nAddressModel) && - GroupTypeOfServerFieldType(GetStorageType()) == - FieldTypeGroup::kAddress) { + GroupTypeOfFieldType(GetStorageType()) == FieldTypeGroup::kAddress) { const AddressCountryCode country_code = AddressCountryCode( base::UTF16ToUTF8(GetRootNode().GetValueForType(ADDRESS_HOME_COUNTRY)));
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc b/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc index a2dd71e..0eb50fa 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc
@@ -1801,6 +1801,9 @@ } TEST(AutofillStructuredAddressAddressComponent, TestFillTreeGaps) { + base::test::ScopedFeatureList scoped_feature; + scoped_feature.InitAndEnableFeature( + features::kAutofillEnableSupportForHonorificPrefixes); NameFullWithPrefix name; AddressComponentTestValues name_filled_values = { @@ -1894,6 +1897,9 @@ } TEST(AutofillStructuredAddressAddressComponent, TestFillTreeGapsParsing) { + base::test::ScopedFeatureList scoped_feature; + scoped_feature.InitAndEnableFeature( + features::kAutofillEnableSupportForHonorificPrefixes); NameFullWithPrefix name; AddressComponentTestValues name_filled_values = {
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_name.cc b/components/autofill/core/browser/data_model/autofill_structured_address_name.cc index 0d33891..6d30f0d6 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_name.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address_name.cc
@@ -18,6 +18,7 @@ #include "components/autofill/core/browser/data_model/autofill_structured_address_regex_provider.h" #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/common/autofill_features.h" namespace autofill { @@ -123,11 +124,12 @@ } NameHonorificPrefix::NameHonorificPrefix() - : AddressComponent(NAME_HONORIFIC_PREFIX, - {}, - MergeMode::kUseBetterOrNewerForSameValue | - MergeMode::kReplaceEmpty | - MergeMode::kUseBetterOrMostRecentIfDifferent) {} + : FeatureGuardedAddressComponent( + &features::kAutofillEnableSupportForHonorificPrefixes, + NAME_HONORIFIC_PREFIX, + {}, + MergeMode::kUseBetterOrNewerForSameValue | MergeMode::kReplaceEmpty | + MergeMode::kUseBetterOrMostRecentIfDifferent) {} NameHonorificPrefix::~NameHonorificPrefix() = default; @@ -229,9 +231,11 @@ NameFull::~NameFull() = default; NameFullWithPrefix::NameFullWithPrefix() - : AddressComponent(NAME_FULL_WITH_HONORIFIC_PREFIX, - {}, - MergeMode::kMergeChildrenAndReformatIfNeeded) { + : FeatureGuardedAddressComponent( + &features::kAutofillEnableSupportForHonorificPrefixes, + NAME_FULL_WITH_HONORIFIC_PREFIX, + {}, + MergeMode::kMergeChildrenAndReformatIfNeeded) { RegisterChildNode(std::make_unique<NameHonorificPrefix>()); RegisterChildNode(std::make_unique<NameFull>()); }
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_name.h b/components/autofill/core/browser/data_model/autofill_structured_address_name.h index c4b7061..ea65f50 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_name.h +++ b/components/autofill/core/browser/data_model/autofill_structured_address_name.h
@@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "components/autofill/core/browser/data_model/autofill_feature_guarded_address_component.h" #include "components/autofill/core/browser/data_model/autofill_structured_address_component.h" #include "components/autofill/core/browser/field_types.h" @@ -132,7 +133,9 @@ }; // Atomic component that represents a honorific prefix. -class NameHonorificPrefix : public AddressComponent { +// Without the second generation of the structured name tree, honorific +// prefixes and the name including the prefix are unsupported types. +class NameHonorificPrefix : public FeatureGuardedAddressComponent { public: NameHonorificPrefix(); ~NameHonorificPrefix() override; @@ -164,7 +167,9 @@ // | _FIRST | | _CONJUNCTION | | _SECOND | // +--------+ +--------------+ +---------+ // -class NameFullWithPrefix : public AddressComponent { +// Without the second generation of the structured name tree, honorific +// prefixes and the name including the prefix are unsupported types. +class NameFullWithPrefix : public FeatureGuardedAddressComponent { public: NameFullWithPrefix(); NameFullWithPrefix(const NameFullWithPrefix& other);
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc b/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc index 2e42f2d..c4a9f63 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc
@@ -12,6 +12,7 @@ #include "base/feature_list.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "components/autofill/core/browser/data_model/autofill_structured_address_test_utils.h" #include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h" #include "components/autofill/core/common/autofill_features.h" @@ -104,11 +105,20 @@ } // namespace +class AutofillStructuredName : public testing::Test { + public: + AutofillStructuredName() = default; + + private: + base::test::ScopedFeatureList features_{ + features::kAutofillEnableSupportForHonorificPrefixes}; +}; + // Tests the parsing of last names into their tree components: // * The first part, that is only used in Latinx/Hispanic names. // * The conjunction, that is optional in Latinx/Hispanic names. // * The second part, for Latinx/Hispanic and all other last names. -TEST(AutofillStructuredName, ParseLastName) { +TEST_F(AutofillStructuredName, ParseLastName) { LastNameParserTestRecord last_name_tests[] = { // "von" is a known prefix for a surname and should be therefore parsed // into the second last name @@ -134,7 +144,7 @@ } // Tests the parsing of full names into their subcomponents. -TEST(AutofillStructuredName, ParseFullName) { +TEST_F(AutofillStructuredName, ParseFullName) { NameParserTestRecord name_tests[] = { // Name starting with a last name, followed by a comma and the first and // middle name. @@ -251,7 +261,7 @@ } // Tests the detection of CJK name characteristics. -TEST(AutofillStructuredName, HasCjkNameCharacteristics) { +TEST_F(AutofillStructuredName, HasCjkNameCharacteristics) { EXPECT_FALSE(HasCjkNameCharacteristics("Peterson")); EXPECT_TRUE(HasCjkNameCharacteristics("ㅎ")); EXPECT_TRUE(HasCjkNameCharacteristics("房仕龙")); @@ -286,14 +296,14 @@ } // Test the detection of Hispanic/Latinx name characteristics. -TEST(AutofillStructuredName, HasHispanicLatinxNameCharacteristics) { +TEST_F(AutofillStructuredName, HasHispanicLatinxNameCharacteristics) { EXPECT_TRUE(HasHispanicLatinxNameCharacteristics("Pablo Ruiz Picasso")); EXPECT_FALSE(HasHispanicLatinxNameCharacteristics("Werner Heisenberg")); EXPECT_TRUE(HasHispanicLatinxNameCharacteristics("SomeName y SomeOtherName")); } // Test the detection of middle name initials. -TEST(AutofillStructuredName, HasMiddleNameInitialsCharacteristics) { +TEST_F(AutofillStructuredName, HasMiddleNameInitialsCharacteristics) { EXPECT_FALSE(HasMiddleNameInitialsCharacteristics("Diego")); EXPECT_FALSE(HasMiddleNameInitialsCharacteristics("d")); EXPECT_TRUE(HasMiddleNameInitialsCharacteristics("D")); @@ -305,7 +315,7 @@ } // Test the reduction of a name to its initials. -TEST(AutofillStructuredName, ReduceToInitials) { +TEST_F(AutofillStructuredName, ReduceToInitials) { EXPECT_EQ(ReduceToInitials(u""), u""); EXPECT_EQ(ReduceToInitials(u"George"), u"G"); EXPECT_EQ(ReduceToInitials(u"George Walker"), u"GW"); @@ -314,7 +324,7 @@ } // Test getting the field type |NAME_MIDDLE_INITIAL|. -TEST(AutofillStructuredName, GetNameMiddleInitial) { +TEST_F(AutofillStructuredName, GetNameMiddleInitial) { NameFull full_name; full_name.SetValueForType(NAME_MIDDLE, u"Michael", @@ -345,7 +355,7 @@ EXPECT_EQ(full_name.GetValueForType(NAME_MIDDLE_INITIAL), u"G.-W."); } -TEST(AutofillStructuredName, TestGetSupportedTypes_FullNameWithPrefix) { +TEST_F(AutofillStructuredName, TestGetSupportedTypes_FullNameWithPrefix) { NameFullWithPrefix full_name_with_prefix; FieldTypeSet supported_types; full_name_with_prefix.GetSupportedTypes(&supported_types); @@ -356,7 +366,7 @@ supported_types); } -TEST(AutofillStructuredName, TestGetSupportedTypes_FullName) { +TEST_F(AutofillStructuredName, TestGetSupportedTypes_FullName) { NameFull full_name; FieldTypeSet supported_types; full_name.GetSupportedTypes(&supported_types); @@ -366,7 +376,7 @@ supported_types); } -TEST(AutofillStructuredName, TestSettingMiddleNameInitial) { +TEST_F(AutofillStructuredName, TestSettingMiddleNameInitial) { NameFullWithPrefix full_name_with_prefix; EXPECT_EQ(full_name_with_prefix.GetValueForType(NAME_MIDDLE), std::u16string()); @@ -377,7 +387,7 @@ EXPECT_EQ(full_name_with_prefix.GetValueForType(NAME_MIDDLE), u"M"); } -TEST(AutofillStructuredName, MergePermutedNames) { +TEST_F(AutofillStructuredName, MergePermutedNames) { NameFull one; NameFull two; @@ -421,8 +431,8 @@ VerificationStatus::kObserved); } -TEST(AutofillStructuredName, - MergeNamesByCombiningSubstructureObservations_WithAdditionalPrefix) { +TEST_F(AutofillStructuredName, + MergeNamesByCombiningSubstructureObservations_WithAdditionalPrefix) { NameFullWithPrefix one; NameFullWithPrefix two; @@ -529,7 +539,7 @@ // Tests that the root node of NameFullWithPrefix is correctly populated after a // migration from a NameFull structure. -TEST(AutofillStructuredName, TestPopulationOfNameFullWithPrefix) { +TEST_F(AutofillStructuredName, TestPopulationOfNameFullWithPrefix) { NameFullWithPrefix name_full_with_prefix; // The first name has an incorrect componentization of the last name, but a @@ -592,8 +602,8 @@ VerifyTestValues(&name_full_with_prefix, expectation); } -TEST(AutofillStructuredName, - MergeNamesByCombiningSubstructureObservations_FullName) { +TEST_F(AutofillStructuredName, + MergeNamesByCombiningSubstructureObservations_FullName) { NameFull one; NameFull two; @@ -683,8 +693,8 @@ VerifyTestValues(&two, merge_expectation); } -TEST(AutofillStructuredName, - MergeNamesByCombiningSubstructureObservations_FullNameWithPrefix) { +TEST_F(AutofillStructuredName, + MergeNamesByCombiningSubstructureObservations_FullNameWithPrefix) { NameFullWithPrefix one; NameFullWithPrefix two; @@ -793,7 +803,7 @@ VerifyTestValues(&two, merge_expectation); } -TEST(AutofillStructuredName, TestCopyConstructor) { +TEST_F(AutofillStructuredName, TestCopyConstructor) { NameFull original; // The first name has an incorrect componentization of the last name, but // a correctly observed structure of title, first, middle, last. @@ -813,8 +823,8 @@ EXPECT_TRUE(original.SameAs(copy)); } -TEST(AutofillStructuredName, - MigrationFromLegacyStructure_WithFullName_Unverified) { +TEST_F(AutofillStructuredName, + MigrationFromLegacyStructure_WithFullName_Unverified) { NameFull name; name.SetValueForType(NAME_FULL, u"Thomas Neo Anderson", VerificationStatus::kNoStatus); @@ -844,7 +854,7 @@ VerificationStatus::kParsed); } -TEST(AutofillStructuredName, MigrationFromLegacyStructure_WithoutFullName) { +TEST_F(AutofillStructuredName, MigrationFromLegacyStructure_WithoutFullName) { NameFull name; // The first name has an incorrect componentization of the last name, but // a correctly observed structure of title, first, middle, last. @@ -874,7 +884,7 @@ VerificationStatus::kObserved); } -TEST(AutofillStructuredName, MergeSubsetLastname) { +TEST_F(AutofillStructuredName, MergeSubsetLastname) { NameFull name; NameFull subset_name; name.SetMergeModeForTesting(kRecursivelyMergeSingleTokenSubset | @@ -934,7 +944,7 @@ VerifyTestValues(&name, name_values); } -TEST(AutofillStructuredName, MergeSubsetLastname_WithNonSpaceSeparators) { +TEST_F(AutofillStructuredName, MergeSubsetLastname_WithNonSpaceSeparators) { NameFull name; NameFull subset_name; name.SetMergeModeForTesting(kRecursivelyMergeSingleTokenSubset | @@ -1004,7 +1014,7 @@ VerifyTestValues(&name, expectation); } -TEST(AutofillStructuredName, MergeSubsetLastname2) { +TEST_F(AutofillStructuredName, MergeSubsetLastname2) { NameFullWithPrefix name; NameFullWithPrefix subset_name; name.SetMergeModeForTesting(kRecursivelyMergeSingleTokenSubset |
diff --git a/components/autofill/core/browser/data_model/birthdate.cc b/components/autofill/core/browser/data_model/birthdate.cc index 35dfe7e..dcb463e 100644 --- a/components/autofill/core/browser/data_model/birthdate.cc +++ b/components/autofill/core/browser/data_model/birthdate.cc
@@ -16,7 +16,7 @@ } std::u16string Birthdate::GetRawInfo(FieldType type) const { - DCHECK_EQ(GroupTypeOfServerFieldType(type), FieldTypeGroup::kBirthdateField); + DCHECK_EQ(GroupTypeOfFieldType(type), FieldTypeGroup::kBirthdateField); switch (type) { case BIRTHDATE_DAY: @@ -48,7 +48,7 @@ void Birthdate::SetRawInfoWithVerificationStatus(FieldType type, const std::u16string& value, VerificationStatus status) { - DCHECK_EQ(GroupTypeOfServerFieldType(type), FieldTypeGroup::kBirthdateField); + DCHECK_EQ(GroupTypeOfFieldType(type), FieldTypeGroup::kBirthdateField); switch (type) { case BIRTHDATE_DAY:
diff --git a/components/autofill/core/browser/data_model/contact_info.cc b/components/autofill/core/browser/data_model/contact_info.cc index acef678c..646ecb97 100644 --- a/components/autofill/core/browser/data_model/contact_info.cc +++ b/components/autofill/core/browser/data_model/contact_info.cc
@@ -78,7 +78,7 @@ } std::u16string NameInfo::GetRawInfo(FieldType type) const { - DCHECK_EQ(FieldTypeGroup::kName, GroupTypeOfServerFieldType(type)); + DCHECK_EQ(FieldTypeGroup::kName, GroupTypeOfFieldType(type)); // TODO(crbug.com/1141460): Remove once honorific prefixes are launched. if (type == NAME_FULL_WITH_HONORIFIC_PREFIX && !HonorificPrefixEnabled()) { @@ -96,16 +96,8 @@ void NameInfo::SetRawInfoWithVerificationStatus(FieldType type, const std::u16string& value, VerificationStatus status) { - DCHECK_EQ(FieldTypeGroup::kName, GroupTypeOfServerFieldType(type)); - // Without the second generation of the structured name tree, honorific - // prefixes and the name including the prefix are unsupported types. - if ((type == NAME_HONORIFIC_PREFIX || - type == NAME_FULL_WITH_HONORIFIC_PREFIX) && - !HonorificPrefixEnabled()) { - return; - } - bool success = name_->SetValueForType(type, value, status); - DCHECK(success) << FieldTypeToStringView(type); + DCHECK_EQ(FieldTypeGroup::kName, GroupTypeOfFieldType(type)); + name_->SetValueForType(type, value, status); } void NameInfo::GetSupportedTypes(FieldTypeSet* supported_types) const { @@ -150,14 +142,7 @@ } VerificationStatus NameInfo::GetVerificationStatusImpl(FieldType type) const { - // Without the second generation of the structured name tree, honorific - // prefixes and the name including the prefix are unsupported types. - if (!((type == NAME_HONORIFIC_PREFIX || - type == NAME_FULL_WITH_HONORIFIC_PREFIX) && - !HonorificPrefixEnabled())) { - return name_->GetVerificationStatusForType(type); - } - return VerificationStatus::kNoStatus; + return name_->GetVerificationStatusForType(type); } EmailInfo::EmailInfo() = default;
diff --git a/components/autofill/core/browser/data_model/contact_info_unittest.cc b/components/autofill/core/browser/data_model/contact_info_unittest.cc index b848812..8ae2f37 100644 --- a/components/autofill/core/browser/data_model/contact_info_unittest.cc +++ b/components/autofill/core/browser/data_model/contact_info_unittest.cc
@@ -39,7 +39,7 @@ NameInfo name; name.SetInfo(AutofillType(NAME_FULL), ASCIIToUTF16(test_case.full_name_input), "en-US"); - name.FinalizeAfterImport(); + EXPECT_TRUE(name.FinalizeAfterImport()); EXPECT_EQ(ASCIIToUTF16(test_case.given_name_output), name.GetInfo(AutofillType(NAME_FIRST), "en-US")); EXPECT_EQ(ASCIIToUTF16(test_case.middle_name_output), @@ -178,7 +178,9 @@ FullNameTestCase{"Mikhail Yevgrafovich Saltykov-Shchedrin", "Mikhail", "Yevgrafovich", "Saltykov-Shchedrin"}, FullNameTestCase{"Arthur Ignatius Conan Doyle", "Arthur", - "Ignatius Conan", "Doyle"})); + "Ignatius Conan", "Doyle"}, + FullNameTestCase{"Pablo Diego Ruiz y Picasso", "Pablo Diego", "", + "Ruiz y Picasso"})); TEST(CompanyTest, SetRawInfo) { CompanyInfo company;
diff --git a/components/autofill/core/browser/data_model/credit_card.cc b/components/autofill/core/browser/data_model/credit_card.cc index 98cffbe..62f5f647 100644 --- a/components/autofill/core/browser/data_model/credit_card.cc +++ b/components/autofill/core/browser/data_model/credit_card.cc
@@ -606,9 +606,15 @@ return name_on_card_; case CREDIT_CARD_NAME_FIRST: + if (!temp_card_first_name_.empty()) { + return temp_card_first_name_; + } return data_util::SplitName(name_on_card_).given; case CREDIT_CARD_NAME_LAST: + if (!temp_card_last_name_.empty()) { + return temp_card_last_name_; + } return data_util::SplitName(name_on_card_).family; case CREDIT_CARD_EXP_MONTH: @@ -654,10 +660,12 @@ void CreditCard::SetRawInfoWithVerificationStatus(FieldType type, const std::u16string& value, VerificationStatus status) { - DCHECK_EQ(FieldTypeGroup::kCreditCard, GroupTypeOfServerFieldType(type)); + DCHECK_EQ(FieldTypeGroup::kCreditCard, GroupTypeOfFieldType(type)); switch (type) { case CREDIT_CARD_NAME_FULL: name_on_card_ = value; + temp_card_first_name_ = u""; + temp_card_last_name_ = u""; break; case CREDIT_CARD_NAME_FIRST: @@ -1384,6 +1392,8 @@ void CreditCard::SetNameOnCardFromSeparateParts() { DCHECK(!temp_card_first_name_.empty() && !temp_card_last_name_.empty()); name_on_card_ = temp_card_first_name_ + u" " + temp_card_last_name_; + temp_card_first_name_ = u""; + temp_card_last_name_ = u""; } } // namespace autofill
diff --git a/components/autofill/core/browser/data_model/phone_number.cc b/components/autofill/core/browser/data_model/phone_number.cc index 8f71e1a..4e909b4 100644 --- a/components/autofill/core/browser/data_model/phone_number.cc +++ b/components/autofill/core/browser/data_model/phone_number.cc
@@ -82,7 +82,7 @@ } std::u16string PhoneNumber::GetRawInfo(FieldType type) const { - DCHECK_EQ(FieldTypeGroup::kPhone, GroupTypeOfServerFieldType(type)); + DCHECK_EQ(FieldTypeGroup::kPhone, GroupTypeOfFieldType(type)); if (type == PHONE_HOME_WHOLE_NUMBER) return number_; @@ -95,7 +95,7 @@ void PhoneNumber::SetRawInfoWithVerificationStatus(FieldType type, const std::u16string& value, VerificationStatus status) { - DCHECK_EQ(FieldTypeGroup::kPhone, GroupTypeOfServerFieldType(type)); + DCHECK_EQ(FieldTypeGroup::kPhone, GroupTypeOfFieldType(type)); if (type != PHONE_HOME_WHOLE_NUMBER) { // Only full phone numbers should be set directly. The browser is // intentionally caused to crash to prevent all users from setting raw info
diff --git a/components/autofill/core/browser/data_model/phone_number_unittest.cc b/components/autofill/core/browser/data_model/phone_number_unittest.cc index 330e23ad..b74bd3e 100644 --- a/components/autofill/core/browser/data_model/phone_number_unittest.cc +++ b/components/autofill/core/browser/data_model/phone_number_unittest.cc
@@ -300,7 +300,7 @@ profile.GetSupportedTypes(&types); std::vector<FieldType> fields{types.begin(), types.end()}; std::erase_if(fields, [](FieldType type) { - return GroupTypeOfServerFieldType(type) != FieldTypeGroup::kPhone; + return GroupTypeOfFieldType(type) != FieldTypeGroup::kPhone; }); base::ranges::for_each(fields, [](FieldType type) {
diff --git a/components/autofill/core/browser/field_type_utils.cc b/components/autofill/core/browser/field_type_utils.cc index ce10600..0b163b7 100644 --- a/components/autofill/core/browser/field_type_utils.cc +++ b/components/autofill/core/browser/field_type_utils.cc
@@ -58,7 +58,7 @@ size_t NumberOfPossibleFieldTypesInGroup(const AutofillField& field, FieldTypeGroup group) { return base::ranges::count(field.possible_types(), group, - GroupTypeOfServerFieldType); + GroupTypeOfFieldType); } bool FieldHasMeaningfulPossibleFieldTypes(const AutofillField& field) { @@ -84,7 +84,7 @@ } bool IsAddressType(FieldType type) { - switch (GroupTypeOfServerFieldType(type)) { + switch (GroupTypeOfFieldType(type)) { case FieldTypeGroup::kName: case FieldTypeGroup::kEmail: case FieldTypeGroup::kCompany:
diff --git a/components/autofill/core/browser/field_types.cc b/components/autofill/core/browser/field_types.cc index 8f16c5ea..320eacb 100644 --- a/components/autofill/core/browser/field_types.cc +++ b/components/autofill/core/browser/field_types.cc
@@ -459,14 +459,14 @@ FieldTypeSet GetFieldTypesOfGroup(FieldTypeGroup group) { FieldTypeSet fields_matching_group; for (FieldType field_type : kAllFieldTypes) { - if (GroupTypeOfServerFieldType(field_type) == group) { + if (GroupTypeOfFieldType(field_type) == group) { fields_matching_group.insert(field_type); } } return fields_matching_group; } -FieldTypeGroup GroupTypeOfServerFieldType(FieldType field_type) { +FieldTypeGroup GroupTypeOfFieldType(FieldType field_type) { switch (field_type) { case NAME_HONORIFIC_PREFIX: case NAME_FIRST: @@ -675,8 +675,7 @@ NOTREACHED_NORETURN(); } -FieldType HtmlFieldTypeToBestCorrespondingServerFieldType( - HtmlFieldType field_type) { +FieldType HtmlFieldTypeToBestCorrespondingFieldType(HtmlFieldType field_type) { switch (field_type) { case HtmlFieldType::kUnspecified: return UNKNOWN_TYPE;
diff --git a/components/autofill/core/browser/field_types.h b/components/autofill/core/browser/field_types.h index 0399248..c9cf410 100644 --- a/components/autofill/core/browser/field_types.h +++ b/components/autofill/core/browser/field_types.h
@@ -504,12 +504,11 @@ // There's a one-to-many relationship between FieldTypeGroup and // FieldType as well as HtmlFieldType. FieldTypeSet GetFieldTypesOfGroup(FieldTypeGroup group); -FieldTypeGroup GroupTypeOfServerFieldType(FieldType field_type); +FieldTypeGroup GroupTypeOfFieldType(FieldType field_type); FieldTypeGroup GroupTypeOfHtmlFieldType(HtmlFieldType field_type); // Not all HtmlFieldTypes have a corresponding FieldType. -FieldType HtmlFieldTypeToBestCorrespondingServerFieldType( - HtmlFieldType field_type); +FieldType HtmlFieldTypeToBestCorrespondingFieldType(HtmlFieldType field_type); // Returns |raw_value| if it corresponds to a non-deprecated enumeration // constant of ServerFieldType other than MAX_VALID_FIELD_TYPE. Otherwise,
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc index 6b8058b93..0eea923 100644 --- a/components/autofill/core/browser/form_data_importer.cc +++ b/components/autofill/core/browser/form_data_importer.cc
@@ -77,7 +77,7 @@ // - phone number components because a form might request several phone // numbers. // TODO(crbug.com/1156315) Clean up when launched. - FieldTypeGroup field_type_group = GroupTypeOfServerFieldType(field_type); + FieldTypeGroup field_type_group = GroupTypeOfFieldType(field_type); if (observed_types.contains(field_type) && field_type != EMAIL_ADDRESS && (!base::FeatureList::IsEnabled( features::kAutofillEnableImportWhenMultiplePhoneNumbers) || @@ -959,6 +959,10 @@ FormDataImporter::ExtractCreditCardFromFormResult FormDataImporter::ExtractCreditCardFromForm(const FormStructure& form) { + if (base::FeatureList::IsEnabled(features::kAutofillRelaxCreditCardImport)) { + return ExtractCreditCardFromFormRelaxed(form); + } + ExtractCreditCardFromFormResult result; FieldTypeSet types_seen; @@ -1024,6 +1028,98 @@ return result; } +FormDataImporter::ExtractCreditCardFromFormResult +FormDataImporter::ExtractCreditCardFromFormRelaxed(const FormStructure& form) { + // Populated by the lambdas below. + ExtractCreditCardFromFormResult result; + + // Populates `result` from `field` if it's a credit card field. + // For example, if `field` contains credit card number, this sets the number + // of `result.card` to the `field`'s value. + auto extract_if_credit_card_field = [&result, &app_locale = app_locale_]( + const AutofillField& field) { + // The value of interest is `field->value` or `field->user_input`. + std::u16string_view value_view = + base::TrimWhitespace(field.value, base::TRIM_ALL); + std::u16string_view user_input_view = + base::TrimWhitespace(field.user_input, base::TRIM_ALL); + if (!user_input_view.empty() && + field.Type().GetStorableType() == ServerFieldType::CREDIT_CARD_NUMBER && + base::FeatureList::IsEnabled( + features::kAutofillUseTypedCreditCardNumber)) { + value_view = user_input_view; + } + std::u16string value(value_view); + + // If we don't know the type of the field, or the user hasn't entered any + // information into the field, then skip it. + if (!field.IsFieldFillable() || value.empty() || + field.Type().group() != FieldTypeGroup::kCreditCard) { + return; + } + std::u16string old_value = result.card.GetInfo(field.Type(), app_locale); + if (field.form_control_type == FormControlType::kInputMonth) { + // If |field| is an HTML5 month input, handle it as a special case. + DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, + field.Type().GetStorableType()); + result.card.SetInfoForMonthInputType(value); + } else { + bool saved = result.card.SetInfo(field.Type(), value, app_locale); + if (!saved && field.IsSelectOrSelectListElement()) { + // Saving with the option text (here `value`) may fail for the + // expiration month. Attempt to save with the option value. First find + // the index of the option text in the select options and try the + // corresponding value. + if (auto it = base::ranges::find(field.options, value, + &SelectOption::content); + it != field.options.end()) { + result.card.SetInfo(field.Type(), it->value, app_locale); + } + } + } + std::u16string new_value = result.card.GetInfo(field.Type(), app_locale); + result.has_duplicate_credit_card_field_type |= + !old_value.empty() && old_value != new_value; + }; + + // Populates `result` from `fields` that satisfy `pred`, and erases those + // fields. Afterwards, it also erases all remaining fields whose type is now + // present in `result.card`. + // For example, if a `CREDIT_CARD_NAME_FULL` field matches `pred`, this + // function sets the credit card first, last, and full name and erases + // all `fields` of type `CREDIT_CARD_NAME_{FULL,FIRST,LAST}`. + auto extract_data_and_remove_field_if = + [&result, &extract_if_credit_card_field, &app_locale = app_locale_]( + std::vector<const AutofillField*>& fields, const auto& pred) { + for (const AutofillField* field : fields) { + if (std::invoke(pred, *field)) { + extract_if_credit_card_field(*field); + } + } + std::erase_if(fields, [&](const AutofillField* field) { + return std::invoke(pred, *field) || + !result.card.GetInfo(field->Type(), app_locale).empty(); + }); + }; + + // We split the fields into three priority groups: user-typed values, + // autofilled values, other values. The duplicate-value recognition is limited + // to values of the respective group. + // + // Suppose the user first autofills a form, including invisible fields. Then + // they edited a visible fields. The priority groups ensure that the invisible + // field does not prevent credit card import. + std::vector<const AutofillField*> fields; + fields.reserve(form.fields().size()); + for (const std::unique_ptr<AutofillField>& field : form.fields()) { + fields.push_back(field.get()); + } + extract_data_and_remove_field_if(fields, &AutofillField::is_user_edited); + extract_data_and_remove_field_if(fields, &AutofillField::is_autofilled); + extract_data_and_remove_field_if(fields, [](const auto&) { return true; }); + return result; +} + Iban FormDataImporter::ExtractIbanFromForm(const FormStructure& form) { // Creates an IBAN candidate with `kUnknown` record type as it is currently // unknown if this IBAN already exists locally or on the server.
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h index dc1224d6..e731023a 100644 --- a/components/autofill/core/browser/form_data_importer.h +++ b/components/autofill/core/browser/form_data_importer.h
@@ -91,6 +91,11 @@ ExtractCreditCardFromFormResult ExtractCreditCardFromForm( const FormStructure& form); + // TODO(crbug.com/1381477): Rename to ExtractCreditCardFromForm() once + // `features::kAutofillRelaxCreditCardImport` is launched. + ExtractCreditCardFromFormResult ExtractCreditCardFromFormRelaxed( + const FormStructure& form); + // Tries to initiate the saving of `extracted_iban` if applicable. bool ProcessIbanImportCandidate(const Iban& extracted_iban);
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc index 5b8807f..f9c0b24 100644 --- a/components/autofill/core/browser/form_data_importer_unittest.cc +++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -531,7 +531,8 @@ features::kAutofillEnableSupportForAddressOverflow, features::kAutofillEnableSupportForBetweenStreetsOrLandmark, features::kAutofillEnableSupportForAddressOverflowAndLandmark, - features::kAutofillEnableParsingOfStreetLocation}, + features::kAutofillEnableParsingOfStreetLocation, + features::kAutofillRelaxCreditCardImport}, {}); } @@ -4230,4 +4231,115 @@ EXPECT_TRUE(observed_field_types.empty()); } +// Test case for credit card extraction. +class FormDataImporterTest_ExtractCreditCardFromForm + : public FormDataImporterTest { + public: + enum class Mode { kDefaultValue, kAutofilled, kUserEdited }; + + void PushField(FieldType field_type, + std::u16string value, + Mode mode = Mode::kDefaultValue) { + AutofillField& f = test_api(form_).PushField(); + f.set_server_predictions({test::CreateFieldPrediction(field_type)}); + f.value = std::move(value); + f.is_autofilled = mode == Mode::kAutofilled; + f.is_user_edited = mode == Mode::kUserEdited; + } + + FormStructure form_{/*form=*/{}}; +}; + +// Tests that inconsistent values from different priority classes do not prevent +// import. +// For example, the user-edited "Donald Trump" has higher priority than the +// autofilled "Joe Biden", which has still higher priority than default-value +// "Joe Average". +TEST_F(FormDataImporterTest_ExtractCreditCardFromForm, + IgnoreInconsistentValuesFromDifferentPriorityClasses) { + PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Average", + Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Donald Trump", + Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_NUMBER, u"4444444444444444", + Mode::kDefaultValue); + PushField(FieldType::CREDIT_CARD_NUMBER, u"4444333322221111", + Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, u"01/2020", + Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"01/2021", + Mode::kUserEdited); + auto r = form_data_importer().ExtractCreditCardFromForm(form_); + EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NAME_FULL, kLocale), + u"Donald Trump"); + EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale), + u"4444333322221111"); + EXPECT_EQ( + r.card.GetInfo(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, kLocale), + u"01/2021"); + EXPECT_FALSE(r.has_duplicate_credit_card_field_type); +} + +// Tests that equivalent values of different types do not prevent import: +// - first name + last names = full name; +// - month + year = expiration date. +TEST_F(FormDataImporterTest_ExtractCreditCardFromForm, MergeDerivedValues) { + PushField(FieldType::CREDIT_CARD_NAME_FIRST, u"Donald", Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_NAME_LAST, u"Trump", Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_NUMBER, u"4444333322221111", + Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_EXP_MONTH, u"12", Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2020", + Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, u"12/20", + Mode::kUserEdited); + auto r = form_data_importer().ExtractCreditCardFromForm(form_); + EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NAME_FULL, kLocale), + u"Donald Trump"); + EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale), + u"4444333322221111"); + EXPECT_EQ( + r.card.GetInfo(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, kLocale), + u"12/2020"); + EXPECT_FALSE(r.has_duplicate_credit_card_field_type); +} + +// Tests detection of inconsistent values (first names "Audrey" and "Katherine") +// in the same priority class (user-edited fields). +TEST_F(FormDataImporterTest_ExtractCreditCardFromForm, + BlockImportForInconsistentValues) { + PushField(FieldType::CREDIT_CARD_NAME_FIRST, u"Katherine", Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_NAME_FIRST, u"Audrey", Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_NAME_LAST, u"Hepburn", Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_NUMBER, u"4444333322221111", + Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"12/2020", + Mode::kUserEdited); + auto r = form_data_importer().ExtractCreditCardFromForm(form_); + ASSERT_TRUE(r.has_duplicate_credit_card_field_type); +} + +// Tests that even editing only a first name (without editing the last name) is +// is reflected in the import candidate. +TEST_F(FormDataImporterTest_ExtractCreditCardFromForm, PartialFirstLastNames) { + PushField(FieldType::CREDIT_CARD_NAME_FIRST, u"Katherine", Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_NAME_FIRST, u"Audrey", Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_NAME_LAST, u"Hepburn", Mode::kAutofilled); + PushField(FieldType::CREDIT_CARD_NUMBER, u"4444333322221111", + Mode::kUserEdited); + PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"12/2020", + Mode::kUserEdited); + auto r = form_data_importer().ExtractCreditCardFromForm(form_); + EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NAME_FULL, kLocale), + u"Audrey Hepburn"); + EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale), + u"4444333322221111"); + EXPECT_EQ( + r.card.GetInfo(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, kLocale), + u"12/2020"); + EXPECT_FALSE(r.has_duplicate_credit_card_field_type); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/form_parsing/form_field.cc b/components/autofill/core/browser/form_parsing/form_field.cc index 4774b05..d7d3b70 100644 --- a/components/autofill/core/browser/form_parsing/form_field.cc +++ b/components/autofill/core/browser/form_parsing/form_field.cc
@@ -9,7 +9,6 @@ #include <iterator> #include <numeric> -#include "base/feature_list.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -36,7 +35,6 @@ #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/common/autocomplete_parsing_util.h" #include "components/autofill/core/common/autofill_constants.h" -#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_internals/log_message.h" #include "components/autofill/core/common/autofill_internals/logging_scope.h" #include "components/autofill/core/common/autofill_payments_features.h" @@ -63,13 +61,40 @@ } // namespace +RegexMatchesCache::RegexMatchesCache(int capacity) : cache_(capacity) {} +RegexMatchesCache::~RegexMatchesCache() = default; + +RegexMatchesCache::Key RegexMatchesCache::BuildKey( + base::StringPiece16 input, + base::StringPiece16 pattern) { + return Key(std::hash<std::u16string_view>{}(input), + std::hash<std::u16string_view>{}(pattern)); +} + +absl::optional<bool> RegexMatchesCache::Get(RegexMatchesCache::Key key) { + if (auto it = cache_.Get(key); it != cache_.end()) { + return it->second; + } + return absl::nullopt; +} + +void RegexMatchesCache::Put(RegexMatchesCache::Key key, bool value) { + cache_.Put(key, value); +} + ParsingContext::ParsingContext(GeoIpCountryCode client_country, LanguageCode page_language, PatternSource pattern_source) : client_country(std::move(client_country)), page_language(std::move(page_language)), pattern_source(pattern_source), - regex_cache(GetAutofillRegexCache()) {} + regex_cache(GetAutofillRegexCache()) { + if (base::FeatureList::IsEnabled( + features::kAutofillEnableCacheForRegexMatching)) { + matches_cache.emplace( + features::kAutofillEnableCacheForRegexMatchingCacheSizeParam.Get()); + } +} ParsingContext::~ParsingContext() = default; @@ -78,9 +103,21 @@ base::StringPiece16 input, base::StringPiece16 pattern, std::vector<std::u16string>* groups) { + RegexMatchesCache::Key key; + if (!groups && context.matches_cache) { + key = RegexMatchesCache::BuildKey(input, pattern); + absl::optional<bool> cache_entry = context.matches_cache->Get(key); + if (cache_entry.has_value()) { + return cache_entry.value(); + } + } const icu::RegexPattern* regex_pattern = context.regex_cache->GetRegexPattern(pattern); - return autofill::MatchesRegex(input, *regex_pattern, groups); + bool result = autofill::MatchesRegex(input, *regex_pattern, groups); + if (!groups && context.matches_cache) { + context.matches_cache->Put(key, result); + } + return result; } // static @@ -568,12 +605,12 @@ base::StringPiece16 value; std::vector<std::u16string> matches; std::vector<std::u16string>* capture_destination = - logging.log_manager ? &matches : nullptr; + logging.log_manager && logging.log_manager->IsLoggingActive() ? &matches + : nullptr; // TODO(crbug/1165780): Remove once shared labels are launched. const std::u16string& label = - base::FeatureList::IsEnabled( - features::kAutofillEnableSupportForParsingWithSharedLabels) + context.autofill_enable_support_for_parsing_with_shared_labels ? field->parseable_label() : field->label; @@ -593,8 +630,7 @@ match_type_string = "Match in name"; value = name; } else if (match_label && pattern != kEmptyLabelRegex && - base::FeatureList::IsEnabled( - features::kAutofillAlwaysParsePlaceholders) && + context.autofill_always_parse_placeholders && MatchesRegexWithCache(context, field->placeholder, pattern, capture_destination)) { // Placeholders are matched against the same regexes as labels. However, to @@ -609,7 +645,7 @@ value = field->placeholder; } - if (found_match) { + if (found_match && capture_destination) { LogBuffer table_rows(IsLoggingActive(logging.log_manager)); LOG_AF(table_rows) << Tr{} << "Match type:" << match_type_string; LOG_AF(table_rows) << Tr{} << "RegEx:" << logging.regex_name;
diff --git a/components/autofill/core/browser/form_parsing/form_field.h b/components/autofill/core/browser/form_parsing/form_field.h index 0b17466f..66b92ce 100644 --- a/components/autofill/core/browser/form_parsing/form_field.h +++ b/components/autofill/core/browser/form_parsing/form_field.h
@@ -11,15 +11,19 @@ #include <utility> #include <vector> +#include "base/containers/lru_cache.h" +#include "base/feature_list.h" #include "base/functional/callback.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "base/strings/string_piece.h" #include "components/autofill/core/browser/country_type.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h" #include "components/autofill/core/browser/form_parsing/field_candidates.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" +#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/language_code.h" namespace autofill { @@ -43,6 +47,54 @@ const char* regex_name = ""; }; +// LRU cache to prevent the repetitive evaluation of identical regular +// expressions (`pattern`) on identical `input` strings. +class RegexMatchesCache { + public: + // A good capacity for the cache according to an empirical study of forms + // with AllForms/HeuristicClassificationTests.EndToEnd is 300. This needs + // to be confirmed in real world experiments. + // RegexMatchesCache is not intended as a permanent cache but instantiated + // once per form parsing, so this is not allocating a lot of memory + // permanently. + explicit RegexMatchesCache(int capacity); + RegexMatchesCache(const RegexMatchesCache&) = delete; + RegexMatchesCache& operator=(const RegexMatchesCache&) = delete; + ~RegexMatchesCache(); + + // Hash values of an input and a pattern. There is a theoretical risk of + // collision which we are accepting here to not store the inputs an patterns + // which both may be large. Given that our heuristics are not 100% accurate + // the small risk of a collision seems acceptable. + // TODO(crbug.com/1121990): Once we don't use autofill_regex_constants.h + // anymore, the second `std::size_t` should probably be a MatchPatternRef: + // - more accurate (they uniquely identify the pattern across all pattern + // sources), + // - more time-efficient (no hashing needed), + // - more space-efficient (2 vs 8 bytes) + using Key = std::pair<std::size_t, std::size_t>; + + // Creates a key for an `input` string and a `pattern` to be used in the LRU + // cache. + static Key BuildKey(base::StringPiece16 input, base::StringPiece16 pattern); + + // Returns whether `pattern` in the key matched `input` if this information is + // cached. absl::nullopt if the information is not cached. + absl::optional<bool> Get(Key key); + + // Stores whether `pattern` in the key matched `input`. + void Put(Key key, bool value); + + private: + struct Hasher { + std::size_t operator()(const Key& key) const noexcept { + return std::get<0>(key) ^ std::get<1>(key); + } + }; + + base::HashingLRUCache<Key, bool, Hasher> cache_; +}; + // This is a helper class that is instantiated before form parsing. It contains // a) environmental information that is needed in many places and b) caches to // prevent repetitive work. @@ -58,6 +110,19 @@ const LanguageCode page_language; const PatternSource pattern_source; + // Cache for autofill features that are tested on hot code paths. Testing + // whether a feature is enabled is pretty expensive. Caching the status of two + // features led to a performance improvement for form field classification of + // 19% in release builds. + // Note that adding features here may push users into the respective + // experiment/control groups earlier than you may want. + const bool autofill_enable_support_for_parsing_with_shared_labels{ + base::FeatureList::IsEnabled( + features::kAutofillEnableSupportForParsingWithSharedLabels)}; + const bool autofill_always_parse_placeholders{ + base::FeatureList::IsEnabled(features::kAutofillAlwaysParsePlaceholders)}; + + std::optional<RegexMatchesCache> matches_cache; base::raw_ref<AutofillRegexCache> regex_cache; };
diff --git a/components/autofill/core/browser/form_parsing/regex_patterns.cc b/components/autofill/core/browser/form_parsing/regex_patterns.cc index e514db4..7925ce9 100644 --- a/components/autofill/core/browser/form_parsing/regex_patterns.cc +++ b/components/autofill/core/browser/form_parsing/regex_patterns.cc
@@ -53,13 +53,13 @@ } // namespace -absl::optional<PatternSource> GetActivePatternSource() { +std::optional<PatternSource> GetActivePatternSource() { return HeuristicSourceToPatternSource(GetActiveHeuristicSource()); } base::span<const MatchPatternRef> GetMatchPatterns( std::string_view name, - absl::optional<LanguageCode> language_code, + std::optional<LanguageCode> language_code, PatternSource pattern_source) { return language_code ? GetMatchPatterns(name, **language_code, pattern_source) : GetMatchPatterns(name, "", pattern_source); @@ -67,7 +67,7 @@ base::span<const MatchPatternRef> GetMatchPatterns( FieldType type, - absl::optional<LanguageCode> language_code, + std::optional<LanguageCode> language_code, PatternSource pattern_source) { return GetMatchPatterns(FieldTypeToStringView(type), language_code, pattern_source);
diff --git a/components/autofill/core/browser/form_parsing/regex_patterns.h b/components/autofill/core/browser/form_parsing/regex_patterns.h index f6d0fb4..f6357f7 100644 --- a/components/autofill/core/browser/form_parsing/regex_patterns.h +++ b/components/autofill/core/browser/form_parsing/regex_patterns.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PARSING_REGEX_PATTERNS_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PARSING_REGEX_PATTERNS_H_ +#include <optional> #include <string_view> #include "base/containers/span.h" @@ -12,7 +13,6 @@ #include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h" #include "components/autofill/core/browser/form_parsing/buildflags.h" #include "components/autofill/core/common/language_code.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -92,7 +92,7 @@ // The active pattern and the available patterns depend on the build config and // the Finch config. If the active `HeuristicSource` is not a `PatternSource`, // then a nullopt is returned. -absl::optional<PatternSource> GetActivePatternSource(); +std::optional<PatternSource> GetActivePatternSource(); // Looks up the patterns for the given name and language. // The name is typically a field type. @@ -106,12 +106,12 @@ // decreasing order. base::span<const MatchPatternRef> GetMatchPatterns( std::string_view name, - absl::optional<LanguageCode> language_code, + std::optional<LanguageCode> language_code, PatternSource pattern_source); base::span<const MatchPatternRef> GetMatchPatterns( FieldType type, - absl::optional<LanguageCode> language_code, + std::optional<LanguageCode> language_code, PatternSource pattern_source); // Returns true iff there at least one pattern for some PatternSource and
diff --git a/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc b/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc index 1a1f17d..8772c13 100644 --- a/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc +++ b/components/autofill/core/browser/form_parsing/regex_patterns_unittest.cc
@@ -39,9 +39,9 @@ explicit MatchPatternRefTestApi(MatchPatternRef p) : p_(p) {} - absl::optional<MatchPatternRef> MakeSupplementary() const { + std::optional<MatchPatternRef> MakeSupplementary() const { if (!(*p_).match_field_attributes.contains(MatchAttribute::kName)) - return absl::nullopt; + return std::nullopt; return MatchPatternRef(true, index()); } @@ -206,9 +206,9 @@ std::erase_if(expected, [](auto p) { return test_api(p).is_supplementary(); }); - EXPECT_THAT(GetMatchPatterns(kSomeName, absl::nullopt, pattern_source()), + EXPECT_THAT(GetMatchPatterns(kSomeName, std::nullopt, pattern_source()), UnorderedElementsAreArray(expected)); - EXPECT_THAT(GetMatchPatterns(kSomeName, absl::nullopt, pattern_source()), + EXPECT_THAT(GetMatchPatterns(kSomeName, std::nullopt, pattern_source()), Each(Not(IsSupplementary))); } @@ -220,7 +220,7 @@ EXPECT_THAT( GetMatchPatterns(kSomeName, kNonexistingLanguage, pattern_source()), ElementsAreArray( - GetMatchPatterns(kSomeName, absl::nullopt, pattern_source()))); + GetMatchPatterns(kSomeName, std::nullopt, pattern_source()))); } // Tests that for a given pattern name, the non-English languages are
diff --git a/components/autofill/core/browser/form_processing/label_processing_util.cc b/components/autofill/core/browser/form_processing/label_processing_util.cc index 6ee5d75..5bf60cd 100644 --- a/components/autofill/core/browser/form_processing/label_processing_util.cc +++ b/components/autofill/core/browser/form_processing/label_processing_util.cc
@@ -17,7 +17,7 @@ // The maximum length of a label that can be shared among fields. const int kMaxLengthOfShareableLabel = 40; -absl::optional<std::vector<std::u16string>> GetParseableLabels( +std::optional<std::vector<std::u16string>> GetParseableLabels( const LabelPieces& labels) { // Make a copy of the labels. LabelPieces shared_labels = labels; @@ -92,7 +92,7 @@ } if (!shared_labels_found) { - return absl::nullopt; + return std::nullopt; } // Otherwise convert the shared label string pieces into strings for memory @@ -101,7 +101,7 @@ result.reserve(shared_labels.size()); base::ranges::transform(shared_labels, std::back_inserter(result), [](auto& s) { return std::u16string(s); }); - return absl::make_optional(std::move(result)); + return std::make_optional(std::move(result)); } } // namespace autofill
diff --git a/components/autofill/core/browser/form_processing/label_processing_util.h b/components/autofill/core/browser/form_processing/label_processing_util.h index a2124a43..05f24b55 100644 --- a/components/autofill/core/browser/form_processing/label_processing_util.h +++ b/components/autofill/core/browser/form_processing/label_processing_util.h
@@ -5,18 +5,19 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_LABEL_PROCESSING_UTIL_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_LABEL_PROCESSING_UTIL_H_ +#include <optional> #include <vector> + #include "base/strings/string_piece.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { // If parseable labels can be derived from |labels|, a vector of // |std::u16string| is return that is aligned with |labels|. // Parseable labels can be derived by splitting one label between multiple -// adjacent fields. If there aren't any changes to the labels, |absl::nullopt| +// adjacent fields. If there aren't any changes to the labels, |std::nullopt| // is returned. -absl::optional<std::vector<std::u16string>> GetParseableLabels( +std::optional<std::vector<std::u16string>> GetParseableLabels( const std::vector<base::StringPiece16>& labels); } // namespace autofill
diff --git a/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc b/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc index 2cac002..d0d2ffbb 100644 --- a/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc +++ b/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc
@@ -35,19 +35,19 @@ EXPECT_EQ( GetParseableLabels({u"City", u"Street & House Number & Floor & Stairs", u"", u"", u"", u"Zip"}), - absl::nullopt); + std::nullopt); } TEST(LabelProcessingUtil, GetParseableNameStringPieces_UnmachtingComponents) { EXPECT_EQ(GetParseableLabels( {u"City", u"Street & House Number & Floor", u"", u"Zip"}), - absl::nullopt); + std::nullopt); } TEST(LabelProcessingUtil, GetParseableNameStringPieces_SplitableLabelAtEnd) { EXPECT_EQ(GetParseableLabels( {u"City", u"", u"Zip", u"Street & House Number & Floor"}), - absl::nullopt); + std::nullopt); } TEST(LabelProcessingUtil, GetParseableNameStringPieces_TooLongLabel) { @@ -56,7 +56,7 @@ u"additional text that exceeds 40 " u"characters by far", u"", u"Zip"}), - absl::nullopt); + std::nullopt); } } // namespace autofill
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 3c6afdb..334a561 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -81,7 +81,6 @@ #include "components/autofill/core/common/unique_ids.h" #include "components/security_state/core/security_state.h" #include "components/version_info/version_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" namespace autofill { @@ -388,7 +387,7 @@ bool HasPasswordManagerPrediction(const FieldSuggestion& field_suggestion) { return base::ranges::any_of( field_suggestion.predictions(), [](const auto& prediction) { - auto group_type = GroupTypeOfServerFieldType( + auto group_type = GroupTypeOfFieldType( ToSafeFieldType(prediction.type(), NO_SERVER_DATA)); return group_type == FieldTypeGroup::kPasswordField || group_type == FieldTypeGroup::kUsernameField; @@ -402,7 +401,7 @@ FieldSuggestion& merge_to_predictions) { CHECK_NE(&merge_to_predictions, &merge_from_predictions); for (const auto& prediction : merge_from_predictions.predictions()) { - FieldTypeGroup group_type = GroupTypeOfServerFieldType( + FieldTypeGroup group_type = GroupTypeOfFieldType( ToSafeFieldType(prediction.type(), NO_SERVER_DATA)); // Only add predictions relevant for PasswordManager. if (group_type == FieldTypeGroup::kPasswordField || @@ -491,7 +490,7 @@ client_country_ = client_country; // The active heuristic source might not be a pattern source. - if (absl::optional<PatternSource> pattern_source = GetActivePatternSource()) { + if (std::optional<PatternSource> pattern_source = GetActivePatternSource()) { ParseFieldTypesWithPatterns(*pattern_source, log_manager); } @@ -1006,7 +1005,7 @@ for (const auto* form : forms) { for (const auto& field : form->fields_) { FieldTypeGroup field_type_group = - GroupTypeOfServerFieldType(field->server_type()); + GroupTypeOfFieldType(field->server_type()); // In order to trigger the payments bottom sheet that assists users to // manually fill the form, credit card form fields are marked eligible for // manual filling. Also, if a field is not classified to a type, we can @@ -1631,8 +1630,7 @@ for (const auto& field : fields_) { const FieldType current_type = field->Type().GetStorableType(); // Put credit card fields into one, separate credit card section. - if (GroupTypeOfServerFieldType(current_type) == - FieldTypeGroup::kCreditCard) { + if (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kCreditCard) { if (!credit_card_section) { credit_card_section = Section::FromFieldIdentifier(*field, frame_token_ids); @@ -1649,7 +1647,7 @@ // Forms often ask for multiple phone numbers -- e.g. both a daytime and // evening phone number. Our phone number detection is also generally a // little off. Hence, ignore this field type as a signal here. - if (GroupTypeOfServerFieldType(current_type) == FieldTypeGroup::kPhone) { + if (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kPhone) { already_saw_current_type = false; } @@ -1798,8 +1796,7 @@ for (const auto& field : fields_) { const FieldType current_type = field->Type().GetStorableType(); // Credit card fields are already in one, separate credit card section. - if (GroupTypeOfServerFieldType(current_type) == - FieldTypeGroup::kCreditCard) { + if (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kCreditCard) { continue; } @@ -1811,7 +1808,7 @@ // Forms often ask for multiple phone numbers -- e.g. both a daytime and // evening phone number. Our phone number detection is also generally a // little off. Hence, ignore this field type as a signal here. - if (GroupTypeOfServerFieldType(current_type) == FieldTypeGroup::kPhone) { + if (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kPhone) { already_saw_current_type = false; } @@ -1910,7 +1907,7 @@ } // Determine the parsable labels and write them back. - absl::optional<std::vector<std::u16string>> parsable_labels = + std::optional<std::vector<std::u16string>> parsable_labels = GetParseableLabels(field_labels); // If not single label was split, the function can return, because the // |parsable_label_| is assigned to |label| by default.
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index e1f7344..5dd1a16d 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -9,6 +9,7 @@ #include <deque> #include <memory> +#include <optional> #include <set> #include <string> #include <string_view> @@ -32,7 +33,6 @@ #include "components/autofill/core/common/language_code.h" #include "components/autofill/core/common/mojom/autofill_types.mojom.h" #include "components/autofill/core/common/unique_ids.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -382,7 +382,7 @@ password_attributes_vote_ = vote; } - absl::optional<std::pair<PasswordAttribute, bool>> + std::optional<std::pair<PasswordAttribute, bool>> get_password_attributes_vote() const { return password_attributes_vote_; } @@ -448,9 +448,9 @@ // The signatures of forms recently submitted on the same origin within a // small period of time. struct FormAssociations { - absl::optional<FormSignature> last_address_form_submitted; - absl::optional<FormSignature> second_last_address_form_submitted; - absl::optional<FormSignature> last_credit_card_form_submitted; + std::optional<FormSignature> last_address_form_submitted; + std::optional<FormSignature> second_last_address_form_submitted; + std::optional<FormSignature> last_credit_card_form_submitted; }; void set_form_associations(FormAssociations associations) { @@ -637,7 +637,7 @@ // The vote about password attributes (e.g. whether the password has a numeric // character). - absl::optional<std::pair<PasswordAttribute, bool>> password_attributes_vote_; + std::optional<std::pair<PasswordAttribute, bool>> password_attributes_vote_; // If |password_attribute_vote_| contains (kHasSpecialSymbol, true), this // field contains noisified information about a special symbol in a
diff --git a/components/autofill/core/browser/form_structure_rationalizer.cc b/components/autofill/core/browser/form_structure_rationalizer.cc index a8956172..66380a81 100644 --- a/components/autofill/core/browser/form_structure_rationalizer.cc +++ b/components/autofill/core/browser/form_structure_rationalizer.cc
@@ -820,7 +820,7 @@ // is a country. for (int field_index = upper_index - 1; field_index >= 0; --field_index) { if ((*fields_)[field_index]->IsFocusable() && - GroupTypeOfServerFieldType( + GroupTypeOfFieldType( (*fields_)[field_index]->Type().GetStorableType()) == FieldTypeGroup::kAddress && (*fields_)[field_index]->section == (*fields_)[upper_index]->section) { @@ -1018,7 +1018,7 @@ const GeoIpCountryCode& client_country, const LanguageCode& language_code, LogManager* log_manager) { - absl::optional<PatternSource> pattern_source = GetActivePatternSource(); + std::optional<PatternSource> pattern_source = GetActivePatternSource(); if (!pattern_source.has_value()) { pattern_source = PatternSource::kLegacy; }
diff --git a/components/autofill/core/browser/form_structure_rationalizer_unittest.cc b/components/autofill/core/browser/form_structure_rationalizer_unittest.cc index 0909424..ca262b39 100644 --- a/components/autofill/core/browser/form_structure_rationalizer_unittest.cc +++ b/components/autofill/core/browser/form_structure_rationalizer_unittest.cc
@@ -53,12 +53,12 @@ // Section name of a field. std::string_view section = ""; FormControlType form_control_type = FormControlType::kInputText; - absl::optional<AutocompleteParsingResult> parsed_autocomplete = absl::nullopt; + std::optional<AutocompleteParsingResult> parsed_autocomplete = std::nullopt; bool is_focusable = true; size_t max_length = std::numeric_limits<int>::max(); FormFieldData::RoleAttribute role = FormFieldData::RoleAttribute::kOther; - absl::optional<url::Origin> subframe_origin; - absl::optional<FormGlobalId> host_form; + std::optional<url::Origin> subframe_origin; + std::optional<FormGlobalId> host_form; bool field_type_is_override = false; // Only appled if BuildFormStructure is called with run_heuristics=false. FieldType heuristic_type = UNKNOWN_TYPE;
diff --git a/components/autofill/core/browser/form_structure_sectioning_util.cc b/components/autofill/core/browser/form_structure_sectioning_util.cc index f731460..8fb89e7b 100644 --- a/components/autofill/core/browser/form_structure_sectioning_util.cc +++ b/components/autofill/core/browser/form_structure_sectioning_util.cc
@@ -44,8 +44,8 @@ FieldType previous_type) { if (previous_type == current_type) return true; - if (GroupTypeOfServerFieldType(current_type) == FieldTypeGroup::kName && - GroupTypeOfServerFieldType(previous_type) == FieldTypeGroup::kName) { + if (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kName && + GroupTypeOfFieldType(previous_type) == FieldTypeGroup::kName) { return true; } if (FieldTypeSet({ADDRESS_HOME_ZIP, ADDRESS_HOME_DEPENDENT_LOCALITY, @@ -150,7 +150,7 @@ // There are many phone number field types and their classification is // generally a little bit off. Furthermore, forms often ask for multiple phone // numbers, e.g. both a daytime and evening phone number. - if (GroupTypeOfServerFieldType(current_type) == FieldTypeGroup::kPhone) { + if (GroupTypeOfFieldType(current_type) == FieldTypeGroup::kPhone) { return true; }
diff --git a/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc b/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc index 5a78b5cf..1229de2 100644 --- a/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc +++ b/components/autofill/core/browser/form_structure_sectioning_util_unittest.cc
@@ -5,6 +5,7 @@ #include "components/autofill/core/browser/form_structure_sectioning_util.h" #include <memory> +#include <optional> #include <string> #include <vector> @@ -22,7 +23,6 @@ #include "components/autofill/core/common/signatures.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" using autofill::features::kAutofillSectioningModeCreateGaps; using autofill::features::kAutofillSectioningModeExpand;
diff --git a/components/autofill/core/browser/form_structure_test_api.cc b/components/autofill/core/browser/form_structure_test_api.cc index 3a49992..1d13bb6 100644 --- a/components/autofill/core/browser/form_structure_test_api.cc +++ b/components/autofill/core/browser/form_structure_test_api.cc
@@ -18,7 +18,6 @@ using FieldPrediction = AutofillQueryResponse::FormSuggestion::FieldSuggestion::FieldPrediction; -// static void FormStructureTestApi::SetFieldTypes( const std::vector<std::vector<std::pair<HeuristicSource, FieldType>>>& heuristic_types, @@ -47,7 +46,7 @@ const std::vector<FieldType>& server_types) { std::vector<FieldPrediction> server_predictions; for (FieldType type : server_types) { - server_predictions.push_back(::autofill::test::CreateFieldPrediction(type)); + server_predictions.push_back(test::CreateFieldPrediction(type)); } SetFieldTypes(heuristic_types, server_predictions); }
diff --git a/components/autofill/core/browser/form_structure_test_api.h b/components/autofill/core/browser/form_structure_test_api.h index 410b9ba..d9972695 100644 --- a/components/autofill/core/browser/form_structure_test_api.h +++ b/components/autofill/core/browser/form_structure_test_api.h
@@ -43,6 +43,11 @@ explicit FormStructureTestApi(FormStructure* form_structure) : form_structure_(*form_structure) {} + AutofillField& PushField() { + form_structure_->fields_.push_back(std::make_unique<AutofillField>()); + return *form_structure_->fields_.back(); + } + [[nodiscard]] bool ShouldBeParsed(ShouldBeParsedParams params = {}, LogManager* log_manager = nullptr) { return form_structure_->ShouldBeParsed(params, log_manager);
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc index 3730162..cbefe237 100644 --- a/components/autofill/core/browser/form_structure_unittest.cc +++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -10,6 +10,7 @@ #include <algorithm> #include <functional> #include <memory> +#include <optional> #include <string> #include <vector> @@ -46,7 +47,6 @@ #include "components/version_info/version_info.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/re2/src/re2/re2.h" #include "url/gurl.h" @@ -2471,7 +2471,7 @@ //////////////// std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = true; @@ -2644,7 +2644,7 @@ //////////////// std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); @@ -2761,7 +2761,7 @@ //////////////// std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = true; @@ -2879,7 +2879,7 @@ TEST_F(FormStructureTestImpl, EncodeUploadRequest) { std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = true; @@ -3074,7 +3074,7 @@ EncodeUploadRequestWithAdditionalPasswordFormSignature) { std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = true; @@ -3181,7 +3181,7 @@ TEST_F(FormStructureTestImpl, EncodeUploadRequestWithPropertiesMask) { std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = true; @@ -3265,7 +3265,7 @@ TEST_F(FormStructureTestImpl, EncodeUploadRequest_ObservedSubmissionFalse) { std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = true; @@ -3343,7 +3343,7 @@ TEST_F(FormStructureTestImpl, EncodeUploadRequest_WithLabels) { std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = true; @@ -3416,7 +3416,7 @@ TEST_F(FormStructureTestImpl, EncodeUploadRequest_WithSubForms) { std::unique_ptr<FormStructure> form_structure; std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.host_frame = test::MakeLocalFrameToken(); form.url = GURL("http://www.foo.com/"); @@ -3581,7 +3581,7 @@ fs_field->host_form_signature = form_structure.form_signature(); std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; for (size_t i = 0; i < form_structure.field_count(); ++i) { test::InitializePossibleTypesAndValidities( @@ -3803,7 +3803,7 @@ // Check that multiple types for the field are processed correctly. std::vector<FieldTypeSet> possible_field_types; - std::vector<ServerFieldTypeValidityStatesMap> possible_field_types_validities; + std::vector<FieldTypeValidityStatesMap> possible_field_types_validities; FormData form; form.url = GURL("http://www.foo.com/"); form.is_form_tag = false;
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map.cc b/components/autofill/core/browser/geo/alternative_state_name_map.cc index ed22752..8df7532 100644 --- a/components/autofill/core/browser/geo/alternative_state_name_map.cc +++ b/components/autofill/core/browser/geo/alternative_state_name_map.cc
@@ -37,7 +37,7 @@ } // static -absl::optional<AlternativeStateNameMap::CanonicalStateName> +std::optional<AlternativeStateNameMap::CanonicalStateName> AlternativeStateNameMap::GetCanonicalStateName( const std::string& country_code, const std::u16string& state_name) { @@ -48,7 +48,7 @@ AlternativeStateNameMap::AlternativeStateNameMap() = default; -absl::optional<AlternativeStateNameMap::CanonicalStateName> +std::optional<AlternativeStateNameMap::CanonicalStateName> AlternativeStateNameMap::GetCanonicalStateName( const CountryCode& country_code, const StateName& state_name, @@ -78,15 +78,15 @@ if (it != localized_state_names_reverse_lookup_map_.end()) return it->second; - return absl::nullopt; + return std::nullopt; } -absl::optional<StateEntry> AlternativeStateNameMap::GetEntry( +std::optional<StateEntry> AlternativeStateNameMap::GetEntry( const CountryCode& country_code, const StateName& state_string_from_profile) const { StateName normalized_state_string_from_profile = NormalizeStateName(state_string_from_profile); - absl::optional<CanonicalStateName> canonical_state_name = + std::optional<CanonicalStateName> canonical_state_name = GetCanonicalStateName(country_code, normalized_state_string_from_profile, /*is_state_name_normalized=*/true); @@ -98,7 +98,7 @@ return it->second; } - return absl::nullopt; + return std::nullopt; } void AlternativeStateNameMap::AddEntry(
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map.h b/components/autofill/core/browser/geo/alternative_state_name_map.h index b4ff808e..c1e48ee8 100644 --- a/components/autofill/core/browser/geo/alternative_state_name_map.h +++ b/components/autofill/core/browser/geo/alternative_state_name_map.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_ALTERNATIVE_STATE_NAME_MAP_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_ALTERNATIVE_STATE_NAME_MAP_H_ +#include <optional> #include <string> #include "base/i18n/case_conversion.h" @@ -13,7 +14,6 @@ #include "base/thread_annotations.h" #include "base/types/strong_alias.h" #include "components/autofill/core/browser/proto/states.pb.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -89,7 +89,7 @@ // Calls |GetCanonicalStateName()| member method of AlternativeStateNameMap // and returns the canonical state name corresponding to |country_code| and // |state_name| if present. - static absl::optional<AlternativeStateNameMap::CanonicalStateName> + static std::optional<AlternativeStateNameMap::CanonicalStateName> GetCanonicalStateName(const std::string& country_code, const std::u16string& state_name); @@ -102,15 +102,15 @@ // (|country_code|, |state_name|). // |is_state_name_normalized| denotes whether the |state_name| has been // normalized or not. - absl::optional<CanonicalStateName> GetCanonicalStateName( + std::optional<CanonicalStateName> GetCanonicalStateName( const CountryCode& country_code, const StateName& state_name, bool is_state_name_normalized = false) const; // Returns the value present in |localized_state_names_map_| corresponding // to (|country_code|, |state_string_from_profile|). In case, the entry does - // not exist in the map, absl::nullopt is returned. - absl::optional<StateEntry> GetEntry( + // not exist in the map, std::nullopt is returned. + std::optional<StateEntry> GetEntry( const CountryCode& country_code, const StateName& state_string_from_profile) const;
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc b/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc index be9f7969..996db24 100644 --- a/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc +++ b/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc
@@ -31,15 +31,15 @@ SCOPED_TRACE(valid_match); EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName( "DE", base::ASCIIToUTF16(valid_match)), - absl::nullopt); + std::nullopt); } EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName("US", u"Bavaria"), - absl::nullopt); + std::nullopt); EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName("DE", u""), - absl::nullopt); + std::nullopt); EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName("", u""), - absl::nullopt); + std::nullopt); } // Tests that the separate entries are created in the map for the different @@ -49,9 +49,9 @@ test::PopulateAlternativeStateNameMapForTesting("DE"); test::PopulateAlternativeStateNameMapForTesting("US"); EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName("DE", u"Bavaria"), - absl::nullopt); + std::nullopt); EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName("US", u"Bavaria"), - absl::nullopt); + std::nullopt); } // Tests that |AlternativeStateNameMap::NormalizeStateName()| removes "-", " " @@ -84,11 +84,11 @@ EXPECT_EQ(alternative_state_name_map->GetEntry( AlternativeStateNameMap::CountryCode("DE"), AlternativeStateNameMap::StateName(u"Random")), - absl::nullopt); + std::nullopt); auto entry = alternative_state_name_map->GetEntry( AlternativeStateNameMap::CountryCode("DE"), AlternativeStateNameMap::StateName(u"Bavaria")); - EXPECT_NE(entry, absl::nullopt); + EXPECT_NE(entry, std::nullopt); ASSERT_TRUE(entry->has_canonical_name()); EXPECT_EQ(entry->canonical_name(), "Bavaria"); EXPECT_THAT(entry->abbreviations(),
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc b/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc index e75ab01..f619f63 100644 --- a/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc +++ b/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc
@@ -3,6 +3,9 @@ // found in the LICENSE file. #include "components/autofill/core/browser/geo/alternative_state_name_map_updater.h" + +#include <optional> + #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -23,7 +26,6 @@ #include "components/prefs/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" using base::ASCIIToUTF16; using base::UTF8ToUTF16; @@ -98,7 +100,7 @@ for (size_t i = 0; i < test_strings.size(); i++) { SCOPED_TRACE(test_strings[i]); EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName( - "DE", test_strings[i].value()) != absl::nullopt, + "DE", test_strings[i].value()) != std::nullopt, state_data_present[i]); } } @@ -121,7 +123,7 @@ run_loop.Run(); EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName("DE", u"Bavaria"), - absl::nullopt); + std::nullopt); } // Tests that there is no insertion in the AlternativeStateNameMap when a @@ -170,22 +172,22 @@ run_loop.QuitClosure()); run_loop.Run(); - absl::optional<StateEntry> entry1 = + std::optional<StateEntry> entry1 = AlternativeStateNameMap::GetInstance()->GetEntry( AlternativeStateNameMap::CountryCode("ES"), AlternativeStateNameMap::StateName(u"Paraná")); - EXPECT_NE(entry1, absl::nullopt); + EXPECT_NE(entry1, std::nullopt); EXPECT_EQ(entry1->canonical_name(), "Paraná"); EXPECT_THAT(entry1->abbreviations(), testing::UnorderedElementsAreArray({"PR"})); EXPECT_THAT(entry1->alternative_names(), testing::UnorderedElementsAreArray( {"Parana", "State of Parana"})); - absl::optional<StateEntry> entry2 = + std::optional<StateEntry> entry2 = AlternativeStateNameMap::GetInstance()->GetEntry( AlternativeStateNameMap::CountryCode("ES"), AlternativeStateNameMap::StateName(u"Parana")); - EXPECT_NE(entry2, absl::nullopt); + EXPECT_NE(entry2, std::nullopt); EXPECT_EQ(entry2->canonical_name(), "Paraná"); EXPECT_THAT(entry2->abbreviations(), testing::UnorderedElementsAreArray({"PR"})); @@ -222,22 +224,22 @@ run_loop.QuitClosure()); run_loop.Run(); - absl::optional<StateEntry> entry1 = + std::optional<StateEntry> entry1 = AlternativeStateNameMap::GetInstance()->GetEntry( AlternativeStateNameMap::CountryCode("ES"), AlternativeStateNameMap::StateName(u"Paraná")); - EXPECT_NE(entry1, absl::nullopt); + EXPECT_NE(entry1, std::nullopt); EXPECT_EQ(entry1->canonical_name(), "Paraná"); EXPECT_THAT(entry1->abbreviations(), testing::UnorderedElementsAreArray({"PR"})); EXPECT_THAT(entry1->alternative_names(), testing::UnorderedElementsAreArray( {"Parana", "State of Parana"})); - absl::optional<StateEntry> entry2 = + std::optional<StateEntry> entry2 = AlternativeStateNameMap::GetInstance()->GetEntry( AlternativeStateNameMap::CountryCode("DE"), AlternativeStateNameMap::StateName(u"Bavaria")); - EXPECT_NE(entry2, absl::nullopt); + EXPECT_NE(entry2, std::nullopt); EXPECT_EQ(entry2->canonical_name(), "Bavaria"); EXPECT_THAT(entry2->abbreviations(), testing::UnorderedElementsAreArray({"BY"}));
diff --git a/components/autofill/core/browser/geo/autofill_country.cc b/components/autofill/core/browser/geo/autofill_country.cc index 86c2afa..a37c662 100644 --- a/components/autofill/core/browser/geo/autofill_country.cc +++ b/components/autofill/core/browser/geo/autofill_country.cc
@@ -82,7 +82,7 @@ } // namespace AutofillCountry::AutofillCountry(const std::string& country_code, - const absl::optional<std::string>& locale) { + const std::optional<std::string>& locale) { CountryDataMap* country_data_map = CountryDataMap::GetInstance(); // If the country code is an alias (e.g. "GB" for "UK") expand the country
diff --git a/components/autofill/core/browser/geo/autofill_country.h b/components/autofill/core/browser/geo/autofill_country.h index b89bfbaa..3fa6d062 100644 --- a/components/autofill/core/browser/geo/autofill_country.h +++ b/components/autofill/core/browser/geo/autofill_country.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_AUTOFILL_COUNTRY_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_AUTOFILL_COUNTRY_H_ +#include <optional> #include <string> #include <string_view> @@ -13,7 +14,6 @@ #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/geo/country_data.h" #include "components/autofill/core/common/autofill_features.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h" namespace autofill { @@ -30,7 +30,7 @@ // if the name is not queried. explicit AutofillCountry( const std::string& country_code, - const absl::optional<std::string>& locale = absl::nullopt); + const std::optional<std::string>& locale = std::nullopt); AutofillCountry(const AutofillCountry&) = delete; AutofillCountry& operator=(const AutofillCountry&) = delete;
diff --git a/components/autofill/core/browser/heuristic_classification_unittests.cc b/components/autofill/core/browser/heuristic_classification_unittests.cc index 3e46555c..a4573a0 100644 --- a/components/autofill/core/browser/heuristic_classification_unittests.cc +++ b/components/autofill/core/browser/heuristic_classification_unittests.cc
@@ -499,7 +499,7 @@ ASSERT_TRUE(base::ReadFileToString(input_file, &input_json_text)); // Convert to JSON dictionary. - absl::optional<base::Value> opt_json_file = + std::optional<base::Value> opt_json_file = base::JSONReader::Read(input_json_text); ASSERT_TRUE(opt_json_file); base::Value::Dict* json_file = opt_json_file->GetIfDict(); @@ -538,7 +538,8 @@ // Other improvements. features::kAutofillEnableZipOnlyAddressForms, features::kAutofillDefaultToCityAndNumber, - features::kAutofillPreferLabelsInSomeCountries}; + features::kAutofillPreferLabelsInSomeCountries, + features::kAutofillEnableCacheForRegexMatching}; std::vector<base::test::FeatureRef> disabled_features = {}; auto init_feature_to_value = [&](base::test::FeatureRef feature, bool value) { @@ -590,7 +591,7 @@ std::string new_stats = SummarizeStatistics(*json_file); // Serialize the result. - absl::optional<std::string> output_json_text = + std::optional<std::string> output_json_text = base::WriteJsonWithOptions(*opt_json_file, base::OPTIONS_PRETTY_PRINT); ASSERT_TRUE(output_json_text);
diff --git a/components/autofill/core/browser/heuristic_source.cc b/components/autofill/core/browser/heuristic_source.cc index d772c95d..5f8d82e 100644 --- a/components/autofill/core/browser/heuristic_source.cc +++ b/components/autofill/core/browser/heuristic_source.cc
@@ -52,7 +52,7 @@ return sources; } -absl::optional<PatternSource> HeuristicSourceToPatternSource( +std::optional<PatternSource> HeuristicSourceToPatternSource( HeuristicSource source) { switch (source) { case HeuristicSource::kLegacy: @@ -66,7 +66,7 @@ return PatternSource::kNextGen; #endif case autofill::HeuristicSource::kMachineLearning: - return absl::nullopt; + return std::nullopt; } NOTREACHED_NORETURN(); }
diff --git a/components/autofill/core/browser/heuristic_source.h b/components/autofill/core/browser/heuristic_source.h index 88ec2a4..90bec6ba9 100644 --- a/components/autofill/core/browser/heuristic_source.h +++ b/components/autofill/core/browser/heuristic_source.h
@@ -43,7 +43,7 @@ // Converts a `HeuristicSource` to `PatternSource`. If the passed // source is not a `PatternSource` then a nullopt is returned. -absl::optional<PatternSource> HeuristicSourceToPatternSource( +std::optional<PatternSource> HeuristicSourceToPatternSource( HeuristicSource source); HeuristicSource PatternSourceToHeuristicSource(PatternSource source);
diff --git a/components/autofill/core/browser/heuristic_source_unittest.cc b/components/autofill/core/browser/heuristic_source_unittest.cc index ef3ce653..6bd5a559 100644 --- a/components/autofill/core/browser/heuristic_source_unittest.cc +++ b/components/autofill/core/browser/heuristic_source_unittest.cc
@@ -24,8 +24,8 @@ // as the active heuristic source. struct HeuristicSourceParams { - absl::optional<bool> model_predictions_feature; - absl::optional<std::string> pattern_provider_feature; + std::optional<bool> model_predictions_feature; + std::optional<std::string> pattern_provider_feature; const HeuristicSource expected_active_source; const DenseSet<HeuristicSource> expected_nonactive_sources; };
diff --git a/components/autofill/core/browser/logging/log_buffer_submitter.cc b/components/autofill/core/browser/logging/log_buffer_submitter.cc index 432ae63..1b818e6 100644 --- a/components/autofill/core/browser/logging/log_buffer_submitter.cc +++ b/components/autofill/core/browser/logging/log_buffer_submitter.cc
@@ -31,7 +31,7 @@ LogBufferSubmitter::~LogBufferSubmitter() { if (!destruct_with_logging_ || !log_manager_) return; - absl::optional<base::Value::Dict> message = buffer_.RetrieveResult(); + std::optional<base::Value::Dict> message = buffer_.RetrieveResult(); if (!message) return; log_manager_->ProcessLog(std::move(*message), {});
diff --git a/components/autofill/core/browser/logging/log_buffer_submitter_unittest.cc b/components/autofill/core/browser/logging/log_buffer_submitter_unittest.cc index 92b97a8..1f020cd4 100644 --- a/components/autofill/core/browser/logging/log_buffer_submitter_unittest.cc +++ b/components/autofill/core/browser/logging/log_buffer_submitter_unittest.cc
@@ -26,7 +26,7 @@ TEST(LogBufferSubmitter, VerifySubmissionOnDestruction) { LogBuffer buffer; buffer << 42; - absl::optional<base::Value::Dict> expected = buffer.RetrieveResult(); + std::optional<base::Value::Dict> expected = buffer.RetrieveResult(); MockLogReceiver receiver; LogRouter router;
diff --git a/components/autofill/core/browser/logging/log_manager.cc b/components/autofill/core/browser/logging/log_manager.cc index 86a6d1d01..f5260648 100644 --- a/components/autofill/core/browser/logging/log_manager.cc +++ b/components/autofill/core/browser/logging/log_manager.cc
@@ -114,7 +114,7 @@ private: std::vector<base::Value::Dict> nodes_; - absl::optional<base::PassKey<LogBufferSubmitter>> pass_key_; + std::optional<base::PassKey<LogBufferSubmitter>> pass_key_; }; void BufferingLogManagerImpl::Flush(LogManager& destination) {
diff --git a/components/autofill/core/browser/logging/text_log_receiver_unittest.cc b/components/autofill/core/browser/logging/text_log_receiver_unittest.cc index 70ac7ab..ad6d06dc 100644 --- a/components/autofill/core/browser/logging/text_log_receiver_unittest.cc +++ b/components/autofill/core/browser/logging/text_log_receiver_unittest.cc
@@ -10,7 +10,7 @@ namespace autofill { TEST(TextLogReceiver, IntegrationTest) { - absl::optional<base::Value> input = base::JSONReader::Read( + std::optional<base::Value> input = base::JSONReader::Read( R"( { "type": "element",
diff --git a/components/autofill/core/browser/manual_testing_import.cc b/components/autofill/core/browser/manual_testing_import.cc index 8e441c1..c2cb910 100644 --- a/components/autofill/core/browser/manual_testing_import.cc +++ b/components/autofill/core/browser/manual_testing_import.cc
@@ -28,15 +28,15 @@ namespace { // Util struct for storing the list of profiles and credit cards to be imported. -// If any of `profiles` or `credit_cards` are absl::nullopt, then the data used +// If any of `profiles` or `credit_cards` are std::nullopt, then the data used // for import is malformed, and this will cause a crash. // When any of `profiles` or `credit_cards` is empty, it means that the JSON // file used for import did not include the corresponding key. It'll be treated // as valid but won't be imported so that existing data in the PDM isn't // cleared without replacement. struct AutofillProfilesAndCreditCards { - absl::optional<std::vector<AutofillProfile>> profiles; - absl::optional<std::vector<CreditCard>> credit_cards; + std::optional<std::vector<AutofillProfile>> profiles; + std::optional<std::vector<CreditCard>> credit_cards; }; constexpr std::string_view kKeyProfiles = "profiles"; @@ -64,8 +64,8 @@ // Extracts the `kKeySource` value of the `dict` and translates it into an // AutofillProfile::Source. If no source is present, Source::kLocalOrSyncable is // returned. If a source with invalid value is specified, an error message is -// logged and absl::nullopt is returned. -absl::optional<AutofillProfile::Source> GetProfileSourceFromDict( +// logged and std::nullopt is returned. +std::optional<AutofillProfile::Source> GetProfileSourceFromDict( const base::Value::Dict& dict) { if (!dict.contains(kKeySource)) { return AutofillProfile::Source::kLocalOrSyncable; @@ -77,7 +77,7 @@ } } LOG(ERROR) << "Invalid " << kKeySource << " value."; - return absl::nullopt; + return std::nullopt; } // Given a `dict` of "field-type" : "value" mappings, constructs an @@ -86,12 +86,12 @@ // `kUserVerified` is problematic, since the data model expects that only root // level (= setting-visible) nodes are user verified. // If a field type cannot be mapped, or if the resulting profile is not -// `IsFullyStructuredProfile()`, absl::nullopt is returned. -absl::optional<AutofillProfile> MakeProfile(const base::Value::Dict& dict) { - absl::optional<AutofillProfile::Source> source = +// `IsFullyStructuredProfile()`, std::nullopt is returned. +std::optional<AutofillProfile> MakeProfile(const base::Value::Dict& dict) { + std::optional<AutofillProfile::Source> source = GetProfileSourceFromDict(dict); if (!source.has_value()) { - return absl::nullopt; + return std::nullopt; } const std::string* country_code = dict.FindString(FieldTypeToStringView(ADDRESS_HOME_COUNTRY)); @@ -105,18 +105,18 @@ continue; } if (key == kKeyInitialCreatorId) { - if (const absl::optional<int> creator_id = dict.FindInt(key)) { + if (const std::optional<int> creator_id = dict.FindInt(key)) { profile.set_initial_creator_id(*creator_id); continue; } else { LOG(ERROR) << "Incorrect value for " << key << "."; - return absl::nullopt; + return std::nullopt; } } const FieldType type = TypeNameToFieldType(key); if (type == UNKNOWN_TYPE || !IsAddressType(type)) { LOG(ERROR) << "Unknown or non-address type " << key << "."; - return absl::nullopt; + return std::nullopt; } profile.SetRawInfoWithVerificationStatus( type, base::UTF8ToUTF16(value.GetString()), @@ -124,12 +124,12 @@ } if (!IsFullyStructuredProfile(profile)) { LOG(ERROR) << "Some profile is not fully structured."; - return absl::nullopt; + return std::nullopt; } return profile; } -absl::optional<CreditCard> MakeCard(const base::Value::Dict& dict) { +std::optional<CreditCard> MakeCard(const base::Value::Dict& dict) { CreditCard card; // `dict` is a dictionary of std::string -> base::Value. for (const auto [key, value] : dict) { @@ -139,15 +139,15 @@ } const FieldType type = TypeNameToFieldType(key); if (type == UNKNOWN_TYPE || - GroupTypeOfServerFieldType(type) != FieldTypeGroup::kCreditCard) { + GroupTypeOfFieldType(type) != FieldTypeGroup::kCreditCard) { LOG(ERROR) << "Unknown or non-credit card type " << key << "."; - return absl::nullopt; + return std::nullopt; } card.SetRawInfo(type, base::UTF8ToUTF16(value.GetString())); } if (!card.IsValid()) { LOG(ERROR) << "Some credit card is not valid."; - return absl::nullopt; + return std::nullopt; } return card; } @@ -168,7 +168,7 @@ // `credit_cards`, if the `pdm` still exists. void SetData( base::WeakPtr<PersonalDataManager> pdm, - absl::optional<AutofillProfilesAndCreditCards> profiles_or_credit_cards) { + std::optional<AutofillProfilesAndCreditCards> profiles_or_credit_cards) { // This check intentionally crashes when the data is malformed, to prevent // testing with incorrect data. LOG_IF(FATAL, !profiles_or_credit_cards.has_value() || @@ -194,9 +194,9 @@ // Converts all `entries of `json_array` to a vector of Ts using // `to_data_model`. In case any conversion fails, nullopt is returned. template <class T> -absl::optional<std::vector<T>> DataModelsFromJSON( +std::optional<std::vector<T>> DataModelsFromJSON( const base::Value::List* const json_array, - base::RepeatingCallback<absl::optional<T>(const base::Value::Dict&)> + base::RepeatingCallback<std::optional<T>(const base::Value::Dict&)> to_data_model) { if (!json_array) { return std::vector<T>{}; @@ -205,11 +205,11 @@ for (const base::Value& json : *json_array) { if (!json.is_dict()) { LOG(ERROR) << "Description is not a dictionary."; - return absl::nullopt; + return std::nullopt; } - absl::optional<T> data_model = to_data_model.Run(json.GetDict()); + std::optional<T> data_model = to_data_model.Run(json.GetDict()); if (!data_model.has_value()) { - return absl::nullopt; + return std::nullopt; } data_models.push_back(std::move(*data_model)); } @@ -218,17 +218,17 @@ } // Parses AutofillProfiles from the JSON `content` string. -// If parsing fails the error is logged and absl::nullopt is returned. -absl::optional<AutofillProfilesAndCreditCards> LoadDataFromJSONContent( +// If parsing fails the error is logged and std::nullopt is returned. +std::optional<AutofillProfilesAndCreditCards> LoadDataFromJSONContent( const std::string& file_content) { - absl::optional<base::Value> json = base::JSONReader::Read(file_content); + std::optional<base::Value> json = base::JSONReader::Read(file_content); if (!json.has_value()) { LOG(ERROR) << "Failed to parse JSON file."; - return absl::nullopt; + return std::nullopt; } if (!json->is_dict()) { LOG(ERROR) << "JSON is not a dictionary at it's top level."; - return absl::nullopt; + return std::nullopt; } const base::Value::List* const profiles_json = json->GetDict().FindList(kKeyProfiles); @@ -237,49 +237,49 @@ if (!cards_json && !profiles_json) { LOG(ERROR) << "JSON has no " << kKeyProfiles << " or " << kKeyCreditCards << " keys."; - return absl::nullopt; + return std::nullopt; } return AutofillProfilesAndCreditCards{ .profiles = AutofillProfilesFromJSON(profiles_json), .credit_cards = CreditCardsFromJSON(cards_json)}; } -absl::optional<AutofillProfilesAndCreditCards> LoadDataFromFile( +std::optional<AutofillProfilesAndCreditCards> LoadDataFromFile( base::FilePath file) { std::string file_content; if (!base::ReadFileToString(file, &file_content)) { LOG(ERROR) << "Failed to read file " << file.MaybeAsASCII() << "."; - return absl::nullopt; + return std::nullopt; } return LoadDataFromJSONContent(file_content); } } // namespace -absl::optional<std::vector<AutofillProfile>> LoadProfilesFromFile( +std::optional<std::vector<AutofillProfile>> LoadProfilesFromFile( base::FilePath file) { - if (absl::optional<AutofillProfilesAndCreditCards> profiles_and_credit_cards = + if (std::optional<AutofillProfilesAndCreditCards> profiles_and_credit_cards = LoadDataFromFile(file)) { return profiles_and_credit_cards->profiles; } - return absl::nullopt; + return std::nullopt; } -absl::optional<std::vector<CreditCard>> LoadCreditCardsFromFile( +std::optional<std::vector<CreditCard>> LoadCreditCardsFromFile( base::FilePath file) { - if (absl::optional<AutofillProfilesAndCreditCards> profiles_and_credit_cards = + if (std::optional<AutofillProfilesAndCreditCards> profiles_and_credit_cards = LoadDataFromFile(file)) { return profiles_and_credit_cards->credit_cards; } - return absl::nullopt; + return std::nullopt; } -absl::optional<std::vector<AutofillProfile>> AutofillProfilesFromJSON( +std::optional<std::vector<AutofillProfile>> AutofillProfilesFromJSON( const base::Value::List* const profiles_json) { return DataModelsFromJSON(profiles_json, base::BindRepeating(&MakeProfile)); } -absl::optional<std::vector<CreditCard>> CreditCardsFromJSON( +std::optional<std::vector<CreditCard>> CreditCardsFromJSON( const base::Value::List* const cards_json) { return DataModelsFromJSON(cards_json, base::BindRepeating(&MakeCard)); }
diff --git a/components/autofill/core/browser/manual_testing_import.h b/components/autofill/core/browser/manual_testing_import.h index f0666182..52adbc0 100644 --- a/components/autofill/core/browser/manual_testing_import.h +++ b/components/autofill/core/browser/manual_testing_import.h
@@ -5,13 +5,13 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_MANUAL_TESTING_IMPORT_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_MANUAL_TESTING_IMPORT_H_ +#include <optional> #include <vector> #include "base/memory/weak_ptr.h" #include "base/values.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/personal_data_manager.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -61,34 +61,34 @@ // Reads the contents of `file`, parses it as a JSON file and converts its // content into a list of AutofillProfiles. -// If any step fails, an error message is logged and absl::nullopt is returned. -absl::optional<std::vector<AutofillProfile>> LoadProfilesFromFile( +// If any step fails, an error message is logged and std::nullopt is returned. +std::optional<std::vector<AutofillProfile>> LoadProfilesFromFile( base::FilePath file); // Reads the contents of `file`, parses it as a JSON file and converts its // content into a list of CreditCards. -// If any step fails, an error message is logged and absl::nullopt is returned. -absl::optional<std::vector<CreditCard>> LoadCreditCardsFromFile( +// If any step fails, an error message is logged and std::nullopt is returned. +std::optional<std::vector<CreditCard>> LoadCreditCardsFromFile( base::FilePath file); // Given the array of descriptions of fully structured profiles in the // aforementioned JSON format, converts it to a vector of AutofillProfiles. // If the JSON list doesn't adhere to the above format, or if any of the -// profiles is not fully structured, an error is logged and absl::nullopt is +// profiles is not fully structured, an error is logged and std::nullopt is // returned. A profile is considered "fully structured" if // `FinalizeAfterImport()` doesn't change it. This condition exists to prevent // profiles from silently changing, since `FinalizeAfterImport()` is called when // retrieving a profile from the database. For example, if the structure is // invalid because the last name is not part of the full name, the routine will // clear this information. -absl::optional<std::vector<AutofillProfile>> AutofillProfilesFromJSON( +std::optional<std::vector<AutofillProfile>> AutofillProfilesFromJSON( const base::Value::List* const profiles_json); // Given the array of valid credit cards in the aforementioned JSON format, // converts it to a vector of CreditCards. // If the JSON list doesn't adhere to the above format, an error message is -// logged and absl::nullopt is returned. -absl::optional<std::vector<CreditCard>> CreditCardsFromJSON( +// logged and std::nullopt is returned. +std::optional<std::vector<CreditCard>> CreditCardsFromJSON( const base::Value::List* const cards_json); // Checks if the `kManualImportForTestingFlag` flag is present. If so,
diff --git a/components/autofill/core/browser/manual_testing_import_unittest.cc b/components/autofill/core/browser/manual_testing_import_unittest.cc index 4fb66ef..ae956c46 100644 --- a/components/autofill/core/browser/manual_testing_import_unittest.cc +++ b/components/autofill/core/browser/manual_testing_import_unittest.cc
@@ -8,6 +8,7 @@ #include "components/autofill/core/browser/country_type.h" #include "components/autofill/core/browser/manual_testing_import.h" +#include <optional> #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -19,7 +20,6 @@ #include "components/autofill/core/common/autofill_features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -366,7 +366,7 @@ ADDRESS_HOME_STREET_NAME, u"street", VerificationStatus::kObserved); expected_profile2.SetRawInfoWithVerificationStatus( ADDRESS_HOME_HOUSE_NUMBER, u"123", VerificationStatus::kObserved); - absl::optional<std::vector<AutofillProfile>> loaded_profiles = + std::optional<std::vector<AutofillProfile>> loaded_profiles = LoadProfilesFromFile(file_path); EXPECT_THAT(loaded_profiles, testing::Optional(testing::Pointwise( DataModelsCompareEqual(),
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc index 19ad8f4..9e9d50c 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -158,7 +158,7 @@ DCHECK_LT(metric, AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); FieldTypeGroupForMetrics group = GROUP_AMBIGUOUS; - switch (GroupTypeOfServerFieldType(field_type)) { + switch (GroupTypeOfFieldType(field_type)) { case FieldTypeGroup::kNoGroup: group = GROUP_AMBIGUOUS; break; @@ -746,13 +746,6 @@ const int kMaxBucketsCount = 50; // static -void AutofillMetrics::LogProfileSuggestionsMadeWithFormatter( - bool made_with_formatter) { - UMA_HISTOGRAM_BOOLEAN("Autofill.ProfileSuggestionsMadeWithFormatter", - made_with_formatter); -} - -// static void AutofillMetrics::LogSubmittedCardStateMetric( SubmittedCardStateMetric metric) { DCHECK_LT(metric, NUM_SUBMITTED_CARD_STATE_METRICS); @@ -2823,7 +2816,7 @@ bool suggestion_filled, const FormInteractionCounts& form_interaction_counts, const FormInteractionsFlowId& flow_id, - absl::optional<int64_t> fast_checkout_run_id) { + std::optional<int64_t> fast_checkout_run_id) { if (!CanLog()) return;
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.h b/components/autofill/core/browser/metrics/autofill_metrics.h index a7c9722..6a7ce14 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics.h +++ b/components/autofill/core/browser/metrics/autofill_metrics.h
@@ -776,7 +776,7 @@ bool suggestion_filled, const FormInteractionCounts& form_interaction_counts, const FormInteractionsFlowId& flow_id, - absl::optional<int64_t> fast_checkout_run_id); + std::optional<int64_t> fast_checkout_run_id); void LogFormEvent(autofill_metrics::FormEvent form_event, const DenseSet<FormType>& form_types, const base::TimeTicks& form_parsed_timestamp); @@ -813,7 +813,7 @@ raw_ptr<AutofillClient> autofill_client_; raw_ptr<ukm::UkmRecorder> ukm_recorder_; - absl::optional<ukm::SourceId> source_id_; + std::optional<ukm::SourceId> source_id_; base::TimeTicks pinned_timestamp_; }; @@ -867,11 +867,6 @@ AutofillMetrics(const AutofillMetrics&) = delete; AutofillMetrics& operator=(const AutofillMetrics&) = delete; - // When the autofill-use-improved-label-disambiguation experiment is enabled - // and suggestions are available, records if a LabelFormatter successfully - // created the suggestions. - static void LogProfileSuggestionsMadeWithFormatter(bool made_with_formatter); - static void LogSubmittedCardStateMetric(SubmittedCardStateMetric metric); // If a credit card that matches a server card (unmasked or not) was submitted
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc index 2c4d67b..c5ee169 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc
@@ -146,7 +146,7 @@ ->AllowFidoRegistration(true); access_manager.is_authentication_in_progress_ = false; access_manager.can_fetch_unmask_details_ = true; - access_manager.is_user_verifiable_ = absl::nullopt; + access_manager.is_user_verifiable_ = std::nullopt; } void AutofillMetricsBaseTest::OnDidGetRealPan(
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc index 9d08702..0bd3958 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -337,7 +337,7 @@ struct Field { FieldType field_type; bool is_autofilled = true; - absl::optional<std::u16string> value = absl::nullopt; + std::optional<std::u16string> value = std::nullopt; }; struct PerfectFillingTestCase {
diff --git a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h index 79c561acd..152b08a 100644 --- a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h +++ b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h
@@ -92,7 +92,7 @@ return flow_id_; } - const absl::optional<int64_t> fast_checkout_run_id_for_test() const { + const std::optional<int64_t> fast_checkout_run_id_for_test() const { return fast_checkout_run_id_; } @@ -194,7 +194,7 @@ bool is_heuristic_only_email_form_ = false; AblationGroup ablation_group_ = AblationGroup::kDefault; AblationGroup conditional_ablation_group_ = AblationGroup::kDefault; - absl::optional<base::TimeDelta> time_from_interaction_to_submission_; + std::optional<base::TimeDelta> time_from_interaction_to_submission_; // The last field that was polled for suggestions. FormFieldData last_polled_field_; @@ -208,7 +208,7 @@ // during the flow. FormInteractionsFlowId flow_id_; // Unique ID of a Fast Checkout run. Used for metrics. - absl::optional<int64_t> fast_checkout_run_id_; + std::optional<int64_t> fast_checkout_run_id_; // Form types of the submitted form. DenseSet<FormType> submitted_form_types_;
diff --git a/components/autofill/core/browser/ml_model/autofill_ml_prediction_model_handler.cc b/components/autofill/core/browser/ml_model/autofill_ml_prediction_model_handler.cc index ce116cc1..7331df2 100644 --- a/components/autofill/core/browser/ml_model/autofill_ml_prediction_model_handler.cc +++ b/components/autofill/core/browser/ml_model/autofill_ml_prediction_model_handler.cc
@@ -31,10 +31,10 @@ base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::USER_VISIBLE}), std::make_unique<AutofillModelExecutor>(), - /*model_inference_timeout=*/absl::nullopt, + /*model_inference_timeout=*/std::nullopt, optimization_guide::proto::OptimizationTarget:: OPTIMIZATION_TARGET_AUTOFILL_FIELD_CLASSIFICATION, - /*model_metadata=*/absl::nullopt) { + /*model_metadata=*/std::nullopt) { // Store the model in memory as soon as it is available and keep it loaded for // the whole browser session since we query predictions very regularly. // TODO(crbug.com/1465926): Maybe change both back to default behavior if we @@ -60,12 +60,10 @@ [](base::WeakPtr<AutofillMlPredictionModelHandler> self, std::unique_ptr<FormStructure> form_structure, base::OnceCallback<void(std::unique_ptr<FormStructure>)> callback, - const absl::optional<AutofillModelExecutor::ModelOutput>& output) { - if (!self) { - return; + const std::optional<AutofillModelExecutor::ModelOutput>& output) { + if (self && output) { + self->AssignMostLikelyTypes(*form_structure, *output); } - CHECK(output); - self->AssignMostLikelyTypes(*form_structure, *output); std::move(callback).Run(std::move(form_structure)); }, weak_ptr_factory_.GetWeakPtr(), std::move(form_structure),
diff --git a/components/autofill/core/browser/ml_model/autofill_model_executor.cc b/components/autofill/core/browser/ml_model/autofill_model_executor.cc index 6b17dfc..30b1bf4 100644 --- a/components/autofill/core/browser/ml_model/autofill_model_executor.cc +++ b/components/autofill/core/browser/ml_model/autofill_model_executor.cc
@@ -74,7 +74,7 @@ return true; } -absl::optional<AutofillModelExecutor::ModelOutput> +std::optional<AutofillModelExecutor::ModelOutput> AutofillModelExecutor::Postprocess( const std::vector<const TfLiteTensor*>& output_tensors) { // `output_tensors` is a 3D vector of floats. The first dimension is used
diff --git a/components/autofill/core/browser/ml_model/autofill_model_executor.h b/components/autofill/core/browser/ml_model/autofill_model_executor.h index 87a36b0..15300490 100644 --- a/components/autofill/core/browser/ml_model/autofill_model_executor.h +++ b/components/autofill/core/browser/ml_model/autofill_model_executor.h
@@ -10,7 +10,6 @@ #include "components/autofill/core/browser/ml_model/autofill_model_vectorizer.h" #include "components/optimization_guide/core/base_model_executor.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -50,7 +49,7 @@ // optimization_guide::BaseModelExecutor: bool Preprocess(const std::vector<TfLiteTensor*>& input_tensors, const ModelInput& input) override; - absl::optional<ModelOutput> Postprocess( + std::optional<ModelOutput> Postprocess( const std::vector<const TfLiteTensor*>& output_tensors) override; // Stores the number of fields sent to the model via `Preprocess()`. This will
diff --git a/components/autofill/core/browser/ml_model/autofill_model_executor_unittest.cc b/components/autofill/core/browser/ml_model/autofill_model_executor_unittest.cc index 7a6c5ae2..939ab58 100644 --- a/components/autofill/core/browser/ml_model/autofill_model_executor_unittest.cc +++ b/components/autofill/core/browser/ml_model/autofill_model_executor_unittest.cc
@@ -45,7 +45,7 @@ {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); model_executor_ = std::make_unique<AutofillModelExecutor>(); model_executor_->InitializeAndMoveToExecutionThread( - /*model_inference_timeout=*/absl::nullopt, + /*model_inference_timeout=*/std::nullopt, optimization_guide::proto:: OPTIMIZATION_TARGET_AUTOFILL_FIELD_CLASSIFICATION, execution_task_runner_, base::SequencedTaskRunner::GetCurrentDefault()); @@ -79,7 +79,7 @@ {TokenId(1), TokenId(2), TokenId(3), TokenId(4), TokenId(5)}, {TokenId(2), TokenId(3), TokenId(4), TokenId(5), TokenId(6)}}; base::test::TestFuture< - const absl::optional<AutofillModelExecutor::ModelOutput>&> + const std::optional<AutofillModelExecutor::ModelOutput>&> predictions; execution_task_runner_->PostTask( FROM_HERE,
diff --git a/components/autofill/core/browser/payments/account_info_getter.h b/components/autofill/core/browser/payments/account_info_getter.h index 59a9f86..3655752 100644 --- a/components/autofill/core/browser/payments/account_info_getter.h +++ b/components/autofill/core/browser/payments/account_info_getter.h
@@ -15,7 +15,7 @@ // Returns the account info that should be used when communicating with the // Payments server. The AccountInfo could be empty if there is no account to // be used by the Payments server. - // TODO(crbug.com/1411720): Make it return absl::optional. + // TODO(crbug.com/1411720): Make it return std::optional. virtual CoreAccountInfo GetAccountInfoForPaymentsServer() const = 0; // Returns true - When user is both signed-in and enabled sync.
diff --git a/components/autofill/core/browser/payments/autofill_error_dialog_context.h b/components/autofill/core/browser/payments/autofill_error_dialog_context.h index 461d1a6..8a58a21 100644 --- a/components/autofill/core/browser/payments/autofill_error_dialog_context.h +++ b/components/autofill/core/browser/payments/autofill_error_dialog_context.h
@@ -5,10 +5,9 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_ERROR_DIALOG_CONTEXT_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_ERROR_DIALOG_CONTEXT_H_ +#include <optional> #include <string> -#include "third_party/abseil-cpp/absl/types/optional.h" - namespace autofill { // Keep in sync with `AutofillErrorDialogType` in enums.xml. @@ -60,14 +59,14 @@ // related to the error to the user. This should be preferred for the title of // the autofill error dialog if a value is present. The language is based on // the client's locale. - absl::optional<std::string> server_returned_title; + std::optional<std::string> server_returned_title; // Autofill error dialog description returned from the server. Present in // situations where the server returns an error, and wants to display a // detailed description related to the error to the user. This should be // preferred for the description of the autofill error dialog if a value is // present. The language is based on the client's locale. - absl::optional<std::string> server_returned_description; + std::optional<std::string> server_returned_description; }; } // namespace autofill
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc index 16ec9d8b..94ee944 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -79,7 +79,7 @@ if (auto* form_data_importer = client_->GetFormDataImporter()) { form_data_importer ->SetCardRecordTypeIfNonInteractiveAuthenticationFlowCompleted( - absl::nullopt); + std::nullopt); } } } @@ -253,7 +253,7 @@ // Set delay as fido request timeout if available, otherwise set to default. int delay_ms = kDelayForGetUnmaskDetails; if (unmask_details_.fido_request_options.has_value()) { - const absl::optional<int> request_timeout = + const std::optional<int> request_timeout = unmask_details_.fido_request_options->FindInt("timeout_millis"); if (request_timeout.has_value()) { delay_ms = *request_timeout; @@ -283,7 +283,7 @@ // autofill non-interactive flow successfully completes. client_->GetFormDataImporter() ->SetCardRecordTypeIfNonInteractiveAuthenticationFlowCompleted( - absl::nullopt); + std::nullopt); // Return error if authentication is already in progress, but don't reset // status. @@ -528,7 +528,7 @@ // UnmaskResponseDetails while for masked server cards, it comes from the // UnmaskDetails. base::Value::Dict fido_request_options; - absl::optional<std::string> context_token; + std::optional<std::string> context_token; if (card_->record_type() == CreditCard::RecordType::kVirtualCard) { context_token = virtual_card_unmask_response_details_.context_token; fido_request_options = std::move( @@ -653,7 +653,7 @@ unmask_auth_flow_type_ = UnmaskAuthFlowType::kNone; } else if (should_register_card_with_fido) { #if !BUILDFLAG(IS_IOS) - absl::optional<base::Value::Dict> request_options = absl::nullopt; + std::optional<base::Value::Dict> request_options = std::nullopt; if (unmask_details_.fido_request_options.has_value()) { // For opted-in user (CVC then FIDO case), request options are returned in // unmask detail response. @@ -1391,6 +1391,12 @@ : AutofillClient::PaymentsRpcCardType::kServerCard, autofill_metrics::ServerCardUnmaskFlowType::kRiskBased); + if (!card_->cvc().empty()) { + autofill_metrics::LogCvcFilling( + autofill_metrics::CvcFillingFlowType::kNoInteractiveAuthentication, + record_type); + } + // `OnCreditCardFetchedCallback` makes a copy of `card` and `cvc` before it // asynchronously fills them into the form. Thus we can safely call // `Reset()` here, and we should as from this class' point of view the @@ -1408,7 +1414,7 @@ card_selected_without_unmask_details_timestamp_.value()); autofill_metrics::LogUserPerceivedLatencyOnCardSelectionTimedOut( /*did_time_out=*/!get_unmask_details_returned); - card_selected_without_unmask_details_timestamp_ = absl::nullopt; + card_selected_without_unmask_details_timestamp_ = std::nullopt; } // Start the authentication after the wait ends. @@ -1506,9 +1512,9 @@ weak_ptr_factory_.InvalidateWeakPtrs(); unmask_auth_flow_type_ = UnmaskAuthFlowType::kNone; is_authentication_in_progress_ = false; - preflight_call_timestamp_ = absl::nullopt; - card_selected_without_unmask_details_timestamp_ = absl::nullopt; - is_user_verifiable_called_timestamp_ = absl::nullopt; + preflight_call_timestamp_ = std::nullopt; + card_selected_without_unmask_details_timestamp_ = std::nullopt; + is_user_verifiable_called_timestamp_ = std::nullopt; #if !BUILDFLAG(IS_IOS) opt_in_intention_ = UserOptInIntention::kUnspecified; #endif
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h index 94f9470..3dedfa02 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.h +++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -459,14 +459,14 @@ const raw_ptr<autofill_metrics::CreditCardFormEventLogger> form_event_logger_; // Timestamp used for preflight call metrics. - absl::optional<base::TimeTicks> preflight_call_timestamp_; + std::optional<base::TimeTicks> preflight_call_timestamp_; // Timestamp used for user-perceived latency metrics. - absl::optional<base::TimeTicks> + std::optional<base::TimeTicks> card_selected_without_unmask_details_timestamp_; // Timestamp for when fido_authenticator_->IsUserVerifiable() is called. - absl::optional<base::TimeTicks> is_user_verifiable_called_timestamp_; + std::optional<base::TimeTicks> is_user_verifiable_called_timestamp_; #if !BUILDFLAG(IS_IOS) std::unique_ptr<CreditCardFidoAuthenticator> fido_authenticator_; @@ -513,7 +513,7 @@ // Set to true only if user has a verifying platform authenticator. // e.g. Touch/Face ID, Windows Hello, Android fingerprint, etc., is available // and enabled. - absl::optional<bool> is_user_verifiable_; + std::optional<bool> is_user_verifiable_; // True only if currently waiting on unmask details. This avoids making // unnecessary calls to payments.
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc index 01a73feb..0c574599 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -205,7 +205,7 @@ credit_card_access_manager().is_authentication_in_progress_ = false; credit_card_access_manager().can_fetch_unmask_details_ = true; credit_card_access_manager().unmask_details_request_in_progress_ = false; - credit_card_access_manager().is_user_verifiable_ = absl::nullopt; + credit_card_access_manager().is_user_verifiable_ = std::nullopt; } void ClearCards() { personal_data().ClearCreditCards(); } @@ -957,7 +957,7 @@ // There was no interactive authentication in this flow, so check that this // is signaled correctly. - absl::optional<CreditCard::RecordType> card_identifier = + std::optional<CreditCard::RecordType> card_identifier = autofill_client_.GetFormDataImporter() ->GetCardRecordTypeIfNonInteractiveAuthenticationFlowCompleted(); ASSERT_TRUE(card_identifier.has_value()); @@ -2949,7 +2949,7 @@ // There was no interactive authentication in this flow, so check that this // is signaled correctly. - absl::optional<CreditCard::RecordType> card_identifier = + std::optional<CreditCard::RecordType> card_identifier = autofill_client_.GetFormDataImporter() ->GetCardRecordTypeIfNonInteractiveAuthenticationFlowCompleted(); ASSERT_TRUE(card_identifier.has_value()); @@ -3222,6 +3222,75 @@ .has_value()); } +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) + +// Ensures that CVC filling gets logged after masked server card risk-based +// unmasking success if the card has CVC. +TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest, + LogCvcFilling_RiskBasedMaskedServerCardUnmaskingSuccess) { + base::HistogramTester histogram_tester; + CreateServerCard(kTestGUID, kTestNumber, /*masked=*/true, kTestServerId); + CreditCard* masked_server_card = + personal_data().GetCreditCardByGUID(kTestGUID); + masked_server_card->set_cvc(kTestCvc16); + + credit_card_access_manager().FetchCreditCard( + masked_server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched, + accessor_->GetWeakPtr())); + + // Mock CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse to + // successfully return the valid card number. + CreditCard card = *masked_server_card; + card.set_record_type(CreditCard::RecordType::kFullServerCard); + // Mock that CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse + // indicates a green path with valid card number returned. + credit_card_access_manager().OnRiskBasedAuthenticationResponseReceived( + CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse() + .with_result(CreditCardRiskBasedAuthenticator:: + RiskBasedAuthenticationResponse::Result:: + kNoAuthenticationRequired) + .with_card(card)); + + // Expect the metrics are logged correctly. + histogram_tester.ExpectUniqueSample( + "Autofill.CvcStorage.CvcFilling.ServerCard", + autofill_metrics::CvcFillingFlowType::kNoInteractiveAuthentication, 1); +} + +// Ensures that CVC filling doesn't get logged after after masked server card +// risk-based unmasking success if the card doesn't have CVC. +TEST_F(CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingTest, + DoNotLogCvcFilling_RiskBasedMaskedServerCardUnmaskingSuccess) { + base::HistogramTester histogram_tester; + CreateServerCard(kTestGUID, kTestNumber, /*masked=*/true, kTestServerId); + CreditCard* masked_server_card = + personal_data().GetCreditCardByGUID(kTestGUID); + masked_server_card->set_cvc(u""); + + credit_card_access_manager().FetchCreditCard( + masked_server_card, base::BindOnce(&TestAccessor::OnCreditCardFetched, + accessor_->GetWeakPtr())); + + // Mock CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse to + // successfully return the valid card number. + CreditCard card = *masked_server_card; + card.set_record_type(CreditCard::RecordType::kFullServerCard); + // Mock that CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse + // indicates a green path with valid card number returned. + credit_card_access_manager().OnRiskBasedAuthenticationResponseReceived( + CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse() + .with_result(CreditCardRiskBasedAuthenticator:: + RiskBasedAuthenticationResponse::Result:: + kNoAuthenticationRequired) + .with_card(card)); + + // Expect the metrics are logged correctly. + histogram_tester.ExpectUniqueSample( + "Autofill.CvcStorage.CvcFilling.ServerCard", + autofill_metrics::CvcFillingFlowType::kNoInteractiveAuthentication, 0); +} + +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) // Params of the // CreditCardAccessManagerRiskBasedMaskedServerCardUnmaskingPreflightCallReturnedTest: // -- bool fido_opted_in; @@ -3336,7 +3405,7 @@ // There was no interactive authentication in this flow, so check that this // is signaled correctly. - absl::optional<CreditCard::RecordType> card_identifier = + std::optional<CreditCard::RecordType> card_identifier = autofill_client_.GetFormDataImporter() ->GetCardRecordTypeIfNonInteractiveAuthenticationFlowCompleted(); ASSERT_TRUE(card_identifier.has_value());
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc index 3cb7bb1..ef0a9869 100644 --- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc +++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc
@@ -30,8 +30,8 @@ const CreditCard* card, base::WeakPtr<Requester> requester, PersonalDataManager* personal_data_manager, - absl::optional<std::string> vcn_context_token, - absl::optional<CardUnmaskChallengeOption> selected_challenge_option) { + std::optional<std::string> vcn_context_token, + std::optional<CardUnmaskChallengeOption> selected_challenge_option) { requester_ = requester; if (!card) { return OnFullCardRequestFailed(
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h index 5ab33c4..35243778 100644 --- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h +++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
@@ -45,7 +45,7 @@ return *this; } CvcAuthenticationResponse& with_request_options( - absl::optional<base::Value::Dict> v) { + std::optional<base::Value::Dict> v) { request_options = std::move(v); return *this; } @@ -57,7 +57,7 @@ raw_ptr<const CreditCard> card = nullptr; // TODO(crbug.com/1475052): Remove CVC. std::u16string cvc = std::u16string(); - absl::optional<base::Value::Dict> request_options; + std::optional<base::Value::Dict> request_options; std::string card_authorization_token = std::string(); }; class Requester { @@ -91,13 +91,12 @@ ~CreditCardCvcAuthenticator() override; // Authentication - void Authenticate( - const CreditCard* card, - base::WeakPtr<Requester> requester, - PersonalDataManager* personal_data_manager, - absl::optional<std::string> vcn_context_token = absl::nullopt, - absl::optional<CardUnmaskChallengeOption> selected_challenge_option = - absl::nullopt); + void Authenticate(const CreditCard* card, + base::WeakPtr<Requester> requester, + PersonalDataManager* personal_data_manager, + std::optional<std::string> vcn_context_token = std::nullopt, + std::optional<CardUnmaskChallengeOption> + selected_challenge_option = std::nullopt); // payments::FullCardRequest::ResultDelegate void OnFullCardRequestSucceeded(
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc index 72543bf8..24f5600 100644 --- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
@@ -199,7 +199,7 @@ payments::FullCardRequest* full_card_request = GetFullCardRequest(); ASSERT_TRUE(full_card_request->GetShouldUnmaskCardForTesting()); - absl::optional<CardUnmaskChallengeOption> challenge_option = + std::optional<CardUnmaskChallengeOption> challenge_option = full_card_request->GetUnmaskRequestDetailsForTesting() ->selected_challenge_option; ASSERT_TRUE(challenge_option);
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc index 8173861..a835ee62 100644 --- a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc +++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
@@ -73,7 +73,7 @@ CreditCard card, base::WeakPtr<Requester> requester, base::Value::Dict request_options, - absl::optional<std::string> context_token) { + std::optional<std::string> context_token) { card_ = std::move(card); requester_ = requester; context_token_ = context_token; @@ -524,7 +524,7 @@ DCHECK(challenge); options->challenge = Base64ToBytes(*challenge); - const absl::optional<int> timeout = request_options.FindInt("timeout_millis"); + const std::optional<int> timeout = request_options.FindInt("timeout_millis"); options->timeout = base::Milliseconds(timeout.value_or(kWebAuthnTimeoutMs)); options->user_verification = device::UserVerificationRequirement::kRequired; @@ -576,8 +576,7 @@ } } - const absl::optional<int> timeout = - creation_options.FindInt("timeout_millis"); + const std::optional<int> timeout = creation_options.FindInt("timeout_millis"); options->timeout = base::Milliseconds(timeout.value_or(kWebAuthnTimeoutMs)); const auto* attestation = @@ -624,7 +623,7 @@ key_info.GetDict().FindList("authenticator_transport_support"); if (transports && !transports->empty()) { for (const base::Value& transport_type : *transports) { - absl::optional<device::FidoTransportProtocol> protocol = + std::optional<device::FidoTransportProtocol> protocol = device::ConvertToFidoTransportProtocol( base::ToLowerASCII(transport_type.GetString())); if (protocol.has_value()) @@ -755,7 +754,7 @@ autofill_client_, autofill_client_->GetPaymentsNetworkInterface(), autofill_client_->GetPersonalDataManager()); - absl::optional<GURL> last_committed_primary_main_frame_origin; + std::optional<GURL> last_committed_primary_main_frame_origin; if (card_->record_type() == CreditCard::RecordType::kVirtualCard && autofill_client_->GetLastCommittedPrimaryMainFrameURL().is_valid()) { last_committed_primary_main_frame_origin =
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator.h b/components/autofill/core/browser/payments/credit_card_fido_authenticator.h index 8711831..d84962d8 100644 --- a/components/autofill/core/browser/payments/credit_card_fido_authenticator.h +++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_CREDIT_CARD_FIDO_AUTHENTICATOR_H_ #include <memory> +#include <optional> #include <string> #include "base/gtest_prod_util.h" @@ -20,7 +21,6 @@ #include "components/autofill/core/browser/strike_databases/payments/fido_authentication_strike_database.h" #include "components/webauthn/core/browser/internal_authenticator.h" #include "device/fido/fido_constants.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/webauthn/authenticator.mojom-forward.h" namespace autofill { @@ -98,7 +98,7 @@ CreditCard card, base::WeakPtr<Requester> requester, base::Value::Dict request_options, - absl::optional<std::string> context_token = absl::nullopt); + std::optional<std::string> context_token = std::nullopt); // Invokes Registration flow. Sends credentials created from // |creation_options| along with the |card_authorization_token| to Payments in @@ -252,7 +252,7 @@ webauthn::InternalAuthenticator* authenticator(); // Card being unmasked. - absl::optional<CreditCard> card_; + std::optional<CreditCard> card_; // The current flow in progress. Flow current_flow_ = NONE_FLOW; @@ -294,7 +294,7 @@ // The context token used for sharing context between different server // requests. Will be populated only for virtual card unmasking. - absl::optional<std::string> context_token_; + std::optional<std::string> context_token_; base::WeakPtrFactory<CreditCardFidoAuthenticator> weak_ptr_factory_{this}; };
diff --git a/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc b/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc index ce472b9..8a0fa0b 100644 --- a/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc +++ b/components/autofill/core/browser/payments/credit_card_otp_authenticator.cc
@@ -40,7 +40,7 @@ } if (card_->record_type() == CreditCard::RecordType::kVirtualCard) { - absl::optional<GURL> last_committed_primary_main_frame_origin; + std::optional<GURL> last_committed_primary_main_frame_origin; if (autofill_client_->GetLastCommittedPrimaryMainFrameURL().is_valid()) { last_committed_primary_main_frame_origin = autofill_client_->GetLastCommittedPrimaryMainFrameURL() @@ -386,8 +386,8 @@ selected_challenge_option_request_ongoing_ = false; select_challenge_option_request_.reset(); unmask_request_.reset(); - select_challenge_option_request_timestamp_ = absl::nullopt; - unmask_card_request_timestamp_ = absl::nullopt; + select_challenge_option_request_timestamp_ = std::nullopt; + unmask_card_request_timestamp_ = std::nullopt; } } // namespace autofill
diff --git a/components/autofill/core/browser/payments/credit_card_otp_authenticator.h b/components/autofill/core/browser/payments/credit_card_otp_authenticator.h index bac3079..cbc6c132 100644 --- a/components/autofill/core/browser/payments/credit_card_otp_authenticator.h +++ b/components/autofill/core/browser/payments/credit_card_otp_authenticator.h
@@ -177,8 +177,8 @@ unmask_request_; // The timestamps when the requests are sent. Used for logging. - absl::optional<base::TimeTicks> select_challenge_option_request_timestamp_; - absl::optional<base::TimeTicks> unmask_card_request_timestamp_; + std::optional<base::TimeTicks> select_challenge_option_request_timestamp_; + std::optional<base::TimeTicks> unmask_card_request_timestamp_; base::WeakPtrFactory<CreditCardOtpAuthenticator> weak_ptr_factory_{this}; };
diff --git a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h index 659c6829..5c6f959 100644 --- a/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h +++ b/components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h
@@ -68,11 +68,11 @@ AutofillErrorDialogContext error_dialog_context; // The card will be set when the server response was successful and the // card's real pan was returned from the server side. - absl::optional<CreditCard> card; + std::optional<CreditCard> card; // The items below will be set when the server response was successful and // the card's real pan was not returned from the server side. // FIDO request options will be present only when FIDO is available. - absl::optional<base::Value::Dict> fido_request_options; + std::optional<base::Value::Dict> fido_request_options; // Stores the latest version of the context token, passed between Payments // calls and unmodified by Chrome. std::string context_token; @@ -151,7 +151,7 @@ unmask_request_details_; // The timestamp when the unmask request is sent. Used for logging. - absl::optional<base::TimeTicks> unmask_card_request_timestamp_; + std::optional<base::TimeTicks> unmask_card_request_timestamp_; base::WeakPtrFactory<CreditCardRiskBasedAuthenticator> weak_ptr_factory_{ this};
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.h b/components/autofill/core/browser/payments/credit_card_save_manager.h index 7dd9da0a..d60a556c 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager.h +++ b/components/autofill/core/browser/payments/credit_card_save_manager.h
@@ -7,6 +7,7 @@ #include <map> #include <memory> +#include <optional> #include <string> #include <utility> #include <vector> @@ -26,7 +27,6 @@ #include "components/autofill/core/browser/strike_databases/payments/credit_card_save_strike_database.h" #include "components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.h" #include "components/autofill/core/browser/strike_databases/payments/local_card_migration_strike_database.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" class SaveCardOfferObserver; @@ -372,8 +372,8 @@ int upload_decision_metrics_ = 0; // |true| if the offer-to-save bubble/infobar should pop-up, |false| if not. - // Will be absl::nullopt until data has been retrieved from the StrikeSystem. - absl::optional<bool> show_save_prompt_; + // Will be std::nullopt until data has been retrieved from the StrikeSystem. + std::optional<bool> show_save_prompt_; // |true| if the card being offered for upload is already a local card on the // device; |false| otherwise.
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc index 1b96312..193ded2f 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -176,8 +176,8 @@ InitVirtualCardEnroll, (const CreditCard& credit_card, VirtualCardEnrollmentSource virtual_card_enrollment_source, - absl::optional<payments::PaymentsNetworkInterface:: - GetDetailsForEnrollmentResponseDetails> + std::optional<payments::PaymentsNetworkInterface:: + GetDetailsForEnrollmentResponseDetails> get_details_for_enrollment_response_details, PrefService* user_prefs, VirtualCardEnrollmentManager::RiskAssessmentFunction @@ -5650,8 +5650,8 @@ CreditCard arg_credit_card; VirtualCardEnrollmentSource arg_virtual_card_enrollment_source; - absl::optional<payments::PaymentsNetworkInterface:: - GetDetailsForEnrollmentResponseDetails> + std::optional<payments::PaymentsNetworkInterface:: + GetDetailsForEnrollmentResponseDetails> arg_get_details_for_enrollment_response_details; EXPECT_CALL(autofill_client_, GetVirtualCardEnrollmentManager).Times(1); EXPECT_CALL(*virtual_card_enrollment_manager_,
diff --git a/components/autofill/core/browser/payments/full_card_request.cc b/components/autofill/core/browser/payments/full_card_request.cc index 5a69cbc..9cf7c44 100644 --- a/components/autofill/core/browser/payments/full_card_request.cc +++ b/components/autofill/core/browser/payments/full_card_request.cc
@@ -52,10 +52,10 @@ const url::Origin& merchant_domain_for_footprints) { DCHECK(ui_delegate); GetFullCardImpl(card, reason, result_delegate, ui_delegate, - /*fido_assertion_info=*/absl::nullopt, - /*last_committed_primary_main_frame_origin=*/absl::nullopt, - /*context_token=*/absl::nullopt, - /*selected_challenge_option=*/absl::nullopt, + /*fido_assertion_info=*/std::nullopt, + /*last_committed_primary_main_frame_origin=*/std::nullopt, + /*context_token=*/std::nullopt, + /*selected_challenge_option=*/std::nullopt, merchant_domain_for_footprints); } @@ -73,7 +73,7 @@ DCHECK(!vcn_context_token.empty()); DCHECK(selected_challenge_option.type == CardUnmaskChallengeOptionType::kCvc); GetFullCardImpl(card, reason, result_delegate, ui_delegate, - /*fido_assertion_info=*/absl::nullopt, + /*fido_assertion_info=*/std::nullopt, last_committed_primary_main_frame_origin, vcn_context_token, selected_challenge_option, merchant_domain_for_footprints); } @@ -84,12 +84,12 @@ base::WeakPtr<ResultDelegate> result_delegate, base::Value::Dict fido_assertion_info, const url::Origin& merchant_domain_for_footprints, - absl::optional<GURL> last_committed_primary_main_frame_origin, - absl::optional<std::string> context_token) { + std::optional<GURL> last_committed_primary_main_frame_origin, + std::optional<std::string> context_token) { GetFullCardImpl( card, reason, result_delegate, nullptr, std::move(fido_assertion_info), std::move(last_committed_primary_main_frame_origin), - std::move(context_token), /*selected_challenge_option=*/absl::nullopt, + std::move(context_token), /*selected_challenge_option=*/std::nullopt, merchant_domain_for_footprints); } @@ -98,10 +98,10 @@ AutofillClient::UnmaskCardReason reason, base::WeakPtr<ResultDelegate> result_delegate, base::WeakPtr<UIDelegate> ui_delegate, - absl::optional<base::Value::Dict> fido_assertion_info, - absl::optional<GURL> last_committed_primary_main_frame_origin, - absl::optional<std::string> context_token, - absl::optional<CardUnmaskChallengeOption> selected_challenge_option, + std::optional<base::Value::Dict> fido_assertion_info, + std::optional<GURL> last_committed_primary_main_frame_origin, + std::optional<std::string> context_token, + std::optional<CardUnmaskChallengeOption> selected_challenge_option, const url::Origin& merchant_domain_for_footprints) { // Retrieval of card information should happen via CVC auth or FIDO, but not // both. Use |ui_delegate|'s existence as evidence of doing CVC auth and
diff --git a/components/autofill/core/browser/payments/full_card_request.h b/components/autofill/core/browser/payments/full_card_request.h index 3a794b8..3308eb3 100644 --- a/components/autofill/core/browser/payments/full_card_request.h +++ b/components/autofill/core/browser/payments/full_card_request.h
@@ -166,9 +166,9 @@ base::WeakPtr<ResultDelegate> result_delegate, base::Value::Dict fido_assertion_info, const url::Origin& merchant_domain_for_footprints, - absl::optional<GURL> last_committed_primary_main_frame_origin = - absl::nullopt, - absl::optional<std::string> context_token = absl::nullopt); + std::optional<GURL> last_committed_primary_main_frame_origin = + std::nullopt, + std::optional<std::string> context_token = std::nullopt); // Called by the PaymentsNetworkInterface when a card has been unmasked. void OnDidGetRealPan( @@ -226,10 +226,10 @@ AutofillClient::UnmaskCardReason reason, base::WeakPtr<ResultDelegate> result_delegate, base::WeakPtr<UIDelegate> ui_delegate, - absl::optional<base::Value::Dict> fido_assertion_info, - absl::optional<GURL> last_committed_primary_main_frame_origin, - absl::optional<std::string> context_token, - absl::optional<CardUnmaskChallengeOption> selected_challenge_option, + std::optional<base::Value::Dict> fido_assertion_info, + std::optional<GURL> last_committed_primary_main_frame_origin, + std::optional<std::string> context_token, + std::optional<CardUnmaskChallengeOption> selected_challenge_option, const url::Origin& merchant_domain_for_footprints); // CardUnmaskDelegate:
diff --git a/components/autofill/core/browser/payments/full_card_request_unittest.cc b/components/autofill/core/browser/payments/full_card_request_unittest.cc index 051fb8c..497ceb0b 100644 --- a/components/autofill/core/browser/payments/full_card_request_unittest.cc +++ b/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -471,7 +471,7 @@ url::Origin::Create(GURL("http://example.com")))); payments::PaymentsNetworkInterface::UnmaskRequestDetails* request_details = request()->GetUnmaskRequestDetailsForTesting(); - ASSERT_EQ(request_details->merchant_domain_for_footprints, absl::nullopt); + ASSERT_EQ(request_details->merchant_domain_for_footprints, std::nullopt); CardUnmaskDelegate::UserProvidedUnmaskDetails details; details.cvc = u"123";
diff --git a/components/autofill/core/browser/payments/legal_message_line_fuzzer.cc b/components/autofill/core/browser/payments/legal_message_line_fuzzer.cc index f6eb3d16..793c12a 100644 --- a/components/autofill/core/browser/payments/legal_message_line_fuzzer.cc +++ b/components/autofill/core/browser/payments/legal_message_line_fuzzer.cc
@@ -5,17 +5,17 @@ #include <stdint.h> #include <fuzzer/FuzzedDataProvider.h> +#include <optional> #include "base/json/json_reader.h" #include "base/values.h" #include "components/autofill/core/browser/payments/legal_message_line.h" -#include "third_party/abseil-cpp/absl/types/optional.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider provider(data, size); // Prepare fuzzed parameters. - absl::optional<base::Value> legal_message = + std::optional<base::Value> legal_message = base::JSONReader::Read(provider.ConsumeRandomLengthString()); if (!legal_message || !legal_message->is_dict()) return 0;
diff --git a/components/autofill/core/browser/payments/legal_message_line_unittest.cc b/components/autofill/core/browser/payments/legal_message_line_unittest.cc index d1f38b36..db7221ce 100644 --- a/components/autofill/core/browser/payments/legal_message_line_unittest.cc +++ b/components/autofill/core/browser/payments/legal_message_line_unittest.cc
@@ -292,7 +292,7 @@ // Verifies that legal message parsing is correct. TEST_P(LegalMessageLineTest, Parsing) { const TestCase& test_case = TestCaseData()[GetParam()]; - absl::optional<base::Value> value( + std::optional<base::Value> value( base::JSONReader::Read(test_case.message_json)); ASSERT_TRUE(value); ASSERT_TRUE(value->is_dict());
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager.cc b/components/autofill/core/browser/payments/local_card_migration_manager.cc index 04b264f..5a23c12 100644 --- a/components/autofill/core/browser/payments/local_card_migration_manager.cc +++ b/components/autofill/core/browser/payments/local_card_migration_manager.cc
@@ -60,7 +60,7 @@ LocalCardMigrationManager::~LocalCardMigrationManager() {} bool LocalCardMigrationManager::ShouldOfferLocalCardMigration( - const absl::optional<CreditCard>& extracted_credit_card, + const std::optional<CreditCard>& extracted_credit_card, int credit_card_import_type) { // Reset and store the extracted credit card info for a later check of whether // the extracted card is supported.
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager.h b/components/autofill/core/browser/payments/local_card_migration_manager.h index 6da69f2b..59c543e 100644 --- a/components/autofill/core/browser/payments/local_card_migration_manager.h +++ b/components/autofill/core/browser/payments/local_card_migration_manager.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_LOCAL_CARD_MIGRATION_MANAGER_H_ #include <memory> +#include <optional> #include <string> #include <unordered_map> #include <utility> @@ -19,7 +20,6 @@ #include "components/autofill/core/browser/payments/legal_message_line.h" #include "components/autofill/core/browser/payments/payments_network_interface.h" #include "components/autofill/core/browser/strike_databases/payments/local_card_migration_strike_database.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -107,7 +107,7 @@ // the imported card is supported. `extracted_credit_card` might be // null if a user used server card. bool ShouldOfferLocalCardMigration( - const absl::optional<CreditCard>& extracted_credit_card, + const std::optional<CreditCard>& extracted_credit_card, int credit_card_import_type); // Called from FormDataImporter or settings page when all migration @@ -236,7 +236,7 @@ raw_ptr<PersonalDataManager> personal_data_manager_; // The imported credit card number from the form submission. - absl::optional<std::u16string> extracted_credit_card_number_; + std::optional<std::u16string> extracted_credit_card_number_; // The imported credit card record type from the form submission. int credit_card_import_type_;
diff --git a/components/autofill/core/browser/payments/mandatory_reauth_manager.cc b/components/autofill/core/browser/payments/mandatory_reauth_manager.cc index dde0b0d7..2b5c5d36 100644 --- a/components/autofill/core/browser/payments/mandatory_reauth_manager.cc +++ b/components/autofill/core/browser/payments/mandatory_reauth_manager.cc
@@ -49,7 +49,7 @@ } bool MandatoryReauthManager::ShouldOfferOptin( - absl::optional<CreditCard::RecordType> + std::optional<CreditCard::RecordType> card_record_type_if_non_interactive_authentication_flow_completed) { opt_in_source_ = autofill_metrics::MandatoryReauthOptInOrOutSource::kUnknown; // We should not offer to update a user pref in off the record mode.
diff --git a/components/autofill/core/browser/payments/mandatory_reauth_manager.h b/components/autofill/core/browser/payments/mandatory_reauth_manager.h index f68adbc5..15058bc0 100644 --- a/components/autofill/core/browser/payments/mandatory_reauth_manager.h +++ b/components/autofill/core/browser/payments/mandatory_reauth_manager.h
@@ -68,7 +68,7 @@ // authentication, and will hold the record type of the card that had the most // recent non-interactive authentication. virtual bool ShouldOfferOptin( - absl::optional<CreditCard::RecordType> + std::optional<CreditCard::RecordType> card_record_type_if_non_interactive_authentication_flow_completed); // Starts the opt-in flow. This flow includes an opt-in bubble, an
diff --git a/components/autofill/core/browser/payments/mandatory_reauth_manager_unittest.cc b/components/autofill/core/browser/payments/mandatory_reauth_manager_unittest.cc index 4a5683a..deaa8fa 100644 --- a/components/autofill/core/browser/payments/mandatory_reauth_manager_unittest.cc +++ b/components/autofill/core/browser/payments/mandatory_reauth_manager_unittest.cc
@@ -310,7 +310,7 @@ // 'card_identifier_if_non_interactive_authentication_flow_completed' is not // present, implying interactive authentication happened. - EXPECT_FALSE(mandatory_reauth_manager_->ShouldOfferOptin(absl::nullopt)); + EXPECT_FALSE(mandatory_reauth_manager_->ShouldOfferOptin(std::nullopt)); ExpectUniqueOfferOptInDecision( MandatoryReauthOfferOptInDecision::kWentThroughInteractiveAuthentication); }
diff --git a/components/autofill/core/browser/payments/payments_network_interface.cc b/components/autofill/core/browser/payments/payments_network_interface.cc index 53bd6eda..d121c2c 100644 --- a/components/autofill/core/browser/payments/payments_network_interface.cc +++ b/components/autofill/core/browser/payments/payments_network_interface.cc
@@ -490,7 +490,7 @@ case net::HTTP_OK: { std::string error_code; std::string error_api_error_reason; - absl::optional<base::Value> message_value = base::JSONReader::Read(data); + std::optional<base::Value> message_value = base::JSONReader::Read(data); if (message_value && message_value->is_dict()) { const auto* found_error_code = message_value->GetDict().FindStringByDottedPath("error.code");
diff --git a/components/autofill/core/browser/payments/payments_network_interface.h b/components/autofill/core/browser/payments/payments_network_interface.h index eebd26e..07d7a95 100644 --- a/components/autofill/core/browser/payments/payments_network_interface.h +++ b/components/autofill/core/browser/payments/payments_network_interface.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_NETWORK_INTERFACE_H_ #include <memory> +#include <optional> #include <set> #include <string> #include <unordered_map> @@ -27,7 +28,6 @@ #include "components/autofill/core/browser/payments/client_behavior_constants.h" #include "components/autofill/core/browser/payments/virtual_card_enrollment_flow.h" #include "google_apis/gaia/google_service_auth_error.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" namespace signin { @@ -101,7 +101,7 @@ bool offer_fido_opt_in = false; // Public Key Credential Request Options required for authentication. // https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialrequestoptions - absl::optional<base::Value::Dict> fido_request_options; + std::optional<base::Value::Dict> fido_request_options; // Set of credit cards ids that are eligible for FIDO Authentication. std::set<std::string> fido_eligible_card_ids; }; @@ -118,23 +118,23 @@ CreditCard card; std::string risk_data; CardUnmaskDelegate::UserProvidedUnmaskDetails user_response; - absl::optional<base::Value::Dict> fido_assertion_info; + std::optional<base::Value::Dict> fido_assertion_info; std::u16string otp; // An opaque token used to chain consecutive payments requests together. std::string context_token; // The origin of the primary main frame where the unmasking happened. // Should be populated when the unmasking is for a virtual-card. - absl::optional<GURL> last_committed_primary_main_frame_origin; + std::optional<GURL> last_committed_primary_main_frame_origin; // The selected challenge option. Should be populated when we are doing CVC // unmasking for a virtual card. - absl::optional<CardUnmaskChallengeOption> selected_challenge_option; + std::optional<CardUnmaskChallengeOption> selected_challenge_option; // A vector of signals used to share client behavior with the Payments // server. std::vector<ClientBehaviorConstants> client_behavior_signals; // The origin of the primary main frame where the unmasking happened. Should // only be populated when the client is not in incognito mode since it will // be used for personalization. - absl::optional<url::Origin> merchant_domain_for_footprints; + std::optional<url::Origin> merchant_domain_for_footprints; }; // Information retrieved from an UnmaskRequest. @@ -168,7 +168,7 @@ std::string expiration_year; // Challenge required for authorizing user for FIDO authentication for // future card unmasking. - absl::optional<base::Value::Dict> fido_request_options; + std::optional<base::Value::Dict> fido_request_options; // An opaque token used to logically chain consecutive UnmaskCard and // OptChange calls together. std::string card_authorization_token; @@ -188,7 +188,7 @@ // If present, that means this response was an error, and these fields // should be used for the autofill error dialog as they will provide detail // into the specific error that occurred. - absl::optional<AutofillErrorDialogContext> autofill_error_dialog_context; + std::optional<AutofillErrorDialogContext> autofill_error_dialog_context; }; // A collection of information required to make an unmask IBAN request. @@ -228,7 +228,7 @@ Reason reason; // Signature required for enrolling user into FIDO authentication for future // card unmasking. - absl::optional<base::Value::Dict> fido_authenticator_response; + std::optional<base::Value::Dict> fido_authenticator_response; // An opaque token used to logically chain consecutive UnmaskCard and // OptChange calls together. std::string card_authorization_token = std::string(); @@ -242,13 +242,13 @@ // Unset if response failed. True if user is opted-in for FIDO // authentication for card unmasking. False otherwise. - absl::optional<bool> user_is_opted_in; + std::optional<bool> user_is_opted_in; // Challenge required for enrolling user into FIDO authentication for future // card unmasking. - absl::optional<base::Value::Dict> fido_creation_options; + std::optional<base::Value::Dict> fido_creation_options; // Challenge required for authorizing user for FIDO authentication for // future card unmasking. - absl::optional<base::Value::Dict> fido_request_options; + std::optional<base::Value::Dict> fido_request_options; }; // A collection of the information required to make local credit cards @@ -305,12 +305,12 @@ int64_t billing_customer_number = 0; // Populated if it is an unenroll request. |instrument_id| lets the server // know which card to unenroll from VCN. - absl::optional<int64_t> instrument_id; + std::optional<int64_t> instrument_id; // Populated if it is an enroll request. Based on the |vcn_context_token| // the server is able to retrieve the instrument id, and using // |vcn_context_token| for enroll allows the server to link a // GetDetailsForEnroll call with the corresponding Enroll call. - absl::optional<std::string> vcn_context_token; + std::optional<std::string> vcn_context_token; }; // The struct to hold all detailed information to construct a @@ -422,7 +422,7 @@ // enrollment flow. Will only not be populated in the case of an imperfect // conversion from string to int64_t, or if the server does not return an // instrument id. - absl::optional<int64_t> instrument_id; + std::optional<int64_t> instrument_id; // |virtual_card_enrollment_state| is used to determine whether we want to // pursue further action with the credit card that was uploaded regarding // virtual card enrollment. For example, if the state is @@ -443,8 +443,8 @@ // |get_details_for_enrollment_response_details| will be populated so that // we can display the virtual card enrollment bubble without needing to do // another GetDetailsForEnroll network call. - absl::optional<GetDetailsForEnrollmentResponseDetails> - get_details_for_enrollment_response_details = absl::nullopt; + std::optional<GetDetailsForEnrollmentResponseDetails> + get_details_for_enrollment_response_details = std::nullopt; }; // |url_loader_factory| is reference counted so it has no lifetime or
diff --git a/components/autofill/core/browser/payments/payments_network_interface_unittest.cc b/components/autofill/core/browser/payments/payments_network_interface_unittest.cc index 9224282d..3613998 100644 --- a/components/autofill/core/browser/payments/payments_network_interface_unittest.cc +++ b/components/autofill/core/browser/payments/payments_network_interface_unittest.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 <optional> #include <set> #include <string> #include <string_view> @@ -42,7 +43,6 @@ #include "services/network/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" using ::testing::HasSubstr; @@ -616,9 +616,9 @@ return profile; } - absl::optional<PaymentsNetworkInterface::UnmaskDetails> unmask_details_; + std::optional<PaymentsNetworkInterface::UnmaskDetails> unmask_details_; // The UnmaskResponseDetails retrieved from an UnmaskRequest. Includes PAN. - absl::optional<PaymentsNetworkInterface::UnmaskResponseDetails> + std::optional<PaymentsNetworkInterface::UnmaskResponseDetails> unmask_response_details_; base::WeakPtrFactory<PaymentsNetworkInterfaceTest> weak_ptr_factory_{this}; }; @@ -1392,7 +1392,7 @@ TEST_F(PaymentsNetworkInterfaceTest, UploadSuccessInstrumentIdPresent) { StartUploading(UploadCardOptions()); IssueOAuthToken(); - upload_card_response_details_.instrument_id = absl::nullopt; + upload_card_response_details_.instrument_id = std::nullopt; // Test the conversion from string to int64_t using the max value for int64_t. ReturnResponse(net::HTTP_OK,
diff --git a/components/autofill/core/browser/payments/payments_requests/get_details_for_enrollment_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/get_details_for_enrollment_request_unittest.cc index 4726c1c8..7a51bba 100644 --- a/components/autofill/core/browser/payments/payments_requests/get_details_for_enrollment_request_unittest.cc +++ b/components/autofill/core/browser/payments/payments_requests/get_details_for_enrollment_request_unittest.cc
@@ -82,7 +82,7 @@ } TEST_P(GetDetailsForEnrollmentRequestTest, ParseResponse) { - absl::optional<base::Value> response = base::JSONReader::Read( + std::optional<base::Value> response = base::JSONReader::Read( "{ \"google_legal_message\": {}, \"external_legal_message\": {}, " "\"context_token\": \"some_token\" }"); ASSERT_TRUE(response.has_value());
diff --git a/components/autofill/core/browser/payments/payments_requests/get_unmask_details_request.cc b/components/autofill/core/browser/payments/payments_requests/get_unmask_details_request.cc index bc7ca1c..c7e4471 100644 --- a/components/autofill/core/browser/payments/payments_requests/get_unmask_details_request.cc +++ b/components/autofill/core/browser/payments/payments_requests/get_unmask_details_request.cc
@@ -63,7 +63,7 @@ } } - const absl::optional<bool> offer_fido_opt_in = + const std::optional<bool> offer_fido_opt_in = response.FindBool("offer_fido_opt_in"); unmask_details_.offer_fido_opt_in = offer_fido_opt_in.value_or(false);
diff --git a/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc b/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc index 75df2474..fd111ad7 100644 --- a/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc +++ b/components/autofill/core/browser/payments/payments_requests/unmask_card_request.cc
@@ -70,7 +70,7 @@ // Get the OTP length for this challenge. This will be displayed to the user // in the OTP input dialog so that the user knows how many digits the OTP // should be. - absl::optional<int> otp_length = + std::optional<int> otp_length = defined_challenge_option->FindInt("otp_length"); parsed_challenge_option->challenge_input_length = otp_length ? *otp_length : kDefaultOtpLength; @@ -95,7 +95,7 @@ // Get the length of the CVC on the card. In most cases this is 3 digits, // but it is possible for this to be 4 digits, for example in the case of // the Card Identification Number on the front of an American Express card. - absl::optional<int> cvc_length = + std::optional<int> cvc_length = defined_challenge_option->FindInt("cvc_length"); parsed_challenge_option->challenge_input_length = cvc_length ? *cvc_length : kDefaultCvcLength; @@ -340,11 +340,11 @@ const base::Value::Dict* expiration = response.FindDict("expiration"); if (expiration) { - if (absl::optional<int> month = expiration->FindInt("month")) { + if (std::optional<int> month = expiration->FindInt("month")) { response_details_.expiration_month = base::NumberToString(month.value()); } - if (absl::optional<int> year = expiration->FindInt("year")) { + if (std::optional<int> year = expiration->FindInt("year")) { response_details_.expiration_year = base::NumberToString(year.value()); } }
diff --git a/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc index ce408fd..00bff82f 100644 --- a/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc +++ b/components/autofill/core/browser/payments/payments_requests/unmask_card_request_unittest.cc
@@ -133,7 +133,7 @@ features::kAutofillEnableMerchantDomainInUnmaskCardRequest); PaymentsNetworkInterface::UnmaskRequestDetails request_details = GetDefaultUnmaskRequestDetails(); - request_details.merchant_domain_for_footprints = absl::nullopt; + request_details.merchant_domain_for_footprints = std::nullopt; request_ = std::make_unique<UnmaskCardRequest>( request_details, /*full_sync_enabled=*/true, /*callback=*/base::DoNothing()); @@ -143,7 +143,7 @@ // Test to ensure response is correctly parsed when the FIDO challenge is // returned with context token. TEST_F(UnmaskCardRequestTest, FidoChallengeReturned_ParseResponse) { - absl::optional<base::Value> response = base::JSONReader::Read( + std::optional<base::Value> response = base::JSONReader::Read( "{\"fido_request_options\":{\"challenge\":\"fake_fido_challenge\"}," "\"context_token\":\"fake_context_token\"}"); ASSERT_TRUE(response.has_value()); @@ -163,7 +163,7 @@ // Test to ensure the response is complete when context token is returned but // PAN is not. TEST_F(UnmaskCardRequestTest, ContextTokenReturned) { - absl::optional<base::Value> response = + std::optional<base::Value> response = base::JSONReader::Read("{\"context_token\":\"fake_context_token\"}"); ASSERT_TRUE(response.has_value()); GetRequest()->ParseResponse(response->GetDict()); @@ -175,7 +175,7 @@ // Test that the response is not complete when both context token and real PAN // are not returned. TEST_F(UnmaskCardRequestTest, ContextTokenAndPanNotReturned) { - absl::optional<base::Value> response = base::JSONReader::Read("{}"); + std::optional<base::Value> response = base::JSONReader::Read("{}"); ASSERT_TRUE(response.has_value()); GetRequest()->ParseResponse(response->GetDict()); @@ -283,7 +283,7 @@ feature_list_email_otp.InitWithFeatureState( features::kAutofillEnableEmailOtpForVcnYellowPath, /*enabled=*/IsAutofillEnableEmailOtpForVcnYellowPathTurnedOn()); - absl::optional<base::Value> response = base::JSONReader::Read( + std::optional<base::Value> response = base::JSONReader::Read( "{\"fido_request_options\": {\"challenge\": \"fake_fido_challenge\"}, " "\"context_token\": \"fake_context_token\", \"idv_challenge_options\": " "[{\"sms_otp_challenge_option\": {\"challenge_id\": " @@ -376,7 +376,7 @@ // Test that `IsRetryableFailure()` returns true if a flow status is // present. - absl::optional<base::Value> response = base::JSONReader::Read( + std::optional<base::Value> response = base::JSONReader::Read( "{\"flow_status\": \"FLOW_STATUS_INCORRECT_ACCOUNT_SECURITY_CODE\"}"); ASSERT_TRUE(response); GetRequest()->ParseResponse(response->GetDict());
diff --git a/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request.h b/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request.h index 1e0a219..8a36fc4 100644 --- a/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request.h +++ b/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request.h
@@ -5,13 +5,13 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_UPDATE_VIRTUAL_CARD_ENROLLMENT_REQUEST_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_UPDATE_VIRTUAL_CARD_ENROLLMENT_REQUEST_H_ +#include <optional> #include <string> #include "base/functional/callback.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/payments/payments_network_interface.h" #include "components/autofill/core/browser/payments/payments_requests/payments_request.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class Value; @@ -58,7 +58,7 @@ PaymentsNetworkInterface::UpdateVirtualCardEnrollmentRequestDetails request_details_; base::OnceCallback<void(AutofillClient::PaymentsRpcResult)> callback_; - absl::optional<std::string> enroll_result_; + std::optional<std::string> enroll_result_; }; } // namespace payments
diff --git a/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request_unittest.cc index 881db2d..93f9f1e 100644 --- a/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request_unittest.cc +++ b/components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request_unittest.cc
@@ -47,7 +47,7 @@ return request_.get(); } - const absl::optional<std::string>& GetParsedResponse() const { + const std::optional<std::string>& GetParsedResponse() const { return request_->enroll_result_; } @@ -122,7 +122,7 @@ TEST_P(UpdateVirtualCardEnrollmentRequestTest, ParseResponse) { if (std::get<0>(GetParam()) == VirtualCardEnrollmentRequestType::kEnroll) { - absl::optional<base::Value> response = + std::optional<base::Value> response = base::JSONReader::Read("{ \"enroll_result\": \"ENROLL_SUCCESS\" }"); ASSERT_TRUE(response.has_value()); GetRequest()->ParseResponse(response->GetDict()); @@ -135,7 +135,7 @@ VirtualCardEnrollmentRequestType::kUnenroll); // Unenroll is only available from the settings page. if (std::get<1>(GetParam()) == VirtualCardEnrollmentSource::kSettingsPage) { - absl::optional<base::Value> response = base::JSONReader::Read("{}"); + std::optional<base::Value> response = base::JSONReader::Read("{}"); ASSERT_TRUE(response.has_value()); GetRequest()->ParseResponse(response->GetDict());
diff --git a/components/autofill/core/browser/payments/test/mock_mandatory_reauth_manager.h b/components/autofill/core/browser/payments/test/mock_mandatory_reauth_manager.h index 5d30249c..a2d564f4 100644 --- a/components/autofill/core/browser/payments/test/mock_mandatory_reauth_manager.h +++ b/components/autofill/core/browser/payments/test/mock_mandatory_reauth_manager.h
@@ -18,7 +18,7 @@ MOCK_METHOD(bool, ShouldOfferOptin, - (absl::optional<CreditCard::RecordType>), + (std::optional<CreditCard::RecordType>), (override)); MOCK_METHOD(void, StartOptInFlow, (), (override)); MOCK_METHOD(void, OnUserAcceptedOptInPrompt, (), (override));
diff --git a/components/autofill/core/browser/payments/test/test_credit_card_risk_based_authenticator.h b/components/autofill/core/browser/payments/test/test_credit_card_risk_based_authenticator.h index 3f8b48f..a762dda 100644 --- a/components/autofill/core/browser/payments/test/test_credit_card_risk_based_authenticator.h +++ b/components/autofill/core/browser/payments/test/test_credit_card_risk_based_authenticator.h
@@ -32,7 +32,7 @@ private: bool authenticate_invoked_ = false; - absl::optional<CreditCard> card_; + std::optional<CreditCard> card_; int64_t billing_customer_id_; };
diff --git a/components/autofill/core/browser/payments/test_authentication_requester.h b/components/autofill/core/browser/payments/test_authentication_requester.h index a7d7f65e..942ed622 100644 --- a/components/autofill/core/browser/payments/test_authentication_requester.h +++ b/components/autofill/core/browser/payments/test_authentication_requester.h
@@ -72,9 +72,9 @@ base::WeakPtr<TestAuthenticationRequester> GetWeakPtr(); - absl::optional<bool> is_user_verifiable() { return is_user_verifiable_; } + std::optional<bool> is_user_verifiable() { return is_user_verifiable_; } - absl::optional<bool> did_succeed() { return did_succeed_; } + std::optional<bool> did_succeed() { return did_succeed_; } std::u16string number() { return number_; } @@ -94,10 +94,10 @@ private: // Set when CreditCardFidoAuthenticator invokes IsUserVerifiableCallback(). - absl::optional<bool> is_user_verifiable_; + std::optional<bool> is_user_verifiable_; // Is set to true if authentication was successful. - absl::optional<bool> did_succeed_; + std::optional<bool> did_succeed_; // The failure type of the full card request. Set when the request is // finished.
diff --git a/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc b/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc index db034ff..fa700a7 100644 --- a/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc +++ b/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc
@@ -24,7 +24,7 @@ CreditCard card, base::WeakPtr<Requester> requester, base::Value::Dict request_options, - absl::optional<std::string> context_token) { + std::optional<std::string> context_token) { authenticate_invoked_ = true; card_ = std::move(card); context_token_ = context_token; @@ -124,7 +124,7 @@ void TestCreditCardFidoAuthenticator::Reset() { is_user_verifiable_ = false; - is_user_opted_in_ = absl::nullopt; + is_user_opted_in_ = std::nullopt; opt_out_called_ = false; authenticate_invoked_ = false; card_ = CreditCard();
diff --git a/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h b/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h index 3190d869..5e6e29c2 100644 --- a/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h +++ b/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_CREDIT_CARD_FIDO_AUTHENTICATOR_H_ #include <memory> +#include <optional> #include <string> #include <vector> @@ -13,7 +14,6 @@ #include "components/autofill/core/browser/autofill_driver.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/payments/credit_card_fido_authenticator.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -34,7 +34,7 @@ void Authenticate(CreditCard card, base::WeakPtr<Requester> requester, base::Value::Dict request_options, - absl::optional<std::string> context_token) override; + std::optional<std::string> context_token) override; void IsUserVerifiable(base::OnceCallback<void(bool)> callback) override; bool IsUserOptedIn() override; void GetAssertion(blink::mojom::PublicKeyCredentialRequestOptionsPtr @@ -67,7 +67,7 @@ bool IsOptOutCalled() { return opt_out_called_; } bool authenticate_invoked() { return authenticate_invoked_; } const CreditCard& card() { return *card_; } - const absl::optional<std::string>& context_token() { return context_token_; } + const std::optional<std::string>& context_token() { return context_token_; } // Resets all the testing related states. void Reset(); @@ -79,11 +79,11 @@ blink::mojom::PublicKeyCredentialRequestOptionsPtr request_options_; blink::mojom::PublicKeyCredentialCreationOptionsPtr creation_options_; bool is_user_verifiable_ = false; - absl::optional<bool> is_user_opted_in_; + std::optional<bool> is_user_opted_in_; bool opt_out_called_ = false; bool authenticate_invoked_ = false; - absl::optional<CreditCard> card_; - absl::optional<std::string> context_token_; + std::optional<CreditCard> card_; + std::optional<std::string> context_token_; }; } // namespace autofill
diff --git a/components/autofill/core/browser/payments/test_payments_network_interface.cc b/components/autofill/core/browser/payments/test_payments_network_interface.cc index a0a6535..38e52d6 100644 --- a/components/autofill/core/browser/payments/test_payments_network_interface.cc +++ b/components/autofill/core/browser/payments/test_payments_network_interface.cc
@@ -5,6 +5,7 @@ #include "components/autofill/core/browser/payments/test_payments_network_interface.h" #include <memory> +#include <optional> #include <unordered_map> #include "base/json/json_reader.h" @@ -15,7 +16,6 @@ #include "components/autofill/core/browser/personal_data_manager.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill::payments { @@ -206,7 +206,7 @@ } std::unique_ptr<base::Value::Dict> TestPaymentsNetworkInterface::LegalMessage() { - absl::optional<base::Value> parsed_json; + std::optional<base::Value> parsed_json; if (use_invalid_legal_message_) { // Legal message is invalid because it's missing the url. parsed_json = base::JSONReader::Read(
diff --git a/components/autofill/core/browser/payments/test_payments_network_interface.h b/components/autofill/core/browser/payments/test_payments_network_interface.h index 377127d..0b034260 100644 --- a/components/autofill/core/browser/payments/test_payments_network_interface.h +++ b/components/autofill/core/browser/payments/test_payments_network_interface.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_PAYMENTS_NETWORK_INTERFACE_H_ #include <memory> +#include <optional> #include <set> #include <string> #include <unordered_map> @@ -16,7 +17,6 @@ #include "build/build_config.h" #include "components/autofill/core/browser/payments/payments_network_interface.h" #include "components/autofill/core/browser/payments/payments_requests/update_virtual_card_enrollment_request.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace network { class SharedURLLoaderFactory; @@ -129,7 +129,7 @@ payments::PaymentsNetworkInterface::UnmaskDetails* unmask_details() { return &unmask_details_; } - const absl::optional<payments::PaymentsNetworkInterface::UnmaskRequestDetails>& + const std::optional<payments::PaymentsNetworkInterface::UnmaskRequestDetails>& unmask_request() const { return unmask_request_; } @@ -174,7 +174,7 @@ // useful to control whether or not GetUnmaskDetails() is responded to. bool should_return_unmask_details_ = true; payments::PaymentsNetworkInterface::UnmaskDetails unmask_details_; - absl::optional<payments::PaymentsNetworkInterface::UnmaskRequestDetails> + std::optional<payments::PaymentsNetworkInterface::UnmaskRequestDetails> unmask_request_; payments::PaymentsNetworkInterface::SelectChallengeOptionRequestDetails select_challenge_option_request_; @@ -191,9 +191,9 @@ bool use_invalid_legal_message_ = false; bool use_legal_message_with_multiple_lines_ = false; std::unique_ptr<base::Value::Dict> LegalMessage(); - absl::optional<AutofillClient::PaymentsRpcResult> + std::optional<AutofillClient::PaymentsRpcResult> select_challenge_option_result_; - absl::optional<AutofillClient::PaymentsRpcResult> + std::optional<AutofillClient::PaymentsRpcResult> update_virtual_card_enrollment_result_; payments::PaymentsNetworkInterface::GetDetailsForEnrollmentRequestDetails get_details_for_enrollment_request_details_;
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc index aefc912..2d71350f 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc
@@ -66,8 +66,8 @@ void VirtualCardEnrollmentManager::InitVirtualCardEnroll( const CreditCard& credit_card, VirtualCardEnrollmentSource virtual_card_enrollment_source, - absl::optional<payments::PaymentsNetworkInterface:: - GetDetailsForEnrollmentResponseDetails> + std::optional<payments::PaymentsNetworkInterface:: + GetDetailsForEnrollmentResponseDetails> get_details_for_enrollment_response_details, PrefService* user_prefs, RiskAssessmentFunction risk_assessment_function, @@ -124,7 +124,7 @@ } void VirtualCardEnrollmentManager::Enroll( - absl::optional<VirtualCardEnrollmentUpdateResponseCallback> + std::optional<VirtualCardEnrollmentUpdateResponseCallback> virtual_card_enrollment_update_response_callback) { LogUpdateVirtualCardEnrollmentRequestAttempt( state_.virtual_card_enrollment_fields.virtual_card_enrollment_source, @@ -159,7 +159,7 @@ void VirtualCardEnrollmentManager::Unenroll( int64_t instrument_id, - absl::optional<VirtualCardEnrollmentUpdateResponseCallback> + std::optional<VirtualCardEnrollmentUpdateResponseCallback> virtual_card_enrollment_update_response_callback) { LogUpdateVirtualCardEnrollmentRequestAttempt( VirtualCardEnrollmentSource::kSettingsPage, @@ -353,7 +353,7 @@ state_.virtual_card_enrollment_fields, base::BindOnce( &VirtualCardEnrollmentManager::Enroll, weak_ptr_factory_.GetWeakPtr(), - /*virtual_card_enrollment_update_response_callback=*/absl::nullopt), + /*virtual_card_enrollment_update_response_callback=*/std::nullopt), base::BindOnce( &VirtualCardEnrollmentManager::OnVirtualCardEnrollmentBubbleCancelled, weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h index e45a471..3f9fccbad 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h
@@ -74,7 +74,7 @@ const VirtualCardEnrollmentProcessState&); ~VirtualCardEnrollmentProcessState(); // Only populated once the risk engine responded. - absl::optional<std::string> risk_data; + std::optional<std::string> risk_data; // |virtual_card_enrollment_fields|'s |credit_card| and // |virtual_card_enrollment_source| are populated in the beginning of the // virtual card enrollment flow, but the rest of the fields are only populated @@ -85,7 +85,7 @@ // id, and using |vcn_context_token| for enroll allows the server to link a // GetDetailsForEnrollRequest with the corresponding // UpdateVirtualCardEnrollmentRequest for the enroll process. - absl::optional<std::string> vcn_context_token; + std::optional<std::string> vcn_context_token; }; // Owned by FormDataImporter. There is one instance of this class per tab. This @@ -130,9 +130,9 @@ // GetDetailsForEnrollmentResponseDetails from the // UploadCardResponseDetails, so we can then skip the // GetDetailsForEnroll request in the Virtual Card Enrollment flow. - absl::optional<payments::PaymentsNetworkInterface:: - GetDetailsForEnrollmentResponseDetails> - get_details_for_enrollment_response_details = absl::nullopt, + std::optional<payments::PaymentsNetworkInterface:: + GetDetailsForEnrollmentResponseDetails> + get_details_for_enrollment_response_details = std::nullopt, // |user_prefs| will be populated if we are in the Android settings page, // to then be used for loading risk data. Otherwise it will always be // nullptr, and we should load risk data through |autofill_client_| as we @@ -160,12 +160,12 @@ void Enroll( // The callback lets the Android Settings page know whether // (un)enrollment was successful. - absl::optional<VirtualCardEnrollmentUpdateResponseCallback> + std::optional<VirtualCardEnrollmentUpdateResponseCallback> virtual_card_enrollment_update_response_callback); // Unenrolls the card mapped to the given |instrument_id|. void Unenroll(int64_t instrument_id, - absl::optional<VirtualCardEnrollmentUpdateResponseCallback> + std::optional<VirtualCardEnrollmentUpdateResponseCallback> virtual_card_enrollment_update_response_callback); // Returns true if a credit card identified by its |instrument_id| should be @@ -252,7 +252,7 @@ // Callback triggered after getting server response about the success of // virtual card (un)enrollment. - absl::optional<VirtualCardEnrollmentUpdateResponseCallback> + std::optional<VirtualCardEnrollmentUpdateResponseCallback> virtual_card_enrollment_update_response_callback_; // Cancels the entire Virtual Card enrollment process. @@ -372,10 +372,10 @@ // VirtualCardEnrollBubble, we will take the difference between the current // timestamp and |save_card_bubble_accepted_timestamp_| to log as the latency // metric. |save_card_bubble_accepted_timestamp_| will then be reset. - absl::optional<base::Time> save_card_bubble_accepted_timestamp_; + std::optional<base::Time> save_card_bubble_accepted_timestamp_; // The timestamp when a GetDetailsForEnrollment request is sent. - absl::optional<base::Time> get_details_for_enrollment_request_sent_timestamp_; + std::optional<base::Time> get_details_for_enrollment_request_sent_timestamp_; base::WeakPtrFactory<VirtualCardEnrollmentManager> weak_ptr_factory_{this}; };
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc b/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc index 3b344ac4..dc63a79 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc
@@ -200,7 +200,7 @@ #endif virtual_card_enrollment_manager_->InitVirtualCardEnroll( - *card_, virtual_card_enrollment_source, absl::nullopt, + *card_, virtual_card_enrollment_source, std::nullopt, virtual_card_enrollment_manager_->AutofillClientIsPresent() ? user_prefs() : nullptr, @@ -242,8 +242,8 @@ issuer_test_legal_message_line}; get_details_for_enrollment_response_details.vcn_context_token = "vcn_context_token"; - absl::optional<payments::PaymentsNetworkInterface:: - GetDetailsForEnrollmentResponseDetails> + std::optional<payments::PaymentsNetworkInterface:: + GetDetailsForEnrollmentResponseDetails> get_details_for_enrollment_response_details_optional = get_details_for_enrollment_response_details; virtual_card_enrollment_manager_->InitVirtualCardEnroll( @@ -493,7 +493,7 @@ payments_network_interface().set_update_virtual_card_enrollment_result( AutofillClient::PaymentsRpcResult::kSuccess); virtual_card_enrollment_manager_->Enroll( - /*virtual_card_enrollment_update_response_callback=*/absl::nullopt); + /*virtual_card_enrollment_update_response_callback=*/std::nullopt); payments::PaymentsNetworkInterface:: UpdateVirtualCardEnrollmentRequestDetails request_details = @@ -536,7 +536,7 @@ payments_network_interface().set_update_virtual_card_enrollment_result( AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure); virtual_card_enrollment_manager_->Enroll( - /*virtual_card_enrollment_update_response_callback=*/absl::nullopt); + /*virtual_card_enrollment_update_response_callback=*/std::nullopt); // Verifies the logging. histogram_tester.ExpectUniqueSample( @@ -557,7 +557,7 @@ virtual_card_enrollment_manager_->Unenroll( /*instrument_id=*/9223372036854775807, - /*virtual_card_enrollment_update_response_callback=*/absl::nullopt); + /*virtual_card_enrollment_update_response_callback=*/std::nullopt); payments::PaymentsNetworkInterface::UpdateVirtualCardEnrollmentRequestDetails request_details = payments_network_interface() @@ -587,7 +587,7 @@ AutofillClient::PaymentsRpcResult::kVcnRetrievalPermanentFailure); virtual_card_enrollment_manager_->Unenroll( /*instrument_id=*/9223372036854775807, - /*virtual_card_enrollment_update_response_callback=*/absl::nullopt); + /*virtual_card_enrollment_update_response_callback=*/std::nullopt); // Verifies the logging. histogram_tester.ExpectUniqueSample( @@ -620,7 +620,7 @@ // Ensure a strike has been removed after enrollment accepted. virtual_card_enrollment_manager_->Enroll( - /*virtual_card_enrollment_update_response_callback=*/absl::nullopt); + /*virtual_card_enrollment_update_response_callback=*/std::nullopt); EXPECT_EQ( virtual_card_enrollment_manager_->GetVirtualCardEnrollmentStrikeDatabase() ->GetStrikes( @@ -702,7 +702,7 @@ {VirtualCardEnrollmentSource::kUpstream, VirtualCardEnrollmentSource::kDownstream}) { virtual_card_enrollment_manager_->InitVirtualCardEnroll( - *card_, source, absl::nullopt, + *card_, source, std::nullopt, virtual_card_enrollment_manager_->AutofillClientIsPresent() ? user_prefs() : nullptr, @@ -849,7 +849,7 @@ state->virtual_card_enrollment_fields.credit_card = *card_; virtual_card_enrollment_manager_->InitVirtualCardEnroll( - *card_, VirtualCardEnrollmentSource::kDownstream, absl::nullopt, + *card_, VirtualCardEnrollmentSource::kDownstream, std::nullopt, virtual_card_enrollment_manager_->AutofillClientIsPresent() ? user_prefs() : nullptr, base::DoNothing());
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 12f98501..b46e7cc8 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -53,8 +53,6 @@ #include "components/autofill/core/browser/strike_databases/autofill_profile_migration_strike_database.h" #include "components/autofill/core/browser/strike_databases/autofill_profile_save_strike_database.h" #include "components/autofill/core/browser/ui/autofill_image_fetcher.h" -#include "components/autofill/core/browser/ui/label_formatter.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" #include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_clock.h" @@ -700,7 +698,7 @@ prefs::ClearSyncTransportOptIns(pref_service_); } -absl::optional<CoreAccountInfo> PersonalDataManager::GetPrimaryAccountInfo() +std::optional<CoreAccountInfo> PersonalDataManager::GetPrimaryAccountInfo() const { if (identity_manager_ && identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSignin)) { @@ -708,7 +706,7 @@ signin::ConsentLevel::kSignin); } - return absl::nullopt; + return std::nullopt; } bool PersonalDataManager::IsPaymentsDownloadActive() const {
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 4334598..98ca6e9 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -8,6 +8,7 @@ #include <deque> #include <list> #include <memory> +#include <optional> #include <set> #include <string> #include <string_view> @@ -53,7 +54,6 @@ #include "components/sync/base/user_selectable_type.h" #include "components/sync/service/sync_service_observer.h" #include "components/webdata/common/web_data_service_consumer.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class PaymentsSuggestionBottomSheetMediatorTest; class Profile; @@ -217,9 +217,9 @@ // signin::IdentityManager::Observer: void OnAccountsCookieDeletedByUserAction() override; - // Returns the account info of currently signed-in user, or absl::nullopt if + // Returns the account info of currently signed-in user, or std::nullopt if // the user is not signed-in or the identity manager is not available. - absl::optional<CoreAccountInfo> GetPrimaryAccountInfo() const; + std::optional<CoreAccountInfo> GetPrimaryAccountInfo() const; // Returns whether credit card download is active (meaning that wallet sync is // running at least in transport mode).
diff --git a/components/autofill/core/browser/personal_data_manager_test_base.cc b/components/autofill/core/browser/personal_data_manager_test_base.cc index 176990d..4eb1d349 100644 --- a/components/autofill/core/browser/personal_data_manager_test_base.cc +++ b/components/autofill/core/browser/personal_data_manager_test_base.cc
@@ -6,6 +6,7 @@ #include "base/task/single_thread_task_runner.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/common/autofill_clock.h" namespace autofill { @@ -29,6 +30,7 @@ path, base::SingleThreadTaskRunner::GetCurrentDefault(), base::SingleThreadTaskRunner::GetCurrentDefault()); + profile_web_database_->AddTable(std::make_unique<AddressAutofillTable>()); // Hacky: hold onto a pointer but pass ownership. profile_autofill_table_ = new AutofillTable; profile_web_database_->AddTable(
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index 40e8ad4..e2ffb97 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -42,7 +42,6 @@ #include "components/autofill/core/browser/personal_data_manager_test_base.h" #include "components/autofill/core/browser/profile_token_quality_test_api.h" #include "components/autofill/core/browser/test_autofill_clock.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" #include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_constants.h" @@ -3360,20 +3359,6 @@ profile_autofill_table_->GetCreditCards(&cards); EXPECT_EQ(1U, cards.size()); EXPECT_EQ(local_card.LastFourDigits(), cards[0]->LastFourDigits()); - - // Add a local profile - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison", - "johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5", - "Hollywood", "CA", "91601", "US", "12345678910"); - AddProfileToPersonalDataManager(profile); - - std::vector<std::unique_ptr<AutofillProfile>> profiles; - // Expect that a profile is stored in the profile autofill table. - profile_autofill_table_->GetAutofillProfiles( - AutofillProfile::Source::kLocalOrSyncable, &profiles); - EXPECT_EQ(1U, profiles.size()); - EXPECT_EQ(profile, *profiles[0]); } // Tests that the least recently used profile of two existing profiles is
diff --git a/components/autofill/core/browser/server_prediction_overrides.cc b/components/autofill/core/browser/server_prediction_overrides.cc index aaa776c..733ca65 100644 --- a/components/autofill/core/browser/server_prediction_overrides.cc +++ b/components/autofill/core/browser/server_prediction_overrides.cc
@@ -4,6 +4,8 @@ #include "components/autofill/core/browser/server_prediction_overrides.h" +#include <optional> + #include "base/containers/flat_map.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" @@ -12,7 +14,6 @@ #include "base/values.h" #include "components/autofill/core/browser/proto/api_v1.pb.h" #include "components/autofill/core/common/signatures.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -27,12 +28,12 @@ constexpr std::string_view kSeparatorLevel1 = "_"; // Parses a single type prediction for a field. If unsuccessful, it returns -// `absl::nullopt`. -absl::optional<FieldPrediction> ParseSingleFieldTypePrediction( +// `std::nullopt`. +std::optional<FieldPrediction> ParseSingleFieldTypePrediction( std::string_view specification) { int32_t type = 0; if (!base::StringToInt(specification, &type)) { - return absl::nullopt; + return std::nullopt; } FieldPrediction result; @@ -50,7 +51,7 @@ FieldSuggestion result; result.mutable_predictions()->Reserve(specifications.size()); for (std::string_view spec : specifications) { - absl::optional<FieldPrediction> prediction = + std::optional<FieldPrediction> prediction = ParseSingleFieldTypePrediction(spec); if (!prediction) { return base::unexpected(
diff --git a/components/autofill/core/browser/strike_databases/payments/credit_card_save_strike_database.h b/components/autofill/core/browser/strike_databases/payments/credit_card_save_strike_database.h index ead1a9b..76cd7f69 100644 --- a/components/autofill/core/browser/strike_databases/payments/credit_card_save_strike_database.h +++ b/components/autofill/core/browser/strike_databases/payments/credit_card_save_strike_database.h
@@ -12,9 +12,9 @@ struct CreditCardSaveStrikeDatabaseTraits { static constexpr std::string_view kName = "CreditCardSave"; - static constexpr absl::optional<size_t> kMaxStrikeEntities = absl::nullopt; - static constexpr absl::optional<size_t> kMaxStrikeEntitiesAfterCleanup = - absl::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntities = std::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntitiesAfterCleanup = + std::nullopt; static constexpr size_t kMaxStrikeLimit = 3; static constexpr base::TimeDelta kExpiryTimeDelta = base::Days(183); static constexpr bool kUniqueIdRequired = true;
diff --git a/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.cc b/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.cc index f14d1a7..5bea036e 100644 --- a/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.cc +++ b/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.cc
@@ -8,7 +8,7 @@ namespace autofill { -absl::optional<base::TimeDelta> +std::optional<base::TimeDelta> CvcStorageStrikeDatabase::GetRequiredDelaySinceLastStrike() const { return base::Days(7); }
diff --git a/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.h b/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.h index 0bf3654..c8d5912 100644 --- a/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.h +++ b/components/autofill/core/browser/strike_databases/payments/cvc_storage_strike_database.h
@@ -11,9 +11,9 @@ struct CvcStorageStrikeDatabaseTraits { static constexpr std::string_view kName = "CvcStorage"; - static constexpr absl::optional<size_t> kMaxStrikeEntities = absl::nullopt; - static constexpr absl::optional<size_t> kMaxStrikeEntitiesAfterCleanup = - absl::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntities = std::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntitiesAfterCleanup = + std::nullopt; static constexpr size_t kMaxStrikeLimit = 3; static constexpr base::TimeDelta kExpiryTimeDelta = base::Days(183); static constexpr bool kUniqueIdRequired = true; @@ -25,7 +25,7 @@ using SimpleAutofillStrikeDatabase< CvcStorageStrikeDatabaseTraits>::SimpleAutofillStrikeDatabase; - absl::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() + std::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() const override; };
diff --git a/components/autofill/core/browser/strike_databases/payments/fido_authentication_strike_database.h b/components/autofill/core/browser/strike_databases/payments/fido_authentication_strike_database.h index dbba93a..4a2f9c8a 100644 --- a/components/autofill/core/browser/strike_databases/payments/fido_authentication_strike_database.h +++ b/components/autofill/core/browser/strike_databases/payments/fido_authentication_strike_database.h
@@ -12,9 +12,9 @@ struct FidoAuthenticationStrikeDatabaseTraits { static constexpr std::string_view kName = "FidoAuthentication"; - static constexpr absl::optional<size_t> kMaxStrikeEntities = absl::nullopt; - static constexpr absl::optional<size_t> kMaxStrikeEntitiesAfterCleanup = - absl::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntities = std::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntitiesAfterCleanup = + std::nullopt; static constexpr size_t kMaxStrikeLimit = 3; static constexpr base::TimeDelta kExpiryTimeDelta = base::Days(183); static constexpr bool kUniqueIdRequired = false;
diff --git a/components/autofill/core/browser/strike_databases/payments/iban_save_strike_database.h b/components/autofill/core/browser/strike_databases/payments/iban_save_strike_database.h index bdae5216..4003c8d0 100644 --- a/components/autofill/core/browser/strike_databases/payments/iban_save_strike_database.h +++ b/components/autofill/core/browser/strike_databases/payments/iban_save_strike_database.h
@@ -12,9 +12,9 @@ struct IbanSaveStrikeDatabaseTraits { static constexpr std::string_view kName = "IBANSave"; - static constexpr absl::optional<size_t> kMaxStrikeEntities = absl::nullopt; - static constexpr absl::optional<size_t> kMaxStrikeEntitiesAfterCleanup = - absl::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntities = std::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntitiesAfterCleanup = + std::nullopt; static constexpr size_t kMaxStrikeLimit = 3; static constexpr base::TimeDelta kExpiryTimeDelta = base::Days(183); static constexpr bool kUniqueIdRequired = true;
diff --git a/components/autofill/core/browser/strike_databases/payments/local_card_migration_strike_database.h b/components/autofill/core/browser/strike_databases/payments/local_card_migration_strike_database.h index 648999f..11316bf 100644 --- a/components/autofill/core/browser/strike_databases/payments/local_card_migration_strike_database.h +++ b/components/autofill/core/browser/strike_databases/payments/local_card_migration_strike_database.h
@@ -11,12 +11,12 @@ struct LocalCardMigrationStrikeDatabaseTraits { static constexpr std::string_view kName = "LocalCardMigration"; - static constexpr absl::optional<size_t> kMaxStrikeEntities = absl::nullopt; - static constexpr absl::optional<size_t> kMaxStrikeEntitiesAfterCleanup = - absl::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntities = std::nullopt; + static constexpr std::optional<size_t> kMaxStrikeEntitiesAfterCleanup = + std::nullopt; static constexpr size_t kMaxStrikeLimit = 6; - static constexpr absl::optional<base::TimeDelta> kExpiryTimeDelta = - absl::nullopt; + static constexpr std::optional<base::TimeDelta> kExpiryTimeDelta = + std::nullopt; static constexpr bool kUniqueIdRequired = false; };
diff --git a/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.cc b/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.cc index d0dbc20..186344f 100644 --- a/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.cc +++ b/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.cc
@@ -13,9 +13,9 @@ return GetStrikes(instrument_id) == GetMaxStrikesLimit() - 1; } -absl::optional<base::TimeDelta> +std::optional<base::TimeDelta> VirtualCardEnrollmentStrikeDatabase::GetRequiredDelaySinceLastStrike() const { - return absl::optional<base::TimeDelta>( + return std::optional<base::TimeDelta>( base::Days(kEnrollmentEnforcedDelayInDays)); }
diff --git a/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.h b/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.h index a1a368c..2fb82cf 100644 --- a/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.h +++ b/components/autofill/core/browser/strike_databases/payments/virtual_card_enrollment_strike_database.h
@@ -35,7 +35,7 @@ // |instrument_id|. bool IsLastOffer(const std::string& instrument_id) const; - absl::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() + std::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() const override; };
diff --git a/components/autofill/core/browser/strike_databases/simple_autofill_strike_database.h b/components/autofill/core/browser/strike_databases/simple_autofill_strike_database.h index 40337a80..3566fdd 100644 --- a/components/autofill/core/browser/strike_databases/simple_autofill_strike_database.h +++ b/components/autofill/core/browser/strike_databases/simple_autofill_strike_database.h
@@ -6,13 +6,13 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASES_SIMPLE_AUTOFILL_STRIKE_DATABASE_H_ #include <stddef.h> +#include <optional> #include <string> #include <string_view> #include "base/time/time.h" #include "components/autofill/core/browser/strike_databases/strike_database_base.h" #include "components/autofill/core/browser/strike_databases/strike_database_integrator_base.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -23,11 +23,11 @@ // // struct MyStrikeDatabaseTraits { // static constexpr std::string_view kName = "MyStrikeDatabase"; -// static constexpr absl::optional<size_t> kMaxStrikeEntities = 100; -// static constexpr absl::optional<size_t> +// static constexpr std::optional<size_t> kMaxStrikeEntities = 100; +// static constexpr std::optional<size_t> // kMaxStrikeEntitiesAfterCleanup = 70; // static constexpr size_t kMaxStrikeLimit = 3; -// static constexpr absl::optional<base::TimeDelta> kExpiryTimeDelta = +// static constexpr std::optional<base::TimeDelta> kExpiryTimeDelta = // base::Days(180); // static constexpr bool kUniqueIdRequired = true; // }; @@ -45,17 +45,17 @@ } ~SimpleAutofillStrikeDatabase() override = default; - absl::optional<size_t> GetMaximumEntries() const override { + std::optional<size_t> GetMaximumEntries() const override { return Traits::kMaxStrikeEntities; } - absl::optional<size_t> GetMaximumEntriesAfterCleanup() const override { + std::optional<size_t> GetMaximumEntriesAfterCleanup() const override { return Traits::kMaxStrikeEntitiesAfterCleanup; } std::string GetProjectPrefix() const override { return std::string(Traits::kName); } int GetMaxStrikesLimit() const override { return Traits::kMaxStrikeLimit; } - absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override { + std::optional<base::TimeDelta> GetExpiryTimeDelta() const override { return Traits::kExpiryTimeDelta; } bool UniqueIdsRequired() const override { return Traits::kUniqueIdRequired; }
diff --git a/components/autofill/core/browser/strike_databases/simple_autofill_strike_database_unittest.cc b/components/autofill/core/browser/strike_databases/simple_autofill_strike_database_unittest.cc index 62660564..b02cb88b 100644 --- a/components/autofill/core/browser/strike_databases/simple_autofill_strike_database_unittest.cc +++ b/components/autofill/core/browser/strike_databases/simple_autofill_strike_database_unittest.cc
@@ -24,8 +24,8 @@ static constexpr size_t kMaxStrikeEntities = 100; static constexpr size_t kMaxStrikeEntitiesAfterCleanup = 50; static constexpr size_t kMaxStrikeLimit = 3; - static constexpr absl::optional<base::TimeDelta> kExpiryTimeDelta = - absl::nullopt; + static constexpr std::optional<base::TimeDelta> kExpiryTimeDelta = + std::nullopt; static constexpr bool kUniqueIdRequired = true; };
diff --git a/components/autofill/core/browser/strike_databases/strike_database_integrator_base.cc b/components/autofill/core/browser/strike_databases/strike_database_integrator_base.cc index e573bd1fb..ab007b8 100644 --- a/components/autofill/core/browser/strike_databases/strike_database_integrator_base.cc +++ b/components/autofill/core/browser/strike_databases/strike_database_integrator_base.cc
@@ -221,18 +221,18 @@ return GetProjectPrefix() + kKeyDeliminator + id; } -absl::optional<size_t> StrikeDatabaseIntegratorBase::GetMaximumEntries() const { - return absl::nullopt; +std::optional<size_t> StrikeDatabaseIntegratorBase::GetMaximumEntries() const { + return std::nullopt; } -absl::optional<size_t> +std::optional<size_t> StrikeDatabaseIntegratorBase::GetMaximumEntriesAfterCleanup() const { - return absl::nullopt; + return std::nullopt; } -absl::optional<base::TimeDelta> +std::optional<base::TimeDelta> StrikeDatabaseIntegratorBase::GetRequiredDelaySinceLastStrike() const { - return absl::nullopt; + return std::nullopt; } } // namespace autofill
diff --git a/components/autofill/core/browser/strike_databases/strike_database_integrator_base.h b/components/autofill/core/browser/strike_databases/strike_database_integrator_base.h index 3fc358c..24372d7 100644 --- a/components/autofill/core/browser/strike_databases/strike_database_integrator_base.h +++ b/components/autofill/core/browser/strike_databases/strike_database_integrator_base.h
@@ -7,6 +7,7 @@ #include <stdint.h> #include <map> +#include <optional> #include <string> #include <vector> @@ -15,7 +16,6 @@ #include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "components/autofill/core/browser/strike_databases/strike_database_base.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -145,13 +145,13 @@ std::string GetKey(const std::string& id) const; // Returns the maximum number of entries that should be stored for this - // project prefix. absl::nullopt means that there is no limit. - virtual absl::optional<size_t> GetMaximumEntries() const; + // project prefix. std::nullopt means that there is no limit. + virtual std::optional<size_t> GetMaximumEntries() const; // Returns the maximum number of entries that should remain after a cleanup. // This number should be smaller then `GetMaximumEntries()` to create some - // headroom. absl::nullopt means that `GetMaximumEntries()` should be used. - virtual absl::optional<size_t> GetMaximumEntriesAfterCleanup() const; + // headroom. std::nullopt means that `GetMaximumEntries()` should be used. + virtual std::optional<size_t> GetMaximumEntriesAfterCleanup() const; // Returns a prefix unique to each project, which will be used to create // database key. @@ -163,7 +163,7 @@ // Returns the time delta after which the most recent strike should expire. // If the Optional is empty, then strikes don't expire. - virtual absl::optional<base::TimeDelta> GetExpiryTimeDelta() const = 0; + virtual std::optional<base::TimeDelta> GetExpiryTimeDelta() const = 0; // Returns whether or not a unique string identifier is required for every // strike in this project. @@ -172,7 +172,7 @@ // Returns the time delta to wait for before prompting the feature again. If // the Optional is empty, then there is no required delay during which the // feature is blocked. - virtual absl::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() + virtual std::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() const; };
diff --git a/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.cc b/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.cc index b03ef1c..68d9785 100644 --- a/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.cc +++ b/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.cc
@@ -13,7 +13,7 @@ StrikeDatabaseIntegratorTestStrikeDatabase:: StrikeDatabaseIntegratorTestStrikeDatabase( StrikeDatabase* strike_database, - absl::optional<base::TimeDelta> expiry_time_delta) + std::optional<base::TimeDelta> expiry_time_delta) : StrikeDatabaseIntegratorTestStrikeDatabase(strike_database) { expiry_time_delta_ = expiry_time_delta; } @@ -27,7 +27,7 @@ StrikeDatabaseIntegratorTestStrikeDatabase:: StrikeDatabaseIntegratorTestStrikeDatabase( StrikeDatabase* strike_database, - absl::optional<base::TimeDelta> expiry_time_delta, + std::optional<base::TimeDelta> expiry_time_delta, std::string& project_prefix) : StrikeDatabaseIntegratorTestStrikeDatabase(strike_database, expiry_time_delta) { @@ -46,7 +46,7 @@ return kMaxStrikesLimit; } -absl::optional<base::TimeDelta> +std::optional<base::TimeDelta> StrikeDatabaseIntegratorTestStrikeDatabase::GetExpiryTimeDelta() const { return expiry_time_delta_; } @@ -66,18 +66,18 @@ required_delay_since_last_strike_ = required_delay_since_last_strike; } -absl::optional<size_t> +std::optional<size_t> StrikeDatabaseIntegratorTestStrikeDatabase::GetMaximumEntries() const { return maximum_entries_; } -absl::optional<size_t> +std::optional<size_t> StrikeDatabaseIntegratorTestStrikeDatabase::GetMaximumEntriesAfterCleanup() const { return maximum_entries_after_cleanup_; } -absl::optional<base::TimeDelta> +std::optional<base::TimeDelta> StrikeDatabaseIntegratorTestStrikeDatabase::GetRequiredDelaySinceLastStrike() const { return required_delay_since_last_strike_;
diff --git a/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.h b/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.h index 7eab8bb..59add9a 100644 --- a/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.h +++ b/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database.h
@@ -21,25 +21,25 @@ public: StrikeDatabaseIntegratorTestStrikeDatabase( StrikeDatabase* strike_database, - absl::optional<base::TimeDelta> expiry_time_delta); + std::optional<base::TimeDelta> expiry_time_delta); explicit StrikeDatabaseIntegratorTestStrikeDatabase( StrikeDatabase* strike_database); // This constructor initializes the TestStrikeDatabase with a non-default // project prefix. StrikeDatabaseIntegratorTestStrikeDatabase( StrikeDatabase* strike_database, - absl::optional<base::TimeDelta> expiry_time_delta, + std::optional<base::TimeDelta> expiry_time_delta, std::string& project_prefix); ~StrikeDatabaseIntegratorTestStrikeDatabase() override; - absl::optional<size_t> GetMaximumEntries() const override; - absl::optional<size_t> GetMaximumEntriesAfterCleanup() const override; + std::optional<size_t> GetMaximumEntries() const override; + std::optional<size_t> GetMaximumEntriesAfterCleanup() const override; std::string GetProjectPrefix() const override; int GetMaxStrikesLimit() const override; - absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override; + std::optional<base::TimeDelta> GetExpiryTimeDelta() const override; bool UniqueIdsRequired() const override; - absl::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() + std::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike() const override; void SetUniqueIdsRequired(bool unique_ids_required); @@ -48,13 +48,13 @@ private: bool unique_ids_required_ = false; - absl::optional<base::TimeDelta> expiry_time_delta_ = base::Days(365); + std::optional<base::TimeDelta> expiry_time_delta_ = base::Days(365); - absl::optional<size_t> maximum_entries_ = 10; - absl::optional<size_t> maximum_entries_after_cleanup_ = 5; + std::optional<size_t> maximum_entries_ = 10; + std::optional<size_t> maximum_entries_after_cleanup_ = 5; std::string project_prefix_ = "StrikeDatabaseIntegratorTest"; - absl::optional<base::TimeDelta> required_delay_since_last_strike_ = - absl::nullopt; + std::optional<base::TimeDelta> required_delay_since_last_strike_ = + std::nullopt; }; } // namespace autofill
diff --git a/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database_unittest.cc b/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database_unittest.cc index 5ada36c..b7d6e8c5 100644 --- a/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database_unittest.cc +++ b/components/autofill/core/browser/strike_databases/strike_database_integrator_test_strike_database_unittest.cc
@@ -39,7 +39,7 @@ strike_database_service_.get()); no_expiry_strike_database_ = std::make_unique<StrikeDatabaseIntegratorTestStrikeDatabase>( - strike_database_service_.get(), absl::nullopt); + strike_database_service_.get(), std::nullopt); } void TearDown() override { @@ -225,7 +225,7 @@ other_strike_database = std::make_unique<StrikeDatabaseIntegratorTestStrikeDatabase>( strike_database_service_.get(), - /*expiry_time_micros=*/absl::nullopt, other_project_prefix); + /*expiry_time_micros=*/std::nullopt, other_project_prefix); // Add a strike to both integrators. strike_database_->AddStrike();
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h index a72e4e69..5ce26f4 100644 --- a/components/autofill/core/browser/test_autofill_client.h +++ b/components/autofill/core/browser/test_autofill_client.h
@@ -837,11 +837,11 @@ AutofillErrorDialogContext autofill_error_dialog_context_; // Populated if save was offered. True if bubble was shown, false otherwise. - absl::optional<bool> offer_to_save_credit_card_bubble_was_shown_; + std::optional<bool> offer_to_save_credit_card_bubble_was_shown_; // Populated if name fix flow was offered. True if bubble was shown, false // otherwise. - absl::optional<bool> credit_card_name_fix_flow_bubble_was_shown_; + std::optional<bool> credit_card_name_fix_flow_bubble_was_shown_; version_info::Channel channel_for_testing_ = version_info::Channel::UNKNOWN; @@ -859,7 +859,7 @@ std::unique_ptr<AutofillCrowdsourcingManager> crowdsourcing_manager_; // Populated if credit card local save or upload was offered. - absl::optional<AutofillClient::SaveCreditCardOptions> + std::optional<AutofillClient::SaveCreditCardOptions> save_credit_card_options_; // User decision when credit card / CVC local save or upload was offered.
diff --git a/components/autofill/core/browser/test_autofill_driver.h b/components/autofill/core/browser/test_autofill_driver.h index e379082d..1d96efa 100644 --- a/components/autofill/core/browser/test_autofill_driver.h +++ b/components/autofill/core/browser/test_autofill_driver.h
@@ -49,7 +49,7 @@ // AutofillDriver: LocalFrameToken GetFrameToken() const override { return frame_token_; } TestAutofillDriverTemplate* GetParent() override { return parent_; } - absl::optional<LocalFrameToken> Resolve(FrameToken query) override { + std::optional<LocalFrameToken> Resolve(FrameToken query) override { if (auto* local_frame_token = absl::get_if<LocalFrameToken>(&query)) { return *local_frame_token; } @@ -57,7 +57,7 @@ if (it != remote_frame_tokens_.end()) { return it->second; } - return absl::nullopt; + return std::nullopt; } bool IsInActiveFrame() const override { return is_in_active_frame_; } bool IsInAnyMainFrame() const override { return is_in_any_main_frame_; }
diff --git a/components/autofill/core/browser/test_browser_autofill_manager.cc b/components/autofill/core/browser/test_browser_autofill_manager.cc index 31474ca..247f82f5 100644 --- a/components/autofill/core/browser/test_browser_autofill_manager.cc +++ b/components/autofill/core/browser/test_browser_autofill_manager.cc
@@ -119,8 +119,9 @@ run_loop_->Quit(); } - if (expected_observed_submission_ != absl::nullopt) + if (expected_observed_submission_ != std::nullopt) { EXPECT_EQ(expected_observed_submission_, observed_submission); + } // If we have expected field types set, make sure they match. if (!expected_submitted_field_types_.empty()) {
diff --git a/components/autofill/core/browser/test_browser_autofill_manager.h b/components/autofill/core/browser/test_browser_autofill_manager.h index aae2099b..efb7ff6b 100644 --- a/components/autofill/core/browser/test_browser_autofill_manager.h +++ b/components/autofill/core/browser/test_browser_autofill_manager.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_BROWSER_AUTOFILL_MANAGER_H_ #include <memory> +#include <optional> #include <string> #include <utility> #include <vector> @@ -14,7 +15,6 @@ #include "base/time/time.h" #include "components/autofill/core/browser/autofill_trigger_details.h" #include "components/autofill/core/browser/browser_autofill_manager.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/image/image_unittest_util.h" namespace autofill { @@ -130,7 +130,7 @@ private: bool autofill_profile_enabled_ = true; bool autofill_payment_methods_enabled_ = true; - absl::optional<bool> expected_observed_submission_; + std::optional<bool> expected_observed_submission_; const gfx::Image card_image_ = gfx::test::CreateImage(40, 24); std::unique_ptr<base::RunLoop> run_loop_;
diff --git a/components/autofill/core/browser/test_personal_data_manager.h b/components/autofill/core/browser/test_personal_data_manager.h index c38906e..7855e7b 100644 --- a/components/autofill/core/browser/test_personal_data_manager.h +++ b/components/autofill/core/browser/test_personal_data_manager.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_PERSONAL_DATA_MANAGER_H_ #include <memory> +#include <optional> #include <string> #include <string_view> #include <utility> @@ -20,7 +21,6 @@ #include "components/autofill/core/browser/strike_databases/autofill_profile_migration_strike_database.h" #include "components/autofill/core/browser/strike_databases/test_inmemory_strike_database.h" #include "components/signin/public/identity_manager/account_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -176,14 +176,14 @@ std::string timezone_country_code_; std::string default_country_code_; int num_times_save_imported_credit_card_called_ = 0; - absl::optional<bool> autofill_profile_enabled_; - absl::optional<bool> autofill_payment_methods_enabled_; - absl::optional<bool> autofill_wallet_import_enabled_; - absl::optional<bool> eligible_for_account_storage_; - absl::optional<bool> payment_methods_mandatory_reauth_enabled_; - absl::optional<bool> payments_wallet_sync_transport_enabled_; + std::optional<bool> autofill_profile_enabled_; + std::optional<bool> autofill_payment_methods_enabled_; + std::optional<bool> autofill_wallet_import_enabled_; + std::optional<bool> eligible_for_account_storage_; + std::optional<bool> payment_methods_mandatory_reauth_enabled_; + std::optional<bool> payments_wallet_sync_transport_enabled_; CoreAccountInfo account_info_; - absl::optional<bool> payments_cvc_storage_enabled_; + std::optional<bool> payments_cvc_storage_enabled_; TestInMemoryStrikeDatabase inmemory_strike_database_; AutofillProfileMigrationStrikeDatabase
diff --git a/components/autofill/core/browser/test_utils/vote_uploads_test_matchers.h b/components/autofill/core/browser/test_utils/vote_uploads_test_matchers.h index 2c11e858b..7a2aa65 100644 --- a/components/autofill/core/browser/test_utils/vote_uploads_test_matchers.h +++ b/components/autofill/core/browser/test_utils/vote_uploads_test_matchers.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_UTILS_VOTE_UPLOADS_TEST_MATCHERS_H_ #include <initializer_list> +#include <optional> #include <string> #include "components/autofill/core/browser/proto/server.pb.h"
diff --git a/components/autofill/core/browser/ui/accessory_sheet_data.h b/components/autofill/core/browser/ui/accessory_sheet_data.h index b556175..7a715e2 100644 --- a/components/autofill/core/browser/ui/accessory_sheet_data.h +++ b/components/autofill/core/browser/ui/accessory_sheet_data.h
@@ -5,13 +5,13 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ACCESSORY_SHEET_DATA_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ACCESSORY_SHEET_DATA_H_ +#include <optional> #include <string> #include <utility> #include <vector> #include "base/types/strong_alias.h" #include "components/autofill/core/browser/ui/accessory_sheet_enums.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace autofill { @@ -280,7 +280,7 @@ void set_option_toggle(OptionToggle toggle) { option_toggle_ = std::move(toggle); } - const absl::optional<OptionToggle>& option_toggle() const { + const std::optional<OptionToggle>& option_toggle() const { return option_toggle_; } @@ -328,7 +328,7 @@ AccessoryTabType sheet_type_; std::u16string title_; std::u16string warning_; - absl::optional<OptionToggle> option_toggle_; + std::optional<OptionToggle> option_toggle_; std::vector<PasskeySection> passkey_section_list_; std::vector<UserInfo> user_info_list_; std::vector<PromoCodeInfo> promo_code_info_list_;
diff --git a/components/autofill/core/browser/ui/address_combobox_model.cc b/components/autofill/core/browser/ui/address_combobox_model.cc index 97b636b..817d114 100644 --- a/components/autofill/core/browser/ui/address_combobox_model.cc +++ b/components/autofill/core/browser/ui/address_combobox_model.cc
@@ -72,7 +72,7 @@ return index == 1; } -absl::optional<size_t> AddressComboboxModel::GetDefaultIndex() const { +std::optional<size_t> AddressComboboxModel::GetDefaultIndex() const { if (!default_selected_guid_.empty()) { const auto index = GetIndexOfIdentifier(default_selected_guid_); if (index.has_value()) @@ -96,13 +96,13 @@ return addresses_[index - kNbHeaderEntries].first; } -absl::optional<size_t> AddressComboboxModel::GetIndexOfIdentifier( +std::optional<size_t> AddressComboboxModel::GetIndexOfIdentifier( const std::string& identifier) const { for (size_t i = 0; i < addresses_.size(); ++i) { if (addresses_[i].first == identifier) return i + kNbHeaderEntries; } - return absl::nullopt; + return std::nullopt; } void AddressComboboxModel::UpdateAddresses() {
diff --git a/components/autofill/core/browser/ui/address_combobox_model.h b/components/autofill/core/browser/ui/address_combobox_model.h index ca9e4fd..615f1ba6 100644 --- a/components/autofill/core/browser/ui/address_combobox_model.h +++ b/components/autofill/core/browser/ui/address_combobox_model.h
@@ -39,7 +39,7 @@ size_t GetItemCount() const override; std::u16string GetItemAt(size_t index) const override; bool IsItemSeparatorAt(size_t index) const override; - absl::optional<size_t> GetDefaultIndex() const override; + std::optional<size_t> GetDefaultIndex() const override; // Adds |profile| to model and return its combobox index. The lifespan of // |profile| beyond this call is undefined so a copy must be made. @@ -51,7 +51,7 @@ // Returns the combobox index of the item with the given id or nullopt if it's // not found. - absl::optional<size_t> GetIndexOfIdentifier( + std::optional<size_t> GetIndexOfIdentifier( const std::string& identifier) const; private:
diff --git a/components/autofill/core/browser/ui/address_contact_form_label_formatter.cc b/components/autofill/core/browser/ui/address_contact_form_label_formatter.cc deleted file mode 100644 index cc816c8..0000000 --- a/components/autofill/core/browser/ui/address_contact_form_label_formatter.cc +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2019 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/ui/address_contact_form_label_formatter.h" - -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" - -namespace autofill { - -AddressContactFormLabelFormatter::AddressContactFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types) - : LabelFormatter(profiles, - app_locale, - focused_field_type, - groups, - field_types), - form_has_street_address_(HasStreetAddress(field_types_for_labels())), - email_disambiguates_(!HaveSameEmailAddresses(profiles, app_locale)), - phone_disambiguates_(!HaveSamePhoneNumbers(profiles, app_locale)) {} - -AddressContactFormLabelFormatter::~AddressContactFormLabelFormatter() = default; - -// Note that the order in which parts of the label are added--name, street -// address, phone, and email--ensures that the label is formatted correctly for -// |focused_group|, |focused_field_type_|, and this kind of formatter. -std::u16string AddressContactFormLabelFormatter::GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - std::vector<std::u16string> label_parts; - - bool street_address_is_focused = focused_group == FieldTypeGroup::kAddress && - IsStreetAddressPart(focused_field_type()); - bool non_street_address_is_focused = - focused_group == FieldTypeGroup::kAddress && - !IsStreetAddressPart(focused_field_type()); - - if (focused_group != FieldTypeGroup::kName && - !non_street_address_is_focused && data_util::ContainsName(groups())) { - AddLabelPartIfNotEmpty( - GetLabelName(field_types_for_labels(), profile, app_locale()), - &label_parts); - } - - if (!street_address_is_focused) { - AddLabelPartIfNotEmpty( - GetLabelAddress(form_has_street_address_, profile, app_locale(), - field_types_for_labels()), - &label_parts); - } - - if (focused_group != FieldTypeGroup::kPhone && phone_disambiguates_) { - AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts); - } - - if (focused_group != FieldTypeGroup::kEmail && email_disambiguates_) { - AddLabelPartIfNotEmpty(GetLabelEmail(profile, app_locale()), &label_parts); - } - - // |label_parts| is empty if all of the following are true: - // (A) The form doesn't have a name field. - // (B) The user is focused on the street address. - // (C) The user either (i) has one profile or (ii) has multiple profiles and - // has the same phone number and email address in the profiles. - if (street_address_is_focused && label_parts.empty()) { - AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts); - } - - return ConstructLabelLine(label_parts); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/address_contact_form_label_formatter.h b/components/autofill/core/browser/ui/address_contact_form_label_formatter.h deleted file mode 100644 index 55d3c923..0000000 --- a/components/autofill/core/browser/ui/address_contact_form_label_formatter.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2019 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_UI_ADDRESS_CONTACT_FORM_LABEL_FORMATTER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_CONTACT_FORM_LABEL_FORMATTER_H_ - -#include <string> -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter.h" - -namespace autofill { - -// A LabelFormatter that creates Suggestions' disambiguating labels for forms -// with name, address, email, and phone fields. -class AddressContactFormLabelFormatter : public LabelFormatter { - public: - AddressContactFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types); - - ~AddressContactFormLabelFormatter() override; - - std::u16string GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const override; - - private: - // True if this formatter's associated form has a street address field. A - // form may have an address-related field, e.g. zip code, without having a - // street address field. If a form does not include a street address field, - // street addresses should not appear in labels. - bool form_has_street_address_; - - // True if the field disambiguates |profiles_|. - bool email_disambiguates_; - bool phone_disambiguates_; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_CONTACT_FORM_LABEL_FORMATTER_H_
diff --git a/components/autofill/core/browser/ui/address_contact_form_label_formatter_unittest.cc b/components/autofill/core/browser/ui/address_contact_form_label_formatter_unittest.cc deleted file mode 100644 index 6299278..0000000 --- a/components/autofill/core/browser/ui/address_contact_form_label_formatter_unittest.cc +++ /dev/null
@@ -1,457 +0,0 @@ -// Copyright 2019 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/ui/address_contact_form_label_formatter.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/strings/utf_string_conversions.h" -#include "base/uuid.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::ElementsAre; - -namespace autofill { -namespace { - -FieldTypeSet GetFieldTypes() { - return {NO_SERVER_DATA, NAME_FULL, - EMAIL_ADDRESS, ADDRESS_HOME_LINE1, - ADDRESS_HOME_LINE2, ADDRESS_HOME_DEPENDENT_LOCALITY, - ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, - ADDRESS_HOME_ZIP, ADDRESS_HOME_COUNTRY, - PHONE_HOME_WHOLE_NUMBER}; -} - -TEST(AddressContactFormLabelFormatterTest, GetLabelsWithMissingProfiles) { - const std::vector<const AutofillProfile*> profiles{}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FULL, GetFieldTypes()); - EXPECT_TRUE(formatter->GetLabels().empty()); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "L", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - "6175141600"); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "Deborah", "", "Katabi", "deborah@mit.edu", - "", "", "", "", "", "", "US", "6173240000"); - - AutofillProfile profile5(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile5, "", "", "", "", "", "Old North Church", - "193 Salem St", "Boston", "MA", "02113", "US", ""); - - AutofillProfile profile6(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile6, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{ - &profile1, &profile2, &profile3, &profile4, &profile5, &profile6}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FULL, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"19 North Sq", u"(617) 523-2338", - u"sarah.revere@aol.com"}), - ConstructLabelLine({u"151 Irving Ave", u"(617) 514-1600"}), - ConstructLabelLine({u"19 North Sq", u"paul1775@gmail.com"}), - ConstructLabelLine({u"(617) 324-0000", u"deborah@mit.edu"}), - u"Old North Church, 193 Salem St", std::u16string())); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "L", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - "6175141600"); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "Deborah", "", "Katabi", "deborah@mit.edu", - "", "", "", "", "", "", "US", "6173240000"); - - AutofillProfile profile5(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile5, "", "", "", "", "", "Old North Church", - "193 Salem St", "Boston", "MA", "02113", "US", ""); - - AutofillProfile profile6(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile6, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{ - &profile1, &profile2, &profile3, &profile4, &profile5, &profile6}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Sarah Revere", u"(617) 523-2338", - u"sarah.revere@aol.com"}), - ConstructLabelLine({u"Jackie L Kennedy", u"(617) 514-1600"}), - ConstructLabelLine({u"Paul Revere", u"paul1775@gmail.com"}), - ConstructLabelLine({u"Deborah Katabi", u"(617) 324-0000", - u"deborah@mit.edu"}), - u"", std::u16string())); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "L", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - "6175141600"); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "Deborah", "", "Katabi", "deborah@mit.edu", - "", "", "", "", "", "", "US", "6173240000"); - - AutofillProfile profile5(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile5, "", "", "", "", "", "Old North Church", - "193 Salem St", "Boston", "MA", "02113", "US", ""); - - AutofillProfile profile6(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile6, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{ - &profile1, &profile2, &profile3, &profile4, &profile5, &profile6}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_CITY, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"19 North Sq", u"(617) 523-2338", - u"sarah.revere@aol.com"}), - ConstructLabelLine({u"151 Irving Ave", u"(617) 514-1600"}), - ConstructLabelLine({u"19 North Sq", u"paul1775@gmail.com"}), - ConstructLabelLine({u"(617) 324-0000", u"deborah@mit.edu"}), - u"Old North Church, 193 Salem St", std::u16string())); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedEmail) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "L", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - "6175141600"); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "Deborah", "", "Katabi", "deborah@mit.edu", - "", "", "", "", "", "", "US", "6173240000"); - - AutofillProfile profile5(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile5, "", "", "", "", "", "Old North Church", - "193 Salem St", "Boston", "MA", "02113", "US", ""); - - AutofillProfile profile6(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile6, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{ - &profile1, &profile2, &profile3, &profile4, &profile5, &profile6}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", EMAIL_ADDRESS, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine( - {u"Sarah Revere", u"19 North Sq", u"(617) 523-2338"}), - ConstructLabelLine({u"Jackie L Kennedy", u"151 Irving Ave", - u"(617) 514-1600"}), - ConstructLabelLine({u"Paul Revere", u"19 North Sq"}), - ConstructLabelLine({u"Deborah Katabi", u"(617) 324-0000"}), - u"Old North Church, 193 Salem St", std::u16string())); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedPhone) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "L", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - "6175141600"); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "Deborah", "", "Katabi", "deborah@mit.edu", - "", "", "", "", "", "", "US", "6173240000"); - - AutofillProfile profile5(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile5, "", "", "", "", "", "Old North Church", - "193 Salem St", "Boston", "MA", "02113", "US", ""); - - AutofillProfile profile6(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile6, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{ - &profile1, &profile2, &profile3, &profile4, &profile5, &profile6}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Sarah Revere", u"19 North Sq", - u"sarah.revere@aol.com"}), - ConstructLabelLine({u"Jackie L Kennedy", u"151 Irving Ave"}), - ConstructLabelLine( - {u"Paul Revere", u"19 North Sq", u"paul1775@gmail.com"}), - ConstructLabelLine({u"Deborah Katabi", u"deborah@mit.edu"}), - u"Old North Church, 193 Salem St", std::u16string())); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", " SP ", " 04094-050 ", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "pt-BR", NAME_FULL, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre( - ConstructLabelLine({u"Av. Pedro Álvares Cabral, 1301", - u"(11) 2648-0254", u"tarsila@aol.com"}), - ConstructLabelLine({u"Estr. Dona Castorina, 110", u"(21) 98765-0000", - u"aavila@uol.com.br"}))); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", " SP ", " 04094-050 ", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Tarsila do Amaral", u"(11) 2648-0254", - u"tarsila@aol.com"}), - ConstructLabelLine({u"Artur Avila", u"(21) 98765-0000", - u"aavila@uol.com.br"}))); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", " SP ", " 04094-050 ", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_ZIP, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre( - ConstructLabelLine({u"Av. Pedro Álvares Cabral, 1301", - u"(11) 2648-0254", u"tarsila@aol.com"}), - ConstructLabelLine({u"Estr. Dona Castorina, 110", u"(21) 98765-0000", - u"aavila@uol.com.br"}))); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedEmail) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", " SP ", " 04094-050 ", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "pt-BR", EMAIL_ADDRESS, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Tarsila do Amaral", - u"Av. Pedro Álvares Cabral, 1301", - u"(11) 2648-0254"}), - ConstructLabelLine({u"Artur Avila", - u"Estr. Dona Castorina, 110", - u"(21) 98765-0000"}))); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedPhone) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", " SP ", " 04094-050 ", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", PHONE_HOME_WHOLE_NUMBER, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Tarsila do Amaral", - u"Av. Pedro Álvares Cabral, 1301", - u"tarsila@aol.com"}), - ConstructLabelLine({u"Artur Avila", - u"Estr. Dona Castorina, 110", - u"aavila@uol.com.br"}))); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForFormWithPartialAddressFields) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", EMAIL_ADDRESS, - {NAME_FULL, EMAIL_ADDRESS, ADDRESS_HOME_ZIP, PHONE_HOME_WHOLE_NUMBER}); - - // Checks that only address fields in the form are shown in the label. - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Sarah Revere", u"02113"}))); -} - -TEST(AddressContactFormLabelFormatterTest, - GetLabelsForFormWithoutName_FocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - std::vector<const AutofillProfile*> profiles{&profile1}; - std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, - {ADDRESS_HOME_ZIP, EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}); - - // Checks that the name is not in the label and that the phone number is for - // a unique profile. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"(617) 523-2338")); - - profiles = {&profile1, &profile1}; - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - {ADDRESS_HOME_LINE1, ADDRESS_HOME_ZIP, - EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}); - - // Checks that the name is not in the label and that the phone number is for - // multiple profiles with the same phone number and email address. - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"(617) 523-2338", u"(617) 523-2338")); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Sarah", "", "Revere", "sarah@gmail.com", "", - "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - profiles = {&profile1, &profile2}; - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - {ADDRESS_HOME_LINE1, ADDRESS_HOME_ZIP, - EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}); - // Checks that the name is not in the label and that the email address is - // shown because the profiles' email addresses are different. - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"sarah.revere@aol.com", u"sarah@gmail.com")); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/address_email_form_label_formatter.cc b/components/autofill/core/browser/ui/address_email_form_label_formatter.cc deleted file mode 100644 index 2b894be..0000000 --- a/components/autofill/core/browser/ui/address_email_form_label_formatter.cc +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2019 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/ui/address_email_form_label_formatter.h" - -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" - -namespace autofill { - -AddressEmailFormLabelFormatter::AddressEmailFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types) - : LabelFormatter(profiles, - app_locale, - focused_field_type, - groups, - field_types), - form_has_street_address_(HasStreetAddress(field_types_for_labels())) {} - -AddressEmailFormLabelFormatter::~AddressEmailFormLabelFormatter() = default; - -std::u16string AddressEmailFormLabelFormatter::GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - return focused_group == FieldTypeGroup::kAddress && - !IsStreetAddressPart(focused_field_type()) - ? GetLabelForProfileOnFocusedNonStreetAddress( - form_has_street_address_, profile, app_locale(), - field_types_for_labels(), - GetLabelEmail(profile, app_locale())) - : GetLabelForProfileOnFocusedNameEmailOrStreetAddress( - profile, focused_group); -} - -// Note that the order--name, address, and email--in which parts of the label -// are added ensures that the label is formatted correctly for |focused_group|, -// |focused_field_type_| and for this kind of formatter. -std::u16string AddressEmailFormLabelFormatter:: - GetLabelForProfileOnFocusedNameEmailOrStreetAddress( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - std::vector<std::u16string> label_parts; - - if (focused_group != FieldTypeGroup::kName && - data_util::ContainsName(groups())) { - AddLabelPartIfNotEmpty( - GetLabelName(field_types_for_labels(), profile, app_locale()), - &label_parts); - } - - if (focused_group != FieldTypeGroup::kAddress) { - AddLabelPartIfNotEmpty( - GetLabelAddress(form_has_street_address_, profile, app_locale(), - field_types_for_labels()), - &label_parts); - } - - if (focused_group != FieldTypeGroup::kEmail) { - AddLabelPartIfNotEmpty(GetLabelEmail(profile, app_locale()), &label_parts); - } - - return ConstructLabelLine(label_parts); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/address_email_form_label_formatter.h b/components/autofill/core/browser/ui/address_email_form_label_formatter.h deleted file mode 100644 index 658dc4b..0000000 --- a/components/autofill/core/browser/ui/address_email_form_label_formatter.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2019 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_UI_ADDRESS_EMAIL_FORM_LABEL_FORMATTER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_EMAIL_FORM_LABEL_FORMATTER_H_ - -#include <string> -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter.h" - -namespace autofill { - -// A LabelFormatter that creates Suggestions' disambiguating labels for forms -// with name, address, and email fields and without phone fields. -class AddressEmailFormLabelFormatter : public LabelFormatter { - public: - AddressEmailFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types); - - ~AddressEmailFormLabelFormatter() override; - - std::u16string GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const override; - - private: - // Returns a label to show the user when |focused_field_type_| is a type - // other than a non-street-address field type. For example, - // |focused_field_type_| could be last name, home street address, or email - // address. - std::u16string GetLabelForProfileOnFocusedNameEmailOrStreetAddress( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const; - - // True if this formatter's associated form has a street address field. A - // form may have an address-related field, e.g. zip code, without having a - // street address field. If a form does not include a street address field, - // street addresses should not appear in labels. - bool form_has_street_address_; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_EMAIL_FORM_LABEL_FORMATTER_H_
diff --git a/components/autofill/core/browser/ui/address_email_form_label_formatter_unittest.cc b/components/autofill/core/browser/ui/address_email_form_label_formatter_unittest.cc deleted file mode 100644 index 7f6b756..0000000 --- a/components/autofill/core/browser/ui/address_email_form_label_formatter_unittest.cc +++ /dev/null
@@ -1,300 +0,0 @@ -// Copyright 2019 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/ui/address_email_form_label_formatter.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/strings/utf_string_conversions.h" -#include "base/uuid.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::ElementsAre; - -namespace autofill { -namespace { - -FieldTypeSet GetFieldTypes() { - return {NAME_FULL, - EMAIL_ADDRESS, - ADDRESS_HOME_LINE1, - ADDRESS_HOME_LINE2, - ADDRESS_HOME_CITY, - ADDRESS_HOME_STATE, - ADDRESS_HOME_DEPENDENT_LOCALITY, - ADDRESS_HOME_ZIP, - ADDRESS_HOME_COUNTRY}; -} - -TEST(AddressEmailFormLabelFormatterTest, GetLabelsWithMissingProfiles) { - const std::vector<const AutofillProfile*> profiles{}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FULL, GetFieldTypes()); - EXPECT_TRUE(formatter->GetLabels().empty()); -} - -TEST(AddressEmailFormLabelFormatterTest, GetLabelsForUSProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "", "", "", "", "", "US", ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "John", "", "Adams", "", "", "", "", "Quincy", - "MA", "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FULL, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"333 Washington St", u"jfk@gmail.com"}), - u"151 Irving Ave", u"paul1775@gmail.com", std::u16string())); -} - -TEST(AddressEmailFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "", "", "", "paul1775@gmail.com", "", "", "", - "", "", "", "US", ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "141 Franklin St", "", - "Quincy", "MA", "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John F Kennedy", u"jfk@gmail.com"}), - u"Jackie Kennedy", u"paul1775@gmail.com", std::u16string())); -} - -TEST(AddressEmailFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "", "", "", "paul1775@gmail.com", "", "", "", - "", "", "", "US", ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "", "", "Quincy", "MA", - "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_ZIP, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"333 Washington St", u"jfk@gmail.com"}), - u"151 Irving Ave", u"paul1775@gmail.com", std::u16string())); -} - -TEST(AddressEmailFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedEmail) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "jackie@outlook.com", - "", "", "", "Hyannis", "MA", "02601", "US", ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "", "", "", "paul1775@gmail.com", "", "", "", - "", "", "", "US", ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "141 Franklin St", "", - "Quincy", "MA", "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", EMAIL_ADDRESS, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John F Kennedy", u"333 Washington St"}), - u"Jackie Kennedy", std::u16string(), u"141 Franklin St")); -} - -TEST(AddressEmailFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "pt-BR", NAME_FULL, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Av. Pedro Álvares Cabral, 1301", - u"tarsila@aol.com"}), - ConstructLabelLine({u"Estr. Dona Castorina, 110", - u"aavila@uol.com.br"}))); -} - -TEST(AddressEmailFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre( - ConstructLabelLine({u"Tarsila do Amaral", u"tarsila@aol.com"}), - ConstructLabelLine({u"Artur Avila", u"aavila@uol.com.br"}))); -} - -TEST(AddressEmailFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_DEPENDENT_LOCALITY, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Av. Pedro Álvares Cabral, 1301", - u"tarsila@aol.com"}), - ConstructLabelLine({u"Estr. Dona Castorina, 110", - u"aavila@uol.com.br"}))); -} - -TEST(AddressEmailFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedEmail) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "pt-BR", EMAIL_ADDRESS, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre( - ConstructLabelLine( - {u"Tarsila do Amaral", u"Av. Pedro Álvares Cabral, 1301"}), - ConstructLabelLine({u"Artur Avila", u"Estr. Dona Castorina, 110"}))); -} - -TEST(AddressEmailFormLabelFormatterTest, - GetLabelsForFormWithAddressFieldsMinusStreetAddress) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", EMAIL_ADDRESS, - {NAME_FULL, EMAIL_ADDRESS, ADDRESS_HOME_CITY, ADDRESS_HOME_STATE}); - - // Checks that only address fields in the form are shown in the label. - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John F Kennedy", u"Brookline, MA"}))); -} - -TEST(AddressEmailFormLabelFormatterTest, GetLabelsForFormWithoutName) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, - {ADDRESS_HOME_LINE1, ADDRESS_HOME_ZIP, EMAIL_ADDRESS}); - - // Checks that the name does not appear in the labels. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"sarah.revere@aol.com")); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/address_form_label_formatter.cc b/components/autofill/core/browser/ui/address_form_label_formatter.cc deleted file mode 100644 index d0f3942d..0000000 --- a/components/autofill/core/browser/ui/address_form_label_formatter.cc +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2019 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/ui/address_form_label_formatter.h" - -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" - -namespace autofill { - -AddressFormLabelFormatter::AddressFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types) - : LabelFormatter(profiles, - app_locale, - focused_field_type, - groups, - field_types), - form_has_street_address_(HasStreetAddress(field_types_for_labels())) {} - -AddressFormLabelFormatter::~AddressFormLabelFormatter() = default; - -std::u16string AddressFormLabelFormatter::GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - if (focused_group != FieldTypeGroup::kAddress) { - return GetLabelNationalAddress(field_types_for_labels(), profile, - app_locale()); - } else { - std::vector<std::u16string> label_parts; - - if (data_util::ContainsName(groups())) { - AddLabelPartIfNotEmpty( - GetLabelName(field_types_for_labels(), profile, app_locale()), - &label_parts); - } - - AddLabelPartIfNotEmpty(GetLabelForFocusedAddress( - focused_field_type(), form_has_street_address_, - profile, app_locale(), field_types_for_labels()), - &label_parts); - return ConstructLabelLine(label_parts); - } -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/address_form_label_formatter.h b/components/autofill/core/browser/ui/address_form_label_formatter.h deleted file mode 100644 index 79cd934..0000000 --- a/components/autofill/core/browser/ui/address_form_label_formatter.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2019 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_UI_ADDRESS_FORM_LABEL_FORMATTER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_FORM_LABEL_FORMATTER_H_ - -#include <string> -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter.h" - -namespace autofill { - -// A LabelFormatter that creates Suggestions' disambiguating labels for forms -// with name and address fields and without email or phone fields. -class AddressFormLabelFormatter : public LabelFormatter { - public: - AddressFormLabelFormatter(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types); - - ~AddressFormLabelFormatter() override; - - std::u16string GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const override; - - private: - // True if this formatter's associated form has a street address field. A - // form may have an address-related field, e.g. zip code, without having a - // street address field. If a form does not include a street address field, - // street addresses should not appear in labels. - bool form_has_street_address_; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_FORM_LABEL_FORMATTER_H_
diff --git a/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc b/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc deleted file mode 100644 index ac640d0..0000000 --- a/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc +++ /dev/null
@@ -1,186 +0,0 @@ -// Copyright 2019 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/ui/address_form_label_formatter.h" - -#include <string> -#include <vector> - -#include "base/strings/utf_string_conversions.h" -#include "base/uuid.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::ElementsAre; - -namespace autofill { -namespace { - -FieldTypeSet GetFieldTypes() { - return {NO_SERVER_DATA, NAME_FIRST, - NAME_LAST, ADDRESS_HOME_LINE1, - ADDRESS_HOME_LINE2, ADDRESS_HOME_DEPENDENT_LOCALITY, - ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, - ADDRESS_HOME_ZIP, ADDRESS_HOME_COUNTRY}; -} - -TEST(AddressFormLabelFormatterTest, GetLabelsWithMissingProfiles) { - const std::vector<const AutofillProfile*> profiles{}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FIRST, GetFieldTypes()); - EXPECT_TRUE(formatter->GetLabels().empty()); -} - -TEST(AddressFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "", "", "", "jackie@outlook.com", "", - "151 Irving Ave", "", "Hyannis", "MA", "", "US", - "5087717796"); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "", "", "", "", "", "US", ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John Kennedy", u"Brookline, MA 02445"}), - u"Hyannis, MA", u"Paul Revere", std::u16string())); -} - -TEST(AddressFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "", "", "", "jackie@outlook.com", "", - "151 Irving Ave", "", "Hyannis", "MA", "", "US", - "5087717796"); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", - "", "", "", "", "", "", "US", ""); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_CITY, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John Kennedy", u"333 Washington St"}), - u"151 Irving Ave", u"Paul Revere", std::u16string())); -} - -TEST(AddressFormLabelFormatterTest, GetLabelsForUSProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "jackie@outlook.com", - "", "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - "5087717796"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FIRST, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"333 Washington St, Brookline, MA 02445", - u"151 Irving Ave, Hyannis, MA 02601")); -} - -TEST(AddressFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedStreetAddress) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", ""); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine( - {u"Tarsila Amaral", u"Vila Mariana, São Paulo-SP, 04094-050"}))); -} - -TEST(AddressFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", ""); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_ZIP, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine( - {u"Tarsila Amaral", u"Av. Pedro Álvares Cabral, 1301"}))); -} - -TEST(AddressFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedName) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", ""); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "pt-BR", NAME_FIRST, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"Av. Pedro Álvares Cabral, 1301, Vila Mariana, São " - u"Paulo-SP, 04094-050")); -} - -TEST(AddressFormLabelFormatterTest, GetLabelsForFormWithoutName) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, - {ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, ADDRESS_HOME_DEPENDENT_LOCALITY, - ADDRESS_HOME_ZIP}); - - // Checks that the name does not appear in the labels. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"Boston, MA 02113")); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/address_phone_form_label_formatter.cc b/components/autofill/core/browser/ui/address_phone_form_label_formatter.cc deleted file mode 100644 index 97a47ffe9..0000000 --- a/components/autofill/core/browser/ui/address_phone_form_label_formatter.cc +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2019 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/ui/address_phone_form_label_formatter.h" - -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" - -namespace autofill { - -AddressPhoneFormLabelFormatter::AddressPhoneFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types) - : LabelFormatter(profiles, - app_locale, - focused_field_type, - groups, - field_types), - form_has_street_address_(HasStreetAddress(field_types_for_labels())) {} - -AddressPhoneFormLabelFormatter::~AddressPhoneFormLabelFormatter() = default; - -std::u16string AddressPhoneFormLabelFormatter::GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - return focused_group == FieldTypeGroup::kAddress && - !IsStreetAddressPart(focused_field_type()) - ? GetLabelForProfileOnFocusedNonStreetAddress( - form_has_street_address_, profile, app_locale(), - field_types_for_labels(), - GetLabelPhone(profile, app_locale())) - : GetLabelForProfileOnFocusedNamePhoneOrStreetAddress( - profile, focused_group); -} - -// Note that the order--name, phone, and address--in which parts of the label -// are added ensures that the label is formatted correctly for |focused_group|, -// |focused_field_type_| and for this kind of formatter. -std::u16string AddressPhoneFormLabelFormatter:: - GetLabelForProfileOnFocusedNamePhoneOrStreetAddress( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - std::vector<std::u16string> label_parts; - if (focused_group != FieldTypeGroup::kName && - data_util::ContainsName(groups())) { - AddLabelPartIfNotEmpty( - GetLabelName(field_types_for_labels(), profile, app_locale()), - &label_parts); - } - - if (focused_group != FieldTypeGroup::kPhone) { - AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts); - } - - if (focused_group != FieldTypeGroup::kAddress) { - AddLabelPartIfNotEmpty( - GetLabelAddress(form_has_street_address_, profile, app_locale(), - field_types_for_labels()), - &label_parts); - } - - return ConstructLabelLine(label_parts); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/address_phone_form_label_formatter.h b/components/autofill/core/browser/ui/address_phone_form_label_formatter.h deleted file mode 100644 index 0a3ec700..0000000 --- a/components/autofill/core/browser/ui/address_phone_form_label_formatter.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2019 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_UI_ADDRESS_PHONE_FORM_LABEL_FORMATTER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_PHONE_FORM_LABEL_FORMATTER_H_ - -#include <string> -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter.h" - -namespace autofill { - -// A LabelFormatter that creates Suggestions' disambiguating labels for forms -// with name, address, and phone fields and without email fields. -class AddressPhoneFormLabelFormatter : public LabelFormatter { - public: - AddressPhoneFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types); - - ~AddressPhoneFormLabelFormatter() override; - - std::u16string GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const override; - - private: - // Returns a label to show the user when |focused_field_type_| is a type - // other than a non-street-address field type. For example, - // |focused_field_type_| could be first name, address line 1, or phone number. - std::u16string GetLabelForProfileOnFocusedNamePhoneOrStreetAddress( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const; - - // True if this formatter's associated form has a street address field. A - // form may have an address-related field, e.g. zip code, without having a - // street address field. If a form does not include a street address field, - // street addresses should not appear in labels. - bool form_has_street_address_; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_ADDRESS_PHONE_FORM_LABEL_FORMATTER_H_
diff --git a/components/autofill/core/browser/ui/address_phone_form_label_formatter_unittest.cc b/components/autofill/core/browser/ui/address_phone_form_label_formatter_unittest.cc deleted file mode 100644 index 4e685eed..0000000 --- a/components/autofill/core/browser/ui/address_phone_form_label_formatter_unittest.cc +++ /dev/null
@@ -1,295 +0,0 @@ -// Copyright 2019 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/ui/address_phone_form_label_formatter.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/strings/utf_string_conversions.h" -#include "base/uuid.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::ElementsAre; - -namespace autofill { -namespace { - -FieldTypeSet GetFieldTypes() { - return {NO_SERVER_DATA, NAME_FULL, PHONE_HOME_WHOLE_NUMBER, - ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2, ADDRESS_HOME_CITY, - ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP, ADDRESS_HOME_COUNTRY}; -} - -TEST(AddressPhoneFormLabelFormatterTest, GetLabelsWithMissingProfiles) { - const std::vector<const AutofillProfile*> profiles{}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FULL, GetFieldTypes()); - EXPECT_TRUE(formatter->GetLabels().empty()); -} - -TEST(AddressPhoneFormLabelFormatterTest, GetLabelsForUSProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "", "", "", "", "", "", - "", "US", "6175232338"); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "John", "", "Adams", "", "", "", "", "", "", - "", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_FULL, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"(617) 730-2000", u"333 Washington St"}), - u"151 Irving Ave", u"(617) 523-2338", std::u16string())); -} - -TEST(AddressPhoneFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "", "", "", "", "", "", "", "", "", "", "US", - "6175232338"); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "141 Franklin St", "", - "Quincy", "MA", "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John F Kennedy", u"(617) 730-2000"}), - u"Jackie Kennedy", u"(617) 523-2338", std::u16string())); -} - -TEST(AddressPhoneFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", - "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "", "", "", "", "", "", "", "", "", "", "US", - "6175232338"); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "", "", "Quincy", "MA", - "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_CITY, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"333 Washington St", u"(617) 730-2000"}), - u"151 Irving Ave", u"(617) 523-2338", std::u16string())); -} - -TEST(AddressPhoneFormLabelFormatterTest, - GetLabelsForUSProfilesAndFocusedPhone) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", "", "", "", - "", "", "US", ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "", "", "", "", "", "Paul Revere House", - "19 North Square", "Boston", "MA", "02113", "US", - "6175232338"); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "", "", "", "", "", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John F Kennedy", u"333 Washington St"}), - u"Jackie Kennedy", u"Paul Revere House, 19 North Square", - std::u16string())); -} - -TEST(AddressPhoneFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "pt-BR", NAME_FULL, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine( - {u"(11) 2648-0254", u"Av. Pedro Álvares Cabral, 1301"}), - ConstructLabelLine( - {u"(21) 98765-0000", u"Estr. Dona Castorina, 110"}))); -} - -TEST(AddressPhoneFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_LINE1, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Tarsila do Amaral", u"(11) 2648-0254"}), - ConstructLabelLine({u"Artur Avila", u"(21) 98765-0000"}))); -} - -TEST(AddressPhoneFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedNonStreetAddress) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", ADDRESS_HOME_ZIP, GetFieldTypes()); - - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Av. Pedro Álvares Cabral, 1301", - u"(11) 2648-0254"}), - ConstructLabelLine({u"Estr. Dona Castorina, 110", - u"(21) 98765-0000"}))); -} - -TEST(AddressPhoneFormLabelFormatterTest, - GetLabelsForBRProfilesAndFocusedPhone) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", PHONE_HOME_WHOLE_NUMBER, GetFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre( - ConstructLabelLine( - {u"Tarsila do Amaral", u"Av. Pedro Álvares Cabral, 1301"}), - ConstructLabelLine({u"Artur Avila", u"Estr. Dona Castorina, 110"}))); -} - -TEST(AddressPhoneFormLabelFormatterTest, - GetLabelsForFormWithAddressFieldsMinusStreetAddress) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, - {NAME_FULL, PHONE_HOME_WHOLE_NUMBER, ADDRESS_HOME_ZIP}); - - // Checks that only address fields in the form are shown in the label. - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John F Kennedy", u"02445"}))); -} - -TEST(AddressPhoneFormLabelFormatterTest, GetLabelsForFormWithoutName) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, - {ADDRESS_HOME_LINE1, ADDRESS_HOME_ZIP, PHONE_HOME_WHOLE_NUMBER}); - - // Checks that the name does not appear in the labels. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"(617) 523-2338")); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/autofill_image_fetcher.cc b/components/autofill/core/browser/ui/autofill_image_fetcher.cc index ebf9fea..b20aeb8f 100644 --- a/components/autofill/core/browser/ui/autofill_image_fetcher.cc +++ b/components/autofill/core/browser/ui/autofill_image_fetcher.cc
@@ -102,7 +102,7 @@ base::OnceCallback<void(std::unique_ptr<CreditCardArtImage>)> barrier_callback, const GURL& card_art_url, - const absl::optional<base::TimeTicks>& fetch_image_request_timestamp, + const std::optional<base::TimeTicks>& fetch_image_request_timestamp, const gfx::Image& card_art_image, const image_fetcher::RequestMetadata& metadata) { CHECK(fetch_image_request_timestamp.has_value());
diff --git a/components/autofill/core/browser/ui/autofill_image_fetcher.h b/components/autofill/core/browser/ui/autofill_image_fetcher.h index ec6d795..ad78d70 100644 --- a/components/autofill/core/browser/ui/autofill_image_fetcher.h +++ b/components/autofill/core/browser/ui/autofill_image_fetcher.h
@@ -8,11 +8,11 @@ #include "components/autofill/core/browser/ui/autofill_image_fetcher_base.h" #include <memory> +#include <optional> #include "base/barrier_callback.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -73,7 +73,7 @@ base::OnceCallback<void(std::unique_ptr<CreditCardArtImage>)> barrier_callback, const GURL& card_art_url, - const absl::optional<base::TimeTicks>& fetch_image_request_timestamp, + const std::optional<base::TimeTicks>& fetch_image_request_timestamp, const gfx::Image& card_art_image, const image_fetcher::RequestMetadata& metadata);
diff --git a/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc b/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc index dbcef9a..6d85ee3 100644 --- a/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc +++ b/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc
@@ -50,7 +50,7 @@ base::OnceCallback<void(std::unique_ptr<CreditCardArtImage>)> barrier_callback, const GURL& url, - const absl::optional<base::TimeTicks>& fetch_image_request_timestamp, + const std::optional<base::TimeTicks>& fetch_image_request_timestamp, const gfx::Image& image) { OnCardArtImageFetched(std::move(barrier_callback), url, fetch_image_request_timestamp, image,
diff --git a/components/autofill/core/browser/ui/contact_form_label_formatter.cc b/components/autofill/core/browser/ui/contact_form_label_formatter.cc deleted file mode 100644 index 9ffaf1e..0000000 --- a/components/autofill/core/browser/ui/contact_form_label_formatter.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2019 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/ui/contact_form_label_formatter.h" - -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" - -namespace autofill { - -ContactFormLabelFormatter::ContactFormLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types) - : LabelFormatter(profiles, - app_locale, - focused_field_type, - groups, - field_types) {} - -ContactFormLabelFormatter::~ContactFormLabelFormatter() = default; - -// Note that the order--name, phone, and email--in which parts of the label -// are possibly added ensures that the label is formatted correctly for -// |focused_group| and for this kind of formatter. -std::u16string ContactFormLabelFormatter::GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - std::vector<std::u16string> label_parts; - if (focused_group != FieldTypeGroup::kName && - data_util::ContainsName(groups())) { - AddLabelPartIfNotEmpty( - GetLabelName(field_types_for_labels(), profile, app_locale()), - &label_parts); - } - - if (focused_group != FieldTypeGroup::kPhone) { - AddLabelPartIfNotEmpty(MaybeGetPhone(profile), &label_parts); - } - - if (focused_group != FieldTypeGroup::kEmail) { - AddLabelPartIfNotEmpty(MaybeGetEmail(profile), &label_parts); - } - - return ConstructLabelLine(label_parts); -} - -std::u16string ContactFormLabelFormatter::MaybeGetEmail( - const AutofillProfile& profile) const { - return data_util::ContainsEmail(groups()) - ? GetLabelEmail(profile, app_locale()) - : std::u16string(); -} - -std::u16string ContactFormLabelFormatter::MaybeGetPhone( - const AutofillProfile& profile) const { - return data_util::ContainsPhone(groups()) - ? GetLabelPhone(profile, app_locale()) - : std::u16string(); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/contact_form_label_formatter.h b/components/autofill/core/browser/ui/contact_form_label_formatter.h deleted file mode 100644 index 0967ca65..0000000 --- a/components/autofill/core/browser/ui/contact_form_label_formatter.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2019 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_UI_CONTACT_FORM_LABEL_FORMATTER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_CONTACT_FORM_LABEL_FORMATTER_H_ - -#include <string> -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter.h" - -namespace autofill { - -// A LabelFormatter that creates Suggestions' disambiguating labels for forms -// containing name and phone or email fields. -class ContactFormLabelFormatter : public LabelFormatter { - public: - ContactFormLabelFormatter(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types); - - ~ContactFormLabelFormatter() override; - - std::u16string GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const override; - - private: - // Returns |profile|'s email address if |profile| has a valid email address - // and if this formatter's associated form has an email field. - std::u16string MaybeGetEmail(const AutofillProfile& profile) const; - - // Returns |profile|'s phone number if |profile| has a phone number and if - // this formatter's associated form has a phone field. - std::u16string MaybeGetPhone(const AutofillProfile& profile) const; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_CONTACT_FORM_LABEL_FORMATTER_H_
diff --git a/components/autofill/core/browser/ui/contact_form_label_formatter_unittest.cc b/components/autofill/core/browser/ui/contact_form_label_formatter_unittest.cc deleted file mode 100644 index 1d7b5eb..0000000 --- a/components/autofill/core/browser/ui/contact_form_label_formatter_unittest.cc +++ /dev/null
@@ -1,281 +0,0 @@ -// Copyright 2019 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/ui/contact_form_label_formatter.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/strings/utf_string_conversions.h" -#include "base/uuid.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::ElementsAre; - -namespace autofill { -namespace { - -FieldTypeSet GetNamePhoneAndEmailFieldTypes() { - return {NAME_FIRST, NAME_LAST, PHONE_HOME_WHOLE_NUMBER, EMAIL_ADDRESS}; -} - -TEST(ContactFormLabelFormatterTest, GetLabelsWithMissingProfiles) { - const std::vector<const AutofillProfile*> profiles{}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", NAME_FIRST, GetNamePhoneAndEmailFieldTypes()); - EXPECT_TRUE(formatter->GetLabels().empty()); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForUSProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "jackie@outlook.com", - "", "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "", "", "19 N Square", - "", "Boston", "MA", "02113", "US", "+1 (617) 523-2338"); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "John", "", "Adams", "", "", - "141 Franklin St.", "", "Quincy", "MA", "02169", "US", - ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", NAME_LAST, GetNamePhoneAndEmailFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"(617) 730-2000", u"jfk@gmail.com"}), - u"jackie@outlook.com", u"(617) 523-2338", std::u16string())); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForUSProfilesAndFocusedEmail) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "jackie@outlook.com", - "", "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "", "", "19 N Square", - "", "Boston", "MA", "02113", "US", "+1 (617) 523-2338"); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "141 Franklin St.", "", - "Quincy", "MA", "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", EMAIL_ADDRESS, GetNamePhoneAndEmailFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"John Kennedy", u"(617) 730-2000"}), - u"Jackie Kennedy", - ConstructLabelLine({u"Paul Revere", u"(617) 523-2338"}), - std::u16string())); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForUSProfilesAndFocusedPhone) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "jackie@outlook.com", - "", "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", - ""); - - AutofillProfile profile3(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile3, "Paul", "", "Revere", "", "", "19 N Square", - "", "Boston", "MA", "02113", "US", "+1 (617) 523-2338"); - - AutofillProfile profile4(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile4, "", "", "", "", "", "141 Franklin St.", "", - "Quincy", "MA", "02169", "US", ""); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2, - &profile3, &profile4}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, - GetNamePhoneAndEmailFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre( - ConstructLabelLine({u"John Kennedy", u"jfk@gmail.com"}), - ConstructLabelLine({u"Jackie Kennedy", u"jackie@outlook.com"}), - u"Paul Revere", std::u16string())); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedName) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", NAME_LAST, GetNamePhoneAndEmailFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre( - ConstructLabelLine({u"(11) 2648-0254", u"tarsila@aol.com"}), - ConstructLabelLine({u"(21) 98765-0000", u"aavila@uol.com.br"}))); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedEmail) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "pt-BR", EMAIL_ADDRESS, GetNamePhoneAndEmailFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Tarsila Amaral", u"(11) 2648-0254"}), - ConstructLabelLine({u"Artur Avila", u"(21) 98765-0000"}))); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedPhone) { - AutofillProfile profile1(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", - "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", - "São Paulo", "SP", "04094-050", "BR", - "+55 11 2648-0254"); - - AutofillProfile profile2(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", - "Estr. Dona Castorina, 110", "", "Jardim Botânico", - "Rio de Janeiro", "RJ", "22460-320", "BR", - "21987650000"); - - const std::vector<const AutofillProfile*> profiles{&profile1, &profile2}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "pt-BR", PHONE_HOME_WHOLE_NUMBER, - GetNamePhoneAndEmailFieldTypes()); - - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(ConstructLabelLine({u"Tarsila Amaral", u"tarsila@aol.com"}), - ConstructLabelLine({u"Artur Avila", u"aavila@uol.com.br"}))); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForNameAndPhoneWithFocusedName) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", NAME_LAST, - {NAME_FIRST, NAME_LAST, PHONE_HOME_WHOLE_NUMBER}); - - // Checks that the email address is excluded when the form does not contain an - // email field. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"(617) 730-2000")); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForNameAndPhoneWithFocusedPhone) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = - LabelFormatter::Create(profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, - {NAME_FIRST, NAME_LAST, PHONE_HOME_WHOLE_NUMBER}); - - // Checks that the email address is excluded when the form does not contain an - // email field. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"John Kennedy")); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForNameAndEmailWithFocusedName) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", NAME_LAST, {NAME_FIRST, NAME_LAST, EMAIL_ADDRESS}); - - // Checks that the phone number is excluded when the form does not contain a - // phone field. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"jfk@gmail.com")); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForNameAndEmailWithFocusedEmail) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "John", "F", "Kennedy", "jfk@gmail.com", "", - "333 Washington St", "", "Brookline", "MA", "02445", - "US", "16177302000"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", EMAIL_ADDRESS, {NAME_FIRST, NAME_LAST, EMAIL_ADDRESS}); - - // Checks that the phone number is excluded when the form does not contain a - // phone field. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"John Kennedy")); -} - -TEST(ContactFormLabelFormatterTest, GetLabelsForFormWithoutName) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - test::SetProfileInfo(&profile, "Sarah", "", "Revere", "sarah.revere@aol.com", - "", "19 North Sq", "", "Boston", "MA", "02113", "US", - "16175232338"); - - const std::vector<const AutofillProfile*> profiles{&profile}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", PHONE_HOME_COUNTRY_CODE, - {EMAIL_ADDRESS, PHONE_HOME_COUNTRY_CODE, PHONE_HOME_CITY_AND_NUMBER}); - - // Checks that the name does not appear in the labels. - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"sarah.revere@aol.com")); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/label_formatter.cc b/components/autofill/core/browser/ui/label_formatter.cc deleted file mode 100644 index eca72c00..0000000 --- a/components/autofill/core/browser/ui/label_formatter.cc +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2019 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/ui/label_formatter.h" - -#include <iterator> -#include <set> - -#include "base/ranges/algorithm.h" -#include "build/build_config.h" -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/metrics/autofill_metrics.h" -#include "components/autofill/core/browser/ui/address_contact_form_label_formatter.h" -#include "components/autofill/core/browser/ui/address_email_form_label_formatter.h" -#include "components/autofill/core/browser/ui/address_form_label_formatter.h" -#include "components/autofill/core/browser/ui/address_phone_form_label_formatter.h" -#include "components/autofill/core/browser/ui/contact_form_label_formatter.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "components/autofill/core/browser/ui/mobile_label_formatter.h" -#include "components/autofill/core/common/dense_set.h" - -namespace autofill { - -using data_util::ContainsAddress; -using data_util::ContainsEmail; -using data_util::ContainsName; -using data_util::ContainsPhone; -using data_util::bit_field_type_groups::kAddress; -using data_util::bit_field_type_groups::kEmail; -using data_util::bit_field_type_groups::kName; -using data_util::bit_field_type_groups::kPhone; - -LabelFormatter::LabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types) - : profiles_(profiles), - app_locale_(app_locale), - focused_field_type_(focused_field_type), - groups_(groups) { - const FieldTypeGroup focused_group = - GroupTypeOfServerFieldType(focused_field_type); - DenseSet<FieldTypeGroup> groups_for_labels{ - FieldTypeGroup::kName, FieldTypeGroup::kAddress, FieldTypeGroup::kEmail, - FieldTypeGroup::kPhone}; - - // If a user is focused on an address field, then parts of the address may be - // shown in the label. For example, if the user is focusing on a street - // address field, then it may be helpful to show the city in the label. - // Otherwise, the focused field should not appear in the label. - if (focused_group != FieldTypeGroup::kAddress) { - groups_for_labels.erase(focused_group); - } - - // Countries are excluded to prevent them from appearing in labels with - // national addresses. - auto can_be_shown_in_label = - [&groups_for_labels](FieldType field_type) -> bool { - return groups_for_labels.find(GroupTypeOfServerFieldType(field_type)) != - groups_for_labels.end() && - field_type != ADDRESS_HOME_COUNTRY; - }; - - base::ranges::copy_if(field_types, - std::back_inserter(field_types_for_labels_), - can_be_shown_in_label); -} - -LabelFormatter::~LabelFormatter() = default; - -std::vector<std::u16string> LabelFormatter::GetLabels() const { - std::vector<std::u16string> labels; - for (const AutofillProfile* profile : *profiles_) { - labels.push_back(GetLabelForProfile( - *profile, GroupTypeOfServerFieldType(focused_field_type_))); - } - return labels; -} - -// static -std::unique_ptr<LabelFormatter> LabelFormatter::Create( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - const FieldTypeSet& field_types) { - const uint32_t groups = data_util::DetermineGroups(field_types); - if (!data_util::IsSupportedFormType(groups)) { - return nullptr; - } - -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) - return std::make_unique<MobileLabelFormatter>( - profiles, app_locale, focused_field_type, groups, field_types); -#else - switch (groups) { - case kAddress | kEmail | kPhone: - case kName | kAddress | kEmail | kPhone: - return std::make_unique<AddressContactFormLabelFormatter>( - profiles, app_locale, focused_field_type, groups, field_types); - case kAddress | kPhone: - case kName | kAddress | kPhone: - return std::make_unique<AddressPhoneFormLabelFormatter>( - profiles, app_locale, focused_field_type, groups, field_types); - case kAddress | kEmail: - case kName | kAddress | kEmail: - return std::make_unique<AddressEmailFormLabelFormatter>( - profiles, app_locale, focused_field_type, groups, field_types); - case kAddress: - case kName | kAddress: - return std::make_unique<AddressFormLabelFormatter>( - profiles, app_locale, focused_field_type, groups, field_types); - case kEmail | kPhone: - case kName | kEmail | kPhone: - case kName | kEmail: - case kName | kPhone: - return std::make_unique<ContactFormLabelFormatter>( - profiles, app_locale, focused_field_type, groups, field_types); - default: - return nullptr; - } -#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/label_formatter.h b/components/autofill/core/browser/ui/label_formatter.h deleted file mode 100644 index 06bc0077..0000000 --- a/components/autofill/core/browser/ui/label_formatter.h +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright 2019 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_UI_LABEL_FORMATTER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_LABEL_FORMATTER_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/memory/raw_ref.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" - -namespace autofill { - -// Handles the creation of Suggestions' disambiguating labels. -class LabelFormatter { - public: - LabelFormatter(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types); - virtual ~LabelFormatter(); - - // Returns the bitmask indicating which FieldTypeGroups are represented in - // this formatter's associated form. - uint32_t groups() const { return groups_; } - - // Returns a collection of labels formed by extracting useful disambiguating - // information from |profiles_|. - std::vector<std::u16string> GetLabels() const; - - // Creates a form-specific LabelFormatter according to |field_types|. This - // formatter has the ability to build labels with disambiguating information - // from the given |profiles|. - static std::unique_ptr<LabelFormatter> Create( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - const FieldTypeSet& field_types); - - protected: - // Returns a label to show the user. The elements of the label and their - // ordering depend on the kind of LabelFormatter, the data in |profile|, - // |focused_group|, and |focused_field_type_|. - virtual std::u16string GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const = 0; - - const std::string& app_locale() const { return app_locale_; } - - FieldType focused_field_type() const { return focused_field_type_; } - - const std::vector<FieldType>& field_types_for_labels() const { - return field_types_for_labels_; - } - - private: - // The collection of profiles for which to build labels. Storing this - // collection ensures that the profiles for which this formatter is created - // are the profiles for which the labels are constructed. - // - // It is safe to store a reference here because the LabelFormatter is - // destroyed when the suggestions for which the labels are constructed are - // returned. - const raw_ref<const std::vector<const AutofillProfile*>> profiles_; - - // The locale for which to generate labels. This reflects the language and - // country for which the application is translated, e.g. en-AU for Australian - // English. - std::string app_locale_; - - // The type of field on which the user is focused, e.g. NAME_FIRST. - FieldType focused_field_type_; - - // The bitmask indicating which FieldTypeGroups are represented in this - // formatter's associated form. - uint32_t groups_; - - // The collection of field types that can be used to make labels. It includes - // only types related to names, addresses, email addresses, and phone - // numbers. It excludes types related to countries. - std::vector<FieldType> field_types_for_labels_; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_LABEL_FORMATTER_H_
diff --git a/components/autofill/core/browser/ui/label_formatter_unittest.cc b/components/autofill/core/browser/ui/label_formatter_unittest.cc deleted file mode 100644 index 28c9e3a..0000000 --- a/components/autofill/core/browser/ui/label_formatter_unittest.cc +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2019 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/ui/label_formatter.h" - -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace autofill { -namespace { - -TEST(LabelFormatterTest, CreateWithMissingFieldTypes) { - const std::vector<const AutofillProfile*> profiles{}; - EXPECT_EQ(LabelFormatter::Create(profiles, "en-US", NAME_FIRST, {}), nullptr); -} - -TEST(LabelFormatterTest, CreateWithUnsupportedFieldTypes) { - const std::vector<const AutofillProfile*> profiles{}; - EXPECT_EQ( - LabelFormatter::Create(profiles, "en-US", USERNAME, {USERNAME, PASSWORD}), - nullptr); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/label_formatter_utils.cc b/components/autofill/core/browser/ui/label_formatter_utils.cc deleted file mode 100644 index c5277db..0000000 --- a/components/autofill/core/browser/ui/label_formatter_utils.cc +++ /dev/null
@@ -1,398 +0,0 @@ -// Copyright 2019 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/ui/label_formatter_utils.h" - -#include <iterator> -#include <memory> - -#include "base/functional/bind.h" -#include "base/functional/callback.h" -#include "base/ranges/algorithm.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/geo/address_i18n.h" -#include "components/autofill/core/browser/geo/phone_number_i18n.h" -#include "components/autofill/core/browser/validation.h" -#include "components/grit/components_scaled_resources.h" -#include "components/strings/grit/components_strings.h" -#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" -#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h" -#include "ui/base/l10n/l10n_util.h" - -namespace autofill { - -using data_util::ContainsAddress; -using data_util::ContainsEmail; -using data_util::ContainsName; -using data_util::ContainsPhone; - -namespace { - -// Returns true if all |profiles| have the same value for the data retrieved by -// |get_data|. -bool HaveSameData( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - base::RepeatingCallback<std::u16string(const AutofillProfile&, - const std::string&)> get_data, - base::RepeatingCallback<bool(const std::u16string& str1, - const std::u16string& str2)> matches) { - if (profiles.size() <= 1) { - return true; - } - - const std::u16string first_profile_data = - get_data.Run(*profiles[0], app_locale); - for (size_t i = 1; i < profiles.size(); ++i) { - const std::u16string current_profile_data = - get_data.Run(*profiles[i], app_locale); - if (!matches.Run(first_profile_data, current_profile_data)) { - return false; - } - } - return true; -} - -// Used to avoid having the same lambda in HaveSameEmailAddresses, -// HaveSameFirstNames, HaveSameStreetAddresses. -bool Equals(const std::u16string& str1, const std::u16string& str2) { - return str1 == str2; -} - -} // namespace - -void AddLabelPartIfNotEmpty(const std::u16string& part, - std::vector<std::u16string>* parts) { - if (!part.empty()) { - parts->push_back(part); - } -} - -std::u16string ConstructLabelLine(const std::vector<std::u16string>& parts) { - return base::JoinString(parts, l10n_util::GetStringUTF16( - IDS_AUTOFILL_SUGGESTION_LABEL_SEPARATOR)); -} - -std::u16string ConstructMobileLabelLine( - const std::vector<std::u16string>& parts) { - return base::JoinString( - parts, l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR)); -} - -bool IsNonStreetAddressPart(FieldType type) { - switch (type) { - case ADDRESS_HOME_CITY: - case ADDRESS_HOME_ZIP: - case ADDRESS_HOME_STATE: - case ADDRESS_HOME_COUNTRY: - case ADDRESS_HOME_SORTING_CODE: - case ADDRESS_HOME_DEPENDENT_LOCALITY: - return true; - default: - return false; - } -} - -bool IsStreetAddressPart(FieldType type) { - switch (type) { - case ADDRESS_HOME_LINE1: - case ADDRESS_HOME_LINE2: - case ADDRESS_HOME_APT_NUM: - case ADDRESS_HOME_STREET_ADDRESS: - case ADDRESS_HOME_LINE3: - return true; - default: - return false; - } -} - -bool HasNonStreetAddress(const std::vector<FieldType>& types) { - return base::ranges::any_of(types, IsNonStreetAddressPart); -} - -bool HasStreetAddress(const std::vector<FieldType>& types) { - return base::ranges::any_of(types, IsStreetAddressPart); -} - -std::vector<FieldType> ExtractSpecifiedAddressFieldTypes( - bool extract_street_address_types, - const std::vector<FieldType>& types) { - auto should_be_extracted = - [&extract_street_address_types](FieldType type) -> bool { - return GroupTypeOfServerFieldType(type) == FieldTypeGroup::kAddress && - (extract_street_address_types ? IsStreetAddressPart(type) - : !IsStreetAddressPart(type)); - }; - - std::vector<FieldType> extracted_address_types; - base::ranges::copy_if(types, std::back_inserter(extracted_address_types), - should_be_extracted); - - return extracted_address_types; -} - -std::vector<FieldType> TypesWithoutFocusedField( - const std::vector<FieldType>& types, - FieldType field_type_to_remove) { - std::vector<FieldType> types_without_field; - base::ranges::copy_if(types, std::back_inserter(types_without_field), - [&field_type_to_remove](FieldType type) { - return type != field_type_to_remove; - }); - return types_without_field; -} - -AutofillProfile MakeTrimmedProfile(const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types) { - const std::u16string country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY); - - AutofillProfile trimmed_profile( - profile.guid(), AutofillProfile::Source::kLocalOrSyncable, - AddressCountryCode(base::UTF16ToUTF8(country_code))); - trimmed_profile.set_language_code(profile.language_code()); - - for (const FieldType& type : types) { - trimmed_profile.SetInfo(type, profile.GetInfo(type, app_locale), - app_locale); - } - return trimmed_profile; -} - -std::u16string GetLabelForFocusedAddress(FieldType focused_field_type, - bool form_has_street_address, - const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types) { - return GetLabelAddress( - form_has_street_address && !IsStreetAddressPart(focused_field_type), - profile, app_locale, types); -} - -std::u16string GetLabelAddress(bool use_street_address, - const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types) { - return use_street_address - ? GetLabelStreetAddress( - ExtractSpecifiedAddressFieldTypes(use_street_address, types), - profile, app_locale) - : GetLabelNationalAddress( - ExtractSpecifiedAddressFieldTypes(use_street_address, types), - profile, app_locale); -} - -std::u16string GetLabelNationalAddress(const std::vector<FieldType>& types, - const AutofillProfile& profile, - const std::string& app_locale) { - std::unique_ptr<::i18n::addressinput::AddressData> address_data = - i18n::CreateAddressDataFromAutofillProfile( - MakeTrimmedProfile(profile, app_locale, types), app_locale); - - std::string address_line; - ::i18n::addressinput::GetFormattedNationalAddressLine(*address_data, - &address_line); - return base::UTF8ToUTF16(address_line); -} - -std::u16string GetLabelStreetAddress(const std::vector<FieldType>& types, - const AutofillProfile& profile, - const std::string& app_locale) { - std::unique_ptr<::i18n::addressinput::AddressData> address_data = - i18n::CreateAddressDataFromAutofillProfile( - MakeTrimmedProfile(profile, app_locale, types), app_locale); - - std::string address_line; - ::i18n::addressinput::GetStreetAddressLinesAsSingleLine(*address_data, - &address_line); - return base::UTF8ToUTF16(address_line); -} - -std::u16string GetLabelForProfileOnFocusedNonStreetAddress( - bool form_has_street_address, - const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types, - const std::u16string& contact_info) { - std::vector<std::u16string> label_parts; - AddLabelPartIfNotEmpty( - GetLabelAddress(form_has_street_address, profile, app_locale, types), - &label_parts); - AddLabelPartIfNotEmpty(contact_info, &label_parts); - return ConstructLabelLine(label_parts); -} - -std::u16string GetLabelName(const std::vector<FieldType>& types, - const AutofillProfile& profile, - const std::string& app_locale) { - bool has_first_name = false; - bool has_last_name = false; - bool has_full_name = false; - - for (const FieldType type : types) { - if (type == NAME_FULL) { - has_full_name = true; - break; - } - if (type == NAME_FIRST) { - has_first_name = true; - } - if (type == NAME_LAST) { - has_last_name = true; - } - } - - if (has_full_name) { - return profile.GetInfo(AutofillType(NAME_FULL), app_locale); - } - - if (has_first_name && has_last_name) { - std::vector<std::u16string> name_parts; - AddLabelPartIfNotEmpty(GetLabelFirstName(profile, app_locale), &name_parts); - AddLabelPartIfNotEmpty(profile.GetInfo(AutofillType(NAME_LAST), app_locale), - &name_parts); - return base::JoinString(name_parts, u" "); - } - - if (has_first_name) { - return GetLabelFirstName(profile, app_locale); - } - - if (has_last_name) { - return profile.GetInfo(AutofillType(NAME_LAST), app_locale); - } - - // The form contains neither a full name field nor a first name field, - // so choose some name field in the form and make it the label text. - for (const FieldType type : types) { - if (GroupTypeOfServerFieldType(type) == FieldTypeGroup::kName) { - return profile.GetInfo(AutofillType(type), app_locale); - } - } - return std::u16string(); -} - -std::u16string GetLabelFirstName(const AutofillProfile& profile, - const std::string& app_locale) { - return profile.GetInfo(AutofillType(NAME_FIRST), app_locale); -} - -std::u16string GetLabelEmail(const AutofillProfile& profile, - const std::string& app_locale) { - const std::u16string email = - profile.GetInfo(AutofillType(EMAIL_ADDRESS), app_locale); - return IsValidEmailAddress(email) ? email : std::u16string(); -} - -std::u16string GetLabelPhone(const AutofillProfile& profile, - const std::string& app_locale) { - const std::string unformatted_phone = base::UTF16ToUTF8( - profile.GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), app_locale)); - return unformatted_phone.empty() - ? std::u16string() - : base::UTF8ToUTF16(i18n::FormatPhoneNationallyForDisplay( - unformatted_phone, - data_util::GetCountryCodeWithFallback(profile, app_locale))); -} - -bool HaveSameEmailAddresses(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale) { - return HaveSameData(profiles, app_locale, base::BindRepeating(&GetLabelEmail), - base::BindRepeating(base::BindRepeating(&Equals))); -} - -bool HaveSameFirstNames(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale) { - return HaveSameData(profiles, app_locale, - base::BindRepeating(&GetLabelFirstName), - base::BindRepeating(base::BindRepeating(&Equals))); -} - -bool HaveSameNonStreetAddresses( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - const std::vector<FieldType>& types) { - // In general, comparing non street addresses with Equals, which uses ==, is - // not ideal since Düsseldorf and Dusseldorf will be considered distinct. It's - // okay to use it here because near-duplicate non street addresses like this - // are filtered out before a LabelFormatter is created. - return HaveSameData(profiles, app_locale, - base::BindRepeating(&GetLabelNationalAddress, types), - base::BindRepeating(&Equals)); -} - -bool HaveSamePhoneNumbers(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale) { - // Note that the same country code is used in all comparisons. - auto equals = [](const std::string& country_code, - const std::string& app_locale, const std::u16string& phone1, - const std::u16string& phone2) -> bool { - return (phone1.empty() && phone2.empty()) || - i18n::PhoneNumbersMatch(phone1, phone2, country_code, app_locale); - }; - - return profiles.size() <= 1 - ? true - : HaveSameData( - profiles, app_locale, base::BindRepeating(&GetLabelPhone), - base::BindRepeating(equals, - base::UTF16ToASCII(profiles[0]->GetInfo( - ADDRESS_HOME_COUNTRY, app_locale)), - app_locale)); -} - -bool HaveSameStreetAddresses( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - const std::vector<FieldType>& types) { - // In general, comparing street addresses with Equals, which uses ==, is not - // ideal since 3 Elm St and 3 Elm St. will be considered distinct. It's okay - // to use it here because near-duplicate addresses like this are filtered - // out before a LabelFormatter is created. - return HaveSameData(profiles, app_locale, - base::BindRepeating(&GetLabelStreetAddress, types), - base::BindRepeating(&Equals)); -} - -bool HasUnfocusedEmailField(FieldTypeGroup focused_group, - uint32_t form_groups) { - return ContainsEmail(form_groups) && focused_group != FieldTypeGroup::kEmail; -} - -bool HasUnfocusedNameField(FieldTypeGroup focused_group, uint32_t form_groups) { - return ContainsName(form_groups) && focused_group != FieldTypeGroup::kName; -} - -bool HasUnfocusedNonStreetAddressField(FieldType focused_field, - FieldTypeGroup focused_group, - const std::vector<FieldType>& types) { - return HasNonStreetAddress(types) && - (focused_group != FieldTypeGroup::kAddress || - !IsNonStreetAddressPart(focused_field)); -} - -bool HasUnfocusedPhoneField(FieldTypeGroup focused_group, - uint32_t form_groups) { - return ContainsPhone(form_groups) && focused_group != FieldTypeGroup::kPhone; -} - -bool HasUnfocusedStreetAddressField(FieldType focused_field, - FieldTypeGroup focused_group, - const std::vector<FieldType>& types) { - return HasStreetAddress(types) && - (focused_group != FieldTypeGroup::kAddress || - !IsStreetAddressPart(focused_field)); -} - -bool FormHasOnlyNonStreetAddressFields(const std::vector<FieldType>& types, - uint32_t form_groups) { - return ContainsAddress(form_groups) && !HasStreetAddress(types) && - !(ContainsName(form_groups) || ContainsPhone(form_groups) || - ContainsEmail(form_groups)); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/label_formatter_utils.h b/components/autofill/core/browser/ui/label_formatter_utils.h deleted file mode 100644 index f332e50..0000000 --- a/components/autofill/core/browser/ui/label_formatter_utils.h +++ /dev/null
@@ -1,179 +0,0 @@ -// Copyright 2019 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_UI_LABEL_FORMATTER_UTILS_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_LABEL_FORMATTER_UTILS_H_ - -#include <string> -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" - -namespace autofill { - -// Adds |part| to the end of |parts| if |part| is not an empty string. -void AddLabelPartIfNotEmpty(const std::u16string& part, - std::vector<std::u16string>* parts); - -// Returns the text to show to the user. If there is more than one element in -// |parts|, then a separator, |IDS_AUTOFILL_SUGGESTION_LABEL_SEPARATOR|, is -// inserted between them. -std::u16string ConstructLabelLine(const std::vector<std::u16string>& parts); - -// Like ConstructLabelLine, but uses |IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR| -// instead. -std::u16string ConstructMobileLabelLine( - const std::vector<std::u16string>& parts); - -// Returns true if |type| is associated with an address, but not with a street -// address. For example, if the given type is ADDRESS_HOME_ZIP, then true is -// returned. If ADDRESS_BILLING_LINE1 is given then false is returned. -bool IsNonStreetAddressPart(FieldType type); - -// Returns true if |type| is associated with a street address. -bool IsStreetAddressPart(FieldType type); - -// Returns true if |types| has a non-street-address-related type. -bool HasNonStreetAddress(const std::vector<FieldType>& types); - -// Returns true if |types| has a street-address-related type. -bool HasStreetAddress(const std::vector<FieldType>& types); - -// Returns a vector of only street-address-related field types in |types| if -// |extract_street_address_types| is true, e.g. ADDRESS_HOME_LINE1. -// -// Returns a vector of only non-street-address-related field types in |types| -// if |extract_street_address_types| is false, e.g. ADDRESS_BILLING_ZIP. -std::vector<FieldType> ExtractSpecifiedAddressFieldTypes( - bool extract_street_address_types, - const std::vector<FieldType>& types); - -// Returns a collection of the types in |types| without |field_type_to_remove|. -std::vector<FieldType> TypesWithoutFocusedField( - const std::vector<FieldType>& types, - FieldType field_type_to_remove); - -// Returns a pared down copy of |profile|. The copy has the same guid, origin, -// country and language codes, and |field_types| as |profile|. -AutofillProfile MakeTrimmedProfile(const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types); - -// Returns either street-address data or non-street-address data found in -// |profile|. If |focused_field_type| is a street address field, then returns -// non-street-address data, e.g. Lowell, MA 01852. -// -// If the focused type is not a street address field and if -// |form_has_street_address| is true, then returns street-address data, e.g. 375 -// Merrimack St. -// -// If the focused type is not a street address field and if the form does not -// have a street address, then returns the parts of the address in the form -// other than the focused field. For example, if a user focuses on a city -// field and if the state and zip code can be in the label, then MA 01852 is -// returned. If there are no other non-street-address fields or if the data is -// not present in |profile|, then an empty string is returned. -std::u16string GetLabelForFocusedAddress(FieldType focused_field_type, - bool form_has_street_address, - const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types); - -// If |use_street_address| is true and if |profile| is associated with a street -// address, then returns the street address, e.g. 24 Beacon St. -// -// If |use_street_address| is false and |profile| is associated with address -// fields other than street addresses, then returns the non-street- -// address-related data corresponding to |types|. -std::u16string GetLabelAddress(bool use_street_address, - const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types); - -// Returns the national address associated with |profile|, e.g. -// 24 Beacon St., Boston, MA 02133. -std::u16string GetLabelNationalAddress(const std::vector<FieldType>& types, - const AutofillProfile& profile, - const std::string& app_locale); - -// Returns the street address associated with |profile|, e.g. 24 Beacon St. -std::u16string GetLabelStreetAddress(const std::vector<FieldType>& types, - const AutofillProfile& profile, - const std::string& app_locale); - -// Returns a label to show the user when |focused_field_type_| is not part of -// a street address. For example, city and postal code are non-street-address -// field types. -std::u16string GetLabelForProfileOnFocusedNonStreetAddress( - bool form_has_street_address, - const AutofillProfile& profile, - const std::string& app_locale, - const std::vector<FieldType>& types, - const std::u16string& contact_info); - -// Returns a name that is (A) associated with |profile| and (B) found in -// |types|; otherwise, returns an empty string. -std::u16string GetLabelName(const std::vector<FieldType>& types, - const AutofillProfile& profile, - const std::string& app_locale); - -// Returns the first name associated with |profile|, if any; otherwise, returns -// an empty string. -std::u16string GetLabelFirstName(const AutofillProfile& profile, - const std::string& app_locale); - -// Returns the email address associated with |profile|, if any; otherwise, -// returns an empty string. -std::u16string GetLabelEmail(const AutofillProfile& profile, - const std::string& app_locale); - -// Returns the phone number associated with |profile|, if any; otherwise, -// returns an empty string. Phone numbers are given in |profile|'s country's -// national format, if possible. -std::u16string GetLabelPhone(const AutofillProfile& profile, - const std::string& app_locale); - -// Each HaveSame* function below returns true if all |profiles| have the same -// specified data. Note that the absence of data and actual data, e.g. -// joe.bray@aol.com, are considered different pieces of data. -// -// Near-duplicate data, such as Düsseldorf and Dusseldorf or 3 Elm St and 3 Elm -// St., should be filtered out before calling this function. -bool HaveSameEmailAddresses(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale); -bool HaveSameFirstNames(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale); -bool HaveSameNonStreetAddresses( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - const std::vector<FieldType>& types); -bool HaveSamePhoneNumbers(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale); -bool HaveSameStreetAddresses( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - const std::vector<FieldType>& types); - -// Each HasUnfocused* function below returns true if the form described by -// |form_groups| includes a field corresponding to the specified data and if -// this field is not being interacted with by the user, i.e. the specified field -// is not associated with the |focused_group|. -bool HasUnfocusedEmailField(FieldTypeGroup focused_group, uint32_t form_groups); -bool HasUnfocusedNameField(FieldTypeGroup focused_group, uint32_t form_groups); -bool HasUnfocusedNonStreetAddressField(FieldType focused_field, - FieldTypeGroup focused_group, - const std::vector<FieldType>& types); -bool HasUnfocusedPhoneField(FieldTypeGroup focused_group, uint32_t form_groups); -bool HasUnfocusedStreetAddressField(FieldType focused_field, - FieldTypeGroup focused_group, - const std::vector<FieldType>& types); - -// Returns true if the form has only non-street-address-related fields, such as -// city, state, and zip code. -bool FormHasOnlyNonStreetAddressFields(const std::vector<FieldType>& types, - uint32_t form_groups); -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_LABEL_FORMATTER_UTILS_H_
diff --git a/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc b/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc deleted file mode 100644 index 059661f..0000000 --- a/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc +++ /dev/null
@@ -1,216 +0,0 @@ -// Copyright 2019 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/ui/label_formatter_utils.h" - -#include <string> - -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/uuid.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/country_type.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/grit/components_scaled_resources.h" -#include "components/strings/grit/components_strings.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/l10n/l10n_util.h" - -namespace autofill { -namespace { - -TEST(LabelFormatterUtilsTest, HaveSameFirstNames_OneProfileAndNoFirstName) { - AutofillProfile profile(AddressCountryCode("DE")); - test::SetProfileInfo(&profile, "", "", "", "", "", "", "", "", "", "", "DE", - ""); - EXPECT_TRUE(HaveSameFirstNames({&profile}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSameFirstNames_OneProfileAndFirstName) { - AutofillProfile profile(AddressCountryCode("DE")); - test::SetProfileInfo(&profile, "Maria", "", "", "", "", "", "", "", "", "", - "DE", ""); - EXPECT_TRUE(HaveSameFirstNames({&profile}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSameFirstNames_NoFirstNames) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "", "", "Kirch", "", "", "", "", "", "", "", - "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "", "", "Winckelmann", "", "", "", "", "", "", - "", "DE", ""); - EXPECT_TRUE(HaveSameFirstNames({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSameFirstNames_SameFirstNames) { - AutofillProfile profile1(AddressCountryCode("DE")); - ; - test::SetProfileInfo(&profile1, "Maria", "", "Kirch", "", "", "", "", "", "", - "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "", "Winckelmann", "", "", "", "", - "", "", "", "DE", ""); - EXPECT_TRUE(HaveSameFirstNames({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSameFirstNames_DifferentNonEmptyFirstNames) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "", "Kirch", "", "", "", "", "", "", - "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Mary", "", "Kirch", "", "", "", "", "", "", - "", "DE", ""); - EXPECT_FALSE(HaveSameFirstNames({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSameFirstNames_NonEmptyAndEmptyFirstNames) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", - "", "", "", "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "", "Margaretha", "Winckelmann", "", "", "", - "", "", "", "", "DE", ""); - EXPECT_FALSE(HaveSameFirstNames({&profile1, &profile2}, "de")); - EXPECT_FALSE(HaveSameFirstNames({&profile2, &profile1}, "de")); -} - -TEST(LabelFormatterUtilsTest, - HaveSameEmailAddresses_OneProfileAndNoEmailAddress) { - AutofillProfile profile(AddressCountryCode("DE")); - test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", - "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); - EXPECT_TRUE(HaveSameEmailAddresses({&profile}, "de")); -} - -TEST(LabelFormatterUtilsTest, - HaveSameEmailAddresses_OneProfileAndEmailAddress) { - AutofillProfile profile(AddressCountryCode("DE")); - test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", "", "", "", "", - "", "", "", "DE", ""); - EXPECT_TRUE(HaveSameEmailAddresses({&profile}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSameEmailAddresses_NoEmailAddresses) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", - "", "", "", "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", - "", "", "", "", "", "DE", ""); - EXPECT_TRUE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSameEmailAddresses_SameEmailAddresses) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", - "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", - "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); - EXPECT_TRUE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, - HaveSameEmailAddresses_DifferentNonEmptyEmailAddresses) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", - "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", - "mmw@gmail.com", "", "", "", "", "", "", "DE", ""); - EXPECT_FALSE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, - HaveSameEmailAddresses_NonEmptyAndEmptyEmailAddresses) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", - "mmkirch@gmx.de", "", "", "", "", "", "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", - "", "", "", "", "", "DE", ""); - EXPECT_FALSE(HaveSameEmailAddresses({&profile1, &profile2}, "de")); - EXPECT_FALSE(HaveSameEmailAddresses({&profile2, &profile1}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSamePhoneNumbers_OneProfileAndNoPhoneNumber) { - AutofillProfile profile(AddressCountryCode("DE")); - test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", "", "", "", "", - "", "", "", "DE", ""); - EXPECT_TRUE(HaveSamePhoneNumbers({&profile}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSamePhoneNumbers_OneProfileAndPhoneNumber) { - AutofillProfile profile(AddressCountryCode("DE")); - test::SetProfileInfo(&profile, "Maria", "Margaretha", "Kirch", "", "", "", "", - "", "", "", "DE", "+49 30 4504-2823"); - EXPECT_TRUE(HaveSamePhoneNumbers({&profile}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSamePhoneNumbers_NoPhoneNumber) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", - "", "", "", "", "DE", ""); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", - "", "", "", "", "", "DE", ""); - EXPECT_TRUE(HaveSamePhoneNumbers({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, HaveSamePhoneNumbers_SamePhoneNumbers) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", - "", "", "", "", "DE", "+49 30 4504-2823"); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", - "", "", "", "", "", "DE", "493045042823"); - AutofillProfile profile3(AddressCountryCode("DE")); - test::SetProfileInfo(&profile3, "Maria", "Margaretha", "Winckelmann", "", "", - "", "", "", "", "", "DE", "03045042823"); - EXPECT_TRUE(HaveSamePhoneNumbers({&profile1, &profile2, &profile3}, "de")); -} - -TEST(LabelFormatterUtilsTest, - HaveSamePhoneNumbers_DifferentNonEmptyPhoneNumbers) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", - "", "", "", "", "DE", "+49 30 4504-2823"); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", - "", "", "", "", "", "DE", "+49 221 22123828"); - EXPECT_FALSE(HaveSamePhoneNumbers({&profile1, &profile2}, "de")); -} - -TEST(LabelFormatterUtilsTest, - HaveSamePhoneNumbers_NonEmptyAndEmptyPhoneNumbers) { - AutofillProfile profile1(AddressCountryCode("DE")); - test::SetProfileInfo(&profile1, "Maria", "Margaretha", "Kirch", "", "", "", - "", "", "", "", "DE", "+49 30 4504-2823"); - AutofillProfile profile2(AddressCountryCode("DE")); - test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "", - "", "", "", "", "", "DE", ""); - EXPECT_FALSE(HaveSamePhoneNumbers({&profile1, &profile2}, "de")); - EXPECT_FALSE(HaveSamePhoneNumbers({&profile2, &profile1}, "de")); -} - -TEST(LabelFormatterUtilsTest, GetLabelName) { - AutofillProfile profile(AddressCountryCode("DE")); - profile.SetInfo(NAME_FULL, u"Maria Margaretha Kirch", "de"); - profile.FinalizeAfterImport(); - - EXPECT_EQ(u"Maria Margaretha Kirch", - GetLabelName({NAME_SUFFIX, NAME_FULL}, profile, "de")); - EXPECT_EQ(u"Maria Kirch", - GetLabelName({NAME_SUFFIX, NAME_FIRST, NAME_LAST}, profile, "de")); - EXPECT_EQ(u"Maria", GetLabelName({NAME_SUFFIX, NAME_FIRST}, profile, "de")); - EXPECT_EQ(u"Kirch", GetLabelName({NAME_SUFFIX, NAME_LAST}, profile, "de")); - EXPECT_EQ(u"Margaretha", GetLabelName({NAME_MIDDLE}, profile, "de")); - EXPECT_EQ(std::u16string(), GetLabelName({EMPTY_TYPE}, profile, "de")); - EXPECT_EQ(std::u16string(), GetLabelName({}, profile, "de")); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/mobile_label_formatter.cc b/components/autofill/core/browser/ui/mobile_label_formatter.cc deleted file mode 100644 index 8c11b8e..0000000 --- a/components/autofill/core/browser/ui/mobile_label_formatter.cc +++ /dev/null
@@ -1,223 +0,0 @@ -// Copyright 2019 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/ui/mobile_label_formatter.h" - -#include <algorithm> - -#include "base/metrics/field_trial_params.h" -#include "base/notreached.h" -#include "base/ranges/algorithm.h" -#include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "components/autofill/core/common/autofill_features.h" - -namespace autofill { - -using data_util::ContainsAddress; -using data_util::ContainsEmail; -using data_util::ContainsName; -using data_util::ContainsPhone; -using data_util::bit_field_type_groups::kAddress; -using data_util::bit_field_type_groups::kEmail; -using data_util::bit_field_type_groups::kName; -using data_util::bit_field_type_groups::kPhone; - -MobileLabelFormatter::MobileLabelFormatter( - const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types) - : LabelFormatter(profiles, - app_locale, - focused_field_type, - groups, - field_types) { - const FieldTypeGroup focused_group = AutofillType(focused_field_type).group(); - - could_show_email_ = HasUnfocusedEmailField(focused_group, groups) && - !HaveSameEmailAddresses(profiles, app_locale); - - could_show_name_ = HasUnfocusedNameField(focused_group, groups) && - !HaveSameFirstNames(profiles, app_locale); - - // Non street address elements, e.g. Mountain View or 28199 Bremen, can only - // only be included in labels when the form's |field_types| do not have a - // street address field. - could_show_non_street_address_ = - !HasStreetAddress(field_types_for_labels()) && - HasUnfocusedNonStreetAddressField(focused_field_type, focused_group, - field_types_for_labels()) && - !HaveSameNonStreetAddresses(profiles, app_locale, - ExtractSpecifiedAddressFieldTypes( - /*extract_street_address_types=*/false, - field_types_for_labels())); - - could_show_phone_ = HasUnfocusedPhoneField(focused_group, groups) && - !HaveSamePhoneNumbers(profiles, app_locale); - - could_show_street_address_ = - HasUnfocusedStreetAddressField(focused_field_type, focused_group, - field_types_for_labels()) && - !HaveSameStreetAddresses( - profiles, app_locale, - ExtractSpecifiedAddressFieldTypes( - /*extract_street_address_types=*/true, field_types_for_labels())); -} - -MobileLabelFormatter::~MobileLabelFormatter() = default; - -std::u16string MobileLabelFormatter::GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - std::string label_variant = base::GetFieldTrialParamValueByFeature( - features::kAutofillUseMobileLabelDisambiguation, - features::kAutofillUseMobileLabelDisambiguationParameterName); - if (label_variant == - features::kAutofillUseMobileLabelDisambiguationParameterShowOne) { - return GetLabelForShowOneVariant(profile, focused_group); - } else if (label_variant == - features::kAutofillUseMobileLabelDisambiguationParameterShowAll) { - return GetLabelForShowAllVariant(profile, focused_group); - } - // An unknown parameter was received. - NOTREACHED(); - return std::u16string(); -} - -// The order in which pieces of data are considered--address, and then, if the -// data is not the same across |profiles_|, phone number, email address, and -// name--ensures that the label contains the most useful information given the -// |focused_group| and the |focused_field_type_|. -std::u16string MobileLabelFormatter::GetLabelForShowOneVariant( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - if (ShowLabelAddress(focused_group)) { - return GetLabelAddress( - /*use_street_address=*/HasStreetAddress(field_types_for_labels()), - profile, app_locale(), - TypesWithoutFocusedField(field_types_for_labels(), - focused_field_type())); - } - - // If an unfocused form field does not have the same data for all - // |profiles_|, then it is preferable to show this data in the label. - if (could_show_phone_) { - return GetLabelPhone(profile, app_locale()); - } - - if (could_show_email_) { - return GetLabelEmail(profile, app_locale()); - } - - if (could_show_name_) { - return GetLabelName(field_types_for_labels(), profile, app_locale()); - } - - // In the case that data for unfocused form fields is the same for all - // |profiles_|, a label with the most important data is returned. - return GetDefaultLabel(profile, focused_group); -} - -// The order in which parts of a label are added--name, address, phone number, -// and email address--ensures that the label is formatted correctly for the -// |focused_group|, the |focused_field_type_|, and the non-focused form fields -// whose data is not the same across |profiles_|. -std::u16string MobileLabelFormatter::GetLabelForShowAllVariant( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - if (!(could_show_email_ || could_show_name_ || - could_show_non_street_address_ || could_show_phone_ || - could_show_street_address_)) { - // If there is profile data corresponding to unfocused form fields that is - // not the same across all |profiles_|, then include this data in the label. - // Otherwise, show the most important piece of data. - return GetDefaultLabel(profile, focused_group); - } - - std::vector<std::u16string> label_parts; - - // TODO(crbug.com/961819): Maybe put name after address for some app locales. - if (could_show_name_) { - // Due to mobile platforms' space constraints, only the first name is shown - // if the form contains a first name field or a full name field. - base::ranges::any_of( - field_types_for_labels(), - [](auto type) { return type == NAME_FIRST || type == NAME_FULL; }) - ? AddLabelPartIfNotEmpty(GetLabelFirstName(profile, app_locale()), - &label_parts) - : AddLabelPartIfNotEmpty( - GetLabelName(field_types_for_labels(), profile, app_locale()), - &label_parts); - } - - if (could_show_street_address_) { - AddLabelPartIfNotEmpty( - GetLabelAddress(/*use_street_address=*/true, profile, app_locale(), - field_types_for_labels()), - &label_parts); - } - - if (could_show_non_street_address_) { - AddLabelPartIfNotEmpty( - GetLabelAddress(/*use_street_address=*/false, profile, app_locale(), - field_types_for_labels()), - &label_parts); - } - - if (could_show_phone_) { - AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts); - } - - if (could_show_email_) { - AddLabelPartIfNotEmpty(GetLabelEmail(profile, app_locale()), &label_parts); - } - - return ConstructMobileLabelLine(label_parts); -} - -// The order in which pieces of data are considered--address, phone number, -// email address, and name--ensures that the label contains the most useful -// information given the |focused_group| and the |focused_field_type_|. -std::u16string MobileLabelFormatter::GetDefaultLabel( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const { - if (ShowLabelAddress(focused_group)) { - return GetLabelAddress( - /*use_street_address=*/HasStreetAddress(field_types_for_labels()), - profile, app_locale(), - TypesWithoutFocusedField(field_types_for_labels(), - focused_field_type())); - } - - if (HasUnfocusedPhoneField(focused_group, groups())) { - return GetLabelPhone(profile, app_locale()); - } - - if (HasUnfocusedEmailField(focused_group, groups())) { - return GetLabelEmail(profile, app_locale()); - } - - return GetLabelName(field_types_for_labels(), profile, app_locale()); -} - -bool MobileLabelFormatter::ShowLabelAddress( - FieldTypeGroup focused_group) const { - if (HasUnfocusedStreetAddressField(focused_field_type(), focused_group, - field_types_for_labels())) { - return true; - } - - // If a form lacks a street address field, then a non street address field may - // be shown. It is shown in two situations: - // 1. A form has an unfocused non street address field. - // 2. A form has only non street address fields. - return (!HasStreetAddress(field_types_for_labels()) && - HasUnfocusedNonStreetAddressField(focused_field_type(), focused_group, - field_types_for_labels())) || - FormHasOnlyNonStreetAddressFields(field_types_for_labels(), groups()); -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/mobile_label_formatter.h b/components/autofill/core/browser/ui/mobile_label_formatter.h deleted file mode 100644 index 2c89ed5..0000000 --- a/components/autofill/core/browser/ui/mobile_label_formatter.h +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2019 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_UI_MOBILE_LABEL_FORMATTER_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_MOBILE_LABEL_FORMATTER_H_ - -#include <string> -#include <vector> - -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter.h" - -namespace autofill { - -// A LabelFormatter that creates Suggestions' disambiguating labels for forms -// on mobile platforms. -// -// In constructing a label, a MobileLabelFormatter may consider the following: -// -// 1. The type of form, e.g. a form with only name and phone fields or a form -// with name, address, phone, and email fields -// 2. The field on which the user is focused, e.g. a first name field -// 3. The non-focused form fields whose corresponding profile data is not the -// same across |profiles_|, if any -// 4. The relative usefulness of form field data that could be shown in labels -// -// The usefulness, from greatest to least, is as follows: -// address > phone > email > name -// -// There are two address categories: street address and non street address. -// Street address example: 44 Lakeview Ln -// Non street address examples: London, 02113, CA, Rio Comprido, and Germany -class MobileLabelFormatter : public LabelFormatter { - public: - MobileLabelFormatter(const std::vector<const AutofillProfile*>& profiles, - const std::string& app_locale, - FieldType focused_field_type, - uint32_t groups, - const FieldTypeSet& field_types); - - ~MobileLabelFormatter() override; - - std::u16string GetLabelForProfile( - const AutofillProfile& profile, - FieldTypeGroup focused_group) const override; - - private: - // Returns a label for the kAutofillUseMobileLabelDisambiguation feature when - // the ShowOne variant is enabled. - // - // The label has at most one piece of data, e.g. a phone number. For address - // data, note that a street address, e.g. 120 Oak Rd #2, and a non street - // address, e.g. Palo Alto, CA 94303, are each considered one piece of data. - // - // It is possible for the label to be an empty string. For example, suppose - // (A) a user has two profiles with slightly different names, e.g. Joe and - // Joseph, (B) the profile with Joe as its first name lacks an email address - // and (C) this user is interacting with a form that has first name, last - // name, and email address fields. If this user clicks on the first name - // field, then the suggestion with Joe has an empty string as its label. - std::u16string GetLabelForShowOneVariant(const AutofillProfile& profile, - FieldTypeGroup focused_group) const; - - // Returns a label for the kAutofillUseMobileLabelDisambiguation feature when - // the ShowAll variant is enabled. - // - // The label may contain multiple pieces of data, e.g. a street address, a - // phone number, and an email address. It contains only data whose values are - // not the same across |profiles|. - // - // As explained in the comment for GetLabelForShowOneVariant, it is possible - // for the label to be an empty string. - std::u16string GetLabelForShowAllVariant(const AutofillProfile& profile, - FieldTypeGroup focused_group) const; - - // Returns a label with the most useful piece of data according to the - // ordering described in this class' description. - // - // It is possible for the label to be an empty string. This can happen when - // |profile| is missing data corresponding to a field, e.g. a profile without - // a phone number. - std::u16string GetDefaultLabel(const AutofillProfile& profile, - FieldTypeGroup focused_group) const; - - // Returns true if the label should be an address part, e.g. 4 Oak Rd or - // Boston, MA 02116. - bool ShowLabelAddress(FieldTypeGroup focused_group) const; - - // True if the field (A) appears in the form, (B) is not the focused field, - // and (C) does not have the same data for all |profiles_|. - // - // If a field is focused, then its corresponding bool should be false because - // the focused field's data is shown in a suggestion's value. Repeating this - // data in a suggestion's label is not helpful to users. - bool could_show_email_; - bool could_show_name_; - bool could_show_non_street_address_; - bool could_show_phone_; - bool could_show_street_address_; -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_MOBILE_LABEL_FORMATTER_H_
diff --git a/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc b/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc deleted file mode 100644 index 747985a..0000000 --- a/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc +++ /dev/null
@@ -1,411 +0,0 @@ -// Copyright 2019 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/ui/mobile_label_formatter.h" -#include "components/autofill/core/browser/data_model/address.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" -#include "base/uuid.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" -#include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/ui/label_formatter_utils.h" -#include "components/autofill/core/common/autofill_features.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::ElementsAre; - -namespace autofill { -namespace { - -FieldTypeSet GetContactOnlyFieldTypes() { - return {NO_SERVER_DATA, NAME_FIRST, NAME_LAST, EMAIL_ADDRESS, - PHONE_HOME_WHOLE_NUMBER}; -} - -FieldTypeSet GetAddressOnlyFieldTypes() { - return {NO_SERVER_DATA, NAME_FIRST, - NAME_LAST, ADDRESS_HOME_LINE1, - ADDRESS_HOME_LINE2, ADDRESS_HOME_DEPENDENT_LOCALITY, - ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, - ADDRESS_HOME_ZIP, ADDRESS_HOME_COUNTRY}; -} - -FieldTypeSet GetAddressPlusEmailFieldTypes() { - return {NO_SERVER_DATA, - NAME_FIRST, - NAME_LAST, - EMAIL_ADDRESS, - ADDRESS_HOME_LINE1, - ADDRESS_HOME_LINE2, - ADDRESS_HOME_DEPENDENT_LOCALITY, - ADDRESS_HOME_CITY, - ADDRESS_HOME_STATE, - ADDRESS_HOME_ZIP, - ADDRESS_HOME_COUNTRY}; -} - -FieldTypeSet GetAddressPlusContactFieldTypes() { - return {NO_SERVER_DATA, - NAME_FIRST, - NAME_LAST, - EMAIL_ADDRESS, - ADDRESS_HOME_LINE1, - ADDRESS_HOME_LINE2, - ADDRESS_HOME_DEPENDENT_LOCALITY, - ADDRESS_HOME_CITY, - ADDRESS_HOME_STATE, - ADDRESS_HOME_ZIP, - ADDRESS_HOME_COUNTRY, - PHONE_HOME_WHOLE_NUMBER}; -} - -AutofillProfile GetProfileA() { - AutofillProfile profile(AddressCountryCode("US")); - test::SetProfileInfo(&profile, "firstA", "middleA", "lastA", - "emailA@gmail.com", "", "address1A", "address2A", - "cityA", "MA", "02113", "US", "16176660000"); - return profile; -} - -AutofillProfile GetProfileB() { - AutofillProfile profile(AddressCountryCode("US")); - test::SetProfileInfo(&profile, "firstB", "middleB", "lastB", - "emailB@gmail.com", "", "address1B", "address2B", - "cityB", "NY", "12224", "US", "15185550000"); - return profile; -} - -TEST(MobileLabelFormatterTest, GetLabelsWithMissingProfiles) { - const std::vector<const AutofillProfile*> profiles{}; - const std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", NAME_FIRST, {NAME_FIRST, NAME_LAST, EMAIL_ADDRESS}); - EXPECT_TRUE(formatter->GetLabels().empty()); -} - -TEST(MobileLabelFormatterTest, GetLabelsForUnfocusedAddress_ShowOne) { - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - features::kAutofillUseMobileLabelDisambiguationParameterShowOne; - - base::test::ScopedFeatureList features; - features.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - - AutofillProfile profileA = GetProfileA(); - AutofillProfile profileB = GetProfileB(); - AutofillProfile profileC(AddressCountryCode("US")); - test::SetProfileInfo(&profileC, "firstC", "middleC", "lastC", "", "", "", "", - "", "", "", "US", ""); - const std::vector<const AutofillProfile*> profiles{&profileA, &profileB, - &profileC}; - - // Tests that the street address is shown when the form contains a street - // address field and the user is not focused on it. - std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", NAME_FIRST, GetAddressOnlyFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"address1A, address2A", u"address1B, address2B", - std::u16string())); - - // Tests that the non street address is shown when the form's only address - // fields are non street address fields and the user is not focused on any of - // them. - formatter = LabelFormatter::Create(profiles, "en-US", NAME_FIRST, - {NAME_FIRST, NAME_LAST, ADDRESS_HOME_ZIP}); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"02113", u"12224", std::u16string())); - - // Like the previous test, but without name. - formatter = LabelFormatter::Create( - profiles, "en-US", EMAIL_ADDRESS, - {ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, EMAIL_ADDRESS}); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"cityA, MA", u"cityB, NY", std::u16string())); - - // Tests that addresses are not shown when the form does not contain an - // address field. - formatter = LabelFormatter::Create(profiles, "en-US", NAME_FIRST, - GetContactOnlyFieldTypes()); - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(u"(617) 666-0000", u"(518) 555-0000", std::u16string())); -} - -TEST(MobileLabelFormatterTest, - GetLabelsForFocusedAddress_MultipleProfiles_ShowOne) { - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - features::kAutofillUseMobileLabelDisambiguationParameterShowOne; - - base::test::ScopedFeatureList features; - features.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - - AutofillProfile profileA = GetProfileA(); - - // Tests that a street is shown when a form contains an unfocused street - // address and a focused non street address. - AutofillProfile profileB = GetProfileB(); - std::vector<const AutofillProfile*> profiles{&profileA, &profileB}; - - std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_ZIP, GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"address1A, address2A", u"address1B, address2B")); - - // Tests that a non street address is shown when a form contains only - // non focused street address fields and a focused non street address. - formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_ZIP, - {ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP}); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"cityA, MA", u"cityB, NY")); - - // Tests that a non street address is not shown when a form contains - // non focused street address fields and another kind of field and also has a - // focused non street address. - formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_CITY, - {ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, EMAIL_ADDRESS}); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"emailA@gmail.com", u"emailB@gmail.com")); - - // Tests that a phone number is shown when the address cannot be shown and - // there are different phone numbers. - profileB = GetProfileA(); - profileB.SetInfo(PHONE_HOME_WHOLE_NUMBER, u"15185550000", "en-US"); - profiles = {&profileA, &profileB}; - - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"(617) 666-0000", u"(518) 555-0000")); - - // Tests that an email address is shown when the address cannot be shown and - // there are different email addresses. - profileB = GetProfileA(); - profileB.SetInfo(EMAIL_ADDRESS, u"emailB@gmail.com", "en-US"); - profiles = {&profileA, &profileB}; - - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"emailA@gmail.com", u"emailB@gmail.com")); - - // Tests that a name is shown when the address cannot be shown and there are - // different names. - profileB = GetProfileA(); - profileB.SetInfo(NAME_FIRST, u"firstB", "en-US"); - profileB.SetInfo(NAME_LAST, u"lastB", "en-US"); - profiles = {&profileA, &profileB}; - - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"firstA lastA", u"firstB lastB")); - - // Tests that a phone number is shown when the address cannot be shown, when - // profiles have the same data for unfocused form fields, and when the form - // has a phone number field. - profileB = GetProfileA(); - profiles = {&profileA, &profileB}; - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"(617) 666-0000", u"(617) 666-0000")); - - // Tests that an email address is shown when the address cannot be shown, when - // profiles have the same data for unfocused form fields, and when the form - // does not have a phone number field, but has an email address field. - profileB = GetProfileA(); - profiles = {&profileA, &profileB}; - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusEmailFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"emailA@gmail.com", u"emailA@gmail.com")); - - // Tests that a name is shown when the address cannot be shown, when profiles - // have the same data for unfocused form fields, and when the form does not - // have a phone number or email address field, but has a name field. - profileB = GetProfileA(); - profiles = {&profileA, &profileB}; - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressOnlyFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"firstA lastA", u"firstA lastA")); -} - -TEST(MobileLabelFormatterTest, - GetLabelsForFocusedAddress_UniqueProfile_ShowOne) { - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - features::kAutofillUseMobileLabelDisambiguationParameterShowOne; - - base::test::ScopedFeatureList features; - features.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - - AutofillProfile profileA = GetProfileA(); - std::vector<const AutofillProfile*> profiles{&profileA}; - - // Tests that the second most important piece of data, phone, is shown when - // the form has an unfocused form field corresponding to this data and the - // most important piece cannot be shown. - std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_LINE1, GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"(617) 666-0000")); - - // Tests that the third most important piece of data, email, is shown when - // the form has an unfocused form field corresponding to this data and the - // two most important pieces of data cannot be shown. - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusEmailFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"emailA@gmail.com")); - - // Tests that the least important piece of data, name, is shown when the form - // has an unfocused form field corresponding to this data and the more - // important pieces of data cannot be shown. - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressOnlyFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"firstA lastA")); -} - -TEST(MobileLabelFormatterTest, GetLabels_DistinctProfiles_ShowAll) { - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - features::kAutofillUseMobileLabelDisambiguationParameterShowAll; - - base::test::ScopedFeatureList features; - features.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - - AutofillProfile profileA = GetProfileA(); - AutofillProfile profileB = GetProfileB(); - AutofillProfile profileC(AddressCountryCode("US")); - test::SetProfileInfo(&profileC, "firstC", "middleC", "lastC", "", "", "", "", - "", "", "", "US", ""); - const std::vector<const AutofillProfile*> profiles{&profileA, &profileB, - &profileC}; - - // Tests that unfocused data that is not the same across profiles is shown in - // the label for forms with addresses. - std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", NAME_FIRST, GetAddressPlusContactFieldTypes()); - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(u"address1A, address2A, (617) 666-0000, emailA@gmail.com", - u"address1B, address2B, (518) 555-0000, emailB@gmail.com", - std::u16string())); - - // Like the previous test, but focuses on an address field rather than a name - // field to check that the name is correctly added to the label. - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusContactFieldTypes()); - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(u"firstA, (617) 666-0000, emailA@gmail.com", - u"firstB, (518) 555-0000, emailB@gmail.com", u"firstC")); - - // Tests that unfocused data that is not the same across profiles is shown in - // the label for forms with non street addresses and without street addresses. - formatter = LabelFormatter::Create(profiles, "en-US", NAME_FIRST, - {NAME_FIRST, NAME_LAST, ADDRESS_HOME_ZIP}); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"02113", u"12224", std::u16string())); - - // Like the previous test, but focuses on an address field rather than a name - // field to check that the name is correctly added to the label. - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_ZIP, - {NAME_FIRST, NAME_LAST, ADDRESS_HOME_ZIP}); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"firstA", u"firstB", u"firstC")); - - // Tests that unfocused data that is not the same across profiles is shown in - // the label for forms without addresses. - formatter = LabelFormatter::Create(profiles, "en-US", NAME_FIRST, - GetContactOnlyFieldTypes()); - EXPECT_THAT( - formatter->GetLabels(), - ElementsAre(u"(617) 666-0000, emailA@gmail.com", - u"(518) 555-0000, emailB@gmail.com", std::u16string())); - - // Like the previous test, but focuses on a phone field rather than a name - // field to check that the name is correctly added to the label. - formatter = LabelFormatter::Create(profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, - GetContactOnlyFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), - ElementsAre(u"firstA, emailA@gmail.com", - u"firstB, emailB@gmail.com", u"firstC")); -} - -TEST(MobileLabelFormatterTest, GetDefaultLabel_ShowAll) { - std::map<std::string, std::string> parameters; - parameters[features::kAutofillUseMobileLabelDisambiguationParameterName] = - features::kAutofillUseMobileLabelDisambiguationParameterShowAll; - - base::test::ScopedFeatureList features; - features.InitAndEnableFeatureWithParameters( - features::kAutofillUseMobileLabelDisambiguation, parameters); - - AutofillProfile profileA = GetProfileA(); - const std::vector<const AutofillProfile*> profiles{&profileA}; - - // Tests that the most important piece of data, address, is shown when the - // form has an unfocused form field corresponding to this data. - std::unique_ptr<LabelFormatter> formatter = LabelFormatter::Create( - profiles, "en-US", NAME_FIRST, GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"address1A, address2A")); - - // Tests that the most important piece of data, address, is shown when the - // form has an unfocused form field corresponding to this data. - formatter = LabelFormatter::Create(profiles, "en-US", NAME_FIRST, - {NAME_FIRST, NAME_LAST, ADDRESS_HOME_ZIP}); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"02113")); - - // Tests that the second most important piece of data, phone, is shown when - // the form has an unfocused form field corresponding to this data and the - // most important piece cannot be shown. - formatter = LabelFormatter::Create(profiles, "en-US", ADDRESS_HOME_LINE1, - GetAddressPlusContactFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"(617) 666-0000")); - - // Tests that the third most important piece of data, email, is shown when - // the form has an unfocused form field corresponding to this data and the - // two more important pieces of data cannot be shown. - formatter = LabelFormatter::Create(profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, - GetContactOnlyFieldTypes()); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"emailA@gmail.com")); - - // Tests that the least important piece of data, name, is shown when - // the form has an unfocused form field corresponding to this data and the - // more important pieces of data cannot be shown. - formatter = - LabelFormatter::Create(profiles, "en-US", PHONE_HOME_WHOLE_NUMBER, - {NAME_FIRST, NAME_LAST, PHONE_HOME_WHOLE_NUMBER}); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"firstA lastA")); - - // Tests that a non street address is shown when a form contains only - // non focused street address fields and a focused non street address. - formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_ZIP, - {ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP}); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"cityA, MA")); - - // Tests that a non street address is not shown when a form contains - // non focused street address fields and another kind of field and also has a - // focused non street address. - formatter = LabelFormatter::Create( - profiles, "en-US", ADDRESS_HOME_CITY, - {ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, EMAIL_ADDRESS}); - EXPECT_THAT(formatter->GetLabels(), ElementsAre(u"emailA@gmail.com")); -} - -} // namespace -} // namespace autofill
diff --git a/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h b/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h index 83d511e..297da6c 100644 --- a/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h +++ b/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h
@@ -7,10 +7,11 @@ #include "components/autofill/core/browser/ui/autofill_popup_delegate.h" +#include <optional> + #include "base/functional/callback.h" #include "base/memory/weak_ptr.h" #include "testing/gmock/include/gmock/gmock.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill {
diff --git a/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc b/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc index 29b16c9..c038678 100644 --- a/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc +++ b/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc
@@ -124,8 +124,8 @@ // Shows the Card Unmask Prompt. `challenge_option` being present denotes that // we are in the virtual card use-case. - void ShowPrompt(const absl::optional<autofill::CardUnmaskChallengeOption>& - challenge_option = absl::nullopt) { + void ShowPrompt(const std::optional<autofill::CardUnmaskChallengeOption>& + challenge_option = std::nullopt) { card_.set_record_type(challenge_option.has_value() ? CreditCard::RecordType::kVirtualCard : CreditCard::RecordType::kMaskedServerCard); @@ -150,10 +150,10 @@ bool should_unmask_virtual_card = false, bool was_checkbox_visible = true) { ShowPrompt(should_unmask_virtual_card - ? absl::optional<autofill::CardUnmaskChallengeOption>( + ? std::optional<autofill::CardUnmaskChallengeOption>( test::GetCardUnmaskChallengeOptions( {CardUnmaskChallengeOptionType::kCvc})[0]) - : absl::nullopt); + : std::nullopt); controller_->OnUnmaskPromptAccepted(u"444", u"01", u"2050", enable_fido_auth, was_checkbox_visible); } @@ -542,7 +542,7 @@ TEST_P(LoggingValidationTestForNickname, VirtualCard_LogUnmaskPromptShown) { base::HistogramTester histogram_tester; - ShowPrompt(absl::optional<autofill::CardUnmaskChallengeOption>( + ShowPrompt(std::optional<autofill::CardUnmaskChallengeOption>( test::GetCardUnmaskChallengeOptions( {CardUnmaskChallengeOptionType::kCvc})[0]));
diff --git a/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.cc b/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.cc index 9fdb1a5..4979015 100644 --- a/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.cc +++ b/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.cc
@@ -9,7 +9,7 @@ CardUnmaskPromptOptions::CardUnmaskPromptOptions() = default; CardUnmaskPromptOptions::CardUnmaskPromptOptions( - const absl::optional<CardUnmaskChallengeOption>& challenge_option, + const std::optional<CardUnmaskChallengeOption>& challenge_option, AutofillClient::UnmaskCardReason reason) : challenge_option(challenge_option), reason(reason) {}
diff --git a/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.h b/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.h index 45997c7..cbd26e8 100644 --- a/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.h +++ b/components/autofill/core/browser/ui/payments/card_unmask_prompt_options.h
@@ -17,7 +17,7 @@ struct CardUnmaskPromptOptions { CardUnmaskPromptOptions(); CardUnmaskPromptOptions( - const absl::optional<CardUnmaskChallengeOption>& challenge_option, + const std::optional<CardUnmaskChallengeOption>& challenge_option, AutofillClient::UnmaskCardReason reason); CardUnmaskPromptOptions(const CardUnmaskPromptOptions&); ~CardUnmaskPromptOptions(); @@ -26,7 +26,7 @@ // challenge option the user is presented with. In the // CardUnmaskPromptController, only a CardUnmaskChallengeOptionType::kCvc // challenge option is supported. - absl::optional<CardUnmaskChallengeOption> challenge_option; + std::optional<CardUnmaskChallengeOption> challenge_option; // The origin of the unmask request. AutofillClient::UnmaskCardReason reason;
diff --git a/components/autofill/core/browser/ui/suggestion.h b/components/autofill/core/browser/ui/suggestion.h index 1ab89114..f1c4b6a9 100644 --- a/components/autofill/core/browser/ui/suggestion.h +++ b/components/autofill/core/browser/ui/suggestion.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_SUGGESTION_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_SUGGESTION_H_ +#include <optional> #include <ostream> #include <string> #include <string_view> @@ -16,7 +17,6 @@ #include "build/build_config.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/ui/popup_item_ids.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "ui/gfx/image/image.h" #include "url/gurl.h"
diff --git a/components/autofill/core/browser/webdata/addresses/address_autofill_table.cc b/components/autofill/core/browser/webdata/addresses/address_autofill_table.cc new file mode 100644 index 0000000..5cb16538 --- /dev/null +++ b/components/autofill/core/browser/webdata/addresses/address_autofill_table.cc
@@ -0,0 +1,1192 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" + +#include <stdint.h> + +#include <memory> +#include <string_view> +#include <vector> + +#include "base/notreached.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "base/uuid.h" +#include "components/autofill/core/browser/field_type_utils.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/webdata/autofill_table_utils.h" +#include "components/autofill/core/common/autofill_features.h" +#include "components/webdata/common/web_database.h" +#include "sql/statement.h" +#include "sql/transaction.h" + +namespace autofill { + +namespace { + +constexpr std::string_view kAutofillProfilesTable = "autofill_profiles"; +constexpr std::string_view kGuid = "guid"; +constexpr std::string_view kLabel = "label"; +constexpr std::string_view kCompanyName = "company_name"; +constexpr std::string_view kStreetAddress = "street_address"; +constexpr std::string_view kDependentLocality = "dependent_locality"; +constexpr std::string_view kCity = "city"; +constexpr std::string_view kState = "state"; +constexpr std::string_view kZipcode = "zipcode"; +constexpr std::string_view kSortingCode = "sorting_code"; +constexpr std::string_view kCountryCode = "country_code"; +constexpr std::string_view kUseCount = "use_count"; +constexpr std::string_view kUseDate = "use_date"; +constexpr std::string_view kDateModified = "date_modified"; +constexpr std::string_view kOrigin = "origin"; +constexpr std::string_view kLanguageCode = "language_code"; +constexpr std::string_view kDisallowSettingsVisibleUpdates = + "disallow_settings_visible_updates"; + +constexpr std::string_view kAutofillProfileAddressesTable = + "autofill_profile_addresses"; +// kGuid = "guid" +// kStreetAddress = "street_address" +constexpr std::string_view kStreetName = "street_name"; +constexpr std::string_view kDependentStreetName = "dependent_street_name"; +constexpr std::string_view kHouseNumber = "house_number"; +constexpr std::string_view kSubpremise = "subpremise"; +// kDependentLocality = "dependent_locality" +// kCity = "city" +// kState = "state" +constexpr std::string_view kZipCode = "zip_code"; +// kCountryCode = "country_code" +// kSortingCode = "sorting_code" +constexpr std::string_view kApartmentNumber = "apartment_number"; +constexpr std::string_view kFloor = "floor"; +constexpr std::string_view kStreetAddressStatus = "street_address_status"; +constexpr std::string_view kStreetNameStatus = "street_name_status"; +constexpr std::string_view kDependentStreetNameStatus = + "dependent_street_name_status"; +constexpr std::string_view kHouseNumberStatus = "house_number_status"; +constexpr std::string_view kSubpremiseStatus = "subpremise_status"; +constexpr std::string_view kDependentLocalityStatus = + "dependent_locality_status"; +constexpr std::string_view kCityStatus = "city_status"; +constexpr std::string_view kStateStatus = "state_status"; +constexpr std::string_view kZipCodeStatus = "zip_code_status"; +constexpr std::string_view kCountryCodeStatus = "country_code_status"; +constexpr std::string_view kSortingCodeStatus = "sorting_code_status"; +constexpr std::string_view kApartmentNumberStatus = "apartment_number_status"; +constexpr std::string_view kFloorStatus = "floor_status"; + +constexpr std::string_view kAutofillProfileNamesTable = + "autofill_profile_names"; +// kGuid = "guid" +constexpr std::string_view kHonorificPrefix = "honorific_prefix"; +constexpr std::string_view kFirstName = "first_name"; +constexpr std::string_view kMiddleName = "middle_name"; +constexpr std::string_view kLastName = "last_name"; +constexpr std::string_view kFirstLastName = "first_last_name"; +constexpr std::string_view kConjunctionLastName = "conjunction_last_name"; +constexpr std::string_view kSecondLastName = "second_last_name"; +constexpr std::string_view kFullName = "full_name"; +constexpr std::string_view kFullNameWithHonorificPrefix = + "full_name_with_honorific_prefix"; +constexpr std::string_view kHonorificPrefixStatus = "honorific_prefix_status"; +constexpr std::string_view kFirstNameStatus = "first_name_status"; +constexpr std::string_view kMiddleNameStatus = "middle_name_status"; +constexpr std::string_view kLastNameStatus = "last_name_status"; +constexpr std::string_view kFirstLastNameStatus = "first_last_name_status"; +constexpr std::string_view kConjunctionLastNameStatus = + "conjunction_last_name_status"; +constexpr std::string_view kSecondLastNameStatus = "second_last_name_status"; +constexpr std::string_view kFullNameStatus = "full_name_status"; +constexpr std::string_view kFullNameWithHonorificPrefixStatus = + "full_name_with_honorific_prefix_status"; + +constexpr std::string_view kAutofillProfileEmailsTable = + "autofill_profile_emails"; +// kGuid = "guid" +constexpr std::string_view kEmail = "email"; + +constexpr std::string_view kAutofillProfilePhonesTable = + "autofill_profile_phones"; +// kGuid = "guid" +constexpr std::string_view kNumber = "number"; + +constexpr std::string_view kAutofillProfileBirthdatesTable = + "autofill_profile_birthdates"; +// kGuid = "guid" +constexpr std::string_view kDay = "day"; +constexpr std::string_view kMonth = "month"; +constexpr std::string_view kYear = "year"; + +constexpr std::string_view kContactInfoTable = "contact_info"; +constexpr std::string_view kLocalAddressesTable = "local_addresses"; +// kGuid = "guid" +// kUseCount = "use_count" +// kUseDate = "use_date" +// kDateModified = "date_modified" +// kLanguageCode = "language_code" +// kLabel = "label" +constexpr std::string_view kInitialCreatorId = "initial_creator_id"; +constexpr std::string_view kLastModifierId = "last_modifier_id"; + +constexpr std::string_view kContactInfoTypeTokensTable = + "contact_info_type_tokens"; +constexpr std::string_view kLocalAddressesTypeTokensTable = + "local_addresses_type_tokens"; +// kGuid = "guid" +constexpr std::string_view kType = "type"; +constexpr std::string_view kValue = "value"; +constexpr std::string_view kVerificationStatus = "verification_status"; +constexpr std::string_view kObservations = "observations"; + +// Truncates `data` to the maximum length that can be stored in a column of the +// Autofill database. Shorter strings are left as-is. +std::u16string Truncate(const std::u16string& data) { + return data.substr(0, AddressAutofillTable::kMaxDataLength); +} + +void AddAutofillProfileDetailsFromStatement(sql::Statement& s, + AutofillProfile* profile) { + int index = 0; + for (FieldType type : + {COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS, + ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, + ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY}) { + profile->SetRawInfo(type, s.ColumnString16(index++)); + } + profile->set_use_count(s.ColumnInt64(index++)); + profile->set_use_date(base::Time::FromTimeT(s.ColumnInt64(index++))); + profile->set_modification_date(base::Time::FromTimeT(s.ColumnInt64(index++))); + profile->set_language_code(s.ColumnString(index++)); + profile->set_profile_label(s.ColumnString(index++)); +} + +bool AddAutofillProfileNamesToProfile(sql::Database* db, + AutofillProfile* profile) { + if (!db->DoesTableExist(kAutofillProfileNamesTable)) { + return false; + } + sql::Statement s; + if (SelectByGuid( + db, s, kAutofillProfileNamesTable, + {kGuid, kHonorificPrefix, kHonorificPrefixStatus, kFirstName, + kFirstNameStatus, kMiddleName, kMiddleNameStatus, kFirstLastName, + kFirstLastNameStatus, kConjunctionLastName, + kConjunctionLastNameStatus, kSecondLastName, kSecondLastNameStatus, + kLastName, kLastNameStatus, kFullName, kFullNameStatus, + kFullNameWithHonorificPrefix, kFullNameWithHonorificPrefixStatus}, + profile->guid())) { + DCHECK_EQ(profile->guid(), s.ColumnString(0)); + + int index = 1; + for (FieldType type : + {NAME_HONORIFIC_PREFIX, NAME_FIRST, NAME_MIDDLE, NAME_LAST_FIRST, + NAME_LAST_CONJUNCTION, NAME_LAST_SECOND, NAME_LAST, NAME_FULL, + NAME_FULL_WITH_HONORIFIC_PREFIX}) { + profile->SetRawInfoWithVerificationStatusInt( + type, s.ColumnString16(index), s.ColumnInt(index + 1)); + index += 2; + } + } + return s.Succeeded(); +} + +bool AddAutofillProfileAddressesToProfile(sql::Database* db, + AutofillProfile* profile) { + if (!db->DoesTableExist(kAutofillProfileAddressesTable)) { + return false; + } + sql::Statement s; + if (SelectByGuid(db, s, kAutofillProfileAddressesTable, + {kGuid, + kStreetAddress, + kStreetAddressStatus, + kStreetName, + kStreetNameStatus, + kHouseNumber, + kHouseNumberStatus, + kSubpremise, + kSubpremiseStatus, + kDependentLocality, + kDependentLocalityStatus, + kCity, + kCityStatus, + kState, + kStateStatus, + kZipCode, + kZipCodeStatus, + kSortingCode, + kSortingCodeStatus, + kCountryCode, + kCountryCodeStatus, + kApartmentNumber, + kApartmentNumberStatus, + kFloor, + kFloorStatus}, + profile->guid())) { + DCHECK_EQ(profile->guid(), s.ColumnString(0)); + std::u16string street_address = s.ColumnString16(1); + std::u16string dependent_locality = s.ColumnString16(13); + std::u16string city = s.ColumnString16(15); + std::u16string state = s.ColumnString16(17); + std::u16string zip_code = s.ColumnString16(19); + std::u16string sorting_code = s.ColumnString16(21); + std::u16string country = s.ColumnString16(23); + + std::u16string street_address_legacy = + profile->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS); + std::u16string dependent_locality_legacy = + profile->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY); + std::u16string city_legacy = profile->GetRawInfo(ADDRESS_HOME_CITY); + std::u16string state_legacy = profile->GetRawInfo(ADDRESS_HOME_STATE); + std::u16string zip_code_legacy = profile->GetRawInfo(ADDRESS_HOME_ZIP); + std::u16string sorting_code_legacy = + profile->GetRawInfo(ADDRESS_HOME_SORTING_CODE); + std::u16string country_legacy = profile->GetRawInfo(ADDRESS_HOME_COUNTRY); + + // At this stage, the unstructured address was already written to + // the profile. If the address was changed by a legacy client, the + // information diverged from the one in this table that is only written by + // new clients. In this case remove the corresponding row from this table. + // Otherwise, read the new structured tokens and set the verification + // statuses for all tokens. + if (street_address == street_address_legacy && + dependent_locality == dependent_locality_legacy && + city == city_legacy && state == state_legacy && + zip_code == zip_code_legacy && sorting_code == sorting_code_legacy && + country == country_legacy) { + int index = 1; + for (FieldType type : + {ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STREET_NAME, + ADDRESS_HOME_HOUSE_NUMBER, ADDRESS_HOME_SUBPREMISE, + ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY, + ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, + ADDRESS_HOME_COUNTRY, ADDRESS_HOME_APT_NUM, ADDRESS_HOME_FLOOR}) { + profile->SetRawInfoWithVerificationStatusInt( + type, s.ColumnString16(index), s.ColumnInt(index + 1)); + index += 2; + } + } else { + // Remove the structured information from the table for + // eventual deletion consistency. + DeleteWhereColumnEq(db, kAutofillProfileAddressesTable, kGuid, + profile->guid()); + } + } + return s.Succeeded(); +} + +bool AddAutofillProfileEmailsToProfile(sql::Database* db, + AutofillProfile* profile) { + if (!db->DoesTableExist(kAutofillProfileEmailsTable)) { + return false; + } + // TODO(estade): update schema so that multiple emails are not associated + // per unique profile guid. Please refer https://crbug.com/497934. + sql::Statement s; + if (SelectByGuid(db, s, kAutofillProfileEmailsTable, {kGuid, kEmail}, + profile->guid())) { + DCHECK_EQ(profile->guid(), s.ColumnString(0)); + profile->SetRawInfo(EMAIL_ADDRESS, s.ColumnString16(1)); + } + return s.Succeeded(); +} + +bool AddAutofillProfilePhonesToProfile(sql::Database* db, + AutofillProfile* profile) { + if (!db->DoesTableExist(kAutofillProfilePhonesTable)) { + return false; + } + // TODO(estade): update schema so that multiple phone numbers are not + // associated per unique profile guid. Please refer + // https://crbug.com/497934. + sql::Statement s; + if (SelectByGuid(db, s, kAutofillProfilePhonesTable, {kGuid, kNumber}, + profile->guid())) { + DCHECK_EQ(profile->guid(), s.ColumnString(0)); + profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(1)); + } + return s.Succeeded(); +} + +bool AddAutofillProfileBirthdateToProfile(sql::Database* db, + AutofillProfile* profile) { + if (!db->DoesTableExist(kAutofillProfileBirthdatesTable)) { + return false; + } + sql::Statement s; + if (SelectByGuid(db, s, kAutofillProfileBirthdatesTable, + {kGuid, kDay, kMonth, kYear}, profile->guid())) { + DCHECK_EQ(profile->guid(), s.ColumnString(0)); + profile->SetRawInfoAsInt(BIRTHDATE_DAY, s.ColumnInt(1)); + profile->SetRawInfoAsInt(BIRTHDATE_MONTH, s.ColumnInt(2)); + profile->SetRawInfoAsInt(BIRTHDATE_4_DIGIT_YEAR, s.ColumnInt(3)); + } + return s.Succeeded(); +} + +WebDatabaseTable::TypeKey GetKey() { + // We just need a unique constant. Use the address of a static that + // COMDAT folding won't touch in an optimizing linker. + static int table_key = 0; + return reinterpret_cast<void*>(&table_key); +} + +time_t GetEndTime(const base::Time& end) { + if (end.is_null() || end == base::Time::Max()) { + return std::numeric_limits<time_t>::max(); + } + + return end.ToTimeT(); +} + +// This helper function binds the `profile`s properties to the placeholders in +// `s`, in the order the columns are defined in the header file. +void BindAutofillProfileToStatement(const AutofillProfile& profile, + sql::Statement& s) { + int index = 0; + s.BindString(index++, profile.guid()); + s.BindInt64(index++, profile.use_count()); + s.BindInt64(index++, profile.use_date().ToTimeT()); + s.BindInt64(index++, profile.modification_date().ToTimeT()); + s.BindString(index++, profile.language_code()); + s.BindString(index++, profile.profile_label()); + s.BindInt(index++, profile.initial_creator_id()); + s.BindInt(index++, profile.last_modifier_id()); +} + +// Local and account profiles are stored in different tables with the same +// layout. One table contains profile-level metadata, while another table +// contains the values for every relevant FieldType. The following two +// functions are used to map from a profile's `source` to the correct table. +std::string_view GetProfileMetadataTable(AutofillProfile::Source source) { + switch (source) { + case AutofillProfile::Source::kLocalOrSyncable: + return kLocalAddressesTable; + case AutofillProfile::Source::kAccount: + return kContactInfoTable; + } + NOTREACHED_NORETURN(); +} +std::string_view GetProfileTypeTokensTable(AutofillProfile::Source source) { + switch (source) { + case AutofillProfile::Source::kLocalOrSyncable: + return kLocalAddressesTypeTokensTable; + case AutofillProfile::Source::kAccount: + return kContactInfoTypeTokensTable; + } + NOTREACHED_NORETURN(); +} + +// Inserts `profile` into `GetProfileMetadataTable()` and +// `GetProfileTypeTokensTable()`, depending on the profile's source. +bool AddAutofillProfileToTable(sql::Database* db, + const AutofillProfile& profile) { + sql::Statement s; + InsertBuilder(db, s, GetProfileMetadataTable(profile.source()), + {kGuid, kUseCount, kUseDate, kDateModified, kLanguageCode, + kLabel, kInitialCreatorId, kLastModifierId}); + BindAutofillProfileToStatement(profile, s); + if (!s.Run()) { + return false; + } + for (FieldType type : GetDatabaseStoredTypesOfAutofillProfile()) { + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableSupportForAddressOverflowAndLandmark) && + type == ADDRESS_HOME_OVERFLOW_AND_LANDMARK) { + continue; + } + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableSupportForBetweenStreetsOrLandmark) && + type == ADDRESS_HOME_BETWEEN_STREETS_OR_LANDMARK) { + continue; + } + + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableSupportForAddressOverflow) && + type == ADDRESS_HOME_OVERFLOW) { + continue; + } + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableSupportForLandmark) && + type == ADDRESS_HOME_LANDMARK) { + continue; + } + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableSupportForBetweenStreets) && + (type == ADDRESS_HOME_BETWEEN_STREETS || + type == ADDRESS_HOME_BETWEEN_STREETS_1 || + type == ADDRESS_HOME_BETWEEN_STREETS_2)) { + continue; + } + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableSupportForAdminLevel2) && + type == ADDRESS_HOME_ADMIN_LEVEL2) { + continue; + } + InsertBuilder(db, s, GetProfileTypeTokensTable(profile.source()), + {kGuid, kType, kValue, kVerificationStatus, kObservations}); + s.BindString(0, profile.guid()); + s.BindInt(1, type); + s.BindString16(2, Truncate(profile.GetRawInfo(type))); + s.BindInt(3, profile.GetVerificationStatusInt(type)); + s.BindBlob( + 4, profile.token_quality().SerializeObservationsForStoredType(type)); + if (!s.Run()) { + return false; + } + } + return true; +} + +// `MigrateToVersion113MigrateLocalAddressProfilesToNewTable()` migrates +// profiles from one table layout to another. This function inserts the given +// `profile` into the `GetProfileMetadataTable()` of schema version 113. +// `AddAutofillProfileToTable()` can't be reused, since the schema can change in +// future database versions in ways incompatible with version 113 (e.g. adding +// a column). +// The code was copied from `AddAutofillProfileToTable()` in version 113. Like +// the migration logic, it shouldn't be changed. +bool AddAutofillProfileToTableVersion113(sql::Database* db, + const AutofillProfile& profile) { + sql::Statement s; + InsertBuilder(db, s, GetProfileMetadataTable(profile.source()), + {kGuid, kUseCount, kUseDate, kDateModified, kLanguageCode, + kLabel, kInitialCreatorId, kLastModifierId}); + BindAutofillProfileToStatement(profile, s); + if (!s.Run()) { + return false; + } + // Note that `GetDatabaseStoredTypesOfAutofillProfile()` might change in + // future versions. Due to the flexible layout of the type tokens table, this + // is not a problem. + for (FieldType type : GetDatabaseStoredTypesOfAutofillProfile()) { + InsertBuilder(db, s, GetProfileTypeTokensTable(profile.source()), + {kGuid, kType, kValue, kVerificationStatus}); + s.BindString(0, profile.guid()); + s.BindInt(1, type); + s.BindString16(2, Truncate(profile.GetRawInfo(type))); + s.BindInt(3, profile.GetVerificationStatusInt(type)); + if (!s.Run()) { + return false; + } + } + return true; +} + +} // namespace + +// static +const size_t AddressAutofillTable::kMaxDataLength = 1024; + +AddressAutofillTable::AddressAutofillTable() = default; + +AddressAutofillTable::~AddressAutofillTable() = default; + +// static +AddressAutofillTable* AddressAutofillTable::FromWebDatabase(WebDatabase* db) { + return static_cast<AddressAutofillTable*>(db->GetTable(GetKey())); +} + +WebDatabaseTable::TypeKey AddressAutofillTable::GetTypeKey() const { + return GetKey(); +} + +bool AddressAutofillTable::CreateTablesIfNecessary() { + return InitProfileMetadataTable(AutofillProfile::Source::kAccount) && + InitProfileTypeTokensTable(AutofillProfile::Source::kAccount) && + InitProfileMetadataTable(AutofillProfile::Source::kLocalOrSyncable) && + InitProfileTypeTokensTable(AutofillProfile::Source::kLocalOrSyncable); +} + +bool AddressAutofillTable::MigrateToVersion(int version, + bool* update_compatible_version) { + if (!db_->is_open()) { + return false; + } + // Migrate if necessary. + switch (version) { + case 88: + *update_compatible_version = false; + return MigrateToVersion88AddNewNameColumns(); + case 90: + *update_compatible_version = false; + return MigrateToVersion90AddNewStructuredAddressColumns(); + case 91: + *update_compatible_version = false; + return MigrateToVersion91AddMoreStructuredAddressColumns(); + case 92: + *update_compatible_version = false; + return MigrateToVersion92AddNewPrefixedNameColumn(); + case 93: + *update_compatible_version = false; + return MigrateToVersion93AddAutofillProfileLabelColumn(); + case 96: + *update_compatible_version = false; + return MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn(); + case 99: + *update_compatible_version = true; + return MigrateToVersion99RemoveAutofillProfilesTrashTable(); + case 100: + *update_compatible_version = true; + return MigrateToVersion100RemoveProfileValidityBitfieldColumn(); + case 102: + *update_compatible_version = false; + return MigrateToVersion102AddAutofillBirthdatesTable(); + case 107: + *update_compatible_version = false; + return MigrateToVersion107AddContactInfoTables(); + case 110: + *update_compatible_version = false; + return MigrateToVersion110AddInitialCreatorIdAndLastModifierId(); + case 113: + *update_compatible_version = false; + return MigrateToVersion113MigrateLocalAddressProfilesToNewTable(); + case 114: + *update_compatible_version = true; + return MigrateToVersion114DropLegacyAddressTables(); + case 117: + *update_compatible_version = false; + return MigrateToVersion117AddProfileObservationColumn(); + case 121: + *update_compatible_version = true; + return MigrateToVersion121DropServerAddressTables(); + } + return true; +} + +bool AddressAutofillTable::AddAutofillProfile(const AutofillProfile& profile) { + sql::Transaction transaction(db_); + return transaction.Begin() && AddAutofillProfileToTable(db_, profile) && + transaction.Commit(); +} + +bool AddressAutofillTable::UpdateAutofillProfile( + const AutofillProfile& profile) { + DCHECK(base::Uuid::ParseCaseInsensitive(profile.guid()).is_valid()); + + std::unique_ptr<AutofillProfile> old_profile = + GetAutofillProfile(profile.guid(), profile.source()); + if (!old_profile) { + return false; + } + + // Implementing an update as remove + add has multiple advantages: + // - Prevents outdated (FieldType, value) pairs from remaining in the + // `GetProfileTypeTokensTable(profile)`, in case field types are removed. + // - Simpler code. + // The possible downside is performance. This is not an issue, as updates + // happen rarely and asynchronously. + sql::Transaction transaction(db_); + return transaction.Begin() && + RemoveAutofillProfile(profile.guid(), profile.source()) && + AddAutofillProfileToTable(db_, profile) && transaction.Commit(); +} + +bool AddressAutofillTable::RemoveAutofillProfile( + const std::string& guid, + AutofillProfile::Source profile_source) { + DCHECK(base::Uuid::ParseCaseInsensitive(guid).is_valid()); + sql::Transaction transaction(db_); + return transaction.Begin() && + DeleteWhereColumnEq(db_, GetProfileMetadataTable(profile_source), + kGuid, guid) && + DeleteWhereColumnEq(db_, GetProfileTypeTokensTable(profile_source), + kGuid, guid) && + transaction.Commit(); +} + +bool AddressAutofillTable::RemoveAllAutofillProfiles( + AutofillProfile::Source profile_source) { + sql::Transaction transaction(db_); + return transaction.Begin() && + Delete(db_, GetProfileMetadataTable(profile_source)) && + Delete(db_, GetProfileTypeTokensTable(profile_source)) && + transaction.Commit(); +} + +std::unique_ptr<AutofillProfile> AddressAutofillTable::GetAutofillProfile( + const std::string& guid, + AutofillProfile::Source profile_source) const { + DCHECK(base::Uuid::ParseCaseInsensitive(guid).is_valid()); + sql::Statement s; + if (!SelectByGuid(db_, s, GetProfileMetadataTable(profile_source), + {kUseCount, kUseDate, kDateModified, kLanguageCode, kLabel, + kInitialCreatorId, kLastModifierId}, + guid)) { + return nullptr; + } + + int index = 0; + const int64_t use_count = s.ColumnInt64(index++); + const base::Time use_date = base::Time::FromTimeT(s.ColumnInt64(index++)); + const base::Time modification_date = + base::Time::FromTimeT(s.ColumnInt64(index++)); + const std::string language_code = s.ColumnString(index++); + const std::string profile_label = s.ColumnString(index++); + const int creator_id = s.ColumnInt(index++); + const int modifier_id = s.ColumnInt(index++); + + if (!SelectByGuid(db_, s, GetProfileTypeTokensTable(profile_source), + {kType, kValue, kVerificationStatus, kObservations}, + guid)) { + return nullptr; + } + + struct FieldTypeData { + // Type corresponding to the data entry. + FieldType type; + // Value corresponding to the entry type. + std::u16string value; + // VerificationStatus of the data entry's `value`. + int status; + // Serialized observations for the stored type. + std::vector<uint8_t> serialized_data; + }; + + std::vector<FieldTypeData> field_type_values; + std::string country_code; + // As `SelectByGuid()` already calls `s.Step()`, do-while is used here. + do { + FieldType type = ToSafeFieldType(s.ColumnInt(0), UNKNOWN_TYPE); + if (type == UNKNOWN_TYPE) { + // This is possible in two cases: + // - The database was tampered with by external means. + // - The type corresponding to `s.ColumnInt(0)` was deprecated. In this + // case, due to the structure of + // `GetProfileTypeTokensTable(profile_source)`, it is not necessary to + // add database migration logic or drop a column. Instead, during the + // next update, the data will be dropped. + continue; + } + + base::span<const uint8_t> observations_data = s.ColumnBlob(3); + field_type_values.emplace_back( + type, s.ColumnString16(1), s.ColumnInt(2), + std::vector<uint8_t>(observations_data.begin(), + observations_data.end())); + + if (type == ADDRESS_HOME_COUNTRY) { + country_code = base::UTF16ToUTF8(s.ColumnString16(1)); + } + + } while (s.Step()); + + // TODO(crbug.com/1464568): Define a proper migration strategy from stored + // legacy profiles into i18n ones. + auto profile = std::make_unique<AutofillProfile>( + guid, profile_source, AddressCountryCode(country_code)); + profile->set_use_count(use_count); + profile->set_use_date(use_date); + profile->set_modification_date(modification_date); + profile->set_language_code(language_code); + profile->set_profile_label(profile_label); + profile->set_initial_creator_id(creator_id); + profile->set_last_modifier_id(modifier_id); + + for (const auto& data : field_type_values) { + profile->SetRawInfoWithVerificationStatusInt(data.type, data.value, + data.status); + profile->token_quality().LoadSerializedObservationsForStoredType( + data.type, data.serialized_data); + } + + profile->FinalizeAfterImport(); + return profile; +} + +bool AddressAutofillTable::GetAutofillProfiles( + AutofillProfile::Source profile_source, + std::vector<std::unique_ptr<AutofillProfile>>* profiles) const { + CHECK(profiles); + profiles->clear(); + + sql::Statement s; + SelectBuilder(db_, s, GetProfileMetadataTable(profile_source), {kGuid}); + while (s.Step()) { + std::string guid = s.ColumnString(0); + std::unique_ptr<AutofillProfile> profile = + GetAutofillProfile(guid, profile_source); + if (!profile) { + continue; + } + profiles->push_back(std::move(profile)); + } + + return s.Succeeded(); +} + +std::unique_ptr<AutofillProfile> +AddressAutofillTable::GetAutofillProfileFromLegacyTable( + const std::string& guid) const { + sql::Statement s; + if (!SelectByGuid(db_, s, kAutofillProfilesTable, + {kCompanyName, kStreetAddress, kDependentLocality, kCity, + kState, kZipcode, kSortingCode, kCountryCode, kUseCount, + kUseDate, kDateModified, kLanguageCode, kLabel}, + guid)) { + return nullptr; + } + + auto profile = std::make_unique<AutofillProfile>( + guid, AutofillProfile::Source::kLocalOrSyncable, + i18n_model_definition::kLegacyHierarchyCountryCode); + + DCHECK(base::Uuid::ParseCaseInsensitive(profile->guid()).is_valid()); + + // Get associated name info using guid. + AddAutofillProfileNamesToProfile(db_, profile.get()); + + // Get associated email info using guid. + AddAutofillProfileEmailsToProfile(db_, profile.get()); + + // Get associated phone info using guid. + AddAutofillProfilePhonesToProfile(db_, profile.get()); + + // Get associated birthdate info using guid. + AddAutofillProfileBirthdateToProfile(db_, profile.get()); + + // The details should be added after the other info to make sure they don't + // change when we change the names/emails/phones. + AddAutofillProfileDetailsFromStatement(s, profile.get()); + + // The structured address information should be added after the street_address + // from the query above was written because this information is used to + // detect changes by a legacy client. + AddAutofillProfileAddressesToProfile(db_, profile.get()); + + // For more-structured profiles, the profile must be finalized to fully + // populate the name fields. + profile->FinalizeAfterImport(); + + return profile; +} + +// TODO(crbug.com/1443393): This function's implementation is very similar to +// `GetAutofillProfiles()`. Simplify somehow. +bool AddressAutofillTable::GetAutofillProfilesFromLegacyTable( + std::vector<std::unique_ptr<AutofillProfile>>* profiles) const { + DCHECK(profiles); + profiles->clear(); + + sql::Statement s; + SelectBuilder(db_, s, kAutofillProfilesTable, {kGuid}); + + while (s.Step()) { + std::string guid = s.ColumnString(0); + std::unique_ptr<AutofillProfile> profile = + GetAutofillProfileFromLegacyTable(guid); + if (!profile) { + continue; + } + profiles->push_back(std::move(profile)); + } + + return s.Succeeded(); +} + +bool AddressAutofillTable::ClearAllLocalData() { + sql::Transaction transaction(db_); + if (!transaction.Begin()) { + return false; // Some error, nothing was changed. + } + + RemoveAllAutofillProfiles(AutofillProfile::Source::kLocalOrSyncable); + bool changed = db_->GetLastChangeCount() > 0; + + transaction.Commit(); + return changed; +} + +bool AddressAutofillTable::RemoveAutofillDataModifiedBetween( + const base::Time& delete_begin, + const base::Time& delete_end, + std::vector<std::unique_ptr<AutofillProfile>>* profiles) { + DCHECK(delete_end.is_null() || delete_begin < delete_end); + + time_t delete_begin_t = delete_begin.ToTimeT(); + time_t delete_end_t = GetEndTime(delete_end); + + // Remember Autofill profiles in the time range. + sql::Statement s_profiles_get; + SelectBetween( + db_, s_profiles_get, + GetProfileMetadataTable(AutofillProfile::Source::kLocalOrSyncable), + {kGuid}, kDateModified, delete_begin_t, delete_end_t); + + profiles->clear(); + while (s_profiles_get.Step()) { + std::string guid = s_profiles_get.ColumnString(0); + std::unique_ptr<AutofillProfile> profile = + GetAutofillProfile(guid, AutofillProfile::Source::kLocalOrSyncable); + if (!profile) { + return false; + } + profiles->push_back(std::move(profile)); + } + if (!s_profiles_get.Succeeded()) { + return false; + } + + // Remove Autofill profiles in the time range. + for (const std::unique_ptr<AutofillProfile>& profile : *profiles) { + if (!RemoveAutofillProfile(profile->guid(), + AutofillProfile::Source::kLocalOrSyncable)) { + return false; + } + } + return true; +} + +bool AddressAutofillTable::MigrateToVersion88AddNewNameColumns() { + for (std::string_view column : {kHonorificPrefix, kFirstLastName, + kConjunctionLastName, kSecondLastName}) { + if (!AddColumnIfNotExists(db_, kAutofillProfileNamesTable, column, + "VARCHAR")) { + return false; + } + } + + for (std::string_view column : + {kHonorificPrefixStatus, kFirstNameStatus, kMiddleNameStatus, + kLastNameStatus, kFirstLastNameStatus, kConjunctionLastNameStatus, + kSecondLastNameStatus, kFullNameStatus}) { + // The default value of 0 corresponds to the verification status + // |kNoStatus|. + if (!AddColumnIfNotExists(db_, kAutofillProfileNamesTable, column, + "INTEGER DEFAULT 0")) { + return false; + } + } + return true; +} + +bool AddressAutofillTable::MigrateToVersion92AddNewPrefixedNameColumn() { + return AddColumnIfNotExists(db_, kAutofillProfileNamesTable, + kFullNameWithHonorificPrefix, "VARCHAR") && + AddColumnIfNotExists(db_, kAutofillProfileNamesTable, + kFullNameWithHonorificPrefixStatus, + "INTEGER DEFAULT 0"); +} + +bool AddressAutofillTable::MigrateToVersion90AddNewStructuredAddressColumns() { + if (!db_->DoesTableExist("autofill_profile_addresses")) { + InitLegacyProfileAddressesTable(); + } + + for (std::string_view column : {kDependentLocality, kCity, kState, kZipCode, + kSortingCode, kCountryCode}) { + if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, + "VARCHAR")) { + return false; + } + } + + for (std::string_view column : + {kDependentLocalityStatus, kCityStatus, kStateStatus, kZipCodeStatus, + kSortingCodeStatus, kCountryCodeStatus}) { + // The default value of 0 corresponds to the verification status + // |kNoStatus|. + if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, + "INTEGER DEFAULT 0")) { + return false; + } + } + return true; +} + +bool AddressAutofillTable::MigrateToVersion91AddMoreStructuredAddressColumns() { + if (!db_->DoesTableExist(kAutofillProfileAddressesTable)) { + InitLegacyProfileAddressesTable(); + } + + for (std::string_view column : {kApartmentNumber, kFloor}) { + if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, + "VARCHAR")) { + return false; + } + } + + for (std::string_view column : {kApartmentNumberStatus, kFloorStatus}) { + // The default value of 0 corresponds to the verification status + // |kNoStatus|. + if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, + "INTEGER DEFAULT 0")) { + return false; + } + } + return true; +} + +bool AddressAutofillTable::MigrateToVersion93AddAutofillProfileLabelColumn() { + if (!db_->DoesTableExist(kAutofillProfilesTable)) { + InitLegacyProfileAddressesTable(); + } + + return AddColumnIfNotExists(db_, kAutofillProfilesTable, kLabel, "VARCHAR"); +} + +bool AddressAutofillTable:: + MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn() { + if (!db_->DoesTableExist(kAutofillProfilesTable)) { + InitLegacyProfileAddressesTable(); + } + + return AddColumnIfNotExists(db_, kAutofillProfilesTable, + kDisallowSettingsVisibleUpdates, + "INTEGER NOT NULL DEFAULT 0"); +} + +bool AddressAutofillTable:: + MigrateToVersion99RemoveAutofillProfilesTrashTable() { + return DropTableIfExists(db_, "autofill_profiles_trash"); +} + +bool AddressAutofillTable:: + MigrateToVersion100RemoveProfileValidityBitfieldColumn() { + sql::Transaction transaction(db_); + return transaction.Begin() && + DropColumn(db_, kAutofillProfilesTable, "validity_bitfield") && + DropColumn(db_, kAutofillProfilesTable, + "is_client_validity_states_updated") && + transaction.Commit(); +} + +bool AddressAutofillTable::MigrateToVersion102AddAutofillBirthdatesTable() { + return CreateTable(db_, kAutofillProfileBirthdatesTable, + {{kGuid, "VARCHAR"}, + {kDay, "INTEGER DEFAULT 0"}, + {kMonth, "INTEGER DEFAULT 0"}, + {kYear, "INTEGER DEFAULT 0"}}); +} + +bool AddressAutofillTable::MigrateToVersion107AddContactInfoTables() { + sql::Transaction transaction(db_); + return transaction.Begin() && + CreateTable(db_, kContactInfoTable, + {{kGuid, "VARCHAR PRIMARY KEY"}, + {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, + {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, + {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, + {kLanguageCode, "VARCHAR"}, + {kLabel, "VARCHAR"}}) && + CreateTable(db_, kContactInfoTypeTokensTable, + {{kGuid, "VARCHAR"}, + {kType, "INTEGER"}, + {kValue, "VARCHAR"}, + {kVerificationStatus, "INTEGER DEFAULT 0"}}, + /*composite_primary_key=*/{kGuid, kType}) && + transaction.Commit(); +} + +bool AddressAutofillTable:: + MigrateToVersion110AddInitialCreatorIdAndLastModifierId() { + if (!db_->DoesTableExist(kContactInfoTable)) { + return false; + } + sql::Transaction transaction(db_); + return transaction.Begin() && + AddColumnIfNotExists(db_, kContactInfoTable, kInitialCreatorId, + "INTEGER DEFAULT 0") && + AddColumnIfNotExists(db_, kContactInfoTable, kLastModifierId, + "INTEGER DEFAULT 0") && + transaction.Commit(); +} + +bool AddressAutofillTable:: + MigrateToVersion113MigrateLocalAddressProfilesToNewTable() { + sql::Transaction transaction(db_); + if (!transaction.Begin() || + !CreateTableIfNotExists(db_, kLocalAddressesTable, + {{kGuid, "VARCHAR PRIMARY KEY"}, + {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, + {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, + {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, + {kLanguageCode, "VARCHAR"}, + {kLabel, "VARCHAR"}, + {kInitialCreatorId, "INTEGER DEFAULT 0"}, + {kLastModifierId, "INTEGER DEFAULT 0"}}) || + !CreateTableIfNotExists(db_, kLocalAddressesTypeTokensTable, + {{kGuid, "VARCHAR"}, + {kType, "INTEGER"}, + {kValue, "VARCHAR"}, + {kVerificationStatus, "INTEGER DEFAULT 0"}}, + /*composite_primary_key=*/{kGuid, kType})) { + return false; + } + bool success = true; + if (db_->DoesTableExist(kAutofillProfilesTable)) { + std::vector<std::unique_ptr<AutofillProfile>> profiles; + success = GetAutofillProfilesFromLegacyTable(&profiles); + // Migrate profiles to the new tables. Preserve the modification dates. + for (const std::unique_ptr<AutofillProfile>& profile : profiles) { + success = success && AddAutofillProfileToTableVersion113(db_, *profile); + } + } + // Delete all profiles from the legacy tables. The tables are dropped in + // version 114. + for (std::string_view deprecated_table : + {kAutofillProfilesTable, kAutofillProfileAddressesTable, + kAutofillProfileNamesTable, kAutofillProfileEmailsTable, + kAutofillProfilePhonesTable, kAutofillProfileBirthdatesTable}) { + success = success && (!db_->DoesTableExist(deprecated_table) || + Delete(db_, deprecated_table)); + } + return success && transaction.Commit(); +} + +bool AddressAutofillTable::MigrateToVersion114DropLegacyAddressTables() { + sql::Transaction transaction(db_); + bool success = transaction.Begin(); + for (std::string_view deprecated_table : + {kAutofillProfilesTable, kAutofillProfileAddressesTable, + kAutofillProfileNamesTable, kAutofillProfileEmailsTable, + kAutofillProfilePhonesTable, kAutofillProfileBirthdatesTable}) { + success = success && DropTableIfExists(db_, deprecated_table); + } + return success && transaction.Commit(); +} + +bool AddressAutofillTable::MigrateToVersion117AddProfileObservationColumn() { + sql::Transaction transaction(db_); + return transaction.Begin() && + AddColumn(db_, kContactInfoTypeTokensTable, kObservations, "BLOB") && + AddColumn(db_, kLocalAddressesTypeTokensTable, kObservations, + "BLOB") && + transaction.Commit(); +} + +bool AddressAutofillTable::MigrateToVersion121DropServerAddressTables() { + sql::Transaction transaction(db_); + return transaction.Begin() && DropTableIfExists(db_, "server_addresses") && + DropTableIfExists(db_, "server_address_metadata") && + transaction.Commit(); +} + +bool AddressAutofillTable::InitLegacyProfilesTable() { + return CreateTableIfNotExists( + db_, kAutofillProfilesTable, + {{kGuid, "VARCHAR PRIMARY KEY"}, + {kCompanyName, "VARCHAR"}, + {kStreetAddress, "VARCHAR"}, + {kDependentLocality, "VARCHAR"}, + {kCity, "VARCHAR"}, + {kState, "VARCHAR"}, + {kZipcode, "VARCHAR"}, + {kSortingCode, "VARCHAR"}, + {kCountryCode, "VARCHAR"}, + {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, + {kOrigin, "VARCHAR DEFAULT ''"}, + {kLanguageCode, "VARCHAR"}, + {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, + {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, + {kLabel, "VARCHAR"}, + {kDisallowSettingsVisibleUpdates, "INTEGER NOT NULL DEFAULT 0"}}); +} + +bool AddressAutofillTable::InitLegacyProfileNamesTable() { + // The default value of 0 corresponds to the verification status + // |kNoStatus|. + return CreateTableIfNotExists( + db_, kAutofillProfileNamesTable, + {{kGuid, "VARCHAR"}, + {kFirstName, "VARCHAR"}, + {kMiddleName, "VARCHAR"}, + {kLastName, "VARCHAR"}, + {kFullName, "VARCHAR"}, + {kHonorificPrefix, "VARCHAR"}, + {kFirstLastName, "VARCHAR"}, + {kConjunctionLastName, "VARCHAR"}, + {kSecondLastName, "VARCHAR"}, + {kHonorificPrefixStatus, "INTEGER DEFAULT 0"}, + {kFirstNameStatus, "INTEGER DEFAULT 0"}, + {kMiddleNameStatus, "INTEGER DEFAULT 0"}, + {kLastNameStatus, "INTEGER DEFAULT 0"}, + {kFirstLastNameStatus, "INTEGER DEFAULT 0"}, + {kConjunctionLastNameStatus, "INTEGER DEFAULT 0"}, + {kSecondLastNameStatus, "INTEGER DEFAULT 0"}, + {kFullNameStatus, "INTEGER DEFAULT 0"}, + {kFullNameWithHonorificPrefix, "VARCHAR"}, + {kFullNameWithHonorificPrefixStatus, "INTEGER DEFAULT 0"}}); +} + +bool AddressAutofillTable::InitLegacyProfileAddressesTable() { + // The default value of 0 corresponds to the verification status + // |kNoStatus|. + return CreateTableIfNotExists( + db_, kAutofillProfileAddressesTable, + {{kGuid, "VARCHAR"}, + {kStreetAddress, "VARCHAR"}, + {kStreetName, "VARCHAR"}, + {kDependentStreetName, "VARCHAR"}, + {kHouseNumber, "VARCHAR"}, + {kSubpremise, "VARCHAR"}, + {"premise_name", "VARCHAR"}, + {kStreetAddressStatus, "INTEGER DEFAULT 0"}, + {kStreetNameStatus, "INTEGER DEFAULT 0"}, + {kDependentStreetNameStatus, "INTEGER DEFAULT 0"}, + {kHouseNumberStatus, "INTEGER DEFAULT 0"}, + {kSubpremiseStatus, "INTEGER DEFAULT 0"}, + {"premise_name_status", "INTEGER DEFAULT 0"}, + {kDependentLocality, "VARCHAR"}, + {kCity, "VARCHAR"}, + {kState, "VARCHAR"}, + {kZipCode, "VARCHAR"}, + {kSortingCode, "VARCHAR"}, + {kCountryCode, "VARCHAR"}, + {kDependentLocalityStatus, "INTEGER DEFAULT 0"}, + {kCityStatus, "INTEGER DEFAULT 0"}, + {kStateStatus, "INTEGER DEFAULT 0"}, + {kZipCodeStatus, "INTEGER DEFAULT 0"}, + {kSortingCodeStatus, "INTEGER DEFAULT 0"}, + {kCountryCodeStatus, "INTEGER DEFAULT 0"}, + {kApartmentNumber, "VARCHAR"}, + {kFloor, "VARCHAR"}, + {kApartmentNumberStatus, "INTEGER DEFAULT 0"}, + {kFloorStatus, "INTEGER DEFAULT 0"}}); +} + +bool AddressAutofillTable::InitLegacyProfileEmailsTable() { + return CreateTableIfNotExists(db_, kAutofillProfileEmailsTable, + {{kGuid, "VARCHAR"}, {kEmail, "VARCHAR"}}); +} + +bool AddressAutofillTable::InitLegacyProfilePhonesTable() { + return CreateTableIfNotExists(db_, kAutofillProfilePhonesTable, + {{kGuid, "VARCHAR"}, {kNumber, "VARCHAR"}}); +} + +bool AddressAutofillTable::InitLegacyProfileBirthdatesTable() { + return CreateTableIfNotExists(db_, kAutofillProfileBirthdatesTable, + {{kGuid, "VARCHAR"}, + {kDay, "INTEGER DEFAULT 0"}, + {kMonth, "INTEGER DEFAULT 0"}, + {kYear, "INTEGER DEFAULT 0"}}); +} + +bool AddressAutofillTable::InitProfileMetadataTable( + AutofillProfile::Source source) { + return CreateTableIfNotExists(db_, GetProfileMetadataTable(source), + {{kGuid, "VARCHAR PRIMARY KEY"}, + {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, + {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, + {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, + {kLanguageCode, "VARCHAR"}, + {kLabel, "VARCHAR"}, + {kInitialCreatorId, "INTEGER DEFAULT 0"}, + {kLastModifierId, "INTEGER DEFAULT 0"}}); +} + +bool AddressAutofillTable::InitProfileTypeTokensTable( + AutofillProfile::Source source) { + return CreateTableIfNotExists(db_, GetProfileTypeTokensTable(source), + {{kGuid, "VARCHAR"}, + {kType, "INTEGER"}, + {kValue, "VARCHAR"}, + {kVerificationStatus, "INTEGER DEFAULT 0"}, + {kObservations, "BLOB"}}, + /*composite_primary_key=*/{kGuid, kType}); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/webdata/addresses/address_autofill_table.h b/components/autofill/core/browser/webdata/addresses/address_autofill_table.h new file mode 100644 index 0000000..f6156856 --- /dev/null +++ b/components/autofill/core/browser/webdata/addresses/address_autofill_table.h
@@ -0,0 +1,342 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_ADDRESSES_ADDRESS_AUTOFILL_TABLE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_ADDRESSES_ADDRESS_AUTOFILL_TABLE_H_ + +#include <stddef.h> + +#include <memory> +#include <string> +#include <vector> + +#include "base/time/time.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/webdata/common/web_database_table.h" + +class WebDatabase; + +namespace autofill { + +// This class manages the various address Autofill tables within the SQLite +// database passed to the constructor. It expects the following schemas: +// +// Note: The database stores time in seconds, UTC. +// +// DEPRECATED. Use local_addresses instead. +// autofill_profiles This table contains Autofill profile data added by the +// user with the Autofill dialog. Most of the columns are +// standard entries in a contact information form. +// +// guid A guid string to uniquely identify the profile. +// Added in version 31. +// label A user-chosen and user-visible label for the profile to +// help identifying the semantics of the profile. The user +// can choose an arbitrary string in principle, but the +// values '$HOME$' and '$WORK$' indicate a special meaning. +// company_name +// street_address The combined lines of the street address. +// Added in version 54. +// dependent_locality +// A sub-classification beneath the city, e.g. an +// inner-city district or suburb. Added in version 54. +// city +// state +// zipcode +// sorting_code Similar to the zipcode column, but used for businesses +// or organizations that might not be geographically +// contiguous. The canonical example is CEDEX in France. +// Added in version 54. +// country_code +// use_count The number of times this profile has been used to fill +// a form. Added in version 61. +// use_date The date this profile was last used to fill a form, +// in time_t. Added in version 61. +// date_modified The date on which this profile was last modified, in +// time_t. Added in version 30. +// origin The domain of origin for this profile. +// Added in version 50. +// language_code The BCP 47 language code used to format the address for +// display. For example, a JP address with "ja" language +// code starts with the postal code, but a JP address with +// "ja-latn" language code starts with the recipient name. +// Added in version 56. +// disallow_settings_visible_updates +// If true, a profile does not qualify to get merged with +// a profile observed in a form submission. +// +// DEPRECATED. See autofill_profiles. +// autofill_profile_addresses +// guid The guid string that identifies the profile to which +// the name belongs. +// This table stores the structured address information. +// street_address Stores the street address. This field is also stored in +// the profile table and is used to detect if a legacy +// client that does not support writing to this table +// changed the address. If this is true, the address stored +// in the table is removed. +// street_name The name of the street. +// dependent_street_name +// The name of the crossing street. +// house_number The house number. +// subpremise The floor, apartment number and staircase. +// apartment number. +// dependent_locality +// A sub-classification beneath the city, e.g. an +// inner-city district or suburb. +// city The city information of the address. +// state The state information of the address. +// zip_code The zip code of the address. +// country_code The code of the country of the address. +// sorting_code Similar to the zipcode column, but used for businesses +// or organizations that might not be geographically +// contiguous. +// premise_name The name of the premise. +// apartment_number The number of the apartment. +// floor The floor in which the apartment is located. +// street_address_status +// street_name_status +// dependent_street_name_status +// house_number_status +// subpremise_status +// premise_name_status +// dependent_locality_status +// city_status +// state_status +// zip_code_status +// country_code_status +// sorting_code_status +// apartment_number_status +// floor_status +// Each token of the address has an additional validation +// status that indicates if Autofill parsed the value out +// of an unstructured (last) name, or if autofill formatted +// the token from its structured subcomponents, or if the +// value was observed in a form submission, or even +// validated by the user in the settings. +// +// DEPRECATED. See autofill_profiles. +// autofill_profile_names +// This table contains the multi-valued name fields +// associated with a profile. +// +// guid The guid string that identifies the profile to which +// the name belongs. +// honorific_prefix The honorific prefix of a person like Ms, Mr or Prof +// first_name The first name of a person. +// middle_name The middle name or even names of a person. +// last_name The unstructured last name that is a combination of the +// first and second last name. +// first_last_name The first part of the last name. Mostly used for +// Latinx/Hispanic last names. +// conjunction_last_name +// An optional conjunction that is mostly used in +// Hispanic/Latinx last names in between the first and +// second last name in the unstructured representation. +// second_last_name The second part of the last names. Last names only +// consisting of a single part are stored in the second +// part by default. +// full_name The unstructured full name of a person. +// full_name_with_honorific_prefix +// The combination of the full name and the honorific +// prefix. +// honorific_prefix_status +// first_name_status +// middle_name_status +// last_name_status +// first_last_name_status +// conjunction_last_name_status +// second_last_name_status +// full_name_status +// full_name_with_honorific_prefix_status +// Each token of the names has an additional validation +// status that indicates if Autofill parsed the value out +// of an unstructured (last) name, or if autofill formatted +// the token from its structured subcomponents, or if the +// value was observed in a form submission, or even +// validated by the user in the settings. +// +// DEPRECATED. See autofill_profiles. +// autofill_profile_emails +// This table contains the multi-valued email fields +// associated with a profile. +// +// guid The guid string that identifies the profile to which +// the email belongs. +// email +// +// DEPRECATED. See autofill_profiles. +// autofill_profile_phones +// This table contains the multi-valued phone fields +// associated with a profile. +// +// guid The guid string that identifies the profile to which the +// phone number belongs. +// number +// +// DEPRECATED. See autofill_profiles. +// autofill_profile_birthdates +// This table contains the multi-valued birthdate fields +// associated with a profile. +// +// guid The guid string that identifies the profile to which the +// birthdate number belongs. +// day As an integer between 1 and 31 inclusive, or 0 if unset. +// month As an integer between 1 and 12 inclusive, or 0 if unset. +// year As a 4 digit integer, or 0 if unset. +// +// contact_info This table contains Autofill profile data synced from a +// remote source. +// local_addresses This table contains kLocalOrSyncable Autofill profiles. +// It has the same layout as the contact_info table. +// +// guid A guid string to uniquely identify the profile. +// use_count The number of times this profile has been used to fill a +// form. +// use_date The date this profile was last used to fill a form, in +// time_t. +// date_modified The date on which this profile was last modified, in +// time_t. +// language_code The BCP 47 language code used to format the address for +// display. For example, a JP address with "ja" language +// code starts with the postal code, but a JP address with +// "ja-latn" language code starts with the recipient name. +// label A user-chosen and user-visible label for the profile to +// help identifying the semantics of the profile. The user +// can choose an arbitrary string in principle, but the +// values '$HOME$' and '$WORK$' indicate a special meaning. +// initial_creator_id The application that initially created the profile. +// Represented as an integer. See AutofillProfile. +// last_modifier_id The application that performed the last non-metadata +// modification of the profile. +// Represented as an integer. See AutofillProfile. +// +// contact_info_type_tokens +// Contains the values for all relevant FieldTyps of a +// contact_info entry. At most one entry per (guid, type) +// pair exists. +// local_addresses_type_tokens +// Like contact_info_type_tokens, but for local_addresses. +// +// guid The guid of the corresponding profile in contact_info. +// type The FieldType, represented by its integer value in +// the FieldType enum. +// value The string value of the type. +// verification_status Each token has an additional validation status that +// indicates if Autofill parsed the value out of an +// unstructured token, or if Autofill formatted the token +// from a structured subcomponent, or if the value was +// observed in a form submission, or even validated by the +// user in the settings. +// observations An encoding of the observations stored for this `type`. +// See `ProfileTokenConfidence:: +// SerializeObservationsForStoredType()`. +class AddressAutofillTable : public WebDatabaseTable { + public: + AddressAutofillTable(); + + AddressAutofillTable(const AddressAutofillTable&) = delete; + AddressAutofillTable& operator=(const AddressAutofillTable&) = delete; + + ~AddressAutofillTable() override; + + // Retrieves the AddressAutofillTable* owned by |db|. + static AddressAutofillTable* FromWebDatabase(WebDatabase* db); + + // WebDatabaseTable: + WebDatabaseTable::TypeKey GetTypeKey() const override; + bool CreateTablesIfNecessary() override; + bool MigrateToVersion(int version, bool* update_compatible_version) override; + + // Records a single Autofill profile in the autofill_profiles table. + virtual bool AddAutofillProfile(const AutofillProfile& profile); + + // Updates the database values for the specified profile. Multi-value aware. + virtual bool UpdateAutofillProfile(const AutofillProfile& profile); + + // Removes the Autofill profile with the given `guid`. `profile_source` + // indicates where the profile was synced from and thus whether it is stored + // in `kAutofillProfilesTable` or `kContactInfoTable`. + virtual bool RemoveAutofillProfile(const std::string& guid, + AutofillProfile::Source profile_source); + + // Removes all profiles from the given `profile_source`. + bool RemoveAllAutofillProfiles(AutofillProfile::Source profile_source); + + // Retrieves a profile with guid `guid` from `kAutofillProfilesTable` or + // `kContactInfoTable`. + std::unique_ptr<AutofillProfile> GetAutofillProfile( + const std::string& guid, + AutofillProfile::Source profile_source) const; + + // Retrieves profiles in the database. They are returned in unspecified order. + // The `profile_source` specifies if profiles from the legacy or the remote + // backend should be retrieved. + virtual bool GetAutofillProfiles( + AutofillProfile::Source profile_source, + std::vector<std::unique_ptr<AutofillProfile>>* profiles) const; + + // Deletes all data from the local_addresses tables. Returns true if any data + // was deleted, false if not (so false means "commit not needed" rather than + // "error"). + bool ClearAllLocalData(); + + // Removes rows from local_addresses tables if they were created on or after + // `delete_begin` and strictly before `delete_end`. Returns the list of + // of deleted profiles in `profiles`. Return value is true if all rows were + // successfully removed. Returns false on database error. In that case, the + // output vector state is undefined, and may be partially filled. + // TODO(crbug.com/1135188): This function is solely used to remove browsing + // data. Once explicit save dialogs are fully launched, it can be removed. For + // this reason profiles in the `contact_info` table are not considered. + bool RemoveAutofillDataModifiedBetween( + const base::Time& delete_begin, + const base::Time& delete_end, + std::vector<std::unique_ptr<AutofillProfile>>* profiles); + + // Table migration functions. NB: These do not and should not rely on other + // functions in this class. The implementation of a function such as + // GetCreditCard may change over time, but MigrateToVersionXX should never + // change. + bool MigrateToVersion88AddNewNameColumns(); + bool MigrateToVersion90AddNewStructuredAddressColumns(); + bool MigrateToVersion91AddMoreStructuredAddressColumns(); + bool MigrateToVersion92AddNewPrefixedNameColumn(); + bool MigrateToVersion93AddAutofillProfileLabelColumn(); + bool MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn(); + bool MigrateToVersion99RemoveAutofillProfilesTrashTable(); + bool MigrateToVersion100RemoveProfileValidityBitfieldColumn(); + bool MigrateToVersion102AddAutofillBirthdatesTable(); + bool MigrateToVersion107AddContactInfoTables(); + bool MigrateToVersion110AddInitialCreatorIdAndLastModifierId(); + bool MigrateToVersion113MigrateLocalAddressProfilesToNewTable(); + bool MigrateToVersion114DropLegacyAddressTables(); + bool MigrateToVersion117AddProfileObservationColumn(); + bool MigrateToVersion121DropServerAddressTables(); + + // Max data length saved in the table, AKA the maximum length allowed for + // form data. + // Copied to components/autofill/ios/browser/resources/autofill_controller.js. + static const size_t kMaxDataLength; + + private: + // Reads profiles from the deprecated autofill_profiles table. + std::unique_ptr<AutofillProfile> GetAutofillProfileFromLegacyTable( + const std::string& guid) const; + bool GetAutofillProfilesFromLegacyTable( + std::vector<std::unique_ptr<AutofillProfile>>* profiles) const; + + bool InitLegacyProfilesTable(); + bool InitLegacyProfileAddressesTable(); + bool InitLegacyProfileNamesTable(); + bool InitLegacyProfileEmailsTable(); + bool InitLegacyProfilePhonesTable(); + bool InitLegacyProfileBirthdatesTable(); + bool InitProfileMetadataTable(AutofillProfile::Source source); + bool InitProfileTypeTokensTable(AutofillProfile::Source source); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_ADDRESSES_ADDRESS_AUTOFILL_TABLE_H_
diff --git a/components/autofill/core/browser/webdata/addresses/address_autofill_table_unittest.cc b/components/autofill/core/browser/webdata/addresses/address_autofill_table_unittest.cc new file mode 100644 index 0000000..74517db --- /dev/null +++ b/components/autofill/core/browser/webdata/addresses/address_autofill_table_unittest.cc
@@ -0,0 +1,460 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" +#include "base/time/time.h" +#include "base/uuid.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/country_type.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/profile_token_quality.h" +#include "components/autofill/core/browser/profile_token_quality_test_api.h" +#include "components/autofill/core/browser/test_autofill_clock.h" +#include "components/autofill/core/common/autofill_clock.h" +#include "components/autofill/core/common/autofill_features.h" +#include "components/webdata/common/web_database.h" +#include "sql/statement.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/origin.h" + +using base::Time; +using testing::ElementsAre; +using testing::UnorderedElementsAre; + +namespace autofill { + +class AddressAutofillTableTest : public testing::Test { + protected: + void SetUp() override { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + file_ = temp_dir_.GetPath().AppendASCII("TestWebDatabase"); + + table_ = std::make_unique<AddressAutofillTable>(); + db_ = std::make_unique<WebDatabase>(); + db_->AddTable(table_.get()); + ASSERT_EQ(sql::INIT_OK, db_->Init(file_)); + } + + base::FilePath file_; + base::ScopedTempDir temp_dir_; + std::unique_ptr<AddressAutofillTable> table_; + std::unique_ptr<WebDatabase> db_; +}; + +// Tests for the AutofillProfil CRUD interface are tested with both profile +// sources. +class AddressAutofillTableProfileTest + : public AddressAutofillTableTest, + public testing::WithParamInterface<AutofillProfile::Source> { + public: + void SetUp() override { + AddressAutofillTableTest::SetUp(); + features_.InitWithFeatures( + {features::kAutofillEnableSupportForLandmark, + features::kAutofillEnableSupportForBetweenStreets, + features::kAutofillEnableSupportForAdminLevel2, + features::kAutofillEnableSupportForAddressOverflow, + features::kAutofillEnableSupportForAddressOverflowAndLandmark, + features::kAutofillEnableSupportForBetweenStreetsOrLandmark}, + {}); + } + AutofillProfile::Source profile_source() const { return GetParam(); } + + // Creates an `AutofillProfile` with `profile_source()` as its source. + AutofillProfile CreateAutofillProfile() const { + return AutofillProfile(profile_source(), AddressCountryCode("ES")); + } + + // Depending on the `profile_source()`, the AutofillProfiles are stored in a + // different master table. + base::StringPiece GetProfileTable() const { + return profile_source() == AutofillProfile::Source::kLocalOrSyncable + ? "local_addresses" + : "contact_info"; + } + + private: + base::test::ScopedFeatureList features_; +}; + +INSTANTIATE_TEST_SUITE_P( + , + AddressAutofillTableProfileTest, + testing::ValuesIn({AutofillProfile::Source::kLocalOrSyncable, + AutofillProfile::Source::kAccount})); + +// Tests reading/writing name, email, company, address, phone number and +// birthdate information. +TEST_P(AddressAutofillTableProfileTest, AutofillProfile) { + AutofillProfile home_profile = CreateAutofillProfile(); + + // TODO(crbug.com/1113617): Honorifics are temporally disabled. + // home_profile.SetRawInfoWithVerificationStatus( + // NAME_HONORIFIC_PREFIX, u"Dr.", + // VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(NAME_HONORIFIC_PREFIX, u"Dr.", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(NAME_FIRST, u"John", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(NAME_MIDDLE, u"Q.", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(NAME_LAST_FIRST, u"Agent", + VerificationStatus::kParsed); + + home_profile.SetRawInfoWithVerificationStatus(NAME_LAST_CONJUNCTION, u"007", + VerificationStatus::kParsed); + + home_profile.SetRawInfoWithVerificationStatus(NAME_LAST_SECOND, u"Smith", + VerificationStatus::kParsed); + + home_profile.SetRawInfoWithVerificationStatus(NAME_LAST, u"Agent 007 Smith", + VerificationStatus::kParsed); + + home_profile.SetRawInfoWithVerificationStatus( + NAME_FULL, u"John Q. Agent 007 Smith", VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(NAME_FULL_WITH_HONORIFIC_PREFIX, + u"Dr. John Q. Agent 007 Smith", + VerificationStatus::kObserved); + + home_profile.SetRawInfo(EMAIL_ADDRESS, u"js@smith.xyz"); + home_profile.SetRawInfo(COMPANY_NAME, u"Google"); + + home_profile.SetRawInfoWithVerificationStatus( + ADDRESS_HOME_STREET_ADDRESS, + u"Street Name between streets House Number Premise APT 10 Floor 2 " + u"Landmark", + VerificationStatus::kUserVerified); + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_STREET_LOCATION, + u"Street Name House Number", + VerificationStatus::kFormatted); + home_profile.SetRawInfoWithVerificationStatus( + ADDRESS_HOME_STREET_NAME, u"Street Name", VerificationStatus::kFormatted); + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_DEPENDENT_LOCALITY, + u"Dependent Locality", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_CITY, u"City", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_STATE, u"State", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_SORTING_CODE, + u"Sorting Code", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_ZIP, u"ZIP", + VerificationStatus::kObserved); + + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_COUNTRY, u"DE", + VerificationStatus::kObserved); + home_profile.SetRawInfoWithVerificationStatus( + ADDRESS_HOME_HOUSE_NUMBER, u"House Number", + VerificationStatus::kUserVerified); + home_profile.SetRawInfoWithVerificationStatus( + ADDRESS_HOME_SUBPREMISE, u"APT 10 Floor 2", + VerificationStatus::kUserVerified); + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT_NUM, u"10", + VerificationStatus::kParsed); + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_FLOOR, u"2", + VerificationStatus::kParsed); + ASSERT_EQ(home_profile.GetRawInfo(ADDRESS_HOME_STREET_NAME), u"Street Name"); + home_profile.SetRawInfoWithVerificationStatus( + ADDRESS_HOME_LANDMARK, u"Landmark", VerificationStatus::kObserved); + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_OVERFLOW, + u"Andar 1, Apto. 12", + VerificationStatus::kObserved); + home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_BETWEEN_STREETS, + u"between streets", + VerificationStatus::kObserved); + home_profile.SetRawInfoWithVerificationStatus( + ADDRESS_HOME_ADMIN_LEVEL2, u"Oxaca", VerificationStatus::kObserved); + + home_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"18181234567"); + home_profile.SetRawInfoAsInt(BIRTHDATE_DAY, 14); + home_profile.SetRawInfoAsInt(BIRTHDATE_MONTH, 3); + home_profile.SetRawInfoAsInt(BIRTHDATE_4_DIGIT_YEAR, 1997); + home_profile.set_language_code("en"); + + // Add the profile to the table. + EXPECT_TRUE(table_->AddAutofillProfile(home_profile)); + + // Get the 'Home' profile from the table. + std::unique_ptr<AutofillProfile> db_profile = + table_->GetAutofillProfile(home_profile.guid(), home_profile.source()); + ASSERT_TRUE(db_profile); + + // Verify that it is correct. + EXPECT_EQ(home_profile, *db_profile); + + // Remove the profile and expect that no profiles remain. + EXPECT_TRUE( + table_->RemoveAutofillProfile(home_profile.guid(), profile_source())); + std::vector<std::unique_ptr<AutofillProfile>> profiles; + EXPECT_TRUE(table_->GetAutofillProfiles(profile_source(), &profiles)); + EXPECT_TRUE(profiles.empty()); +} + +// Tests that `GetAutofillProfiles(source, profiles)` clears `profiles` and +// only returns profiles from the correct `source`. +// Not part of the `AddressAutofillTableProfileTest` fixture, as it doesn't +// benefit from parameterization on the `profile_source()`. +TEST_F(AddressAutofillTableTest, GetAutofillProfiles) { + AutofillProfile local_profile(AutofillProfile::Source::kLocalOrSyncable, + AddressCountryCode("ES")); + AutofillProfile account_profile(AutofillProfile::Source::kAccount, + AddressCountryCode("ES")); + EXPECT_TRUE(table_->AddAutofillProfile(local_profile)); + EXPECT_TRUE(table_->AddAutofillProfile(account_profile)); + + std::vector<std::unique_ptr<AutofillProfile>> profiles; + EXPECT_TRUE(table_->GetAutofillProfiles( + AutofillProfile::Source::kLocalOrSyncable, &profiles)); + EXPECT_THAT(profiles, ElementsAre(testing::Pointee(local_profile))); + EXPECT_TRUE(table_->GetAutofillProfiles(AutofillProfile::Source::kAccount, + &profiles)); + EXPECT_THAT(profiles, ElementsAre(testing::Pointee(account_profile))); +} + +// Tests that `RemoveAllAutofillProfiles()` clears all profiles of the given +// source. +TEST_P(AddressAutofillTableProfileTest, RemoveAllAutofillProfiles) { + ASSERT_TRUE(table_->AddAutofillProfile( + AutofillProfile(AutofillProfile::Source::kLocalOrSyncable, + i18n_model_definition::kLegacyHierarchyCountryCode))); + ASSERT_TRUE(table_->AddAutofillProfile( + AutofillProfile(AutofillProfile::Source::kAccount, + i18n_model_definition::kLegacyHierarchyCountryCode))); + + EXPECT_TRUE(table_->RemoveAllAutofillProfiles(profile_source())); + + // Expect that the profiles from `profile_source()` are gone. + std::vector<std::unique_ptr<AutofillProfile>> profiles; + ASSERT_TRUE(table_->GetAutofillProfiles(profile_source(), &profiles)); + EXPECT_TRUE(profiles.empty()); + + // Expect that the profile from the opposite source remains. + const auto other_source = + profile_source() == AutofillProfile::Source::kAccount + ? AutofillProfile::Source::kLocalOrSyncable + : AutofillProfile::Source::kAccount; + ASSERT_TRUE(table_->GetAutofillProfiles(other_source, &profiles)); + EXPECT_EQ(profiles.size(), 1u); +} + +// Tests that `ProfileTokenQuality` observations are read and written. +TEST_P(AddressAutofillTableProfileTest, ProfileTokenQuality) { + AutofillProfile profile = CreateAutofillProfile(); + test_api(profile.token_quality()) + .AddObservation(NAME_FIRST, + ProfileTokenQuality::ObservationType::kAccepted, + ProfileTokenQualityTestApi::FormSignatureHash(12)); + + // Add + table_->AddAutofillProfile(profile); + profile = *table_->GetAutofillProfile(profile.guid(), profile.source()); + EXPECT_THAT( + profile.token_quality().GetObservationTypesForFieldType(NAME_FIRST), + UnorderedElementsAre(ProfileTokenQuality::ObservationType::kAccepted)); + EXPECT_THAT( + test_api(profile.token_quality()).GetHashesForStoredType(NAME_FIRST), + UnorderedElementsAre(ProfileTokenQualityTestApi::FormSignatureHash(12))); + + // Update + test_api(profile.token_quality()) + .AddObservation(NAME_FIRST, + ProfileTokenQuality::ObservationType::kEditedFallback, + ProfileTokenQualityTestApi::FormSignatureHash(21)); + table_->UpdateAutofillProfile(profile); + profile = *table_->GetAutofillProfile(profile.guid(), profile.source()); + EXPECT_THAT( + profile.token_quality().GetObservationTypesForFieldType(NAME_FIRST), + UnorderedElementsAre( + ProfileTokenQuality::ObservationType::kAccepted, + ProfileTokenQuality::ObservationType::kEditedFallback)); + EXPECT_THAT( + test_api(profile.token_quality()).GetHashesForStoredType(NAME_FIRST), + UnorderedElementsAre(ProfileTokenQualityTestApi::FormSignatureHash(12), + ProfileTokenQualityTestApi::FormSignatureHash(21))); +} + +TEST_P(AddressAutofillTableProfileTest, UpdateAutofillProfile) { + // Add a profile to the db. + AutofillProfile profile = CreateAutofillProfile(); + profile.SetRawInfo(NAME_FIRST, u"John"); + profile.SetRawInfo(NAME_MIDDLE, u"Q."); + profile.SetRawInfo(NAME_LAST, u"Smith"); + profile.SetRawInfo(EMAIL_ADDRESS, u"js@example.com"); + profile.SetRawInfo(COMPANY_NAME, u"Google"); + profile.SetRawInfo(ADDRESS_HOME_LINE1, u"1234 Apple Way"); + profile.SetRawInfo(ADDRESS_HOME_LINE2, u"unit 5"); + profile.SetRawInfo(ADDRESS_HOME_CITY, u"Los Angeles"); + profile.SetRawInfo(ADDRESS_HOME_STATE, u"CA"); + profile.SetRawInfo(ADDRESS_HOME_ZIP, u"90025"); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"ES"); + profile.SetRawInfo(ADDRESS_HOME_OVERFLOW, u"Andar 1, Apto. 12"); + profile.SetRawInfo(ADDRESS_HOME_LANDMARK, u"Landmark"); + profile.SetRawInfo(ADDRESS_HOME_BETWEEN_STREETS, u"Marcos y Oliva"); + profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"18181234567"); + profile.SetRawInfoAsInt(BIRTHDATE_DAY, 14); + profile.SetRawInfoAsInt(BIRTHDATE_MONTH, 3); + profile.SetRawInfoAsInt(BIRTHDATE_4_DIGIT_YEAR, 1997); + profile.set_language_code("en"); + profile.FinalizeAfterImport(); + table_->AddAutofillProfile(profile); + + // Get the profile. + std::unique_ptr<AutofillProfile> db_profile = + table_->GetAutofillProfile(profile.guid(), profile.source()); + ASSERT_TRUE(db_profile); + EXPECT_EQ(profile, *db_profile); + + // Now, update the profile and save the update to the database. + // The modification date should change to reflect the update. + profile.SetRawInfo(EMAIL_ADDRESS, u"js@smith.xyz"); + table_->UpdateAutofillProfile(profile); + + // Get the profile. + db_profile = table_->GetAutofillProfile(profile.guid(), profile.source()); + ASSERT_TRUE(db_profile); + EXPECT_EQ(profile, *db_profile); +} + +TEST_F(AddressAutofillTableTest, RemoveAutofillDataModifiedBetween) { + // Populate the address tables. + ASSERT_TRUE(db_->GetSQLConnection()->Execute( + "INSERT INTO local_addresses (guid, date_modified) " + "VALUES('00000000-0000-0000-0000-000000000000', 11);" + "INSERT INTO local_addresses_type_tokens (guid, type, value) " + "VALUES('00000000-0000-0000-0000-000000000000', 3, 'first name0');" + "INSERT INTO local_addresses (guid, date_modified) " + "VALUES('00000000-0000-0000-0000-000000000001', 21);" + "INSERT INTO local_addresses_type_tokens (guid, type, value) " + "VALUES('00000000-0000-0000-0000-000000000001', 3, 'first name1');" + "INSERT INTO local_addresses (guid, date_modified) " + "VALUES('00000000-0000-0000-0000-000000000002', 31);" + "INSERT INTO local_addresses_type_tokens (guid, type, value) " + "VALUES('00000000-0000-0000-0000-000000000002', 3, 'first name2');" + "INSERT INTO local_addresses (guid, date_modified) " + "VALUES('00000000-0000-0000-0000-000000000003', 41);" + "INSERT INTO local_addresses_type_tokens (guid, type, value) " + "VALUES('00000000-0000-0000-0000-000000000003', 3, 'first name3');" + "INSERT INTO local_addresses (guid, date_modified) " + "VALUES('00000000-0000-0000-0000-000000000004', 51);" + "INSERT INTO local_addresses_type_tokens (guid, type, value) " + "VALUES('00000000-0000-0000-0000-000000000004', 3, 'first name4');" + "INSERT INTO local_addresses (guid, date_modified) " + "VALUES('00000000-0000-0000-0000-000000000005', 61);" + "INSERT INTO local_addresses_type_tokens (guid, type, value) " + "VALUES('00000000-0000-0000-0000-000000000005', 3, 'first name5');")); + + // Remove all entries modified in the bounded time range [17,41). + std::vector<std::unique_ptr<AutofillProfile>> profiles; + table_->RemoveAutofillDataModifiedBetween(Time::FromTimeT(17), + Time::FromTimeT(41), &profiles); + + // Two profiles should have been removed. + ASSERT_EQ(2UL, profiles.size()); + EXPECT_EQ("00000000-0000-0000-0000-000000000001", profiles[0]->guid()); + EXPECT_EQ("00000000-0000-0000-0000-000000000002", profiles[1]->guid()); + + // Make sure that only the expected profiles are still present. + sql::Statement s_autofill_profiles_bounded( + db_->GetSQLConnection()->GetUniqueStatement( + "SELECT date_modified FROM local_addresses ORDER BY guid")); + ASSERT_TRUE(s_autofill_profiles_bounded.is_valid()); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(11, s_autofill_profiles_bounded.ColumnInt64(0)); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(41, s_autofill_profiles_bounded.ColumnInt64(0)); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(51, s_autofill_profiles_bounded.ColumnInt64(0)); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(61, s_autofill_profiles_bounded.ColumnInt64(0)); + EXPECT_FALSE(s_autofill_profiles_bounded.Step()); + + // Make sure that only the expected profile names are still present. + sql::Statement s_autofill_profile_names_bounded( + db_->GetSQLConnection()->GetUniqueStatement( + "SELECT value FROM local_addresses_type_tokens ORDER BY guid")); + ASSERT_TRUE(s_autofill_profile_names_bounded.is_valid()); + ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); + EXPECT_EQ("first name0", s_autofill_profile_names_bounded.ColumnString(0)); + ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); + EXPECT_EQ("first name3", s_autofill_profile_names_bounded.ColumnString(0)); + ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); + EXPECT_EQ("first name4", s_autofill_profile_names_bounded.ColumnString(0)); + ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); + EXPECT_EQ("first name5", s_autofill_profile_names_bounded.ColumnString(0)); + EXPECT_FALSE(s_autofill_profile_names_bounded.Step()); + + // Remove all entries modified on or after time 51 (unbounded range). + table_->RemoveAutofillDataModifiedBetween(Time::FromTimeT(51), Time(), + &profiles); + ASSERT_EQ(2UL, profiles.size()); + EXPECT_EQ("00000000-0000-0000-0000-000000000004", profiles[0]->guid()); + EXPECT_EQ("00000000-0000-0000-0000-000000000005", profiles[1]->guid()); + + // Make sure that only the expected profiles are still present. + sql::Statement s_autofill_profiles_unbounded( + db_->GetSQLConnection()->GetUniqueStatement( + "SELECT date_modified FROM local_addresses ORDER BY guid")); + ASSERT_TRUE(s_autofill_profiles_unbounded.is_valid()); + ASSERT_TRUE(s_autofill_profiles_unbounded.Step()); + EXPECT_EQ(11, s_autofill_profiles_unbounded.ColumnInt64(0)); + ASSERT_TRUE(s_autofill_profiles_unbounded.Step()); + EXPECT_EQ(41, s_autofill_profiles_unbounded.ColumnInt64(0)); + EXPECT_FALSE(s_autofill_profiles_unbounded.Step()); + + // Make sure that only the expected profile names are still present. + sql::Statement s_autofill_profile_names_unbounded( + db_->GetSQLConnection()->GetUniqueStatement( + "SELECT value FROM local_addresses_type_tokens ORDER BY guid")); + ASSERT_TRUE(s_autofill_profile_names_unbounded.is_valid()); + ASSERT_TRUE(s_autofill_profile_names_unbounded.Step()); + EXPECT_EQ("first name0", s_autofill_profile_names_unbounded.ColumnString(0)); + ASSERT_TRUE(s_autofill_profile_names_unbounded.Step()); + EXPECT_EQ("first name3", s_autofill_profile_names_unbounded.ColumnString(0)); + EXPECT_FALSE(s_autofill_profile_names_unbounded.Step()); + + // Remove all remaining entries. + table_->RemoveAutofillDataModifiedBetween(Time(), Time(), &profiles); + + // Two profiles should have been removed. + ASSERT_EQ(2UL, profiles.size()); + EXPECT_EQ("00000000-0000-0000-0000-000000000000", profiles[0]->guid()); + EXPECT_EQ("00000000-0000-0000-0000-000000000003", profiles[1]->guid()); + + // Make sure there are no profiles remaining. + sql::Statement s_autofill_profiles_empty( + db_->GetSQLConnection()->GetUniqueStatement( + "SELECT date_modified FROM local_addresses")); + ASSERT_TRUE(s_autofill_profiles_empty.is_valid()); + EXPECT_FALSE(s_autofill_profiles_empty.Step()); + + // Make sure there are no profile names remaining. + sql::Statement s_autofill_profile_names_empty( + db_->GetSQLConnection()->GetUniqueStatement( + "SELECT value FROM local_addresses_type_tokens")); + ASSERT_TRUE(s_autofill_profile_names_empty.is_valid()); + EXPECT_FALSE(s_autofill_profile_names_empty.Step()); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h b/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h index 7197764..2c74f0fe 100644 --- a/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOCOMPLETE_SYNC_BRIDGE_H_ #include <memory> +#include <optional> #include <string> #include "base/memory/raw_ptr.h" @@ -20,7 +21,6 @@ #include "components/sync/model/model_error.h" #include "components/sync/model/model_type_change_processor.h" #include "components/sync/model/model_type_sync_bridge.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -52,10 +52,10 @@ // syncer::ModelTypeSyncBridge implementation. std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override;
diff --git a/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc index 00091c8..ab29d61 100644 --- a/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
@@ -200,7 +200,7 @@ initial_updates.push_back(SpecificsToUpdateResponse(specifics)); } real_processor_->OnUpdateReceived(state, std::move(initial_updates), - /*gc_directive=*/absl::nullopt); + /*gc_directive=*/std::nullopt); } void SaveSpecificsToTable(
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc index db5528b..67c930a 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
@@ -15,6 +15,7 @@ #include "components/autofill/core/browser/autofill_profile_sync_util.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/proto/autofill_sync.pb.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h" #include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" @@ -26,8 +27,8 @@ #include "components/sync/model/sync_metadata_store_change_list.h" #include "components/sync/protocol/entity_data.h" -using absl::optional; using base::UTF16ToUTF8; +using std::optional; using sync_pb::AutofillProfileSpecifics; using syncer::EntityData; using syncer::MetadataChangeList; @@ -92,7 +93,7 @@ AutofillProfileSyncBridge::CreateMetadataChangeList() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return std::make_unique<syncer::SyncMetadataStoreChangeList>( - GetAutofillTable(), syncer::AUTOFILL_PROFILE, + GetSyncMetadataStore(), syncer::AUTOFILL_PROFILE, base::BindRepeating(&syncer::ModelTypeChangeProcessor::ReportError, change_processor()->GetWeakPtr())); } @@ -127,7 +128,7 @@ FlushSyncTracker(std::move(metadata_change_list), &initial_sync_tracker)); web_data_backend_->CommitChanges(); - return absl::nullopt; + return std::nullopt; } optional<ModelError> AutofillProfileSyncBridge::ApplyIncrementalSyncChanges( @@ -158,7 +159,7 @@ RETURN_IF_ERROR(FlushSyncTracker(std::move(metadata_change_list), &tracker)); web_data_backend_->CommitChanges(); - return absl::nullopt; + return std::nullopt; } void AutofillProfileSyncBridge::GetData(StorageKeyList storage_keys, @@ -233,7 +234,7 @@ // operation (that triggered this notification to the bridge) finishes. } -absl::optional<syncer::ModelError> AutofillProfileSyncBridge::FlushSyncTracker( +std::optional<syncer::ModelError> AutofillProfileSyncBridge::FlushSyncTracker( std::unique_ptr<MetadataChangeList> metadata_change_list, AutofillProfileSyncDifferenceTracker* tracker) { DCHECK(tracker); @@ -261,15 +262,15 @@ void AutofillProfileSyncBridge::LoadMetadata() { if (!web_data_backend_ || !web_data_backend_->GetDatabase() || - !GetAutofillTable()) { + !GetAutofillTable() || !GetSyncMetadataStore()) { change_processor()->ReportError( {FROM_HERE, "Failed to load AutofillWebDatabase."}); return; } auto batch = std::make_unique<syncer::MetadataBatch>(); - if (!GetAutofillTable()->GetAllSyncMetadata(syncer::AUTOFILL_PROFILE, - batch.get())) { + if (!GetSyncMetadataStore()->GetAllSyncMetadata(syncer::AUTOFILL_PROFILE, + batch.get())) { change_processor()->ReportError( {FROM_HERE, "Failed reading autofill metadata from WebDatabase."}); return; @@ -298,7 +299,12 @@ ActOnLocalChange(change); } -AutofillTable* AutofillProfileSyncBridge::GetAutofillTable() { +AddressAutofillTable* AutofillProfileSyncBridge::GetAutofillTable() { + return AddressAutofillTable::FromWebDatabase( + web_data_backend_->GetDatabase()); +} + +AutofillTable* AutofillProfileSyncBridge::GetSyncMetadataStore() { return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); }
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h index aa1faa7..8204d74 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_SYNC_BRIDGE_H_ #include <memory> +#include <optional> #include <string> #include "base/memory/raw_ptr.h" @@ -16,7 +17,6 @@ #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h" #include "components/sync/model/model_type_sync_bridge.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace syncer { class MetadataChangeList; @@ -26,6 +26,7 @@ namespace autofill { +class AddressAutofillTable; class AutofillProfileSyncDifferenceTracker; class AutofillTable; class AutofillWebDataService; @@ -71,10 +72,10 @@ // syncer::ModelTypeSyncBridge implementation. std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override; @@ -87,14 +88,18 @@ private: // Returns the table associated with the |web_data_backend_|. - AutofillTable* GetAutofillTable(); + AddressAutofillTable* GetAutofillTable(); + + // AutofillTable acts as the metadata storage for all components/autofill- + // related sync code. + AutofillTable* GetSyncMetadataStore(); // Respond to local autofill profile entry changing by notifying sync of the // changes. void ActOnLocalChange(const AutofillProfileChange& change); // Flushes changes accumulated within |tracker| both to local and to sync. - absl::optional<syncer::ModelError> FlushSyncTracker( + std::optional<syncer::ModelError> FlushSyncTracker( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, AutofillProfileSyncDifferenceTracker* tracker);
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc index 79622a2..7e7d4790 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
@@ -25,6 +25,7 @@ #include "components/autofill/core/browser/autofill_profile_sync_util.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/test_autofill_clock.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_change.h" #include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h" @@ -263,6 +264,7 @@ test_clock_.SetNow(kJune2017); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); db_.AddTable(&table_); + db_.AddTable(&sync_metadata_table_); db_.Init(temp_dir_.GetPath().AppendASCII("SyncTestWebDatabase")); ON_CALL(*backend(), GetDatabase()).WillByDefault(Return(&db_)); ResetProcessor(); @@ -308,13 +310,13 @@ initial_updates.push_back(SpecificsToUpdateResponse(specifics)); } real_processor_->OnUpdateReceived(state, std::move(initial_updates), - /*gc_directive=*/absl::nullopt); + /*gc_directive=*/std::nullopt); } void ApplyIncrementalSyncChanges(EntityChangeList changes) { EXPECT_CALL(*backend(), NotifyOnAutofillChangedBySync(syncer::AUTOFILL_PROFILE)); - const absl::optional<syncer::ModelError> error = + const std::optional<syncer::ModelError> error = bridge()->ApplyIncrementalSyncChanges( bridge()->CreateMetadataChangeList(), std::move(changes)); EXPECT_FALSE(error) << error->ToString(); @@ -361,7 +363,7 @@ return mock_processor_; } - AutofillTable* table() { return &table_; } + AddressAutofillTable* table() { return &table_; } MockAutofillWebDataBackend* backend() { return &backend_; } @@ -370,7 +372,8 @@ ScopedTempDir temp_dir_; base::test::SingleThreadTaskEnvironment task_environment_; testing::NiceMock<MockAutofillWebDataBackend> backend_; - AutofillTable table_; + AddressAutofillTable table_; + AutofillTable sync_metadata_table_; WebDatabase db_; testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_; std::unique_ptr<syncer::ClientTagBasedModelTypeProcessor> real_processor_;
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc b/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc index f2eccd1..1b4fa4f 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc +++ b/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc
@@ -10,13 +10,13 @@ #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" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h" -#include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/sync/model/model_error.h" namespace autofill { -using absl::optional; +using std::optional; using syncer::ModelError; // Simplify checking for optional errors and returning only when present. @@ -26,7 +26,7 @@ } AutofillProfileSyncDifferenceTracker::AutofillProfileSyncDifferenceTracker( - AutofillTable* table) + AddressAutofillTable* table) : table_(table) {} AutofillProfileSyncDifferenceTracker::~AutofillProfileSyncDifferenceTracker() = @@ -75,7 +75,7 @@ update_to_local_.push_back(std::move(updated)); } GetLocalOnlyEntries()->erase(remote_storage_key); - return absl::nullopt; + return std::nullopt; } // Check if profile appears under a different storage key to be de-duplicated. @@ -129,13 +129,13 @@ // We keep the local entity and delete the remote one. delete_from_sync_.insert(remote_storage_key); } - return absl::nullopt; + return std::nullopt; } } // If no duplicate was found, just add the remote profile. add_to_local_.push_back(std::move(remote)); - return absl::nullopt; + return std::nullopt; } optional<ModelError> @@ -167,7 +167,7 @@ !update_to_local_.empty()) { std::move(autofill_changes_callback).Run(); } - return absl::nullopt; + return std::nullopt; } optional<ModelError> AutofillProfileSyncDifferenceTracker::FlushToSync( @@ -179,7 +179,7 @@ for (const std::string& entry : delete_from_sync_) { profiles_to_delete_from_sync->push_back(std::move(entry)); } - return absl::nullopt; + return std::nullopt; } optional<AutofillProfile> AutofillProfileSyncDifferenceTracker::ReadEntry( @@ -189,7 +189,7 @@ if (iter != GetLocalOnlyEntries()->end()) { return *iter->second; } - return absl::nullopt; + return std::nullopt; } optional<ModelError> AutofillProfileSyncDifferenceTracker::DeleteFromLocal( @@ -199,7 +199,7 @@ } delete_from_local_.insert(storage_key); GetLocalOnlyEntries()->erase(storage_key); - return absl::nullopt; + return std::nullopt; } std::map<std::string, std::unique_ptr<AutofillProfile>>* @@ -232,7 +232,7 @@ } AutofillProfileInitialSyncDifferenceTracker:: - AutofillProfileInitialSyncDifferenceTracker(AutofillTable* table) + AutofillProfileInitialSyncDifferenceTracker(AddressAutofillTable* table) : AutofillProfileSyncDifferenceTracker(table) {} AutofillProfileInitialSyncDifferenceTracker:: @@ -243,7 +243,7 @@ const std::string& storage_key) { // Remote delete is not allowed in initial sync. NOTREACHED(); - return absl::nullopt; + return std::nullopt; } optional<ModelError> AutofillProfileInitialSyncDifferenceTracker::FlushToSync( @@ -262,7 +262,7 @@ DCHECK(delete_from_local_.count(storage_key) == 0); profiles_to_upload_to_sync->push_back(std::move(data)); } - return absl::nullopt; + return std::nullopt; } optional<ModelError> @@ -315,7 +315,7 @@ RETURN_IF_ERROR(DeleteFromLocal(GetStorageKeyFromAutofillProfile(*local))); } - return absl::nullopt; + return std::nullopt; } optional<AutofillProfile> @@ -328,7 +328,7 @@ return *local_candidate; } } - return absl::nullopt; + return std::nullopt; } } // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h b/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h index f40fdf9..3bbca53 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h +++ b/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h
@@ -7,13 +7,13 @@ #include <map> #include <memory> +#include <optional> #include <set> #include <string> #include <vector> #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace syncer { class ModelError; @@ -23,7 +23,7 @@ class AutofillProfile; class AutofillProfileComparator; -class AutofillTable; +class AddressAutofillTable; // This is used to respond to ApplyIncrementalSyncChanges() and // MergeFullSyncData(). Attempts to lazily load local data, and then react to @@ -32,7 +32,7 @@ // directions. class AutofillProfileSyncDifferenceTracker { public: - explicit AutofillProfileSyncDifferenceTracker(AutofillTable* table); + explicit AutofillProfileSyncDifferenceTracker(AddressAutofillTable* table); AutofillProfileSyncDifferenceTracker( const AutofillProfileSyncDifferenceTracker&) = delete; @@ -43,42 +43,42 @@ // Adds a new |remote| entry to the diff tracker, originating from the sync // server. The provided |remote| entry must be valid. - [[nodiscard]] absl::optional<syncer::ModelError> IncorporateRemoteProfile( + [[nodiscard]] std::optional<syncer::ModelError> IncorporateRemoteProfile( std::unique_ptr<AutofillProfile> remote); // Informs the diff tracker that the entry with |storage_key| has been deleted // from the sync server. |storage_key| must be non-empty. - [[nodiscard]] virtual absl::optional<syncer::ModelError> + [[nodiscard]] virtual std::optional<syncer::ModelError> IncorporateRemoteDelete(const std::string& storage_key); // Writes all local changes to the provided autofill |table_|. After flushing, // not further remote changes should get incorporated. - [[nodiscard]] absl::optional<syncer::ModelError> FlushToLocal( + [[nodiscard]] std::optional<syncer::ModelError> FlushToLocal( base::OnceClosure autofill_changes_callback); // Writes into |profiles_to_upload_to_sync| all autofill profiles to be sent // to the sync server, and into |profiles_to_delete_from_sync| the storage // keys of all profiles to be deleted from the server. After flushing, no // further remote changes should get incorporated. - [[nodiscard]] virtual absl::optional<syncer::ModelError> FlushToSync( + [[nodiscard]] virtual std::optional<syncer::ModelError> FlushToSync( std::vector<std::unique_ptr<AutofillProfile>>* profiles_to_upload_to_sync, std::vector<std::string>* profiles_to_delete_from_sync); protected: - // If the entry is found, |entry| will be return, otherwise absl::nullopt is + // If the entry is found, |entry| will be return, otherwise std::nullopt is // returned. - absl::optional<AutofillProfile> ReadEntry(const std::string& storage_key); + std::optional<AutofillProfile> ReadEntry(const std::string& storage_key); // Tries to find a local entry that is mergeable with |remote| (according to // |comparator|). If such an entry is found, it is returned. Otherwise, - // absl::nullopt is returned. - absl::optional<AutofillProfile> FindMergeableLocalEntry( + // std::nullopt is returned. + std::optional<AutofillProfile> FindMergeableLocalEntry( const AutofillProfile& remote, const AutofillProfileComparator& comparator); // Informs the tracker that a local entry with |storage_key| should get // deleted. - [[nodiscard]] absl::optional<syncer::ModelError> DeleteFromLocal( + [[nodiscard]] std::optional<syncer::ModelError> DeleteFromLocal( const std::string& storage_key); // Accessor for data that is only stored local. Initializes the data if @@ -90,7 +90,7 @@ bool InitializeLocalOnlyEntriesIfNeeded(); // The table for reading local data. - const raw_ptr<AutofillTable> table_; + const raw_ptr<AddressAutofillTable> table_; // This class loads local data from |table_| lazily. This field tracks if that // has happened or not yet. @@ -119,7 +119,8 @@ class AutofillProfileInitialSyncDifferenceTracker : public AutofillProfileSyncDifferenceTracker { public: - explicit AutofillProfileInitialSyncDifferenceTracker(AutofillTable* table); + explicit AutofillProfileInitialSyncDifferenceTracker( + AddressAutofillTable* table); AutofillProfileInitialSyncDifferenceTracker( const AutofillProfileInitialSyncDifferenceTracker&) = delete; @@ -128,23 +129,23 @@ ~AutofillProfileInitialSyncDifferenceTracker() override; - [[nodiscard]] absl::optional<syncer::ModelError> IncorporateRemoteDelete( + [[nodiscard]] std::optional<syncer::ModelError> IncorporateRemoteDelete( const std::string& storage_key) override; - [[nodiscard]] absl::optional<syncer::ModelError> FlushToSync( + [[nodiscard]] std::optional<syncer::ModelError> FlushToSync( std::vector<std::unique_ptr<AutofillProfile>>* profiles_to_upload_to_sync, std::vector<std::string>* profiles_to_delete_from_sync) override; // Performs an additional pass through remote entries incorporated from sync // to find any similarities with local entries. Should be run after all // entries get incorporated but before flushing results to local/sync. - [[nodiscard]] absl::optional<syncer::ModelError> + [[nodiscard]] std::optional<syncer::ModelError> MergeSimilarEntriesForInitialSync(const std::string& app_locale); private: // Returns a local entry that is mergeable with |remote| if it exists. - // Otherwise, returns absl::nullopt. - absl::optional<AutofillProfile> FindMergeableLocalEntry( + // Otherwise, returns std::nullopt. + std::optional<AutofillProfile> FindMergeableLocalEntry( const AutofillProfile& remote, const AutofillProfileComparator& comparator); };
diff --git a/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc b/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc index aae7642..82e28ceb 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc
@@ -14,7 +14,7 @@ #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/geo/country_names.h" #include "components/autofill/core/browser/test_autofill_clock.h" -#include "components/autofill/core/browser/webdata/autofill_table.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/sync/model/model_error.h" #include "components/webdata/common/web_database.h" @@ -70,18 +70,18 @@ } void IncorporateRemoteProfile(const AutofillProfile& profile) { - EXPECT_EQ(absl::nullopt, tracker()->IncorporateRemoteProfile( - std::make_unique<AutofillProfile>(profile))); + EXPECT_EQ(std::nullopt, tracker()->IncorporateRemoteProfile( + std::make_unique<AutofillProfile>(profile))); } UpdatesToSync FlushToSync() { - EXPECT_EQ(absl::nullopt, + EXPECT_EQ(std::nullopt, tracker()->FlushToLocal( /*autofill_changes_callback=*/base::DoNothing())); UpdatesToSync updates; std::vector<std::unique_ptr<AutofillProfile>> vector_of_unique_ptrs; - EXPECT_EQ(absl::nullopt, + EXPECT_EQ(std::nullopt, tracker()->FlushToSync( /*profiles_to_upload_to_sync=*/&vector_of_unique_ptrs, /*profiles_to_delete_from_sync=*/&updates @@ -114,13 +114,13 @@ virtual AutofillProfileSyncDifferenceTracker* tracker() = 0; - AutofillTable* table() { return &table_; } + AddressAutofillTable* table() { return &table_; } private: autofill::TestAutofillClock test_clock_; base::ScopedTempDir temp_dir_; base::test::TaskEnvironment task_environment_; - AutofillTable table_; + AddressAutofillTable table_; WebDatabase db_; }; @@ -320,7 +320,7 @@ MockCallback<base::OnceClosure> autofill_changes_callback; EXPECT_CALL(autofill_changes_callback, Run()).Times(0); - EXPECT_EQ(absl::nullopt, + EXPECT_EQ(std::nullopt, tracker()->FlushToLocal(autofill_changes_callback.Get())); } @@ -330,11 +330,11 @@ i18n_model_definition::kLegacyHierarchyCountryCode); AddAutofillProfilesToTable({local}); - EXPECT_EQ(absl::nullopt, tracker()->IncorporateRemoteDelete(kSmallerGuid)); + EXPECT_EQ(std::nullopt, tracker()->IncorporateRemoteDelete(kSmallerGuid)); MockCallback<base::OnceClosure> autofill_changes_callback; EXPECT_CALL(autofill_changes_callback, Run()).Times(1); - EXPECT_EQ(absl::nullopt, + EXPECT_EQ(std::nullopt, tracker()->FlushToLocal(autofill_changes_callback.Get())); // On top of that, the profile should also get deleted. @@ -350,7 +350,7 @@ MockCallback<base::OnceClosure> autofill_changes_callback; EXPECT_CALL(autofill_changes_callback, Run()).Times(1); - EXPECT_EQ(absl::nullopt, + EXPECT_EQ(std::nullopt, tracker()->FlushToLocal(autofill_changes_callback.Get())); // On top of that, the profile should also get added. @@ -372,7 +372,7 @@ MockCallback<base::OnceClosure> autofill_changes_callback; EXPECT_CALL(autofill_changes_callback, Run()).Times(1); - EXPECT_EQ(absl::nullopt, + EXPECT_EQ(std::nullopt, tracker()->FlushToLocal(autofill_changes_callback.Get())); // On top of that, the profile with key kSmallerGuid should also get updated. @@ -392,7 +392,7 @@ ~AutofillProfileInitialSyncDifferenceTrackerTest() override {} - [[nodiscard]] absl::optional<syncer::ModelError> + [[nodiscard]] std::optional<syncer::ModelError> MergeSimilarEntriesForInitialSync() { return initial_tracker_.MergeSimilarEntriesForInitialSync(kLocaleString); } @@ -427,7 +427,7 @@ merged.set_use_count(27); IncorporateRemoteProfile(remote); - EXPECT_EQ(absl::nullopt, MergeSimilarEntriesForInitialSync()); + EXPECT_EQ(std::nullopt, MergeSimilarEntriesForInitialSync()); // The merged profile needs to get uploaded back to sync and stored locally. UpdatesToSync updates = FlushToSync(); @@ -454,7 +454,7 @@ remote.set_use_count(27); remote.FinalizeAfterImport(); IncorporateRemoteProfile(remote); - EXPECT_EQ(absl::nullopt, MergeSimilarEntriesForInitialSync()); + EXPECT_EQ(std::nullopt, MergeSimilarEntriesForInitialSync()); // Nothing gets uploaded to sync and the remote profile wins. UpdatesToSync updates = FlushToSync(); @@ -479,7 +479,7 @@ remote.SetRawInfo(COMPANY_NAME, u"Frobbers, Inc."); remote.FinalizeAfterImport(); IncorporateRemoteProfile(remote); - EXPECT_EQ(absl::nullopt, MergeSimilarEntriesForInitialSync()); + EXPECT_EQ(std::nullopt, MergeSimilarEntriesForInitialSync()); // The local profile gets uploaded (due to initial sync) and the remote // profile gets stored locally.
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc index 4816d4f67..ef6f527 100644 --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -40,7 +40,6 @@ #include "components/autofill/core/browser/data_model/iban.h" #include "components/autofill/core/browser/field_type_utils.h" #include "components/autofill/core/browser/field_types.h" -#include "components/autofill/core/browser/geo/autofill_country.h" #include "components/autofill/core/browser/payments/payments_customer_data.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/webdata/autofill_change.h" @@ -68,109 +67,16 @@ namespace { -constexpr std::string_view kAutofillProfilesTable = "autofill_profiles"; -constexpr std::string_view kGuid = "guid"; -constexpr std::string_view kLabel = "label"; -constexpr std::string_view kCompanyName = "company_name"; -constexpr std::string_view kStreetAddress = "street_address"; -constexpr std::string_view kDependentLocality = "dependent_locality"; -constexpr std::string_view kCity = "city"; -constexpr std::string_view kState = "state"; -constexpr std::string_view kZipcode = "zipcode"; -constexpr std::string_view kSortingCode = "sorting_code"; -constexpr std::string_view kCountryCode = "country_code"; -constexpr std::string_view kUseCount = "use_count"; -constexpr std::string_view kUseDate = "use_date"; -constexpr std::string_view kDateModified = "date_modified"; -constexpr std::string_view kOrigin = "origin"; -constexpr std::string_view kLanguageCode = "language_code"; -constexpr std::string_view kDisallowSettingsVisibleUpdates = - "disallow_settings_visible_updates"; - -constexpr std::string_view kAutofillProfileAddressesTable = - "autofill_profile_addresses"; -// kGuid = "guid" -// kStreetAddress = "street_address" -constexpr std::string_view kStreetName = "street_name"; -constexpr std::string_view kDependentStreetName = "dependent_street_name"; -constexpr std::string_view kHouseNumber = "house_number"; -constexpr std::string_view kSubpremise = "subpremise"; -// kDependentLocality = "dependent_locality" -// kCity = "city" -// kState = "state" -constexpr std::string_view kZipCode = "zip_code"; -// kCountryCode = "country_code" -// kSortingCode = "sorting_code" -constexpr std::string_view kApartmentNumber = "apartment_number"; -constexpr std::string_view kFloor = "floor"; -constexpr std::string_view kStreetAddressStatus = "street_address_status"; -constexpr std::string_view kStreetNameStatus = "street_name_status"; -constexpr std::string_view kDependentStreetNameStatus = - "dependent_street_name_status"; -constexpr std::string_view kHouseNumberStatus = "house_number_status"; -constexpr std::string_view kSubpremiseStatus = "subpremise_status"; -constexpr std::string_view kDependentLocalityStatus = - "dependent_locality_status"; -constexpr std::string_view kCityStatus = "city_status"; -constexpr std::string_view kStateStatus = "state_status"; -constexpr std::string_view kZipCodeStatus = "zip_code_status"; -constexpr std::string_view kCountryCodeStatus = "country_code_status"; -constexpr std::string_view kSortingCodeStatus = "sorting_code_status"; -constexpr std::string_view kApartmentNumberStatus = "apartment_number_status"; -constexpr std::string_view kFloorStatus = "floor_status"; - -constexpr std::string_view kAutofillProfileNamesTable = - "autofill_profile_names"; -// kGuid = "guid" -constexpr std::string_view kHonorificPrefix = "honorific_prefix"; -constexpr std::string_view kFirstName = "first_name"; -constexpr std::string_view kMiddleName = "middle_name"; -constexpr std::string_view kLastName = "last_name"; -constexpr std::string_view kFirstLastName = "first_last_name"; -constexpr std::string_view kConjunctionLastName = "conjunction_last_name"; -constexpr std::string_view kSecondLastName = "second_last_name"; -constexpr std::string_view kFullName = "full_name"; -constexpr std::string_view kFullNameWithHonorificPrefix = - "full_name_with_honorific_prefix"; -constexpr std::string_view kHonorificPrefixStatus = "honorific_prefix_status"; -constexpr std::string_view kFirstNameStatus = "first_name_status"; -constexpr std::string_view kMiddleNameStatus = "middle_name_status"; -constexpr std::string_view kLastNameStatus = "last_name_status"; -constexpr std::string_view kFirstLastNameStatus = "first_last_name_status"; -constexpr std::string_view kConjunctionLastNameStatus = - "conjunction_last_name_status"; -constexpr std::string_view kSecondLastNameStatus = "second_last_name_status"; -constexpr std::string_view kFullNameStatus = "full_name_status"; -constexpr std::string_view kFullNameWithHonorificPrefixStatus = - "full_name_with_honorific_prefix_status"; - -constexpr std::string_view kAutofillProfileEmailsTable = - "autofill_profile_emails"; -// kGuid = "guid" -constexpr std::string_view kEmail = "email"; - -constexpr std::string_view kAutofillProfilePhonesTable = - "autofill_profile_phones"; -// kGuid = "guid" -constexpr std::string_view kNumber = "number"; - -constexpr std::string_view kAutofillProfileBirthdatesTable = - "autofill_profile_birthdates"; -// kGuid = "guid" -constexpr std::string_view kDay = "day"; -constexpr std::string_view kMonth = "month"; -constexpr std::string_view kYear = "year"; - constexpr std::string_view kCreditCardsTable = "credit_cards"; -// kGuid = "guid" +constexpr std::string_view kGuid = "guid"; constexpr std::string_view kNameOnCard = "name_on_card"; constexpr std::string_view kExpirationMonth = "expiration_month"; constexpr std::string_view kExpirationYear = "expiration_year"; constexpr std::string_view kCardNumberEncrypted = "card_number_encrypted"; -// kUseCount = "use_count" -// kUseDate = "use_date" -// kDateModified = "date_modified" -// kOrigin = "origin" +constexpr std::string_view kUseCount = "use_count"; +constexpr std::string_view kUseDate = "use_date"; +constexpr std::string_view kDateModified = "date_modified"; +constexpr std::string_view kOrigin = "origin"; constexpr std::string_view kBillingAddressId = "billing_address_id"; constexpr std::string_view kNickname = "nickname"; @@ -273,27 +179,6 @@ // kOfferId = "offer_id" constexpr std::string_view kMerchantDomain = "merchant_domain"; -constexpr std::string_view kContactInfoTable = "contact_info"; -constexpr std::string_view kLocalAddressesTable = "local_addresses"; -// kGuid = "guid" -// kUseCount = "use_count" -// kUseDate = "use_date" -// kDateModified = "date_modified" -// kLanguageCode = "language_code" -// kLabel = "label" -constexpr std::string_view kInitialCreatorId = "initial_creator_id"; -constexpr std::string_view kLastModifierId = "last_modifier_id"; - -constexpr std::string_view kContactInfoTypeTokensTable = - "contact_info_type_tokens"; -constexpr std::string_view kLocalAddressesTypeTokensTable = - "local_addresses_type_tokens"; -// kGuid = "guid" -constexpr std::string_view kType = "type"; -// kValue = "value" -constexpr std::string_view kVerificationStatus = "verification_status"; -constexpr std::string_view kObservations = "observations"; - constexpr std::string_view kVirtualCardUsageDataTable = "virtual_card_usage_data"; // kId = "id" @@ -395,38 +280,12 @@ {kBenefitId, "VARCHAR NOT NULL"}, {kMerchantDomain, "VARCHAR NOT NULL"}}; -// Helper struct for AutofillTable::RemoveFormElementsAddedBetween(). -// Contains all the necessary fields to update a row in the 'autofill' table. -struct AutofillUpdate { - std::u16string name; - std::u16string value; - time_t date_created; - time_t date_last_used; - int count; -}; - // Truncates `data` to the maximum length that can be stored in a column of the // Autofill database. Shorter strings are left as-is. std::u16string Truncate(const std::u16string& data) { return data.substr(0, AutofillTable::kMaxDataLength); } -void AddAutofillProfileDetailsFromStatement(sql::Statement& s, - AutofillProfile* profile) { - int index = 0; - for (FieldType type : - {COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS, - ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, - ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY}) { - profile->SetRawInfo(type, s.ColumnString16(index++)); - } - profile->set_use_count(s.ColumnInt64(index++)); - profile->set_use_date(base::Time::FromTimeT(s.ColumnInt64(index++))); - profile->set_modification_date(base::Time::FromTimeT(s.ColumnInt64(index++))); - profile->set_language_code(s.ColumnString(index++)); - profile->set_profile_label(s.ColumnString(index++)); -} - void BindEncryptedValueToColumn(sql::Statement* s, int column_index, const std::u16string& value, @@ -564,7 +423,7 @@ std::unique_ptr<CreditCard> CreditCardFromStatement( sql::Statement& card_statement, - absl::optional<std::reference_wrapper<sql::Statement>> cvc_statement, + std::optional<std::reference_wrapper<sql::Statement>> cvc_statement, const AutofillTableEncryptor& encryptor) { auto credit_card = std::make_unique<CreditCard>(); @@ -619,170 +478,6 @@ return iban; } -bool AddAutofillProfileNamesToProfile(sql::Database* db, - AutofillProfile* profile) { - if (!db->DoesTableExist(kAutofillProfileNamesTable)) { - return false; - } - sql::Statement s; - if (SelectByGuid( - db, s, kAutofillProfileNamesTable, - {kGuid, kHonorificPrefix, kHonorificPrefixStatus, kFirstName, - kFirstNameStatus, kMiddleName, kMiddleNameStatus, kFirstLastName, - kFirstLastNameStatus, kConjunctionLastName, - kConjunctionLastNameStatus, kSecondLastName, kSecondLastNameStatus, - kLastName, kLastNameStatus, kFullName, kFullNameStatus, - kFullNameWithHonorificPrefix, kFullNameWithHonorificPrefixStatus}, - profile->guid())) { - DCHECK_EQ(profile->guid(), s.ColumnString(0)); - - int index = 1; - for (FieldType type : - {NAME_HONORIFIC_PREFIX, NAME_FIRST, NAME_MIDDLE, NAME_LAST_FIRST, - NAME_LAST_CONJUNCTION, NAME_LAST_SECOND, NAME_LAST, NAME_FULL, - NAME_FULL_WITH_HONORIFIC_PREFIX}) { - profile->SetRawInfoWithVerificationStatusInt( - type, s.ColumnString16(index), s.ColumnInt(index + 1)); - index += 2; - } - } - return s.Succeeded(); -} - -bool AddAutofillProfileAddressesToProfile(sql::Database* db, - AutofillProfile* profile) { - if (!db->DoesTableExist(kAutofillProfileAddressesTable)) { - return false; - } - sql::Statement s; - if (SelectByGuid(db, s, kAutofillProfileAddressesTable, - {kGuid, - kStreetAddress, - kStreetAddressStatus, - kStreetName, - kStreetNameStatus, - kHouseNumber, - kHouseNumberStatus, - kSubpremise, - kSubpremiseStatus, - kDependentLocality, - kDependentLocalityStatus, - kCity, - kCityStatus, - kState, - kStateStatus, - kZipCode, - kZipCodeStatus, - kSortingCode, - kSortingCodeStatus, - kCountryCode, - kCountryCodeStatus, - kApartmentNumber, - kApartmentNumberStatus, - kFloor, - kFloorStatus}, - profile->guid())) { - DCHECK_EQ(profile->guid(), s.ColumnString(0)); - std::u16string street_address = s.ColumnString16(1); - std::u16string dependent_locality = s.ColumnString16(13); - std::u16string city = s.ColumnString16(15); - std::u16string state = s.ColumnString16(17); - std::u16string zip_code = s.ColumnString16(19); - std::u16string sorting_code = s.ColumnString16(21); - std::u16string country = s.ColumnString16(23); - - std::u16string street_address_legacy = - profile->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS); - std::u16string dependent_locality_legacy = - profile->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY); - std::u16string city_legacy = profile->GetRawInfo(ADDRESS_HOME_CITY); - std::u16string state_legacy = profile->GetRawInfo(ADDRESS_HOME_STATE); - std::u16string zip_code_legacy = profile->GetRawInfo(ADDRESS_HOME_ZIP); - std::u16string sorting_code_legacy = - profile->GetRawInfo(ADDRESS_HOME_SORTING_CODE); - std::u16string country_legacy = profile->GetRawInfo(ADDRESS_HOME_COUNTRY); - - // At this stage, the unstructured address was already written to - // the profile. If the address was changed by a legacy client, the - // information diverged from the one in this table that is only written by - // new clients. In this case remove the corresponding row from this table. - // Otherwise, read the new structured tokens and set the verification - // statuses for all tokens. - if (street_address == street_address_legacy && - dependent_locality == dependent_locality_legacy && - city == city_legacy && state == state_legacy && - zip_code == zip_code_legacy && sorting_code == sorting_code_legacy && - country == country_legacy) { - int index = 1; - for (FieldType type : - {ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STREET_NAME, - ADDRESS_HOME_HOUSE_NUMBER, ADDRESS_HOME_SUBPREMISE, - ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY, - ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, - ADDRESS_HOME_COUNTRY, ADDRESS_HOME_APT_NUM, ADDRESS_HOME_FLOOR}) { - profile->SetRawInfoWithVerificationStatusInt( - type, s.ColumnString16(index), s.ColumnInt(index + 1)); - index += 2; - } - } else { - // Remove the structured information from the table for - // eventual deletion consistency. - DeleteWhereColumnEq(db, kAutofillProfileAddressesTable, kGuid, - profile->guid()); - } - } - return s.Succeeded(); -} - -bool AddAutofillProfileEmailsToProfile(sql::Database* db, - AutofillProfile* profile) { - if (!db->DoesTableExist(kAutofillProfileEmailsTable)) { - return false; - } - // TODO(estade): update schema so that multiple emails are not associated - // per unique profile guid. Please refer https://crbug.com/497934. - sql::Statement s; - if (SelectByGuid(db, s, kAutofillProfileEmailsTable, {kGuid, kEmail}, - profile->guid())) { - DCHECK_EQ(profile->guid(), s.ColumnString(0)); - profile->SetRawInfo(EMAIL_ADDRESS, s.ColumnString16(1)); - } - return s.Succeeded(); -} - -bool AddAutofillProfilePhonesToProfile(sql::Database* db, - AutofillProfile* profile) { - if (!db->DoesTableExist(kAutofillProfilePhonesTable)) { - return false; - } - // TODO(estade): update schema so that multiple phone numbers are not - // associated per unique profile guid. Please refer - // https://crbug.com/497934. - sql::Statement s; - if (SelectByGuid(db, s, kAutofillProfilePhonesTable, {kGuid, kNumber}, - profile->guid())) { - DCHECK_EQ(profile->guid(), s.ColumnString(0)); - profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(1)); - } - return s.Succeeded(); -} - -bool AddAutofillProfileBirthdateToProfile(sql::Database* db, - AutofillProfile* profile) { - if (!db->DoesTableExist(kAutofillProfileBirthdatesTable)) { - return false; - } - sql::Statement s; - if (SelectByGuid(db, s, kAutofillProfileBirthdatesTable, - {kGuid, kDay, kMonth, kYear}, profile->guid())) { - DCHECK_EQ(profile->guid(), s.ColumnString(0)); - profile->SetRawInfoAsInt(BIRTHDATE_DAY, s.ColumnInt(1)); - profile->SetRawInfoAsInt(BIRTHDATE_MONTH, s.ColumnInt(2)); - profile->SetRawInfoAsInt(BIRTHDATE_4_DIGIT_YEAR, s.ColumnInt(3)); - } - return s.Succeeded(); -} - WebDatabaseTable::TypeKey GetKey() { // We just need a unique constant. Use the address of a static that // COMDAT folding won't touch in an optimizing linker. @@ -797,138 +492,6 @@ return end.ToTimeT(); } -// This helper function binds the `profile`s properties to the placeholders in -// `s`, in the order the columns are defined in the header file. -void BindAutofillProfileToStatement(const AutofillProfile& profile, - sql::Statement& s) { - int index = 0; - s.BindString(index++, profile.guid()); - s.BindInt64(index++, profile.use_count()); - s.BindInt64(index++, profile.use_date().ToTimeT()); - s.BindInt64(index++, profile.modification_date().ToTimeT()); - s.BindString(index++, profile.language_code()); - s.BindString(index++, profile.profile_label()); - s.BindInt(index++, profile.initial_creator_id()); - s.BindInt(index++, profile.last_modifier_id()); -} - -// Local and account profiles are stored in different tables with the same -// layout. One table contains profile-level metadata, while another table -// contains the values for every relevant FieldType. The following two -// functions are used to map from a profile's `source` to the correct table. -std::string_view GetProfileMetadataTable(AutofillProfile::Source source) { - switch (source) { - case AutofillProfile::Source::kLocalOrSyncable: - return kLocalAddressesTable; - case AutofillProfile::Source::kAccount: - return kContactInfoTable; - } - NOTREACHED_NORETURN(); -} -std::string_view GetProfileTypeTokensTable(AutofillProfile::Source source) { - switch (source) { - case AutofillProfile::Source::kLocalOrSyncable: - return kLocalAddressesTypeTokensTable; - case AutofillProfile::Source::kAccount: - return kContactInfoTypeTokensTable; - } - NOTREACHED_NORETURN(); -} - -// Inserts `profile` into `GetProfileMetadataTable()` and -// `GetProfileTypeTokensTable()`, depending on the profile's source. -bool AddAutofillProfileToTable(sql::Database* db, - const AutofillProfile& profile) { - sql::Statement s; - InsertBuilder(db, s, GetProfileMetadataTable(profile.source()), - {kGuid, kUseCount, kUseDate, kDateModified, kLanguageCode, - kLabel, kInitialCreatorId, kLastModifierId}); - BindAutofillProfileToStatement(profile, s); - if (!s.Run()) - return false; - for (FieldType type : GetDatabaseStoredTypesOfAutofillProfile()) { - if (!base::FeatureList::IsEnabled( - features::kAutofillEnableSupportForAddressOverflowAndLandmark) && - type == ADDRESS_HOME_OVERFLOW_AND_LANDMARK) { - continue; - } - if (!base::FeatureList::IsEnabled( - features::kAutofillEnableSupportForBetweenStreetsOrLandmark) && - type == ADDRESS_HOME_BETWEEN_STREETS_OR_LANDMARK) { - continue; - } - - if (!base::FeatureList::IsEnabled( - features::kAutofillEnableSupportForAddressOverflow) && - type == ADDRESS_HOME_OVERFLOW) { - continue; - } - if (!base::FeatureList::IsEnabled( - features::kAutofillEnableSupportForLandmark) && - type == ADDRESS_HOME_LANDMARK) { - continue; - } - if (!base::FeatureList::IsEnabled( - features::kAutofillEnableSupportForBetweenStreets) && - (type == ADDRESS_HOME_BETWEEN_STREETS || - type == ADDRESS_HOME_BETWEEN_STREETS_1 || - type == ADDRESS_HOME_BETWEEN_STREETS_2)) { - continue; - } - if (!base::FeatureList::IsEnabled( - features::kAutofillEnableSupportForAdminLevel2) && - type == ADDRESS_HOME_ADMIN_LEVEL2) { - continue; - } - InsertBuilder(db, s, GetProfileTypeTokensTable(profile.source()), - {kGuid, kType, kValue, kVerificationStatus, kObservations}); - s.BindString(0, profile.guid()); - s.BindInt(1, type); - s.BindString16(2, Truncate(profile.GetRawInfo(type))); - s.BindInt(3, profile.GetVerificationStatusInt(type)); - s.BindBlob( - 4, profile.token_quality().SerializeObservationsForStoredType(type)); - if (!s.Run()) - return false; - } - return true; -} - -// `MigrateToVersion113MigrateLocalAddressProfilesToNewTable()` migrates -// profiles from one table layout to another. This function inserts the given -// `profile` into the `GetProfileMetadataTable()` of schema version 113. -// `AddAutofillProfileToTable()` can't be reused, since the schema can change in -// future database versions in ways incompatible with version 113 (e.g. adding -// a column). -// The code was copied from `AddAutofillProfileToTable()` in version 113. Like -// the migration logic, it shouldn't be changed. -bool AddAutofillProfileToTableVersion113(sql::Database* db, - const AutofillProfile& profile) { - sql::Statement s; - InsertBuilder(db, s, GetProfileMetadataTable(profile.source()), - {kGuid, kUseCount, kUseDate, kDateModified, kLanguageCode, - kLabel, kInitialCreatorId, kLastModifierId}); - BindAutofillProfileToStatement(profile, s); - if (!s.Run()) { - return false; - } - // Note that `GetDatabaseStoredTypesOfAutofillProfile()` might change in - // future versions. Due to the flexible layout of the type tokens table, this - // is not a problem. - for (FieldType type : GetDatabaseStoredTypesOfAutofillProfile()) { - InsertBuilder(db, s, GetProfileTypeTokensTable(profile.source()), - {kGuid, kType, kValue, kVerificationStatus}); - s.BindString(0, profile.guid()); - s.BindInt(1, type); - s.BindString16(2, Truncate(profile.GetRawInfo(type))); - s.BindInt(3, profile.GetVerificationStatusInt(type)); - if (!s.Run()) { - return false; - } - } - return true; -} - } // namespace PaymentInstrumentFields::PaymentInstrumentFields() = default; @@ -962,11 +525,6 @@ InitModelTypeStateTable() && InitPaymentsCustomerDataTable() && InitServerCreditCardCloudTokenDataTable() && InitOfferDataTable() && InitOfferEligibleInstrumentTable() && InitOfferMerchantDomainTable() && - InitProfileMetadataTable(AutofillProfile::Source::kAccount) && - InitProfileTypeTokensTable(AutofillProfile::Source::kAccount) && - InitProfileMetadataTable(AutofillProfile::Source::kLocalOrSyncable) && - InitProfileTypeTokensTable( - AutofillProfile::Source::kLocalOrSyncable) && InitVirtualCardUsageDataTable() && InitStoredCvcTable() && InitMaskedIbansTable() && InitMaskedIbansMetadataTable() && InitBankAccountsTable() && InitPaymentInstrumentsTable() && @@ -998,50 +556,23 @@ case 87: *update_compatible_version = false; return MigrateToVersion87AddCreditCardNicknameColumn(); - case 88: - *update_compatible_version = false; - return MigrateToVersion88AddNewNameColumns(); case 89: *update_compatible_version = false; return MigrateToVersion89AddInstrumentIdColumnToMaskedCreditCard(); - case 90: - *update_compatible_version = false; - return MigrateToVersion90AddNewStructuredAddressColumns(); - case 91: - *update_compatible_version = false; - return MigrateToVersion91AddMoreStructuredAddressColumns(); - case 92: - *update_compatible_version = false; - return MigrateToVersion92AddNewPrefixedNameColumn(); - case 93: - *update_compatible_version = false; - return MigrateToVersion93AddAutofillProfileLabelColumn(); case 94: *update_compatible_version = false; return MigrateToVersion94AddPromoCodeColumnsToOfferData(); case 95: *update_compatible_version = false; return MigrateToVersion95AddVirtualCardMetadata(); - case 96: - *update_compatible_version = false; - return MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn(); case 98: *update_compatible_version = true; return MigrateToVersion98RemoveStatusColumnMaskedCreditCards(); - case 99: - *update_compatible_version = true; - return MigrateToVersion99RemoveAutofillProfilesTrashTable(); - case 100: - *update_compatible_version = true; - return MigrateToVersion100RemoveProfileValidityBitfieldColumn(); case 101: // update_compatible_version is set to false because this table is not // used since M99. *update_compatible_version = false; return MigrateToVersion101RemoveCreditCardArtImageTable(); - case 102: - *update_compatible_version = false; - return MigrateToVersion102AddAutofillBirthdatesTable(); case 104: *update_compatible_version = false; return MigrateToVersion104AddProductDescriptionColumn(); @@ -1051,39 +582,21 @@ case 106: *update_compatible_version = true; return MigrateToVersion106RecreateAutofillIbanTable(); - case 107: - *update_compatible_version = false; - return MigrateToVersion107AddContactInfoTables(); case 108: *update_compatible_version = false; return MigrateToVersion108AddCardIssuerIdColumn(); case 109: *update_compatible_version = false; return MigrateToVersion109AddVirtualCardUsageDataTable(); - case 110: - *update_compatible_version = false; - return MigrateToVersion110AddInitialCreatorIdAndLastModifierId(); case 111: *update_compatible_version = false; return MigrateToVersion111AddVirtualCardEnrollmentTypeColumn(); - case 112: // AutofillTable didn't change in WebDatabase version 112. - *update_compatible_version = false; - return true; - case 113: - *update_compatible_version = false; - return MigrateToVersion113MigrateLocalAddressProfilesToNewTable(); - case 114: - *update_compatible_version = true; - return MigrateToVersion114DropLegacyAddressTables(); case 115: *update_compatible_version = true; return MigrateToVersion115EncryptIbanValue(); case 116: *update_compatible_version = false; return MigrateToVersion116AddStoredCvcTable(); - case 117: - *update_compatible_version = false; - return MigrateToVersion117AddProfileObservationColumn(); case 118: *update_compatible_version = true; return MigrateToVersion118RemovePaymentsUpiVpaTable(); @@ -1093,12 +606,6 @@ case 120: *update_compatible_version = false; return MigrateToVersion120AddPaymentInstrumentAndBankAccountTables(); - case 121: - *update_compatible_version = true; - return MigrateToVersion121DropServerAddressTables(); - case 122: // AutofillTable didn't change in WebDatabase version 122. - *update_compatible_version = false; - return true; case 123: *update_compatible_version = false; return MigrateToVersion123AddProductTermsUrlColumnAndAddCardBenefitsTables(); @@ -1106,233 +613,6 @@ return true; } -bool AutofillTable::AddAutofillProfile(const AutofillProfile& profile) { - sql::Transaction transaction(db_); - return transaction.Begin() && AddAutofillProfileToTable(db_, profile) && - transaction.Commit(); -} - -bool AutofillTable::UpdateAutofillProfile(const AutofillProfile& profile) { - DCHECK(base::Uuid::ParseCaseInsensitive(profile.guid()).is_valid()); - - std::unique_ptr<AutofillProfile> old_profile = - GetAutofillProfile(profile.guid(), profile.source()); - if (!old_profile) - return false; - - // Implementing an update as remove + add has multiple advantages: - // - Prevents outdated (FieldType, value) pairs from remaining in the - // `GetProfileTypeTokensTable(profile)`, in case field types are removed. - // - Simpler code. - // The possible downside is performance. This is not an issue, as updates - // happen rarely and asynchronously. - sql::Transaction transaction(db_); - return transaction.Begin() && - RemoveAutofillProfile(profile.guid(), profile.source()) && - AddAutofillProfileToTable(db_, profile) && transaction.Commit(); -} - -bool AutofillTable::RemoveAutofillProfile( - const std::string& guid, - AutofillProfile::Source profile_source) { - DCHECK(base::Uuid::ParseCaseInsensitive(guid).is_valid()); - sql::Transaction transaction(db_); - return transaction.Begin() && - DeleteWhereColumnEq(db_, GetProfileMetadataTable(profile_source), - kGuid, guid) && - DeleteWhereColumnEq(db_, GetProfileTypeTokensTable(profile_source), - kGuid, guid) && - transaction.Commit(); -} - -bool AutofillTable::RemoveAllAutofillProfiles( - AutofillProfile::Source profile_source) { - sql::Transaction transaction(db_); - return transaction.Begin() && - Delete(db_, GetProfileMetadataTable(profile_source)) && - Delete(db_, GetProfileTypeTokensTable(profile_source)) && - transaction.Commit(); -} - -std::unique_ptr<AutofillProfile> AutofillTable::GetAutofillProfile( - const std::string& guid, - AutofillProfile::Source profile_source) const { - DCHECK(base::Uuid::ParseCaseInsensitive(guid).is_valid()); - sql::Statement s; - if (!SelectByGuid(db_, s, GetProfileMetadataTable(profile_source), - {kUseCount, kUseDate, kDateModified, kLanguageCode, kLabel, - kInitialCreatorId, kLastModifierId}, - guid)) { - return nullptr; - } - - int index = 0; - const int64_t use_count = s.ColumnInt64(index++); - const base::Time use_date = base::Time::FromTimeT(s.ColumnInt64(index++)); - const base::Time modification_date = - base::Time::FromTimeT(s.ColumnInt64(index++)); - const std::string language_code = s.ColumnString(index++); - const std::string profile_label = s.ColumnString(index++); - const int creator_id = s.ColumnInt(index++); - const int modifier_id = s.ColumnInt(index++); - - if (!SelectByGuid(db_, s, GetProfileTypeTokensTable(profile_source), - {kType, kValue, kVerificationStatus, kObservations}, - guid)) { - return nullptr; - } - - struct FieldTypeData { - // Type corresponding to the data entry. - FieldType type; - // Value corresponding to the entry type. - std::u16string value; - // VerificationStatus of the data entry's `value`. - int status; - // Serialized observations for the stored type. - std::vector<uint8_t> serialized_data; - }; - - std::vector<FieldTypeData> field_type_values; - std::string country_code; - // As `SelectByGuid()` already calls `s.Step()`, do-while is used here. - do { - FieldType type = ToSafeFieldType(s.ColumnInt(0), UNKNOWN_TYPE); - if (type == UNKNOWN_TYPE) { - // This is possible in two cases: - // - The database was tampered with by external means. - // - The type corresponding to `s.ColumnInt(0)` was deprecated. In this - // case, due to the structure of - // `GetProfileTypeTokensTable(profile_source)`, it is not necessary to - // add database migration logic or drop a column. Instead, during the - // next update, the data will be dropped. - continue; - } - - base::span<const uint8_t> observations_data = s.ColumnBlob(3); - field_type_values.emplace_back( - type, s.ColumnString16(1), s.ColumnInt(2), - std::vector<uint8_t>(observations_data.begin(), - observations_data.end())); - - if (type == ADDRESS_HOME_COUNTRY) { - country_code = base::UTF16ToUTF8(s.ColumnString16(1)); - } - - } while (s.Step()); - - // TODO(crbug.com/1464568): Define a proper migration strategy from stored - // legacy profiles into i18n ones. - auto profile = std::make_unique<AutofillProfile>( - guid, profile_source, AddressCountryCode(country_code)); - profile->set_use_count(use_count); - profile->set_use_date(use_date); - profile->set_modification_date(modification_date); - profile->set_language_code(language_code); - profile->set_profile_label(profile_label); - profile->set_initial_creator_id(creator_id); - profile->set_last_modifier_id(modifier_id); - - for (const auto& data : field_type_values) { - profile->SetRawInfoWithVerificationStatusInt(data.type, data.value, - data.status); - profile->token_quality().LoadSerializedObservationsForStoredType( - data.type, data.serialized_data); - } - - profile->FinalizeAfterImport(); - return profile; -} - -bool AutofillTable::GetAutofillProfiles( - AutofillProfile::Source profile_source, - std::vector<std::unique_ptr<AutofillProfile>>* profiles) const { - CHECK(profiles); - profiles->clear(); - - sql::Statement s; - SelectBuilder(db_, s, GetProfileMetadataTable(profile_source), {kGuid}); - while (s.Step()) { - std::string guid = s.ColumnString(0); - std::unique_ptr<AutofillProfile> profile = - GetAutofillProfile(guid, profile_source); - if (!profile) { - continue; - } - profiles->push_back(std::move(profile)); - } - - return s.Succeeded(); -} - -std::unique_ptr<AutofillProfile> -AutofillTable::GetAutofillProfileFromLegacyTable( - const std::string& guid) const { - sql::Statement s; - if (!SelectByGuid(db_, s, kAutofillProfilesTable, - {kCompanyName, kStreetAddress, kDependentLocality, kCity, - kState, kZipcode, kSortingCode, kCountryCode, kUseCount, - kUseDate, kDateModified, kLanguageCode, kLabel}, - guid)) { - return nullptr; - } - - auto profile = std::make_unique<AutofillProfile>( - guid, AutofillProfile::Source::kLocalOrSyncable, - i18n_model_definition::kLegacyHierarchyCountryCode); - - DCHECK(base::Uuid::ParseCaseInsensitive(profile->guid()).is_valid()); - - // Get associated name info using guid. - AddAutofillProfileNamesToProfile(db_, profile.get()); - - // Get associated email info using guid. - AddAutofillProfileEmailsToProfile(db_, profile.get()); - - // Get associated phone info using guid. - AddAutofillProfilePhonesToProfile(db_, profile.get()); - - // Get associated birthdate info using guid. - AddAutofillProfileBirthdateToProfile(db_, profile.get()); - - // The details should be added after the other info to make sure they don't - // change when we change the names/emails/phones. - AddAutofillProfileDetailsFromStatement(s, profile.get()); - - // The structured address information should be added after the street_address - // from the query above was written because this information is used to - // detect changes by a legacy client. - AddAutofillProfileAddressesToProfile(db_, profile.get()); - - // For more-structured profiles, the profile must be finalized to fully - // populate the name fields. - profile->FinalizeAfterImport(); - - return profile; -} - -// TODO(crbug.com/1443393): This function's implementation is very similar to -// `GetAutofillProfiles()`. Simplify somehow. -bool AutofillTable::GetAutofillProfilesFromLegacyTable( - std::vector<std::unique_ptr<AutofillProfile>>* profiles) const { - DCHECK(profiles); - profiles->clear(); - - sql::Statement s; - SelectBuilder(db_, s, kAutofillProfilesTable, {kGuid}); - - while (s.Step()) { - std::string guid = s.ColumnString(0); - std::unique_ptr<AutofillProfile> profile = - GetAutofillProfileFromLegacyTable(guid); - if (!profile) - continue; - profiles->push_back(std::move(profile)); - } - - return s.Succeeded(); -} - std::unique_ptr<BankAccount> AutofillTable::GetBankAccount( const PaymentInstrumentFields& payment_instrument_fields) { sql::Statement s; @@ -1821,9 +1101,9 @@ bool has_cvc = cvc_statement.Step(); return CreditCardFromStatement( card_statement, - has_cvc ? absl::optional< - std::reference_wrapper<sql::Statement>>{cvc_statement} - : absl::nullopt, + has_cvc + ? std::optional<std::reference_wrapper<sql::Statement>>{cvc_statement} + : std::nullopt, *autofill_table_encryptor_); } @@ -2590,10 +1870,8 @@ if (!transaction.Begin()) return false; // Some error, nothing was changed. - RemoveAllAutofillProfiles(AutofillProfile::Source::kLocalOrSyncable); - bool changed = db_->GetLastChangeCount() > 0; ClearLocalPaymentMethodsData(); - changed |= db_->GetLastChangeCount() > 0; + bool changed = db_->GetLastChangeCount() > 0; transaction.Commit(); return changed; @@ -2602,40 +1880,12 @@ bool AutofillTable::RemoveAutofillDataModifiedBetween( const base::Time& delete_begin, const base::Time& delete_end, - std::vector<std::unique_ptr<AutofillProfile>>* profiles, std::vector<std::unique_ptr<CreditCard>>* credit_cards) { DCHECK(delete_end.is_null() || delete_begin < delete_end); time_t delete_begin_t = delete_begin.ToTimeT(); time_t delete_end_t = GetEndTime(delete_end); - // Remember Autofill profiles in the time range. - sql::Statement s_profiles_get; - SelectBetween( - db_, s_profiles_get, - GetProfileMetadataTable(AutofillProfile::Source::kLocalOrSyncable), - {kGuid}, kDateModified, delete_begin_t, delete_end_t); - - profiles->clear(); - while (s_profiles_get.Step()) { - std::string guid = s_profiles_get.ColumnString(0); - std::unique_ptr<AutofillProfile> profile = - GetAutofillProfile(guid, AutofillProfile::Source::kLocalOrSyncable); - if (!profile) - return false; - profiles->push_back(std::move(profile)); - } - if (!s_profiles_get.Succeeded()) - return false; - - // Remove Autofill profiles in the time range. - for (const std::unique_ptr<AutofillProfile>& profile : *profiles) { - if (!RemoveAutofillProfile(profile->guid(), - AutofillProfile::Source::kLocalOrSyncable)) { - return false; - } - } - // Remember Autofill credit cards in the time range. sql::Statement s_credit_cards_get; SelectBetween(db_, s_credit_cards_get, kCreditCardsTable, {kGuid}, @@ -2807,7 +2057,7 @@ bool AutofillTable::MigrateToVersion83RemoveServerCardTypeColumn() { sql::Transaction transaction(db_); return transaction.Begin() && - DropColumn(db_, kMaskedCreditCardsTable, kType) && + DropColumn(db_, kMaskedCreditCardsTable, "type") && transaction.Commit(); } @@ -2824,37 +2074,6 @@ "INTEGER DEFAULT 0"); } -bool AutofillTable::MigrateToVersion88AddNewNameColumns() { - for (std::string_view column : {kHonorificPrefix, kFirstLastName, - kConjunctionLastName, kSecondLastName}) { - if (!AddColumnIfNotExists(db_, kAutofillProfileNamesTable, column, - "VARCHAR")) { - return false; - } - } - - for (std::string_view column : - {kHonorificPrefixStatus, kFirstNameStatus, kMiddleNameStatus, - kLastNameStatus, kFirstLastNameStatus, kConjunctionLastNameStatus, - kSecondLastNameStatus, kFullNameStatus}) { - // The default value of 0 corresponds to the verification status - // |kNoStatus|. - if (!AddColumnIfNotExists(db_, kAutofillProfileNamesTable, column, - "INTEGER DEFAULT 0")) { - return false; - } - } - return true; -} - -bool AutofillTable::MigrateToVersion92AddNewPrefixedNameColumn() { - return AddColumnIfNotExists(db_, kAutofillProfileNamesTable, - kFullNameWithHonorificPrefix, "VARCHAR") && - AddColumnIfNotExists(db_, kAutofillProfileNamesTable, - kFullNameWithHonorificPrefixStatus, - "INTEGER DEFAULT 0"); -} - bool AutofillTable::MigrateToVersion86RemoveUnmaskedCreditCardsUseColumns() { sql::Transaction transaction(db_); return transaction.Begin() && @@ -2868,70 +2087,6 @@ return AddColumnIfNotExists(db_, kCreditCardsTable, kNickname, "VARCHAR"); } -bool AutofillTable::MigrateToVersion90AddNewStructuredAddressColumns() { - if (!db_->DoesTableExist("autofill_profile_addresses")) - InitLegacyProfileAddressesTable(); - - for (std::string_view column : {kDependentLocality, kCity, kState, kZipCode, - kSortingCode, kCountryCode}) { - if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, - "VARCHAR")) { - return false; - } - } - - for (std::string_view column : - {kDependentLocalityStatus, kCityStatus, kStateStatus, kZipCodeStatus, - kSortingCodeStatus, kCountryCodeStatus}) { - // The default value of 0 corresponds to the verification status - // |kNoStatus|. - if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, - "INTEGER DEFAULT 0")) { - return false; - } - } - return true; -} - -bool AutofillTable::MigrateToVersion91AddMoreStructuredAddressColumns() { - if (!db_->DoesTableExist(kAutofillProfileAddressesTable)) - InitLegacyProfileAddressesTable(); - - for (std::string_view column : {kApartmentNumber, kFloor}) { - if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, - "VARCHAR")) { - return false; - } - } - - for (std::string_view column : {kApartmentNumberStatus, kFloorStatus}) { - // The default value of 0 corresponds to the verification status - // |kNoStatus|. - if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column, - "INTEGER DEFAULT 0")) { - return false; - } - } - return true; -} - -bool AutofillTable::MigrateToVersion93AddAutofillProfileLabelColumn() { - if (!db_->DoesTableExist(kAutofillProfilesTable)) - InitLegacyProfileAddressesTable(); - - return AddColumnIfNotExists(db_, kAutofillProfilesTable, kLabel, "VARCHAR"); -} - -bool AutofillTable:: - MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn() { - if (!db_->DoesTableExist(kAutofillProfilesTable)) - InitLegacyProfileAddressesTable(); - - return AddColumnIfNotExists(db_, kAutofillProfilesTable, - kDisallowSettingsVisibleUpdates, - "INTEGER NOT NULL DEFAULT 0"); -} - bool AutofillTable:: MigrateToVersion89AddInstrumentIdColumnToMaskedCreditCard() { // Add the new instrument_id column to the masked_credit_cards table and set @@ -2989,31 +2144,10 @@ transaction.Commit(); } -bool AutofillTable::MigrateToVersion99RemoveAutofillProfilesTrashTable() { - return DropTableIfExists(db_, "autofill_profiles_trash"); -} - -bool AutofillTable::MigrateToVersion100RemoveProfileValidityBitfieldColumn() { - sql::Transaction transaction(db_); - return transaction.Begin() && - DropColumn(db_, kAutofillProfilesTable, "validity_bitfield") && - DropColumn(db_, kAutofillProfilesTable, - "is_client_validity_states_updated") && - transaction.Commit(); -} - bool AutofillTable::MigrateToVersion101RemoveCreditCardArtImageTable() { return DropTableIfExists(db_, "credit_card_art_images"); } -bool AutofillTable::MigrateToVersion102AddAutofillBirthdatesTable() { - return CreateTable(db_, kAutofillProfileBirthdatesTable, - {{kGuid, "VARCHAR"}, - {kDay, "INTEGER DEFAULT 0"}, - {kMonth, "INTEGER DEFAULT 0"}, - {kYear, "INTEGER DEFAULT 0"}}); -} - bool AutofillTable::MigrateToVersion104AddProductDescriptionColumn() { sql::Transaction transaction(db_); if (!transaction.Begin()) @@ -3052,25 +2186,6 @@ transaction.Commit(); } -bool AutofillTable::MigrateToVersion107AddContactInfoTables() { - sql::Transaction transaction(db_); - return transaction.Begin() && - CreateTable(db_, kContactInfoTable, - {{kGuid, "VARCHAR PRIMARY KEY"}, - {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, - {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, - {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, - {kLanguageCode, "VARCHAR"}, - {kLabel, "VARCHAR"}}) && - CreateTable(db_, kContactInfoTypeTokensTable, - {{kGuid, "VARCHAR"}, - {kType, "INTEGER"}, - {kValue, "VARCHAR"}, - {kVerificationStatus, "INTEGER DEFAULT 0"}}, - /*composite_primary_key=*/{kGuid, kType}) && - transaction.Commit(); -} - bool AutofillTable::MigrateToVersion108AddCardIssuerIdColumn() { // Add card_issuer_id to masked_credit_cards. return db_->DoesTableExist(kMaskedCreditCardsTable) && @@ -3086,78 +2201,12 @@ {kLastFour, "VARCHAR"}}); } -bool AutofillTable::MigrateToVersion110AddInitialCreatorIdAndLastModifierId() { - if (!db_->DoesTableExist(kContactInfoTable)) { - return false; - } - sql::Transaction transaction(db_); - return transaction.Begin() && - AddColumnIfNotExists(db_, kContactInfoTable, kInitialCreatorId, - "INTEGER DEFAULT 0") && - AddColumnIfNotExists(db_, kContactInfoTable, kLastModifierId, - "INTEGER DEFAULT 0") && - transaction.Commit(); -} - bool AutofillTable::MigrateToVersion111AddVirtualCardEnrollmentTypeColumn() { return db_->DoesTableExist(kMaskedCreditCardsTable) && AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kVirtualCardEnrollmentType, "INTEGER DEFAULT 0"); } -bool AutofillTable::MigrateToVersion113MigrateLocalAddressProfilesToNewTable() { - sql::Transaction transaction(db_); - if (!transaction.Begin() || - !CreateTableIfNotExists(db_, kLocalAddressesTable, - {{kGuid, "VARCHAR PRIMARY KEY"}, - {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, - {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, - {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, - {kLanguageCode, "VARCHAR"}, - {kLabel, "VARCHAR"}, - {kInitialCreatorId, "INTEGER DEFAULT 0"}, - {kLastModifierId, "INTEGER DEFAULT 0"}}) || - !CreateTableIfNotExists(db_, kLocalAddressesTypeTokensTable, - {{kGuid, "VARCHAR"}, - {kType, "INTEGER"}, - {kValue, "VARCHAR"}, - {kVerificationStatus, "INTEGER DEFAULT 0"}}, - /*composite_primary_key=*/{kGuid, kType})) { - return false; - } - bool success = true; - if (db_->DoesTableExist(kAutofillProfilesTable)) { - std::vector<std::unique_ptr<AutofillProfile>> profiles; - success = GetAutofillProfilesFromLegacyTable(&profiles); - // Migrate profiles to the new tables. Preserve the modification dates. - for (const std::unique_ptr<AutofillProfile>& profile : profiles) { - success = success && AddAutofillProfileToTableVersion113(db_, *profile); - } - } - // Delete all profiles from the legacy tables. The tables are dropped in - // version 114. - for (std::string_view deprecated_table : - {kAutofillProfilesTable, kAutofillProfileAddressesTable, - kAutofillProfileNamesTable, kAutofillProfileEmailsTable, - kAutofillProfilePhonesTable, kAutofillProfileBirthdatesTable}) { - success = success && (!db_->DoesTableExist(deprecated_table) || - Delete(db_, deprecated_table)); - } - return success && transaction.Commit(); -} - -bool AutofillTable::MigrateToVersion114DropLegacyAddressTables() { - sql::Transaction transaction(db_); - bool success = transaction.Begin(); - for (std::string_view deprecated_table : - {kAutofillProfilesTable, kAutofillProfileAddressesTable, - kAutofillProfileNamesTable, kAutofillProfileEmailsTable, - kAutofillProfilePhonesTable, kAutofillProfileBirthdatesTable}) { - success = success && DropTableIfExists(db_, deprecated_table); - } - return success && transaction.Commit(); -} - bool AutofillTable::MigrateToVersion115EncryptIbanValue() { // Encrypt all existing IBAN values and rename the column name from `value` to // `value_encrypted` by the following steps: @@ -3210,15 +2259,6 @@ transaction.Commit(); } -bool AutofillTable::MigrateToVersion117AddProfileObservationColumn() { - sql::Transaction transaction(db_); - return transaction.Begin() && - AddColumn(db_, kContactInfoTypeTokensTable, kObservations, "BLOB") && - AddColumn(db_, kLocalAddressesTypeTokensTable, kObservations, - "BLOB") && - transaction.Commit(); -} - bool AutofillTable::MigrateToVersion118RemovePaymentsUpiVpaTable() { sql::Transaction transaction(db_); return transaction.Begin() && DropTableIfExists(db_, kPaymentsUpiVpaTable) && @@ -3262,13 +2302,6 @@ transaction.Commit(); } -bool AutofillTable::MigrateToVersion121DropServerAddressTables() { - sql::Transaction transaction(db_); - return transaction.Begin() && DropTableIfExists(db_, "server_addresses") && - DropTableIfExists(db_, "server_address_metadata") && - transaction.Commit(); -} - bool AutofillTable:: MigrateToVersion123AddProductTermsUrlColumnAndAddCardBenefitsTables() { sql::Transaction transaction(db_); @@ -3433,107 +2466,6 @@ {kNickname, "VARCHAR"}}); } -bool AutofillTable::InitLegacyProfilesTable() { - return CreateTableIfNotExists( - db_, kAutofillProfilesTable, - {{kGuid, "VARCHAR PRIMARY KEY"}, - {kCompanyName, "VARCHAR"}, - {kStreetAddress, "VARCHAR"}, - {kDependentLocality, "VARCHAR"}, - {kCity, "VARCHAR"}, - {kState, "VARCHAR"}, - {kZipcode, "VARCHAR"}, - {kSortingCode, "VARCHAR"}, - {kCountryCode, "VARCHAR"}, - {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, - {kOrigin, "VARCHAR DEFAULT ''"}, - {kLanguageCode, "VARCHAR"}, - {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, - {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, - {kLabel, "VARCHAR"}, - {kDisallowSettingsVisibleUpdates, "INTEGER NOT NULL DEFAULT 0"}}); -} - -bool AutofillTable::InitLegacyProfileNamesTable() { - // The default value of 0 corresponds to the verification status - // |kNoStatus|. - return CreateTableIfNotExists( - db_, kAutofillProfileNamesTable, - {{kGuid, "VARCHAR"}, - {kFirstName, "VARCHAR"}, - {kMiddleName, "VARCHAR"}, - {kLastName, "VARCHAR"}, - {kFullName, "VARCHAR"}, - {kHonorificPrefix, "VARCHAR"}, - {kFirstLastName, "VARCHAR"}, - {kConjunctionLastName, "VARCHAR"}, - {kSecondLastName, "VARCHAR"}, - {kHonorificPrefixStatus, "INTEGER DEFAULT 0"}, - {kFirstNameStatus, "INTEGER DEFAULT 0"}, - {kMiddleNameStatus, "INTEGER DEFAULT 0"}, - {kLastNameStatus, "INTEGER DEFAULT 0"}, - {kFirstLastNameStatus, "INTEGER DEFAULT 0"}, - {kConjunctionLastNameStatus, "INTEGER DEFAULT 0"}, - {kSecondLastNameStatus, "INTEGER DEFAULT 0"}, - {kFullNameStatus, "INTEGER DEFAULT 0"}, - {kFullNameWithHonorificPrefix, "VARCHAR"}, - {kFullNameWithHonorificPrefixStatus, "INTEGER DEFAULT 0"}}); -} - -bool AutofillTable::InitLegacyProfileAddressesTable() { - // The default value of 0 corresponds to the verification status - // |kNoStatus|. - return CreateTableIfNotExists( - db_, kAutofillProfileAddressesTable, - {{kGuid, "VARCHAR"}, - {kStreetAddress, "VARCHAR"}, - {kStreetName, "VARCHAR"}, - {kDependentStreetName, "VARCHAR"}, - {kHouseNumber, "VARCHAR"}, - {kSubpremise, "VARCHAR"}, - {"premise_name", "VARCHAR"}, - {kStreetAddressStatus, "INTEGER DEFAULT 0"}, - {kStreetNameStatus, "INTEGER DEFAULT 0"}, - {kDependentStreetNameStatus, "INTEGER DEFAULT 0"}, - {kHouseNumberStatus, "INTEGER DEFAULT 0"}, - {kSubpremiseStatus, "INTEGER DEFAULT 0"}, - {"premise_name_status", "INTEGER DEFAULT 0"}, - {kDependentLocality, "VARCHAR"}, - {kCity, "VARCHAR"}, - {kState, "VARCHAR"}, - {kZipCode, "VARCHAR"}, - {kSortingCode, "VARCHAR"}, - {kCountryCode, "VARCHAR"}, - {kDependentLocalityStatus, "INTEGER DEFAULT 0"}, - {kCityStatus, "INTEGER DEFAULT 0"}, - {kStateStatus, "INTEGER DEFAULT 0"}, - {kZipCodeStatus, "INTEGER DEFAULT 0"}, - {kSortingCodeStatus, "INTEGER DEFAULT 0"}, - {kCountryCodeStatus, "INTEGER DEFAULT 0"}, - {kApartmentNumber, "VARCHAR"}, - {kFloor, "VARCHAR"}, - {kApartmentNumberStatus, "INTEGER DEFAULT 0"}, - {kFloorStatus, "INTEGER DEFAULT 0"}}); -} - -bool AutofillTable::InitLegacyProfileEmailsTable() { - return CreateTableIfNotExists(db_, kAutofillProfileEmailsTable, - {{kGuid, "VARCHAR"}, {kEmail, "VARCHAR"}}); -} - -bool AutofillTable::InitLegacyProfilePhonesTable() { - return CreateTableIfNotExists(db_, kAutofillProfilePhonesTable, - {{kGuid, "VARCHAR"}, {kNumber, "VARCHAR"}}); -} - -bool AutofillTable::InitLegacyProfileBirthdatesTable() { - return CreateTableIfNotExists(db_, kAutofillProfileBirthdatesTable, - {{kGuid, "VARCHAR"}, - {kDay, "INTEGER DEFAULT 0"}, - {kMonth, "INTEGER DEFAULT 0"}, - {kYear, "INTEGER DEFAULT 0"}}); -} - bool AutofillTable::InitMaskedCreditCardsTable() { return CreateTableIfNotExists( db_, kMaskedCreditCardsTable, @@ -3655,28 +2587,6 @@ {{kOfferId, "UNSIGNED LONG"}, {kMerchantDomain, "VARCHAR"}}); } -bool AutofillTable::InitProfileMetadataTable(AutofillProfile::Source source) { - return CreateTableIfNotExists(db_, GetProfileMetadataTable(source), - {{kGuid, "VARCHAR PRIMARY KEY"}, - {kUseCount, "INTEGER NOT NULL DEFAULT 0"}, - {kUseDate, "INTEGER NOT NULL DEFAULT 0"}, - {kDateModified, "INTEGER NOT NULL DEFAULT 0"}, - {kLanguageCode, "VARCHAR"}, - {kLabel, "VARCHAR"}, - {kInitialCreatorId, "INTEGER DEFAULT 0"}, - {kLastModifierId, "INTEGER DEFAULT 0"}}); -} - -bool AutofillTable::InitProfileTypeTokensTable(AutofillProfile::Source source) { - return CreateTableIfNotExists(db_, GetProfileTypeTokensTable(source), - {{kGuid, "VARCHAR"}, - {kType, "INTEGER"}, - {kValue, "VARCHAR"}, - {kVerificationStatus, "INTEGER DEFAULT 0"}, - {kObservations, "BLOB"}}, - /*composite_primary_key=*/{kGuid, kType}); -} - bool AutofillTable::InitVirtualCardUsageDataTable() { return CreateTableIfNotExists(db_, kVirtualCardUsageDataTable, {{kId, "VARCHAR PRIMARY KEY"},
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h index b0e5aad..e5937f5 100644 --- a/components/autofill/core/browser/webdata/autofill_table.h +++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -15,7 +15,6 @@ #include "base/gtest_prod_util.h" #include "base/time/time.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/payment_instrument.h" #include "components/sync/base/model_type.h" #include "components/sync/model/sync_metadata_store.h" @@ -85,168 +84,6 @@ // // Note: The database stores time in seconds, UTC. // -// DEPRECATED. Use local_addresses instead. -// autofill_profiles This table contains Autofill profile data added by the -// user with the Autofill dialog. Most of the columns are -// standard entries in a contact information form. -// -// guid A guid string to uniquely identify the profile. -// Added in version 31. -// label A user-chosen and user-visible label for the profile to -// help identifying the semantics of the profile. The user -// can choose an arbitrary string in principle, but the -// values '$HOME$' and '$WORK$' indicate a special meaning. -// company_name -// street_address The combined lines of the street address. -// Added in version 54. -// dependent_locality -// A sub-classification beneath the city, e.g. an -// inner-city district or suburb. Added in version 54. -// city -// state -// zipcode -// sorting_code Similar to the zipcode column, but used for businesses -// or organizations that might not be geographically -// contiguous. The canonical example is CEDEX in France. -// Added in version 54. -// country_code -// use_count The number of times this profile has been used to fill -// a form. Added in version 61. -// use_date The date this profile was last used to fill a form, -// in time_t. Added in version 61. -// date_modified The date on which this profile was last modified, in -// time_t. Added in version 30. -// origin The domain of origin for this profile. -// Added in version 50. -// language_code The BCP 47 language code used to format the address for -// display. For example, a JP address with "ja" language -// code starts with the postal code, but a JP address with -// "ja-latn" language code starts with the recipient name. -// Added in version 56. -// disallow_settings_visible_updates -// If true, a profile does not qualify to get merged with -// a profile observed in a form submission. -// -// DEPRECATED. See autofill_profiles. -// autofill_profile_addresses -// guid The guid string that identifies the profile to which -// the name belongs. -// This table stores the structured address information. -// street_address Stores the street address. This field is also stored in -// the profile table and is used to detect if a legacy -// client that does not support writing to this table -// changed the address. If this is true, the address stored -// in the table is removed. -// street_name The name of the street. -// dependent_street_name -// The name of the crossing street. -// house_number The house number. -// subpremise The floor, apartment number and staircase. -// apartment number. -// dependent_locality -// A sub-classification beneath the city, e.g. an -// inner-city district or suburb. -// city The city information of the address. -// state The state information of the address. -// zip_code The zip code of the address. -// country_code The code of the country of the address. -// sorting_code Similar to the zipcode column, but used for businesses -// or organizations that might not be geographically -// contiguous. -// premise_name The name of the premise. -// apartment_number The number of the apartment. -// floor The floor in which the apartment is located. -// street_address_status -// street_name_status -// dependent_street_name_status -// house_number_status -// subpremise_status -// premise_name_status -// dependent_locality_status -// city_status -// state_status -// zip_code_status -// country_code_status -// sorting_code_status -// apartment_number_status -// floor_status -// Each token of the address has an additional validation -// status that indicates if Autofill parsed the value out -// of an unstructured (last) name, or if autofill formatted -// the token from its structured subcomponents, or if the -// value was observed in a form submission, or even -// validated by the user in the settings. -// -// DEPRECATED. See autofill_profiles. -// autofill_profile_names -// This table contains the multi-valued name fields -// associated with a profile. -// -// guid The guid string that identifies the profile to which -// the name belongs. -// honorific_prefix The honorific prefix of a person like Ms, Mr or Prof -// first_name The first name of a person. -// middle_name The middle name or even names of a person. -// last_name The unstructured last name that is a combination of the -// first and second last name. -// first_last_name The first part of the last name. Mostly used for -// Latinx/Hispanic last names. -// conjunction_last_name -// An optional conjunction that is mostly used in -// Hispanic/Latinx last names in between the first and -// second last name in the unstructured representation. -// second_last_name The second part of the last names. Last names only -// consisting of a single part are stored in the second -// part by default. -// full_name The unstructured full name of a person. -// full_name_with_honorific_prefix -// The combination of the full name and the honorific -// prefix. -// honorific_prefix_status -// first_name_status -// middle_name_status -// last_name_status -// first_last_name_status -// conjunction_last_name_status -// second_last_name_status -// full_name_status -// full_name_with_honorific_prefix_status -// Each token of the names has an additional validation -// status that indicates if Autofill parsed the value out -// of an unstructured (last) name, or if autofill formatted -// the token from its structured subcomponents, or if the -// value was observed in a form submission, or even -// validated by the user in the settings. -// -// DEPRECATED. See autofill_profiles. -// autofill_profile_emails -// This table contains the multi-valued email fields -// associated with a profile. -// -// guid The guid string that identifies the profile to which -// the email belongs. -// email -// -// DEPRECATED. See autofill_profiles. -// autofill_profile_phones -// This table contains the multi-valued phone fields -// associated with a profile. -// -// guid The guid string that identifies the profile to which the -// phone number belongs. -// number -// -// DEPRECATED. See autofill_profiles. -// autofill_profile_birthdates -// This table contains the multi-valued birthdate fields -// associated with a profile. -// -// guid The guid string that identifies the profile to which the -// birthdate number belongs. -// day As an integer between 1 and 31 inclusive, or 0 if unset. -// month As an integer between 1 and 12 inclusive, or 0 if unset. -// year As a 4 digit integer, or 0 if unset. -// // credit_cards This table contains credit card data added by the user // with the Autofill dialog. Most of the columns are // standard entries in a credit card form. @@ -464,53 +301,6 @@ // merchant_domain List of full origins for merchant websites on which // this offer would apply. // -// contact_info This table contains Autofill profile data synced from a -// remote source. -// local_addresses This table contains kLocalOrSyncable Autofill profiles. -// It has the same layout as the contact_info table. -// -// guid A guid string to uniquely identify the profile. -// use_count The number of times this profile has been used to fill a -// form. -// use_date The date this profile was last used to fill a form, in -// time_t. -// date_modified The date on which this profile was last modified, in -// time_t. -// language_code The BCP 47 language code used to format the address for -// display. For example, a JP address with "ja" language -// code starts with the postal code, but a JP address with -// "ja-latn" language code starts with the recipient name. -// label A user-chosen and user-visible label for the profile to -// help identifying the semantics of the profile. The user -// can choose an arbitrary string in principle, but the -// values '$HOME$' and '$WORK$' indicate a special meaning. -// initial_creator_id The application that initially created the profile. -// Represented as an integer. See AutofillProfile. -// last_modifier_id The application that performed the last non-metadata -// modification of the profile. -// Represented as an integer. See AutofillProfile. -// -// contact_info_type_tokens -// Contains the values for all relevant ServerFieldTypes of -// a contact_info entry. At most one entry per (guid, type) -// pair exists. -// local_addresses_type_tokens -// Like contact_info_type_tokens, but for local_addresses. -// -// guid The guid of the corresponding profile in contact_info. -// type The FieldType, represented by its integer value in -// the FieldType enum. -// value The string value of the type. -// verification_status Each token has an additional validation status that -// indicates if Autofill parsed the value out of an -// unstructured token, or if Autofill formatted the token -// from a structured subcomponent, or if the value was -// observed in a form submission, or even validated by the -// user in the settings. -// observations An encoding of the observations stored for this `type`. -// See `ProfileTokenConfidence:: -// SerializeObservationsForStoredType()`. -// // virtual_card_usage_data // Contains data related to retrieval attempts of a virtual // card on a particular merchant domain @@ -663,34 +453,6 @@ bool CreateTablesIfNecessary() override; bool MigrateToVersion(int version, bool* update_compatible_version) override; - // Records a single Autofill profile in the autofill_profiles table. - virtual bool AddAutofillProfile(const AutofillProfile& profile); - - // Updates the database values for the specified profile. Multi-value aware. - virtual bool UpdateAutofillProfile(const AutofillProfile& profile); - - // Removes the Autofill profile with the given `guid`. `profile_source` - // indicates where the profile was synced from and thus whether it is stored - // in `kAutofillProfilesTable` or `kContactInfoTable`. - virtual bool RemoveAutofillProfile(const std::string& guid, - AutofillProfile::Source profile_source); - - // Removes all profiles from the given `profile_source`. - bool RemoveAllAutofillProfiles(AutofillProfile::Source profile_source); - - // Retrieves a profile with guid `guid` from `kAutofillProfilesTable` or - // `kContactInfoTable`. - std::unique_ptr<AutofillProfile> GetAutofillProfile( - const std::string& guid, - AutofillProfile::Source profile_source) const; - - // Retrieves profiles in the database. They are returned in unspecified order. - // The `profile_source` specifies if profiles from the legacy or the remote - // backend should be retrieved. - virtual bool GetAutofillProfiles( - AutofillProfile::Source profile_source, - std::vector<std::unique_ptr<AutofillProfile>>* profiles) const; - // Fetches a PaymentInstrument from the autofill db. This will query the below // 3 tables to generate a PaymentInstrument object. // `payment_instruments` @@ -856,29 +618,26 @@ virtual_card_usage_data); bool RemoveAllVirtualCardUsageData(); - // Deletes all data from the server card and profile tables. Returns true if - // any data was deleted, false if not (so false means "commit not needed" - // rather than "error"). + // Deletes all data from the server card tables. Returns true if any data was + // deleted, false if not (so false means "commit not needed" rather than + // "error"). bool ClearAllServerData(); - // Deletes all data from the local card and profiles table. Returns true if - // any data was deleted, false if not (so false means "commit not needed" - // rather than "error"). + // Deletes all data from the local card table. Returns true if any data was + // deleted, false if not (so false means "commit not needed" rather than + // "error"). bool ClearAllLocalData(); - // Removes rows from autofill_profiles and credit_cards if they were created - // on or after `delete_begin` and strictly before `delete_end`. Returns the - // list of deleted profile guids in `profile_guids`. Return value is true if - // all rows were successfully removed. Returns false on database error. In - // that case, the output vector state is undefined, and may be partially - // filled. + // Removes rows from credit_cards if they were created on or after + // `delete_begin` and strictly before `delete_end`. Returns the list of + // deleted cards in `credit_cards`. Return value is true if all rows were + // successfully removed. Returns false on database error. In that case, the + // output vector state is undefined, and may be partially filled. // TODO(crbug.com/1135188): This function is solely used to remove browsing - // data. Once explicit save dialogs are fully launched, it can be removed. For - // this reason profiles in the `contact_info` table are not considered. + // data. Once explicit save dialogs are fully launched, it can be removed. bool RemoveAutofillDataModifiedBetween( const base::Time& delete_begin, const base::Time& delete_end, - std::vector<std::unique_ptr<AutofillProfile>>* profiles, std::vector<std::unique_ptr<CreditCard>>* credit_cards); // Removes origin URLs from the credit_cards tables if they were written on or @@ -918,41 +677,22 @@ bool MigrateToVersion85AddCardIssuerColumnToMaskedCreditCard(); bool MigrateToVersion86RemoveUnmaskedCreditCardsUseColumns(); bool MigrateToVersion87AddCreditCardNicknameColumn(); - bool MigrateToVersion88AddNewNameColumns(); bool MigrateToVersion89AddInstrumentIdColumnToMaskedCreditCard(); - bool MigrateToVersion90AddNewStructuredAddressColumns(); - bool MigrateToVersion91AddMoreStructuredAddressColumns(); - bool MigrateToVersion92AddNewPrefixedNameColumn(); - bool MigrateToVersion93AddAutofillProfileLabelColumn(); bool MigrateToVersion94AddPromoCodeColumnsToOfferData(); bool MigrateToVersion95AddVirtualCardMetadata(); - bool MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn(); bool MigrateToVersion98RemoveStatusColumnMaskedCreditCards(); - bool MigrateToVersion99RemoveAutofillProfilesTrashTable(); - bool MigrateToVersion100RemoveProfileValidityBitfieldColumn(); bool MigrateToVersion101RemoveCreditCardArtImageTable(); - bool MigrateToVersion102AddAutofillBirthdatesTable(); bool MigrateToVersion104AddProductDescriptionColumn(); bool MigrateToVersion105AddAutofillIbanTable(); bool MigrateToVersion106RecreateAutofillIbanTable(); - bool MigrateToVersion107AddContactInfoTables(); bool MigrateToVersion108AddCardIssuerIdColumn(); bool MigrateToVersion109AddVirtualCardUsageDataTable(); - bool MigrateToVersion110AddInitialCreatorIdAndLastModifierId(); bool MigrateToVersion111AddVirtualCardEnrollmentTypeColumn(); - // No MigrateToVersion112. WebDatabase changed, but AutofillTable wasn't - // affected. - bool MigrateToVersion113MigrateLocalAddressProfilesToNewTable(); - bool MigrateToVersion114DropLegacyAddressTables(); bool MigrateToVersion115EncryptIbanValue(); bool MigrateToVersion116AddStoredCvcTable(); - bool MigrateToVersion117AddProfileObservationColumn(); bool MigrateToVersion118RemovePaymentsUpiVpaTable(); bool MigrateToVersion119AddMaskedIbanTablesAndRenameLocalIbanTable(); bool MigrateToVersion120AddPaymentInstrumentAndBankAccountTables(); - bool MigrateToVersion121DropServerAddressTables(); - // No MigrateToVersion122. WebDatabase changed, but AutofillTable wasn't - // affected. bool MigrateToVersion123AddProductTermsUrlColumnAndAddCardBenefitsTables(); // Max data length saved in the table, AKA the maximum length allowed for @@ -982,12 +722,6 @@ bool DeleteFromMaskedCreditCards(const std::string& id); bool DeleteFromUnmaskedCreditCards(const std::string& id); - // Reads profiles from the deprecated autofill_profiles table. - std::unique_ptr<AutofillProfile> GetAutofillProfileFromLegacyTable( - const std::string& guid) const; - bool GetAutofillProfilesFromLegacyTable( - std::vector<std::unique_ptr<AutofillProfile>>* profiles) const; - // Retrieve the data from the `bank_accounts` table and return a BankAccount // object. The `payment_instrument_fields` contain the fields retrieved from // the `payment_instruments` and `payment_instrument_supported_rails` tables @@ -1017,12 +751,6 @@ bool InitCreditCardsTable(); bool InitLocalIbansTable(); - bool InitLegacyProfilesTable(); - bool InitLegacyProfileAddressesTable(); - bool InitLegacyProfileNamesTable(); - bool InitLegacyProfileEmailsTable(); - bool InitLegacyProfilePhonesTable(); - bool InitLegacyProfileBirthdatesTable(); bool InitMaskedCreditCardsTable(); bool InitMaskedIbansTable(); bool InitMaskedIbansMetadataTable(); @@ -1036,8 +764,6 @@ bool InitOfferDataTable(); bool InitOfferEligibleInstrumentTable(); bool InitOfferMerchantDomainTable(); - bool InitProfileMetadataTable(AutofillProfile::Source source); - bool InitProfileTypeTokensTable(AutofillProfile::Source source); bool InitVirtualCardUsageDataTable(); bool InitBankAccountsTable(); bool InitPaymentInstrumentsTable();
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc index 0c837ff..608cc667 100644 --- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -24,18 +24,14 @@ #include "build/build_config.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/autofill_type.h" -#include "components/autofill/core/browser/country_type.h" #include "components/autofill/core/browser/data_model/autofill_metadata.h" #include "components/autofill/core/browser/data_model/autofill_offer_data.h" -#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/autofill_wallet_usage_data.h" #include "components/autofill/core/browser/data_model/bank_account.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/payments/payments_customer_data.h" -#include "components/autofill/core/browser/profile_token_quality.h" -#include "components/autofill/core/browser/profile_token_quality_test_api.h" #include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/browser/webdata/autofill_change.h" #include "components/autofill/core/common/autofill_clock.h" @@ -112,248 +108,6 @@ std::unique_ptr<WebDatabase> db_; }; -// Tests for the AutofillProfil CRUD interface are tested with both profile -// sources. -class AutofillTableProfileTest - : public AutofillTableTest, - public testing::WithParamInterface<AutofillProfile::Source> { - public: - void SetUp() override { - AutofillTableTest::SetUp(); - features_.InitWithFeatures( - {features::kAutofillEnableSupportForLandmark, - features::kAutofillEnableSupportForBetweenStreets, - features::kAutofillEnableSupportForAdminLevel2, - features::kAutofillEnableSupportForAddressOverflow, - features::kAutofillEnableSupportForAddressOverflowAndLandmark, - features::kAutofillEnableSupportForBetweenStreetsOrLandmark}, - {}); - } - AutofillProfile::Source profile_source() const { return GetParam(); } - - // Creates an `AutofillProfile` with `profile_source()` as its source. - AutofillProfile CreateAutofillProfile() const { - return AutofillProfile(profile_source(), AddressCountryCode("ES")); - } - - // Depending on the `profile_source()`, the AutofillProfiles are stored in a - // different master table. - std::string_view GetProfileTable() const { - return profile_source() == AutofillProfile::Source::kLocalOrSyncable - ? "local_addresses" - : "contact_info"; - } - - private: - base::test::ScopedFeatureList features_; -}; - -INSTANTIATE_TEST_SUITE_P( - , - AutofillTableProfileTest, - testing::ValuesIn({AutofillProfile::Source::kLocalOrSyncable, - AutofillProfile::Source::kAccount})); - -// Tests reading/writing name, email, company, address, phone number and -// birthdate information. -TEST_P(AutofillTableProfileTest, AutofillProfile) { - AutofillProfile home_profile = CreateAutofillProfile(); - - // TODO(crbug.com/1113617): Honorifics are temporally disabled. - // home_profile.SetRawInfoWithVerificationStatus( - // NAME_HONORIFIC_PREFIX, u"Dr.", - // VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(NAME_HONORIFIC_PREFIX, u"Dr.", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(NAME_FIRST, u"John", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(NAME_MIDDLE, u"Q.", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(NAME_LAST_FIRST, u"Agent", - VerificationStatus::kParsed); - - home_profile.SetRawInfoWithVerificationStatus(NAME_LAST_CONJUNCTION, u"007", - VerificationStatus::kParsed); - - home_profile.SetRawInfoWithVerificationStatus(NAME_LAST_SECOND, u"Smith", - VerificationStatus::kParsed); - - home_profile.SetRawInfoWithVerificationStatus(NAME_LAST, u"Agent 007 Smith", - VerificationStatus::kParsed); - - home_profile.SetRawInfoWithVerificationStatus( - NAME_FULL, u"John Q. Agent 007 Smith", VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(NAME_FULL_WITH_HONORIFIC_PREFIX, - u"Dr. John Q. Agent 007 Smith", - VerificationStatus::kObserved); - - home_profile.SetRawInfo(EMAIL_ADDRESS, u"js@smith.xyz"); - home_profile.SetRawInfo(COMPANY_NAME, u"Google"); - - home_profile.SetRawInfoWithVerificationStatus( - ADDRESS_HOME_STREET_ADDRESS, - u"Street Name between streets House Number Premise APT 10 Floor 2 " - u"Landmark", - VerificationStatus::kUserVerified); - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_STREET_LOCATION, - u"Street Name House Number", - VerificationStatus::kFormatted); - home_profile.SetRawInfoWithVerificationStatus( - ADDRESS_HOME_STREET_NAME, u"Street Name", VerificationStatus::kFormatted); - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_DEPENDENT_LOCALITY, - u"Dependent Locality", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_CITY, u"City", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_STATE, u"State", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_SORTING_CODE, - u"Sorting Code", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_ZIP, u"ZIP", - VerificationStatus::kObserved); - - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_COUNTRY, u"DE", - VerificationStatus::kObserved); - home_profile.SetRawInfoWithVerificationStatus( - ADDRESS_HOME_HOUSE_NUMBER, u"House Number", - VerificationStatus::kUserVerified); - home_profile.SetRawInfoWithVerificationStatus( - ADDRESS_HOME_SUBPREMISE, u"APT 10 Floor 2", - VerificationStatus::kUserVerified); - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_APT_NUM, u"10", - VerificationStatus::kParsed); - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_FLOOR, u"2", - VerificationStatus::kParsed); - ASSERT_EQ(home_profile.GetRawInfo(ADDRESS_HOME_STREET_NAME), u"Street Name"); - home_profile.SetRawInfoWithVerificationStatus( - ADDRESS_HOME_LANDMARK, u"Landmark", VerificationStatus::kObserved); - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_OVERFLOW, - u"Andar 1, Apto. 12", - VerificationStatus::kObserved); - home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_BETWEEN_STREETS, - u"between streets", - VerificationStatus::kObserved); - home_profile.SetRawInfoWithVerificationStatus( - ADDRESS_HOME_ADMIN_LEVEL2, u"Oxaca", VerificationStatus::kObserved); - - home_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"18181234567"); - home_profile.SetRawInfoAsInt(BIRTHDATE_DAY, 14); - home_profile.SetRawInfoAsInt(BIRTHDATE_MONTH, 3); - home_profile.SetRawInfoAsInt(BIRTHDATE_4_DIGIT_YEAR, 1997); - home_profile.set_language_code("en"); - - // Add the profile to the table. - EXPECT_TRUE(table_->AddAutofillProfile(home_profile)); - - // Get the 'Home' profile from the table. - std::unique_ptr<AutofillProfile> db_profile = - table_->GetAutofillProfile(home_profile.guid(), home_profile.source()); - ASSERT_TRUE(db_profile); - - // Verify that it is correct. - EXPECT_EQ(home_profile, *db_profile); - - // Remove the profile and expect that no profiles remain. - EXPECT_TRUE( - table_->RemoveAutofillProfile(home_profile.guid(), profile_source())); - std::vector<std::unique_ptr<AutofillProfile>> profiles; - EXPECT_TRUE(table_->GetAutofillProfiles(profile_source(), &profiles)); - EXPECT_TRUE(profiles.empty()); -} - -// Tests that `GetAutofillProfiles(source, profiles)` clears `profiles` and -// only returns profiles from the correct `source`. -// Not part of the `AutofillTableProfileTest` fixture, as it doesn't benefit -// from parameterization on the `profile_source()`. -TEST_F(AutofillTableTest, GetAutofillProfiles) { - AutofillProfile local_profile(AutofillProfile::Source::kLocalOrSyncable, - AddressCountryCode("ES")); - AutofillProfile account_profile(AutofillProfile::Source::kAccount, - AddressCountryCode("ES")); - EXPECT_TRUE(table_->AddAutofillProfile(local_profile)); - EXPECT_TRUE(table_->AddAutofillProfile(account_profile)); - - std::vector<std::unique_ptr<AutofillProfile>> profiles; - EXPECT_TRUE(table_->GetAutofillProfiles( - AutofillProfile::Source::kLocalOrSyncable, &profiles)); - EXPECT_THAT(profiles, ElementsAre(testing::Pointee(local_profile))); - EXPECT_TRUE(table_->GetAutofillProfiles(AutofillProfile::Source::kAccount, - &profiles)); - EXPECT_THAT(profiles, ElementsAre(testing::Pointee(account_profile))); -} - -// Tests that `RemoveAllAutofillProfiles()` clears all profiles of the given -// source. -TEST_P(AutofillTableProfileTest, RemoveAllAutofillProfiles) { - ASSERT_TRUE(table_->AddAutofillProfile( - AutofillProfile(AutofillProfile::Source::kLocalOrSyncable, - i18n_model_definition::kLegacyHierarchyCountryCode))); - ASSERT_TRUE(table_->AddAutofillProfile( - AutofillProfile(AutofillProfile::Source::kAccount, - i18n_model_definition::kLegacyHierarchyCountryCode))); - - EXPECT_TRUE(table_->RemoveAllAutofillProfiles(profile_source())); - - // Expect that the profiles from `profile_source()` are gone. - std::vector<std::unique_ptr<AutofillProfile>> profiles; - ASSERT_TRUE(table_->GetAutofillProfiles(profile_source(), &profiles)); - EXPECT_TRUE(profiles.empty()); - - // Expect that the profile from the opposite source remains. - const auto other_source = - profile_source() == AutofillProfile::Source::kAccount - ? AutofillProfile::Source::kLocalOrSyncable - : AutofillProfile::Source::kAccount; - ASSERT_TRUE(table_->GetAutofillProfiles(other_source, &profiles)); - EXPECT_EQ(profiles.size(), 1u); -} - -// Tests that `ProfileTokenQuality` observations are read and written. -TEST_P(AutofillTableProfileTest, ProfileTokenQuality) { - AutofillProfile profile = CreateAutofillProfile(); - test_api(profile.token_quality()) - .AddObservation(NAME_FIRST, - ProfileTokenQuality::ObservationType::kAccepted, - ProfileTokenQualityTestApi::FormSignatureHash(12)); - - // Add - table_->AddAutofillProfile(profile); - profile = *table_->GetAutofillProfile(profile.guid(), profile.source()); - EXPECT_THAT( - profile.token_quality().GetObservationTypesForFieldType(NAME_FIRST), - UnorderedElementsAre(ProfileTokenQuality::ObservationType::kAccepted)); - EXPECT_THAT( - test_api(profile.token_quality()).GetHashesForStoredType(NAME_FIRST), - UnorderedElementsAre(ProfileTokenQualityTestApi::FormSignatureHash(12))); - - // Update - test_api(profile.token_quality()) - .AddObservation(NAME_FIRST, - ProfileTokenQuality::ObservationType::kEditedFallback, - ProfileTokenQualityTestApi::FormSignatureHash(21)); - table_->UpdateAutofillProfile(profile); - profile = *table_->GetAutofillProfile(profile.guid(), profile.source()); - EXPECT_THAT( - profile.token_quality().GetObservationTypesForFieldType(NAME_FIRST), - UnorderedElementsAre( - ProfileTokenQuality::ObservationType::kAccepted, - ProfileTokenQuality::ObservationType::kEditedFallback)); - EXPECT_THAT( - test_api(profile.token_quality()).GetHashesForStoredType(NAME_FIRST), - UnorderedElementsAre(ProfileTokenQualityTestApi::FormSignatureHash(12), - ProfileTokenQualityTestApi::FormSignatureHash(21))); -} - TEST_F(AutofillTableTest, Iban) { // Add a valid IBAN. Iban iban; @@ -841,48 +595,6 @@ EXPECT_EQ(0, credit_card.Compare(*outputs[0])); } -TEST_P(AutofillTableProfileTest, UpdateAutofillProfile) { - // Add a profile to the db. - AutofillProfile profile = CreateAutofillProfile(); - profile.SetRawInfo(NAME_FIRST, u"John"); - profile.SetRawInfo(NAME_MIDDLE, u"Q."); - profile.SetRawInfo(NAME_LAST, u"Smith"); - profile.SetRawInfo(EMAIL_ADDRESS, u"js@example.com"); - profile.SetRawInfo(COMPANY_NAME, u"Google"); - profile.SetRawInfo(ADDRESS_HOME_LINE1, u"1234 Apple Way"); - profile.SetRawInfo(ADDRESS_HOME_LINE2, u"unit 5"); - profile.SetRawInfo(ADDRESS_HOME_CITY, u"Los Angeles"); - profile.SetRawInfo(ADDRESS_HOME_STATE, u"CA"); - profile.SetRawInfo(ADDRESS_HOME_ZIP, u"90025"); - profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"ES"); - profile.SetRawInfo(ADDRESS_HOME_OVERFLOW, u"Andar 1, Apto. 12"); - profile.SetRawInfo(ADDRESS_HOME_LANDMARK, u"Landmark"); - profile.SetRawInfo(ADDRESS_HOME_BETWEEN_STREETS, u"Marcos y Oliva"); - profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"18181234567"); - profile.SetRawInfoAsInt(BIRTHDATE_DAY, 14); - profile.SetRawInfoAsInt(BIRTHDATE_MONTH, 3); - profile.SetRawInfoAsInt(BIRTHDATE_4_DIGIT_YEAR, 1997); - profile.set_language_code("en"); - profile.FinalizeAfterImport(); - table_->AddAutofillProfile(profile); - - // Get the profile. - std::unique_ptr<AutofillProfile> db_profile = - table_->GetAutofillProfile(profile.guid(), profile.source()); - ASSERT_TRUE(db_profile); - EXPECT_EQ(profile, *db_profile); - - // Now, update the profile and save the update to the database. - // The modification date should change to reflect the update. - profile.SetRawInfo(EMAIL_ADDRESS, u"js@smith.xyz"); - table_->UpdateAutofillProfile(profile); - - // Get the profile. - db_profile = table_->GetAutofillProfile(profile.guid(), profile.source()); - ASSERT_TRUE(db_profile); - EXPECT_EQ(profile, *db_profile); -} - TEST_F(AutofillTableTest, UpdateCreditCard) { base::test::ScopedFeatureList features( features::kAutofillEnableCvcStorageAndFilling); @@ -1006,32 +718,8 @@ } TEST_F(AutofillTableTest, RemoveAutofillDataModifiedBetween) { - // Populate the autofill_profiles and credit_cards tables. + // Populate the credit_cards tables. ASSERT_TRUE(db_->GetSQLConnection()->Execute( - "INSERT INTO local_addresses (guid, date_modified) " - "VALUES('00000000-0000-0000-0000-000000000000', 11);" - "INSERT INTO local_addresses_type_tokens (guid, type, value) " - "VALUES('00000000-0000-0000-0000-000000000000', 3, 'first name0');" - "INSERT INTO local_addresses (guid, date_modified) " - "VALUES('00000000-0000-0000-0000-000000000001', 21);" - "INSERT INTO local_addresses_type_tokens (guid, type, value) " - "VALUES('00000000-0000-0000-0000-000000000001', 3, 'first name1');" - "INSERT INTO local_addresses (guid, date_modified) " - "VALUES('00000000-0000-0000-0000-000000000002', 31);" - "INSERT INTO local_addresses_type_tokens (guid, type, value) " - "VALUES('00000000-0000-0000-0000-000000000002', 3, 'first name2');" - "INSERT INTO local_addresses (guid, date_modified) " - "VALUES('00000000-0000-0000-0000-000000000003', 41);" - "INSERT INTO local_addresses_type_tokens (guid, type, value) " - "VALUES('00000000-0000-0000-0000-000000000003', 3, 'first name3');" - "INSERT INTO local_addresses (guid, date_modified) " - "VALUES('00000000-0000-0000-0000-000000000004', 51);" - "INSERT INTO local_addresses_type_tokens (guid, type, value) " - "VALUES('00000000-0000-0000-0000-000000000004', 3, 'first name4');" - "INSERT INTO local_addresses (guid, date_modified) " - "VALUES('00000000-0000-0000-0000-000000000005', 61);" - "INSERT INTO local_addresses_type_tokens (guid, type, value) " - "VALUES('00000000-0000-0000-0000-000000000005', 3, 'first name5');" "INSERT INTO credit_cards (guid, date_modified) " "VALUES('00000000-0000-0000-0000-000000000006', 17);" "INSERT INTO local_stored_cvc (guid, value_encrypted, " @@ -1064,45 +752,9 @@ "VALUES('00000000-0000-0000-0000-000000000011', '', 67);")); // Remove all entries modified in the bounded time range [17,41). - std::vector<std::unique_ptr<AutofillProfile>> profiles; std::vector<std::unique_ptr<CreditCard>> credit_cards; - table_->RemoveAutofillDataModifiedBetween( - Time::FromTimeT(17), Time::FromTimeT(41), &profiles, &credit_cards); - - // Two profiles should have been removed. - ASSERT_EQ(2UL, profiles.size()); - EXPECT_EQ("00000000-0000-0000-0000-000000000001", profiles[0]->guid()); - EXPECT_EQ("00000000-0000-0000-0000-000000000002", profiles[1]->guid()); - - // Make sure that only the expected profiles are still present. - sql::Statement s_autofill_profiles_bounded( - db_->GetSQLConnection()->GetUniqueStatement( - "SELECT date_modified FROM local_addresses ORDER BY guid")); - ASSERT_TRUE(s_autofill_profiles_bounded.is_valid()); - ASSERT_TRUE(s_autofill_profiles_bounded.Step()); - EXPECT_EQ(11, s_autofill_profiles_bounded.ColumnInt64(0)); - ASSERT_TRUE(s_autofill_profiles_bounded.Step()); - EXPECT_EQ(41, s_autofill_profiles_bounded.ColumnInt64(0)); - ASSERT_TRUE(s_autofill_profiles_bounded.Step()); - EXPECT_EQ(51, s_autofill_profiles_bounded.ColumnInt64(0)); - ASSERT_TRUE(s_autofill_profiles_bounded.Step()); - EXPECT_EQ(61, s_autofill_profiles_bounded.ColumnInt64(0)); - EXPECT_FALSE(s_autofill_profiles_bounded.Step()); - - // Make sure that only the expected profile names are still present. - sql::Statement s_autofill_profile_names_bounded( - db_->GetSQLConnection()->GetUniqueStatement( - "SELECT value FROM local_addresses_type_tokens ORDER BY guid")); - ASSERT_TRUE(s_autofill_profile_names_bounded.is_valid()); - ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); - EXPECT_EQ("first name0", s_autofill_profile_names_bounded.ColumnString(0)); - ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); - EXPECT_EQ("first name3", s_autofill_profile_names_bounded.ColumnString(0)); - ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); - EXPECT_EQ("first name4", s_autofill_profile_names_bounded.ColumnString(0)); - ASSERT_TRUE(s_autofill_profile_names_bounded.Step()); - EXPECT_EQ("first name5", s_autofill_profile_names_bounded.ColumnString(0)); - EXPECT_FALSE(s_autofill_profile_names_bounded.Step()); + table_->RemoveAutofillDataModifiedBetween(Time::FromTimeT(17), + Time::FromTimeT(41), &credit_cards); // Three cards should have been removed. ASSERT_EQ(3UL, credit_cards.size()); @@ -1137,32 +789,7 @@ // Remove all entries modified on or after time 51 (unbounded range). table_->RemoveAutofillDataModifiedBetween(Time::FromTimeT(51), Time(), - &profiles, &credit_cards); - ASSERT_EQ(2UL, profiles.size()); - EXPECT_EQ("00000000-0000-0000-0000-000000000004", profiles[0]->guid()); - EXPECT_EQ("00000000-0000-0000-0000-000000000005", profiles[1]->guid()); - - // Make sure that only the expected profiles are still present. - sql::Statement s_autofill_profiles_unbounded( - db_->GetSQLConnection()->GetUniqueStatement( - "SELECT date_modified FROM local_addresses ORDER BY guid")); - ASSERT_TRUE(s_autofill_profiles_unbounded.is_valid()); - ASSERT_TRUE(s_autofill_profiles_unbounded.Step()); - EXPECT_EQ(11, s_autofill_profiles_unbounded.ColumnInt64(0)); - ASSERT_TRUE(s_autofill_profiles_unbounded.Step()); - EXPECT_EQ(41, s_autofill_profiles_unbounded.ColumnInt64(0)); - EXPECT_FALSE(s_autofill_profiles_unbounded.Step()); - - // Make sure that only the expected profile names are still present. - sql::Statement s_autofill_profile_names_unbounded( - db_->GetSQLConnection()->GetUniqueStatement( - "SELECT value FROM local_addresses_type_tokens ORDER BY guid")); - ASSERT_TRUE(s_autofill_profile_names_unbounded.is_valid()); - ASSERT_TRUE(s_autofill_profile_names_unbounded.Step()); - EXPECT_EQ("first name0", s_autofill_profile_names_unbounded.ColumnString(0)); - ASSERT_TRUE(s_autofill_profile_names_unbounded.Step()); - EXPECT_EQ("first name3", s_autofill_profile_names_unbounded.ColumnString(0)); - EXPECT_FALSE(s_autofill_profile_names_unbounded.Step()); + &credit_cards); // Two cards should have been removed. ASSERT_EQ(2UL, credit_cards.size()); @@ -1187,27 +814,7 @@ EXPECT_FALSE(s_cvc_unbounded.Step()); // Remove all remaining entries. - table_->RemoveAutofillDataModifiedBetween(Time(), Time(), &profiles, - &credit_cards); - - // Two profiles should have been removed. - ASSERT_EQ(2UL, profiles.size()); - EXPECT_EQ("00000000-0000-0000-0000-000000000000", profiles[0]->guid()); - EXPECT_EQ("00000000-0000-0000-0000-000000000003", profiles[1]->guid()); - - // Make sure there are no profiles remaining. - sql::Statement s_autofill_profiles_empty( - db_->GetSQLConnection()->GetUniqueStatement( - "SELECT date_modified FROM local_addresses")); - ASSERT_TRUE(s_autofill_profiles_empty.is_valid()); - EXPECT_FALSE(s_autofill_profiles_empty.Step()); - - // Make sure there are no profile names remaining. - sql::Statement s_autofill_profile_names_empty( - db_->GetSQLConnection()->GetUniqueStatement( - "SELECT value FROM local_addresses_type_tokens")); - ASSERT_TRUE(s_autofill_profile_names_empty.is_valid()); - EXPECT_FALSE(s_autofill_profile_names_empty.Step()); + table_->RemoveAutofillDataModifiedBetween(Time(), Time(), &credit_cards); // One credit card should have been deleted. ASSERT_EQ(1UL, credit_cards.size()); @@ -1819,11 +1426,10 @@ table_->UnmaskServerCreditCard(masked_card, full_number); // Delete data in a range a year in the future. - std::vector<std::unique_ptr<AutofillProfile>> profiles; std::vector<std::unique_ptr<CreditCard>> credit_cards; ASSERT_TRUE(table_->RemoveAutofillDataModifiedBetween( unmasked_time + base::Days(365), unmasked_time + base::Days(530), - &profiles, &credit_cards)); + &credit_cards)); // This should not affect the unmasked card (should be unmasked). std::vector<std::unique_ptr<CreditCard>> outputs; @@ -1837,8 +1443,8 @@ // Fudge |now| to make sure it's strictly greater than the |now| that // the database uses. base::Time now = AutofillClock::Now() + base::Seconds(1); - ASSERT_TRUE(table_->RemoveAutofillDataModifiedBetween( - now - base::Days(1), now, &profiles, &credit_cards)); + ASSERT_TRUE(table_->RemoveAutofillDataModifiedBetween(now - base::Days(1), + now, &credit_cards)); // This should re-mask. ASSERT_TRUE(table_->GetServerCreditCards(outputs)); @@ -1858,7 +1464,7 @@ // Delete all data. ASSERT_TRUE(table_->RemoveAutofillDataModifiedBetween( - base::Time(), base::Time::Max(), &profiles, &credit_cards)); + base::Time(), base::Time::Max(), &credit_cards)); // Should be masked again. ASSERT_TRUE(table_->GetServerCreditCards(outputs));
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.cc index b21f9a1..26d8c8c 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.cc
@@ -77,7 +77,7 @@ change_processor()->GetWeakPtr())); } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletCredentialSyncBridge::MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { @@ -87,7 +87,7 @@ std::move(entity_data)); } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletCredentialSyncBridge::ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) {
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.h index e57f7333..4f77360a 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge.h
@@ -59,10 +59,10 @@ // ModelTypeSyncBridge std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge_unittest.cc index 9c45eb5..3ec0cde 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_credential_sync_bridge_unittest.cc
@@ -128,7 +128,7 @@ initial_updates.push_back(SpecificsToUpdateResponse(specifics)); } real_processor_->OnUpdateReceived(state, std::move(initial_updates), - /*gc_directive=*/absl::nullopt); + /*gc_directive=*/std::nullopt); } syncer::UpdateResponseData SpecificsToUpdateResponse( @@ -224,7 +224,7 @@ EXPECT_EQ(bridge()->MergeFullSyncData(bridge()->CreateMetadataChangeList(), std::move(entity_change_list)), - absl::nullopt); + std::nullopt); EXPECT_THAT(GetAllServerCvcDataFromTable(), testing::UnorderedElementsAre(server_cvc)); } @@ -261,7 +261,7 @@ EXPECT_EQ( bridge()->ApplyIncrementalSyncChanges( bridge()->CreateMetadataChangeList(), std::move(entity_change_list)), - absl::nullopt); + std::nullopt); EXPECT_THAT(GetAllServerCvcDataFromTable(), testing::UnorderedElementsAre(server_cvc1, server_cvc2)); } @@ -294,7 +294,7 @@ EXPECT_EQ( bridge()->ApplyIncrementalSyncChanges( bridge()->CreateMetadataChangeList(), std::move(entity_change_list)), - absl::nullopt); + std::nullopt); EXPECT_THAT(GetAllServerCvcDataFromTable(), testing::IsEmpty()); } @@ -330,7 +330,7 @@ EXPECT_EQ( bridge()->ApplyIncrementalSyncChanges( bridge()->CreateMetadataChangeList(), std::move(entity_change_list)), - absl::nullopt); + std::nullopt); EXPECT_THAT(GetAllServerCvcDataFromTable(), testing::UnorderedElementsAre(server_cvc2)); }
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc index ea7ac9c4..4b1089f 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -5,6 +5,7 @@ #include "components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h" #include <map> +#include <optional> #include <unordered_set> #include <utility> #include <vector> @@ -27,7 +28,6 @@ #include "components/sync/model/mutable_data_batch.h" #include "components/sync/model/sync_metadata_store_change_list.h" #include "components/sync/protocol/entity_data.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -338,7 +338,7 @@ change_processor()->GetWeakPtr())); } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletMetadataSyncBridge::MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { @@ -357,7 +357,7 @@ std::move(entity_data)); } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletMetadataSyncBridge::ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { @@ -377,7 +377,7 @@ void AutofillWalletMetadataSyncBridge::GetAllDataForDebugging( DataCallback callback) { // Get all data by not providing any |storage_keys| filter. - GetDataImpl(/*storage_keys=*/absl::nullopt, std::move(callback)); + GetDataImpl(/*storage_keys=*/std::nullopt, std::move(callback)); } std::string AutofillWalletMetadataSyncBridge::GetClientTag( @@ -523,7 +523,7 @@ } void AutofillWalletMetadataSyncBridge::GetDataImpl( - absl::optional<std::unordered_set<std::string>> storage_keys_set, + std::optional<std::unordered_set<std::string>> storage_keys_set, DataCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -567,7 +567,7 @@ } } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletMetadataSyncBridge::MergeRemoteChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { @@ -592,7 +592,7 @@ AutofillMetadata remote = CreateAutofillMetadataFromWalletMetadataSpecifics(specifics); auto it = cache_.find(change->storage_key()); - absl::optional<AutofillMetadata> local = absl::nullopt; + std::optional<AutofillMetadata> local = std::nullopt; if (it != cache_.end()) { local = it->second; } @@ -671,7 +671,7 @@ case AutofillDataModelChange<DataType, KeyType>::UPDATE: AutofillMetadata new_entry = change.data_model().GetMetadata(); auto it = cache_.find(storage_key); - absl::optional<AutofillMetadata> existing_entry = absl::nullopt; + std::optional<AutofillMetadata> existing_entry = std::nullopt; if (it != cache_.end()) { existing_entry = it->second; }
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h index b30945f..1d9fdd0 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
@@ -66,10 +66,10 @@ // ModelTypeSyncBridge implementation. std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override; @@ -105,7 +105,7 @@ // |callback|. If |storage_keys_set| is not set, it returns all data entries. // Otherwise, it returns only entries with storage key in |storage_keys_set|. void GetDataImpl( - absl::optional<std::unordered_set<std::string>> storage_keys_set, + std::optional<std::unordered_set<std::string>> storage_keys_set, DataCallback callback); // Uploads local data that is not part of |entity_data| sent from the server @@ -116,7 +116,7 @@ // Merges remote changes, specified in |entity_data|, with the local DB and, // potentially, writes changes to the local DB and/or commits updates of // entities from |entity_data| up to sync. - absl::optional<syncer::ModelError> MergeRemoteChanges( + std::optional<syncer::ModelError> MergeRemoteChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data);
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc index b77fbb69..eb511ac7 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
@@ -301,7 +301,7 @@ updates.push_back(SpecificsToUpdateResponse(specifics)); } real_processor_->OnUpdateReceived(state, std::move(updates), - /*gc_directive=*/absl::nullopt); + /*gc_directive=*/std::nullopt); } void ReceiveTombstones( @@ -320,7 +320,7 @@ SpecificsToUpdateResponse(specifics, /*is_deleted=*/true)); } real_processor_->OnUpdateReceived(state, std::move(updates), - /*gc_directive=*/absl::nullopt); + /*gc_directive=*/std::nullopt); } EntityData SpecificsToEntity(const WalletMetadataSpecifics& specifics,
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc index 2fd16bf1..f14ddbb7 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
@@ -86,23 +86,23 @@ change_processor()->GetWeakPtr())); } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletOfferSyncBridge::MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); MergeRemoteData(std::move(entity_data)); - return absl::nullopt; + return std::nullopt; } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletOfferSyncBridge::ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { // This bridge does not support incremental updates, so whenever this is // called, the change list should be empty. DCHECK(entity_data.empty()) << "Received an unsupported incremental update."; - return absl::nullopt; + return std::nullopt; } void AutofillWalletOfferSyncBridge::GetData(StorageKeyList storage_keys,
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h index d9f945c2..9c6de42 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h
@@ -48,10 +48,10 @@ // ModelTypeSyncBridge std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc index e85af2b..38de37c 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -175,7 +175,7 @@ change_processor()->GetWeakPtr())); } -absl::optional<syncer::ModelError> AutofillWalletSyncBridge::MergeFullSyncData( +std::optional<syncer::ModelError> AutofillWalletSyncBridge::MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { // We want to notify the metadata bridge about all changes so that the @@ -184,17 +184,17 @@ // TODO(crbug.com/853688): Update the AutofillTable API to know about write // errors and report them here. - return absl::nullopt; + return std::nullopt; } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletSyncBridge::ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { // This bridge does not support incremental updates, so whenever this is // called, the change list should be empty. DCHECK(entity_data.empty()) << "Received an unsupported incremental update."; - return absl::nullopt; + return std::nullopt; } void AutofillWalletSyncBridge::GetData(StorageKeyList storage_keys,
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h index 6e32e0ee..803d2b9 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -56,10 +56,10 @@ // ModelTypeSyncBridge implementation. std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.cc index e0619810..6c387a2 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.cc
@@ -73,7 +73,7 @@ change_processor()->GetWeakPtr())); } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletUsageDataSyncBridge::MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { @@ -82,7 +82,7 @@ std::move(entity_data)); } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> AutofillWalletUsageDataSyncBridge::ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) {
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.h index 67b4bda..dcf0e89 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge.h
@@ -51,10 +51,10 @@ // ModelTypeSyncBridge std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge_unittest.cc index 65fe1f38..b0ba599 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_usage_data_sync_bridge_unittest.cc
@@ -202,7 +202,7 @@ // `MergeFullSyncData()` returns an error if it fails. EXPECT_EQ(bridge()->MergeFullSyncData(bridge()->CreateMetadataChangeList(), std::move(entity_change_list_merge)), - absl::nullopt); + std::nullopt); // Expect `MergeFullSyncData()` was successful. EXPECT_THAT(GetVirtualCardUsageDataFromTable(), testing::UnorderedElementsAre(virtual_card_usage_data1)); @@ -269,7 +269,7 @@ *old_data.usage_data_id(), VirtualCardUsageDataToEntity(old_data))); EXPECT_EQ(bridge()->MergeFullSyncData(bridge()->CreateMetadataChangeList(), std::move(entity_change_list)), - absl::nullopt); + std::nullopt); EXPECT_CALL(backend(), CommitChanges()); EXPECT_CALL(backend(),
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc index 3240fa5e..13606e3d 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -22,6 +22,7 @@ #include "components/autofill/core/browser/data_model/iban.h" #include "components/autofill/core/browser/geo/autofill_country.h" #include "components/autofill/core/browser/payments/payments_customer_data.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autocomplete_entry.h" #include "components/autofill/core/browser/webdata/autocomplete_table.h" #include "components/autofill/core/browser/webdata/autofill_change.h" @@ -321,7 +322,7 @@ const AutofillProfile& profile, WebDatabase* db) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); - AutofillTable* table = AutofillTable::FromWebDatabase(db); + AddressAutofillTable* table = AddressAutofillTable::FromWebDatabase(db); if (!table->AddAutofillProfile(profile)) { ReportResult(Result::kAddAutofillProfile_Failure); return WebDatabase::COMMIT_NOT_NEEDED; @@ -351,7 +352,7 @@ const AutofillProfile& profile, WebDatabase* db) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); - AutofillTable* table = AutofillTable::FromWebDatabase(db); + AddressAutofillTable* table = AddressAutofillTable::FromWebDatabase(db); // Only perform the update if the profile exists. It is currently // valid to try to update a missing profile. We simply drop the write and // the caller will detect this on the next refresh. @@ -392,14 +393,14 @@ WebDatabase* db) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); std::unique_ptr<AutofillProfile> profile = - AutofillTable::FromWebDatabase(db)->GetAutofillProfile(guid, - profile_source); + AddressAutofillTable::FromWebDatabase(db)->GetAutofillProfile( + guid, profile_source); if (!profile) { ReportResult(Result::kRemoveAutofillProfile_ReadFailure); return WebDatabase::COMMIT_NOT_NEEDED; } - if (!AutofillTable::FromWebDatabase(db)->RemoveAutofillProfile( + if (!AddressAutofillTable::FromWebDatabase(db)->RemoveAutofillProfile( guid, profile_source)) { ReportResult(Result::kRemoveAutofillProfile_WriteFailure); return WebDatabase::COMMIT_NOT_NEEDED; @@ -426,8 +427,8 @@ WebDatabase* db) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); std::vector<std::unique_ptr<AutofillProfile>> profiles; - AutofillTable::FromWebDatabase(db)->GetAutofillProfiles(profile_source, - &profiles); + AddressAutofillTable::FromWebDatabase(db)->GetAutofillProfiles(profile_source, + &profiles); return std::unique_ptr<WDTypedResult>( new WDResult<std::vector<std::unique_ptr<AutofillProfile>>>( AUTOFILL_PROFILES_RESULT, std::move(profiles))); @@ -855,12 +856,13 @@ WebDatabase::State AutofillWebDataBackendImpl::ClearAllLocalData( WebDatabase* db) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); - if (AutofillTable::FromWebDatabase(db)->ClearAllLocalData()) { - ReportResult(Result::kClearAllLocalData_Success); - return WebDatabase::COMMIT_NEEDED; - } - ReportResult(Result::kClearAllLocalData_Failure); - return WebDatabase::COMMIT_NOT_NEEDED; + bool a_succeeded = + AddressAutofillTable::FromWebDatabase(db)->ClearAllLocalData(); + bool b_succeeded = AutofillTable::FromWebDatabase(db)->ClearAllLocalData(); + ReportResult(a_succeeded && b_succeeded ? Result::kClearAllLocalData_Success + : Result::kClearAllLocalData_Failure); + return a_succeeded || b_succeeded ? WebDatabase::COMMIT_NEEDED + : WebDatabase::COMMIT_NOT_NEEDED; } WebDatabase::State @@ -870,28 +872,39 @@ WebDatabase* db) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); std::vector<std::unique_ptr<AutofillProfile>> profiles; - std::vector<std::unique_ptr<CreditCard>> credit_cards; - if (AutofillTable::FromWebDatabase(db)->RemoveAutofillDataModifiedBetween( - delete_begin, delete_end, &profiles, &credit_cards)) { + bool commit_needed = false; + bool failures_observed = false; + if (AddressAutofillTable::FromWebDatabase(db) + ->RemoveAutofillDataModifiedBetween(delete_begin, delete_end, + &profiles)) { for (const std::unique_ptr<AutofillProfile>& profile : profiles) { for (auto& db_observer : db_observer_list_) { db_observer.AutofillProfileChanged(AutofillProfileChange( AutofillProfileChange::REMOVE, profile->guid(), *profile)); } } + commit_needed = true; + } else { + failures_observed = true; + } + std::vector<std::unique_ptr<CreditCard>> credit_cards; + if (AutofillTable::FromWebDatabase(db)->RemoveAutofillDataModifiedBetween( + delete_begin, delete_end, &credit_cards)) { for (const std::unique_ptr<CreditCard>& credit_card : credit_cards) { for (auto& db_observer : db_observer_list_) { db_observer.CreditCardChanged(CreditCardChange( CreditCardChange::REMOVE, credit_card->guid(), *credit_card)); } } - // Note: It is the caller's responsibility to post notifications for any - // changes, e.g. by calling the Refresh() method of PersonalDataManager. - ReportResult(Result::kRemoveAutofillDataModifiedBetween_Success); - return WebDatabase::COMMIT_NEEDED; + commit_needed = true; + } else { + failures_observed = true; } - ReportResult(Result::kRemoveAutofillDataModifiedBetween_Failure); - return WebDatabase::COMMIT_NOT_NEEDED; + ReportResult(failures_observed + ? Result::kRemoveAutofillDataModifiedBetween_Success + : Result::kRemoveAutofillDataModifiedBetween_Failure); + return commit_needed ? WebDatabase::COMMIT_NEEDED + : WebDatabase::COMMIT_NOT_NEEDED; } WebDatabase::State AutofillWebDataBackendImpl::RemoveOriginURLsModifiedBetween(
diff --git a/components/autofill/core/browser/webdata/contact_info_sync_bridge.cc b/components/autofill/core/browser/webdata/contact_info_sync_bridge.cc index 6fb98fc..e6938cb 100644 --- a/components/autofill/core/browser/webdata/contact_info_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/contact_info_sync_bridge.cc
@@ -66,12 +66,12 @@ ContactInfoSyncBridge::CreateMetadataChangeList() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return std::make_unique<syncer::SyncMetadataStoreChangeList>( - GetAutofillTable(), syncer::CONTACT_INFO, + GetSyncMetadataStore(), syncer::CONTACT_INFO, base::BindRepeating(&syncer::ModelTypeChangeProcessor::ReportError, change_processor()->GetWeakPtr())); } -absl::optional<syncer::ModelError> ContactInfoSyncBridge::MergeFullSyncData( +std::optional<syncer::ModelError> ContactInfoSyncBridge::MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { // Since the local storage is cleared when the data type is disabled in @@ -81,10 +81,10 @@ std::move(entity_data))) { return error; } - return absl::nullopt; + return std::nullopt; } -absl::optional<syncer::ModelError> +std::optional<syncer::ModelError> ContactInfoSyncBridge::ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) { @@ -134,7 +134,7 @@ if (!entity_changes.empty()) web_data_backend_->NotifyOnAutofillChangedBySync(syncer::CONTACT_INFO); - return absl::nullopt; + return std::nullopt; } void ContactInfoSyncBridge::GetData(StorageKeyList storage_keys, @@ -273,7 +273,12 @@ return false; } -AutofillTable* ContactInfoSyncBridge::GetAutofillTable() { +AddressAutofillTable* ContactInfoSyncBridge::GetAutofillTable() { + return AddressAutofillTable::FromWebDatabase( + web_data_backend_->GetDatabase()); +} + +AutofillTable* ContactInfoSyncBridge::GetSyncMetadataStore() { return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); } @@ -303,8 +308,8 @@ void ContactInfoSyncBridge::LoadMetadata() { auto batch = std::make_unique<syncer::MetadataBatch>(); - if (!GetAutofillTable()->GetAllSyncMetadata(syncer::CONTACT_INFO, - batch.get())) { + if (!GetSyncMetadataStore()->GetAllSyncMetadata(syncer::CONTACT_INFO, + batch.get())) { change_processor()->ReportError( {FROM_HERE, "Failed reading CONTACT_INFO metadata from WebDatabase."}); return; @@ -315,7 +320,8 @@ // contains supported fields, this means that the browser was updated and // we should force the initial sync flow to propagate the cached data into // the local model. - GetAutofillTable()->DeleteAllSyncMetadata(syncer::ModelType::CONTACT_INFO); + GetSyncMetadataStore()->DeleteAllSyncMetadata( + syncer::ModelType::CONTACT_INFO); batch = std::make_unique<syncer::MetadataBatch>(); }
diff --git a/components/autofill/core/browser/webdata/contact_info_sync_bridge.h b/components/autofill/core/browser/webdata/contact_info_sync_bridge.h index 94d259fb3..174338b 100644 --- a/components/autofill/core/browser/webdata/contact_info_sync_bridge.h +++ b/components/autofill/core/browser/webdata/contact_info_sync_bridge.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_CONTACT_INFO_SYNC_BRIDGE_H_ #include <memory> +#include <optional> #include <string> #include "base/functional/callback.h" @@ -14,6 +15,7 @@ #include "base/sequence_checker.h" #include "base/supports_user_data.h" #include "components/autofill/core/browser/contact_info_sync_util.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h" @@ -25,7 +27,6 @@ #include "components/sync/model/model_type_sync_bridge.h" #include "components/sync/model/mutable_data_batch.h" #include "components/sync/protocol/entity_data.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -53,10 +54,10 @@ // syncer::ModelTypeSyncBridge implementation. std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override; - absl::optional<syncer::ModelError> MergeFullSyncData( + std::optional<syncer::ModelError> MergeFullSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) override; - absl::optional<syncer::ModelError> ApplyIncrementalSyncChanges( + std::optional<syncer::ModelError> ApplyIncrementalSyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_changes) override; void GetData(StorageKeyList storage_keys, DataCallback callback) override; @@ -81,7 +82,11 @@ const syncer::EntityMetadataMap& metadata_map) const; // Returns the `AutofillTable` associated with the `web_data_backend_`. - AutofillTable* GetAutofillTable(); + AddressAutofillTable* GetAutofillTable(); + + // AutofillTable acts as the metadata storage for all components/autofill- + // related sync code. + AutofillTable* GetSyncMetadataStore(); // Queries all `Source::kAccount` profiles from `GetAutofillTable()` and // restricts the result to profiles where `filter(guid)` is true.
diff --git a/components/autofill/core/browser/webdata/contact_info_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/contact_info_sync_bridge_unittest.cc index 16f194c..c3bc7d08 100644 --- a/components/autofill/core/browser/webdata/contact_info_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/contact_info_sync_bridge_unittest.cc
@@ -15,6 +15,7 @@ #include "components/autofill/core/browser/contact_info_sync_util.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/test_autofill_clock.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h" #include "components/sync/base/features.h" @@ -77,6 +78,7 @@ void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); db_.AddTable(&table_); + db_.AddTable(&sync_metadata_table_); db_.Init(temp_dir_.GetPath().AppendASCII("SyncTestWebDatabase")); ON_CALL(backend_, GetDatabase()).WillByDefault(testing::Return(&db_)); @@ -144,7 +146,8 @@ base::ScopedTempDir temp_dir_; base::test::SingleThreadTaskEnvironment task_environment_; testing::NiceMock<MockAutofillWebDataBackend> backend_; - AutofillTable table_; + AddressAutofillTable table_; + AutofillTable sync_metadata_table_; WebDatabase db_; testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_; std::unique_ptr<ContactInfoSyncBridge> bridge_;
diff --git a/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/components/autofill/core/browser/webdata/web_data_service_unittest.cc index 198a06638..8bf8a2d 100644 --- a/components/autofill/core/browser/webdata/web_data_service_unittest.cc +++ b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -24,6 +24,7 @@ #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/geo/autofill_country.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autocomplete_entry.h" #include "components/autofill/core/browser/webdata/autocomplete_table.h" #include "components/autofill/core/browser/webdata/autofill_change.h" @@ -118,6 +119,7 @@ wdbs_ = new WebDatabaseService( path, base::SequencedTaskRunner::GetCurrentDefault(), db_task_runner_); + wdbs_->AddTable(std::make_unique<AddressAutofillTable>()); wdbs_->AddTable(std::make_unique<AutocompleteTable>()); wdbs_->AddTable(std::make_unique<AutofillTable>()); wdbs_->LoadDatabase();
diff --git a/components/autofill/core/common/autocomplete_parsing_util.cc b/components/autofill/core/common/autocomplete_parsing_util.cc index 77de0eb6..45cbd943 100644 --- a/components/autofill/core/common/autocomplete_parsing_util.cc +++ b/components/autofill/core/common/autocomplete_parsing_util.cc
@@ -104,17 +104,17 @@ // Chrome Autofill supports a subset of the field types listed at // http://is.gd/whatwg_autocomplete. Returns the corresponding HtmlFieldType, if // `value` matches any of them. -absl::optional<HtmlFieldType> ParseStandardizedAutocompleteAttribute( +std::optional<HtmlFieldType> ParseStandardizedAutocompleteAttribute( std::string_view value) { auto* it = kStandardizedAttributes.find(value); return it != kStandardizedAttributes.end() - ? absl::optional<HtmlFieldType>(it->second) - : absl::nullopt; + ? std::optional<HtmlFieldType>(it->second) + : std::nullopt; } // Maps `value`s that Autofill has proposed for the HTML autocomplete standard, // but which are not standardized, to their HtmlFieldType. -absl::optional<HtmlFieldType> ParseProposedAutocompleteAttribute( +std::optional<HtmlFieldType> ParseProposedAutocompleteAttribute( std::string_view value) { static constexpr auto proposed_attributes = base::MakeFixedFlatMap<std::string_view, HtmlFieldType>({ @@ -126,13 +126,13 @@ auto* it = proposed_attributes.find(value); return it != proposed_attributes.end() - ? absl::optional<HtmlFieldType>(it->second) - : absl::nullopt; + ? std::optional<HtmlFieldType>(it->second) + : std::nullopt; } // Maps non-standardized `value`s for the HTML autocomplete attribute to an // HtmlFieldType. This is primarily a list of "reasonable guesses". -absl::optional<HtmlFieldType> ParseNonStandarizedAutocompleteAttribute( +std::optional<HtmlFieldType> ParseNonStandarizedAutocompleteAttribute( std::string_view value) { static constexpr auto non_standardized_attributes = base::MakeFixedFlatMap<std::string_view, HtmlFieldType>({ @@ -152,8 +152,8 @@ auto* it = non_standardized_attributes.find(value); return it != non_standardized_attributes.end() - ? absl::optional<HtmlFieldType>(it->second) - : absl::nullopt; + ? std::optional<HtmlFieldType>(it->second) + : std::nullopt; } // If the autocomplete `value` doesn't match any of Autofill's supported values, @@ -191,7 +191,7 @@ base::ReplaceFirstSubstringAfterOffset(&value, 0, "phone", "tel"); } - absl::optional<HtmlFieldType> type = + std::optional<HtmlFieldType> type = ParseStandardizedAutocompleteAttribute(value); if (!type.has_value()) { type = ParseProposedAutocompleteAttribute(value); @@ -214,7 +214,7 @@ : HtmlFieldType::kUnrecognized; } -absl::optional<AutocompleteParsingResult> ParseAutocompleteAttribute( +std::optional<AutocompleteParsingResult> ParseAutocompleteAttribute( std::string_view autocomplete_attribute) { std::vector<std::string> tokens = LowercaseAndTokenizeAttributeString(autocomplete_attribute); @@ -224,7 +224,7 @@ // latter type of attribute value. if (tokens.empty() || (tokens.size() == 1 && ShouldIgnoreAutocompleteAttribute(tokens[0]))) { - return absl::nullopt; + return std::nullopt; } AutocompleteParsingResult result; @@ -249,7 +249,7 @@ // Note that an invalid token invalidates the entire attribute value, even // if the other tokens are valid. if (!ContactTypeHintMatchesFieldType(tokens.back(), result.field_type)) - return absl::nullopt; + return std::nullopt; // Chrome Autofill ignores these type hints. tokens.pop_back(); } @@ -276,7 +276,7 @@ // (5) No other tokens are allowed. If there are any remaining, abort. if (!tokens.empty()) - return absl::nullopt; + return std::nullopt; return result; }
diff --git a/components/autofill/core/common/autocomplete_parsing_util.h b/components/autofill/core/common/autocomplete_parsing_util.h index e229cd9..3b86fc1d 100644 --- a/components/autofill/core/common/autocomplete_parsing_util.h +++ b/components/autofill/core/common/autocomplete_parsing_util.h
@@ -5,11 +5,11 @@ #ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOCOMPLETE_PARSING_UTIL_H_ #define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOCOMPLETE_PARSING_UTIL_H_ +#include <optional> #include <string> #include <string_view> #include "components/autofill/core/common/html_field_types.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -18,7 +18,7 @@ // and parses the following tokens: // [section-*] [shipping|billing] [type_hint] field_type [webauthn] // The parsing extracts these components from `field.autocomplete_attribute` or -// returns absl::nullopt, if the parsing fails. The latter happens if: +// returns std::nullopt, if the parsing fails. The latter happens if: // - The autocomplete value is empty or contains more than 5 tokens. // - The type_hint doesn't match the field_type. // - If ShouldIgnoreAutocompleteAttribute(autocomplete) is true. @@ -38,7 +38,7 @@ bool webauthn = false; }; -absl::optional<AutocompleteParsingResult> ParseAutocompleteAttribute( +std::optional<AutocompleteParsingResult> ParseAutocompleteAttribute( std::string_view autocomplete_attribute); // Checks if `autocomplete_attribute` could not be recognized but was
diff --git a/components/autofill/core/common/autocomplete_parsing_util_unittest.cc b/components/autofill/core/common/autocomplete_parsing_util_unittest.cc index 11aac50..89923a2 100644 --- a/components/autofill/core/common/autocomplete_parsing_util_unittest.cc +++ b/components/autofill/core/common/autocomplete_parsing_util_unittest.cc
@@ -4,12 +4,12 @@ #include "components/autofill/core/common/autocomplete_parsing_util.h" +#include <optional> #include <string> #include "base/strings/string_piece.h" #include "components/autofill/core/common/form_field_data.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -17,13 +17,13 @@ // maxlength=`max_length` results in `expected_result`. struct AutocompleteAttributeTestcase { std::string_view autocomplete; - absl::optional<AutocompleteParsingResult> expected_result; + std::optional<AutocompleteParsingResult> expected_result; }; class AutocompleteAttributeProcessingUtilTest : public testing::TestWithParam<AutocompleteAttributeTestcase> {}; -// In general, `ParseAutocompleteAttribute()` returns absl::nullopt if one of +// In general, `ParseAutocompleteAttribute()` returns std::nullopt if one of // the tokens cannot be parsed. The exception is the field type, which defaults // to HtmlFieldType::kUnrecognized. const AutocompleteAttributeTestcase kAutocompleteTestcases[]{ @@ -31,15 +31,15 @@ {"name", {{"", HtmlFieldMode::kNone, HtmlFieldType::kName}}}, {"autofill", {{"", HtmlFieldMode::kNone, HtmlFieldType::kUnrecognized}}}, // autocomplete=off is ignored completely. - {"off", absl::nullopt}, + {"off", std::nullopt}, // Type hints: // They are parsed and validated, but otherwise unused. Type hints are only // valid before tel* and email. {"home email", {{"", HtmlFieldMode::kNone, HtmlFieldType::kEmail}}}, {"work email", {{"", HtmlFieldMode::kNone, HtmlFieldType::kEmail}}}, - {"work cc-number", absl::nullopt}, - {"unrecognized_type_hint email", absl::nullopt}, + {"work cc-number", std::nullopt}, + {"unrecognized_type_hint email", std::nullopt}, // Billing and shipping modes: {"billing country", @@ -50,8 +50,8 @@ {{"", HtmlFieldMode::kBilling, HtmlFieldType::kUnrecognized}}}, {"shipping work tel-local", {{"", HtmlFieldMode::kShipping, HtmlFieldType::kTelLocal}}}, - {"unrecognized_mode country", absl::nullopt}, - {"unrecognized_mode unrecognized", absl::nullopt}, + {"unrecognized_mode country", std::nullopt}, + {"unrecognized_mode unrecognized", std::nullopt}, // Sections: {"section-one tel", {{"one", HtmlFieldMode::kNone, HtmlFieldType::kTel}}}, @@ -60,9 +60,9 @@ {"section-one shipping home tel", {{"one", HtmlFieldMode::kShipping, HtmlFieldType::kTel}}}, {"section- tel", {{"", HtmlFieldMode::kNone, HtmlFieldType::kTel}}}, - {"section tel", absl::nullopt}, - {"no_section tel", absl::nullopt}, - {"no_section work tel", absl::nullopt}, + {"section tel", std::nullopt}, + {"no_section tel", std::nullopt}, + {"no_section work tel", std::nullopt}, {"section-random", {{"", HtmlFieldMode::kNone, HtmlFieldType::kUnrecognized}}}, @@ -77,7 +77,7 @@ /*webauthn=*/true}}}, // Too many tokens. - {"hello section-one shipping home tel webauthn", absl::nullopt}}; + {"hello section-one shipping home tel webauthn", std::nullopt}}; INSTANTIATE_TEST_SUITE_P(, AutocompleteAttributeProcessingUtilTest,
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index bc4fc08..3b24146 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -167,7 +167,6 @@ const base::FeatureParam<int> kAutofillRankingFormulaCreditCardsUsageHalfLife{ &kAutofillEnableRankingFormulaCreditCards, "autofill_ranking_formula_credit_cards_usage_half_life", 20}; - // The boost factor applied to ranking virtual cards. const base::FeatureParam<int> kAutofillRankingFormulaVirtualCardBoost{ &kAutofillEnableRankingFormulaCreditCards, @@ -177,6 +176,12 @@ &kAutofillEnableRankingFormulaCreditCards, "autofill_ranking_formula_virtual_card_boost_half_life", 15}; +// Relaxes the requirements for offering credit card import. +// TODO(crbug.com/1381477): Clean up when launched. +BASE_FEATURE(kAutofillRelaxCreditCardImport, + "AutofillRelaxCreditCardImport", + base::FEATURE_DISABLED_BY_DEFAULT); + // When enabled, autofill will fill <selectlist> elements. // TODO(crbug.com/1427153) Remove once autofilling <selectlist> is launched. BASE_FEATURE(kAutofillEnableSelectList, @@ -636,12 +641,6 @@ "AutofillTrackProfileTokenQuality", base::FEATURE_DISABLED_BY_DEFAULT); -// Controls whether suggestions' labels use the improved label disambiguation -// format. -BASE_FEATURE(kAutofillUseImprovedLabelDisambiguation, - "AutofillUseImprovedLabelDisambiguation", - base::FEATURE_DISABLED_BY_DEFAULT); - // Controls whether to use the combined heuristic and the autocomplete section // implementation for section splitting or not. See https://crbug.com/1076175. BASE_FEATURE(kAutofillUseNewSectioningMethod, @@ -740,6 +739,16 @@ "AutofillAndroidDisableSuggestionsOnJSFocus", base::FEATURE_DISABLED_BY_DEFAULT); +// When enabled, FormField::MatchesRegexWithCache tries to avoid re-computing +// whether a regex matches an input string by caching the result. The result +// size is controlled by kAutofillEnableCacheForRegexMatchingCacheSizeParam. +BASE_FEATURE(kAutofillEnableCacheForRegexMatching, + "AutofillEnableCacheForRegexMatching", + base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam<int> + kAutofillEnableCacheForRegexMatchingCacheSizeParam{ + &kAutofillEnableCacheForRegexMatching, "cache_size", 300}; + #if BUILDFLAG(IS_ANDROID) // Controls the whether the Chrome may provide a virtual view structure for // Android Autofill. @@ -750,13 +759,6 @@ #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) -BASE_FEATURE(kAutofillUseMobileLabelDisambiguation, - "AutofillUseMobileLabelDisambiguation", - base::FEATURE_DISABLED_BY_DEFAULT); -const char kAutofillUseMobileLabelDisambiguationParameterName[] = "variant"; -const char kAutofillUseMobileLabelDisambiguationParameterShowAll[] = "show-all"; -const char kAutofillUseMobileLabelDisambiguationParameterShowOne[] = "show-one"; - // When enabled, the keyboard accessory is shown for autocomplete=unrecognized // fields. Selecting a keyboard accessory suggestion will fill the triggering // field (independently of the autocomplete attribute) and all
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 01d152e..ea64a6cb 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -98,6 +98,8 @@ extern const base::FeatureParam<int> kAutofillRankingFormulaVirtualCardBoostHalfLife; COMPONENT_EXPORT(AUTOFILL) +BASE_DECLARE_FEATURE(kAutofillRelaxCreditCardImport); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableEmailHeuristicOnlyAddressForms); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillEnableSupportForApartmentNumbers); @@ -210,8 +212,6 @@ COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillTrackProfileTokenQuality); COMPONENT_EXPORT(AUTOFILL) -BASE_DECLARE_FEATURE(kAutofillUseImprovedLabelDisambiguation); -COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUseNewSectioningMethod); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillUseParameterizedSectioning); @@ -250,6 +250,11 @@ BASE_DECLARE_FEATURE(kAutofillVirtualCardsOnTouchToFillAndroid); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillAndroidDisableSuggestionsOnJSFocus); +COMPONENT_EXPORT(AUTOFILL) +BASE_DECLARE_FEATURE(kAutofillEnableCacheForRegexMatching); +COMPONENT_EXPORT(AUTOFILL) +extern const base::FeatureParam<int> + kAutofillEnableCacheForRegexMatchingCacheSizeParam; #if BUILDFLAG(IS_ANDROID) COMPONENT_EXPORT(AUTOFILL) @@ -258,14 +263,6 @@ #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) COMPONENT_EXPORT(AUTOFILL) -BASE_DECLARE_FEATURE(kAutofillUseMobileLabelDisambiguation); -COMPONENT_EXPORT(AUTOFILL) -extern const char kAutofillUseMobileLabelDisambiguationParameterName[]; -COMPONENT_EXPORT(AUTOFILL) -extern const char kAutofillUseMobileLabelDisambiguationParameterShowOne[]; -COMPONENT_EXPORT(AUTOFILL) -extern const char kAutofillUseMobileLabelDisambiguationParameterShowAll[]; -COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE( kAutofillSuggestionsForAutocompleteUnrecognizedFieldsOnMobile); #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
diff --git a/components/autofill/core/common/autofill_prefs_unittest.cc b/components/autofill/core/common/autofill_prefs_unittest.cc index 3fbc376..4b7835d 100644 --- a/components/autofill/core/common/autofill_prefs_unittest.cc +++ b/components/autofill/core/common/autofill_prefs_unittest.cc
@@ -110,7 +110,7 @@ // Make sure that the dictionary keys don't contain the account id. const auto& dictionary = pref_service()->GetDict(prefs::kAutofillSyncTransportOptIn); - EXPECT_EQ(absl::nullopt, dictionary.FindInt(account1.ToString())); + EXPECT_EQ(std::nullopt, dictionary.FindInt(account1.ToString())); } // Tests that clearing the AutofillSyncTransportOptIn works as expected.
diff --git a/components/autofill/core/common/field_data_manager.cc b/components/autofill/core/common/field_data_manager.cc index 587a6671..e2ff05a 100644 --- a/components/autofill/core/common/field_data_manager.cc +++ b/components/autofill/core/common/field_data_manager.cc
@@ -70,7 +70,7 @@ if (HasFieldData(id)) { field_value_and_properties_map_[id].second |= mask; } else { - field_value_and_properties_map_[id] = {absl::nullopt, mask}; + field_value_and_properties_map_[id] = {std::nullopt, mask}; } }
diff --git a/components/autofill/core/common/field_data_manager.h b/components/autofill/core/common/field_data_manager.h index 339b4529..6410ccf 100644 --- a/components/autofill/core/common/field_data_manager.h +++ b/components/autofill/core/common/field_data_manager.h
@@ -6,11 +6,11 @@ #define COMPONENTS_AUTOFILL_CORE_COMMON_FIELD_DATA_MANAGER_H_ #include <map> +#include <optional> #include <string> #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/unique_ids.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace autofill { @@ -20,7 +20,7 @@ public: using FieldDataMap = std::map<FieldRendererId, - std::pair<absl::optional<std::u16string>, FieldPropertiesMask>>; + std::pair<std::optional<std::u16string>, FieldPropertiesMask>>; FieldDataManager();
diff --git a/components/autofill/core/common/form_field_data.h b/components/autofill/core/common/form_field_data.h index f85030b6..9922442 100644 --- a/components/autofill/core/common/form_field_data.h +++ b/components/autofill/core/common/form_field_data.h
@@ -287,7 +287,7 @@ FormControlType form_control_type = FormControlType::kInputText; std::string autocomplete_attribute; - absl::optional<AutocompleteParsingResult> parsed_autocomplete; + std::optional<AutocompleteParsingResult> parsed_autocomplete; std::u16string placeholder; std::u16string css_classes; std::u16string aria_label;
diff --git a/components/autofill/core/common/logging/log_buffer.cc b/components/autofill/core/common/logging/log_buffer.cc index f6fab5e..43cb93cf6 100644 --- a/components/autofill/core/common/logging/log_buffer.cc +++ b/components/autofill/core/common/logging/log_buffer.cc
@@ -91,7 +91,7 @@ LogBuffer& LogBuffer::operator=(LogBuffer&& other) = default; LogBuffer::~LogBuffer() = default; -absl::optional<base::Value::Dict> LogBuffer::RetrieveResult() { +std::optional<base::Value::Dict> LogBuffer::RetrieveResult() { // The buffer should always start with a fragment. DCHECK(buffer_.size() >= 1); @@ -101,12 +101,12 @@ auto* children = buffer_[0].FindList("children"); if (!children || children->empty()) - return absl::nullopt; + return std::nullopt; // If the fragment has a single child, remove it from |children| and return // that directly. if (children->size() == 1) { - return absl::optional<base::Value::Dict>( + return std::optional<base::Value::Dict>( std::move((*children).back().GetDict())); } @@ -189,7 +189,7 @@ if (!buf.active()) return buf; - absl::optional<base::Value::Dict> node_to_add = buffer.RetrieveResult(); + std::optional<base::Value::Dict> node_to_add = buffer.RetrieveResult(); if (!node_to_add) return buf;
diff --git a/components/autofill/core/common/logging/log_buffer.h b/components/autofill/core/common/logging/log_buffer.h index daf96558..7ae6a63 100644 --- a/components/autofill/core/common/logging/log_buffer.h +++ b/components/autofill/core/common/logging/log_buffer.h
@@ -112,7 +112,7 @@ LogBuffer& operator=(const LogBuffer& other) = delete; // Returns the contents of the buffer if any and empties it. - absl::optional<base::Value::Dict> RetrieveResult(); + std::optional<base::Value::Dict> RetrieveResult(); // Returns whether an active WebUI is listening. If false, the buffer may // not do any logging.
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h index a8298b3e..49e7030 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
@@ -223,7 +223,7 @@ return r.autocomplete_attribute; } - static const absl::optional<autofill::AutocompleteParsingResult> + static const std::optional<autofill::AutocompleteParsingResult> parsed_autocomplete(const autofill::FormFieldData& r) { return r.parsed_autocomplete; }
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc index cd670b6..503d058 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
@@ -341,7 +341,7 @@ input.id_attribute = u"id"; input.name_attribute = u"name"; input.autocomplete_attribute = "on"; - input.parsed_autocomplete = absl::nullopt; + input.parsed_autocomplete = std::nullopt; input.placeholder = u"placeholder"; input.css_classes = u"class1"; input.aria_label = u"aria label";
diff --git a/components/autofill/ios/browser/autofill_driver_ios.h b/components/autofill/ios/browser/autofill_driver_ios.h index e718f8d..04cea865 100644 --- a/components/autofill/ios/browser/autofill_driver_ios.h +++ b/components/autofill/ios/browser/autofill_driver_ios.h
@@ -45,7 +45,7 @@ // AutofillDriver: LocalFrameToken GetFrameToken() const override; - absl::optional<LocalFrameToken> Resolve(FrameToken query) override; + std::optional<LocalFrameToken> Resolve(FrameToken query) override; AutofillDriverIOS* GetParent() override; BrowserAutofillManager& GetAutofillManager() override; bool IsInActiveFrame() const override;
diff --git a/components/autofill/ios/form_util/form_handlers_java_script_feature.h b/components/autofill/ios/form_util/form_handlers_java_script_feature.h index 26bfbdae..962812b 100644 --- a/components/autofill/ios/form_util/form_handlers_java_script_feature.h +++ b/components/autofill/ios/form_util/form_handlers_java_script_feature.h
@@ -35,7 +35,7 @@ friend class base::NoDestructor<FormHandlersJavaScriptFeature>; // web::JavaScriptFeature - absl::optional<std::string> GetScriptMessageHandlerName() const override; + std::optional<std::string> GetScriptMessageHandlerName() const override; void ScriptMessageReceived(web::WebState* web_state, const web::ScriptMessage& message) override;
diff --git a/components/browser_ui/media/android/BUILD.gn b/components/browser_ui/media/android/BUILD.gn index 7446ad08..46997ab 100644 --- a/components/browser_ui/media/android/BUILD.gn +++ b/components/browser_ui/media/android/BUILD.gn
@@ -13,7 +13,6 @@ "java/src/org/chromium/components/browser_ui/media/MediaNotificationInfo.java", "java/src/org/chromium/components/browser_ui/media/MediaNotificationListener.java", "java/src/org/chromium/components/browser_ui/media/MediaNotificationManager.java", - "java/src/org/chromium/components/browser_ui/media/MediaNotificationUma.java", "java/src/org/chromium/components/browser_ui/media/MediaSessionHelper.java", "java/src/org/chromium/components/browser_ui/media/MediaSessionUma.java", ]
diff --git a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationUma.java b/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationUma.java deleted file mode 100644 index 1650944..0000000 --- a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationUma.java +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.components.browser_ui.media; - -import android.content.Intent; - -import androidx.annotation.IntDef; - -import org.chromium.base.metrics.RecordHistogram; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Helper class to record which kind of media notifications does the user click to go back to - * Chrome. - */ -public class MediaNotificationUma { - @IntDef({Source.INVALID, Source.MEDIA, Source.PRESENTATION, Source.MEDIA_FLING}) - @Retention(RetentionPolicy.SOURCE) - public @interface Source { - int INVALID = -1; - int MEDIA = 0; - int PRESENTATION = 1; - int MEDIA_FLING = 2; - int NUM_ENTRIES = 3; - } - - public static final String INTENT_EXTRA_NAME = - "org.chromium.chrome.browser.metrics.MediaNotificationUma.EXTRA_CLICK_SOURCE"; - - /** - * Record the UMA as specified by {@link intent}. The {@link intent} should contain intent extra - * of name {@link INTENT_EXTRA_NAME} indicating the type. - * @param intent The intent starting the activity. - */ - public static void recordClickSource(Intent intent) { - if (intent == null) return; - @Source int source = intent.getIntExtra(INTENT_EXTRA_NAME, Source.INVALID); - if (source == Source.INVALID || source >= Source.NUM_ENTRIES) return; - RecordHistogram.recordEnumeratedHistogram( - "Media.Notification.Click", source, Source.NUM_ENTRIES); - } -}
diff --git a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaSessionHelper.java b/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaSessionHelper.java index a62c349..11f09067 100644 --- a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaSessionHelper.java +++ b/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaSessionHelper.java
@@ -190,11 +190,6 @@ } Intent contentIntent = mDelegate.createBringTabToFrontIntent(); - if (contentIntent != null) { - contentIntent.putExtra( - MediaNotificationUma.INTENT_EXTRA_NAME, - MediaNotificationUma.Source.MEDIA); - } if (mFallbackTitle == null) mFallbackTitle = sanitizeMediaTitle(mOrigin);
diff --git a/components/client_hints/OWNERS b/components/client_hints/OWNERS index 308a03815..1268c37 100644 --- a/components/client_hints/OWNERS +++ b/components/client_hints/OWNERS
@@ -1,3 +1,4 @@ arichiv@chromium.org ryansturm@chromium.org victortan@chromium.org +yoavweiss@chromium.org
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc index 1b0f509..f046137 100644 --- a/components/content_settings/core/browser/content_settings_default_provider.cc +++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -11,6 +11,7 @@ #include "base/functional/bind.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" +#include "build/blink_buildflags.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "components/content_settings/core/browser/content_settings_info.h" @@ -356,6 +357,15 @@ IntToContentSetting( prefs_->GetInteger(GetPrefName(ContentSettingsType::POPUPS))), CONTENT_SETTING_NUM_SETTINGS); + +#if BUILDFLAG(USE_BLINK) + base::UmaHistogramEnumeration( + "ContentSettings.RegularProfile.DefaultSubresourceFilterSetting", + IntToContentSetting( + prefs_->GetInteger(GetPrefName(ContentSettingsType::ADS))), + CONTENT_SETTING_NUM_SETTINGS); +#endif + #if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) base::UmaHistogramEnumeration( "ContentSettings.RegularProfile.DefaultImagesSetting", @@ -413,11 +423,6 @@ prefs_->GetInteger(GetPrefName(ContentSettingsType::AUTOPLAY))), CONTENT_SETTING_NUM_SETTINGS); base::UmaHistogramEnumeration( - "ContentSettings.RegularProfile.DefaultSubresourceFilterSetting", - IntToContentSetting( - prefs_->GetInteger(GetPrefName(ContentSettingsType::ADS))), - CONTENT_SETTING_NUM_SETTINGS); - base::UmaHistogramEnumeration( "ContentSettings.RegularProfile.DefaultSoundSetting", IntToContentSetting( prefs_->GetInteger(GetPrefName(ContentSettingsType::SOUND))),
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc index efca3144..a5e61efa 100644 --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -110,7 +110,7 @@ WebsiteSettingsInfo::TOP_ORIGIN_WITH_RESOURCE_EXCEPTIONS_SCOPE, WebsiteSettingsRegistry::DESKTOP | WebsiteSettingsRegistry::PLATFORM_ANDROID -#if BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK) +#if BUILDFLAG(USE_BLINK) | WebsiteSettingsRegistry::PLATFORM_IOS #endif , @@ -278,7 +278,11 @@ /*valid_settings=*/{CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK}, WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE, WebsiteSettingsRegistry::DESKTOP | - WebsiteSettingsRegistry::PLATFORM_ANDROID, + WebsiteSettingsRegistry::PLATFORM_ANDROID +#if BUILDFLAG(USE_BLINK) + | WebsiteSettingsRegistry::PLATFORM_IOS +#endif + , ContentSettingsInfo::INHERIT_IN_INCOGNITO, ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS); @@ -599,7 +603,7 @@ /*valid_settings=*/{CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK}, WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE, WebsiteSettingsRegistry::PLATFORM_ANDROID -#if BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK) +#if BUILDFLAG(USE_BLINK) | WebsiteSettingsRegistry::PLATFORM_IOS #endif ,
diff --git a/components/content_settings/core/browser/website_settings_registry.cc b/components/content_settings/core/browser/website_settings_registry.cc index a46ed8a9..c6e1d49e 100644 --- a/components/content_settings/core/browser/website_settings_registry.cc +++ b/components/content_settings/core/browser/website_settings_registry.cc
@@ -136,7 +136,7 @@ WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY, WebsiteSettingsInfo::GENERIC_SINGLE_ORIGIN_SCOPE, DESKTOP | PLATFORM_ANDROID -#if BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK) +#if BUILDFLAG(USE_BLINK) | PLATFORM_IOS #endif , @@ -146,7 +146,7 @@ WebsiteSettingsInfo::LOSSY, WebsiteSettingsInfo::GENERIC_SINGLE_ORIGIN_SCOPE, DESKTOP | PLATFORM_ANDROID -#if BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK) +#if BUILDFLAG(USE_BLINK) | PLATFORM_IOS #endif , @@ -176,11 +176,16 @@ // Set when an origin is activated for subresource filtering and the // associated UI is shown to the user. Cleared when a site is de-activated or // the first URL matching the origin is removed from history. - Register( - ContentSettingsType::ADS_DATA, "subresource-filter-data", base::Value(), - WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY, - WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE, DESKTOP | PLATFORM_ANDROID, - WebsiteSettingsInfo::INHERIT_IN_INCOGNITO); + Register(ContentSettingsType::ADS_DATA, "subresource-filter-data", + base::Value(), WebsiteSettingsInfo::UNSYNCABLE, + WebsiteSettingsInfo::NOT_LOSSY, + WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE, + DESKTOP | PLATFORM_ANDROID +#if BUILDFLAG(USE_BLINK) + | PLATFORM_IOS +#endif + , + WebsiteSettingsInfo::INHERIT_IN_INCOGNITO); Register( ContentSettingsType::MEDIA_ENGAGEMENT, "media-engagement", base::Value(), WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
diff --git a/components/global_media_controls/public/media_session_item_producer.cc b/components/global_media_controls/public/media_session_item_producer.cc index 6dbf357..50cd829 100644 --- a/components/global_media_controls/public/media_session_item_producer.cc +++ b/components/global_media_controls/public/media_session_item_producer.cc
@@ -20,15 +20,6 @@ constexpr const char kAutoDismissTimerInMinutesParamName[] = "timer_in_minutes"; -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. -enum class MediaNotificationClickSource { - kMedia = 0, - kPresentation, - kMediaFling, - kMaxValue = kMediaFling -}; - // Returns the time value to be used for the auto-dismissing of the // notifications after they are inactive. // If the feature (auto-dismiss) is disabled, the returned value will be @@ -336,9 +327,6 @@ it->second.OnSessionInteractedWith(); - base::UmaHistogramEnumeration("Media.Notification.Click", - MediaNotificationClickSource::kMedia); - if (activate_original_media) { it->second.item()->Raise(); }
diff --git a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/CafNotificationController.java b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/CafNotificationController.java index 545b225f..fca92c8 100644 --- a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/CafNotificationController.java +++ b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/CafNotificationController.java
@@ -6,7 +6,6 @@ import android.content.Intent; -import org.chromium.components.browser_ui.media.MediaNotificationUma; import org.chromium.components.media_router.MediaRouterClient; /** NotificationController implementation for presentation. */ @@ -18,13 +17,7 @@ @Override public Intent createContentIntent() { - Intent contentIntent = createBringTabToFrontIntent(); - if (contentIntent != null) { - contentIntent.putExtra( - MediaNotificationUma.INTENT_EXTRA_NAME, - MediaNotificationUma.Source.PRESENTATION); - } - return contentIntent; + return createBringTabToFrontIntent(); } @Override
diff --git a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafExpandedControllerActivity.java b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafExpandedControllerActivity.java index 03817d3..3685c97 100644 --- a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafExpandedControllerActivity.java +++ b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/CafExpandedControllerActivity.java
@@ -17,7 +17,6 @@ import androidx.fragment.app.FragmentActivity; import androidx.mediarouter.app.MediaRouteButton; -import org.chromium.components.browser_ui.media.MediaNotificationUma; import org.chromium.components.media_router.R; import org.chromium.components.media_router.caf.BaseSessionController; import org.chromium.third_party.android.media.MediaController; @@ -100,8 +99,6 @@ mSessionController = RemotingSessionController.getInstance(); - MediaNotificationUma.recordClickSource(getIntent()); - if (mSessionController == null || !mSessionController.isConnected()) { finish(); return;
diff --git a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingNotificationController.java b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingNotificationController.java index a98d6fc..be79de0 100644 --- a/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingNotificationController.java +++ b/components/media_router/browser/android/java/src/org/chromium/components/media_router/caf/remoting/RemotingNotificationController.java
@@ -7,7 +7,6 @@ import android.content.Intent; import org.chromium.base.ContextUtils; -import org.chromium.components.browser_ui.media.MediaNotificationUma; import org.chromium.components.media_router.MediaRouterClient; import org.chromium.components.media_router.caf.BaseNotificationController; import org.chromium.components.media_router.caf.BaseSessionController; @@ -21,12 +20,8 @@ @Override public Intent createContentIntent() { - Intent contentIntent = - new Intent( - ContextUtils.getApplicationContext(), CafExpandedControllerActivity.class); - contentIntent.putExtra( - MediaNotificationUma.INTENT_EXTRA_NAME, MediaNotificationUma.Source.MEDIA_FLING); - return contentIntent; + return new Intent( + ContextUtils.getApplicationContext(), CafExpandedControllerActivity.class); } @Override
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index 225fc6b5d..15ba6cf 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -4315,6 +4315,16 @@ CA_FAILURE = 9; // The referenced certificate provisioning profile does not exist. PROFILE_NOT_FOUND = 10; + // A required attribute of the entity that is requesting a certificate was + // not present. + ESS_ATTRIBUTE_NOT_FOUND = 11; + // The certificate provisioning profile is referencing a non-existent CA + // connection. + CA_CONNECTION_NOT_FOUND = 12; + // The CA connection referenced by the certificate provisioning profile + // is referencing a non-existent PubSub topic, or the system does not have + // permission to publish to that PubSub topic. + PUBSUB_TOPIC_NOT_FOUND = 13; } // The specific error type.
diff --git a/components/safe_search_api/url_checker.cc b/components/safe_search_api/url_checker.cc index 24fbe99c..93fd38f 100644 --- a/components/safe_search_api/url_checker.cc +++ b/components/safe_search_api/url_checker.cc
@@ -4,12 +4,15 @@ #include "components/safe_search_api/url_checker.h" +#include <string> +#include <string_view> #include <utility> #include <vector> #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/time/time.h" #include "base/values.h" @@ -19,6 +22,7 @@ namespace { const size_t kDefaultCacheSize = 1000; const size_t kDefaultCacheTimeoutSeconds = 3600; +constexpr std::string_view kCacheHitMetricKey{"Net.SafeSearch.CacheHit"}; } // namespace struct URLChecker::Check { @@ -52,6 +56,25 @@ URLChecker::~URLChecker() = default; +void URLChecker::MaybeScheduleAsyncCheck(const GURL& url, + CheckCallback callback) { + // See if we already have a check in progress for this URL. + for (const auto& check : checks_in_progress_) { + if (check->url == url) { + DVLOG(1) << "Adding to pending check for " << url.spec(); + check->callbacks.push_back(std::move(callback)); + return; + } + } + + auto it = checks_in_progress_.insert( + checks_in_progress_.begin(), + std::make_unique<Check>(url, std::move(callback))); + async_checker_->CheckURL(url, + base::BindOnce(&URLChecker::OnAsyncCheckComplete, + weak_factory_.GetWeakPtr(), it)); +} + bool URLChecker::CheckURL(const GURL& url, CheckCallback callback) { auto cache_it = cache_.Get(url); if (cache_it != cache_.end()) { @@ -62,28 +85,22 @@ << (result.classification == Classification::UNSAFE ? "NOT" : "") << " safe; certain: " << !result.uncertain; std::move(callback).Run(url, result.classification, result.uncertain); + + base::UmaHistogramEnumeration(std::string(kCacheHitMetricKey), + CacheAccessStatus::kHit); return true; } DVLOG(1) << "Outdated cache entry for " << url.spec() << ", purging"; cache_.Erase(cache_it); + base::UmaHistogramEnumeration(std::string(kCacheHitMetricKey), + CacheAccessStatus::kOutdated); + MaybeScheduleAsyncCheck(url, std::move(callback)); + return false; } - // See if we already have a check in progress for this URL. - for (const auto& check : checks_in_progress_) { - if (check->url == url) { - DVLOG(1) << "Adding to pending check for " << url.spec(); - check->callbacks.push_back(std::move(callback)); - return false; - } - } - - auto it = checks_in_progress_.insert( - checks_in_progress_.begin(), - std::make_unique<Check>(url, std::move(callback))); - async_checker_->CheckURL(url, - base::BindOnce(&URLChecker::OnAsyncCheckComplete, - weak_factory_.GetWeakPtr(), it)); - + base::UmaHistogramEnumeration(std::string(kCacheHitMetricKey), + CacheAccessStatus::kNotFound); + MaybeScheduleAsyncCheck(url, std::move(callback)); return false; }
diff --git a/components/safe_search_api/url_checker.h b/components/safe_search_api/url_checker.h index 3a6b3cd..168a4766d 100644 --- a/components/safe_search_api/url_checker.h +++ b/components/safe_search_api/url_checker.h
@@ -20,6 +20,18 @@ // The SafeSearch API classification of a URL. enum class Classification { SAFE, UNSAFE }; +// These values are sent to Uma to understand Cache utilization. Must not be +// renumbered. +enum class CacheAccessStatus { + // Entry was found. + kHit = 0, + // Entry was not found. + kNotFound = 1, + // Entry was found but was stale. + kOutdated = 2, + kMaxValue = kOutdated, +}; + // This class uses one implementation of URLCheckerClient to check the // classification of the content on a given URL and returns the result // asynchronously via a callback. It is also responsible for the synchronous @@ -63,6 +75,10 @@ const GURL& url, ClientClassification classification); + // Either reuses pending check for given url if it already exists (see + // checks_in_progress_), or schedules a new one. + void MaybeScheduleAsyncCheck(const GURL& url, CheckCallback callback); + std::unique_ptr<URLCheckerClient> async_checker_; CheckList checks_in_progress_;
diff --git a/components/safe_search_api/url_checker_unittest.cc b/components/safe_search_api/url_checker_unittest.cc index 0550c7d..30847c5 100644 --- a/components/safe_search_api/url_checker_unittest.cc +++ b/components/safe_search_api/url_checker_unittest.cc
@@ -6,13 +6,18 @@ #include <stddef.h> +#include <algorithm> +#include <iterator> +#include <map> #include <memory> #include <string> #include <utility> +#include <vector> #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "components/safe_search_api/fake_url_checker_client.h" #include "testing/gmock/include/gmock/gmock.h" @@ -48,6 +53,14 @@ } } +auto Recorded(const std::map<CacheAccessStatus, int>& expected) { + std::vector<base::Bucket> buckets_array; + std::transform( + expected.begin(), expected.end(), std::back_inserter(buckets_array), + [](auto& entry) { return base::Bucket(entry.first, entry.second); }); + return base::BucketsInclude(buckets_array); +} + } // namespace class SafeSearchURLCheckerTest : public testing::Test { @@ -86,10 +99,17 @@ return result; } + std::vector<base::Bucket> CacheHitMetric() { + return histogram_tester_.GetAllSamples("Net.SafeSearch.CacheHit"); + } + size_t next_url_{0}; raw_ptr<FakeURLCheckerClient, DanglingUntriaged> fake_client_; std::unique_ptr<URLChecker> checker_; base::test::SingleThreadTaskEnvironment task_environment_; + + private: + base::HistogramTester histogram_tester_; }; TEST_F(SafeSearchURLCheckerTest, Simple) { @@ -112,6 +132,9 @@ OnCheckDone(url, Classification::SAFE, /*uncertain=*/true)); ASSERT_FALSE(SendResponse(url, Classification::SAFE, /*uncertain=*/true)); } + + EXPECT_THAT(CacheHitMetric(), Recorded({{CacheAccessStatus::kHit, 0}, + {CacheAccessStatus::kNotFound, 3}})); } TEST_F(SafeSearchURLCheckerTest, Cache) { @@ -145,6 +168,9 @@ EXPECT_CALL(*this, OnCheckDone(url2, Classification::SAFE, /*uncertain=*/false)); ASSERT_FALSE(SendResponse(url2, Classification::SAFE, /*uncertain=*/false)); + + EXPECT_THAT(CacheHitMetric(), Recorded({{CacheAccessStatus::kHit, 2}, + {CacheAccessStatus::kNotFound, 4}})); } TEST_F(SafeSearchURLCheckerTest, CoalesceRequestsToSameURL) { @@ -155,6 +181,9 @@ // A single response should answer both of those checks EXPECT_CALL(*this, OnCheckDone(url, Classification::SAFE, false)).Times(2); fake_client_->RunCallback(ToAPIClassification(Classification::SAFE, false)); + + EXPECT_THAT(CacheHitMetric(), Recorded({{CacheAccessStatus::kHit, 0}, + {CacheAccessStatus::kNotFound, 2}})); } TEST_F(SafeSearchURLCheckerTest, CacheTimeout) { @@ -171,6 +200,10 @@ EXPECT_CALL(*this, OnCheckDone(url, Classification::UNSAFE, /*uncertain=*/false)); ASSERT_FALSE(SendResponse(url, Classification::UNSAFE, /*uncertain=*/false)); + + EXPECT_THAT(CacheHitMetric(), Recorded({{CacheAccessStatus::kHit, 0}, + {CacheAccessStatus::kNotFound, 1}, + {CacheAccessStatus::kOutdated, 1}})); } TEST_F(SafeSearchURLCheckerTest, DoNotCacheUncertainClassifications) { @@ -180,6 +213,9 @@ url, Classification::SAFE, /*uncertain=*/true)); // First check was asynchronous (uncached). EXPECT_FALSE(CheckURL(url)); // And so was the second one. + + EXPECT_THAT(CacheHitMetric(), Recorded({{CacheAccessStatus::kHit, 0}, + {CacheAccessStatus::kNotFound, 2}})); } TEST_F(SafeSearchURLCheckerTest, DestroyURLCheckerBeforeCallback) { @@ -196,6 +232,9 @@ // The callback should now be invalid. task_environment_.RunUntilIdle(); + + EXPECT_THAT(CacheHitMetric(), Recorded({{CacheAccessStatus::kHit, 0}, + {CacheAccessStatus::kNotFound, 1}})); } } // namespace safe_search_api
diff --git a/components/soda/constants.cc b/components/soda/constants.cc index 95bb1ab..e5dd19add 100644 --- a/components/soda/constants.cc +++ b/components/soda/constants.cc
@@ -159,20 +159,6 @@ return absl::nullopt; } -absl::optional<SodaLanguagePackComponentConfig> -GetLanguageComponentConfigMatchingLanguageSubtag( - const std::string& language_name) { - for (const SodaLanguagePackComponentConfig& config : - kLanguageComponentConfigs) { - if (l10n_util::GetLanguage(base::ToLowerASCII(config.language_name)) == - l10n_util::GetLanguage(base::ToLowerASCII(language_name))) { - return config; - } - } - - return absl::nullopt; -} - LanguageCode GetLanguageCodeByComponentId(const std::string& component_id) { for (const SodaLanguagePackComponentConfig& config : kLanguageComponentConfigs) {
diff --git a/components/soda/constants.h b/components/soda/constants.h index af5544eb..6d4f5be 100644 --- a/components/soda/constants.h +++ b/components/soda/constants.h
@@ -230,13 +230,6 @@ absl::optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig( const std::string& language_name); -// Get the language component config matching a given language subtag. For -// example, the "fr-CA" language name will return the language component config -// for "fr-FR". -absl::optional<SodaLanguagePackComponentConfig> -GetLanguageComponentConfigMatchingLanguageSubtag( - const std::string& language_name); - LanguageCode GetLanguageCodeByComponentId(const std::string& component_id); std::string GetLanguageName(LanguageCode language_code);
diff --git a/components/subresource_filter/content/browser/BUILD.gn b/components/subresource_filter/content/browser/BUILD.gn index 8b6f78dc..27523cb 100644 --- a/components/subresource_filter/content/browser/BUILD.gn +++ b/components/subresource_filter/content/browser/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/features.gni") + static_library("browser") { sources = [ "activation_state_computing_navigation_throttle.cc", @@ -208,4 +210,7 @@ "//components/strings:components_strings_grit", ] } + if (is_ios && use_blink) { + deps += [ "//components/test:subresource_filter_test_bundle_data" ] + } }
diff --git a/components/supervised_user/core/browser/proto_fetcher.cc b/components/supervised_user/core/browser/proto_fetcher.cc index e9a7aa7..1eb312a 100644 --- a/components/supervised_user/core/browser/proto_fetcher.cc +++ b/components/supervised_user/core/browser/proto_fetcher.cc
@@ -365,16 +365,6 @@ FetcherImpl(const FetcherImpl&) = delete; FetcherImpl& operator=(const FetcherImpl&) = delete; - protected: - std::string GetMetricKey(StringPiece metric_id) const { - return JoinString({config_.histogram_basename, metric_id}, "."); - } - std::string GetMetricKey(StringPiece metric_id, - StringPiece metric_suffix) const { - return JoinString({config_.histogram_basename, metric_id, metric_suffix}, - "."); - } - private: void RecordMetrics(const ProtoFetcherStatus& status) { metrics_.RecordStatus(status);
diff --git a/components/unexportable_keys/BUILD.gn b/components/unexportable_keys/BUILD.gn index 1c7b3977..1aad660 100644 --- a/components/unexportable_keys/BUILD.gn +++ b/components/unexportable_keys/BUILD.gn
@@ -12,6 +12,8 @@ "background_task_priority.h", "background_task_type.cc", "background_task_type.h", + "features.cc", + "features.h", "ref_counted_unexportable_signing_key.cc", "ref_counted_unexportable_signing_key.h", "service_error.h",
diff --git a/components/unexportable_keys/features.cc b/components/unexportable_keys/features.cc new file mode 100644 index 0000000..52e0c92 --- /dev/null +++ b/components/unexportable_keys/features.cc
@@ -0,0 +1,13 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/unexportable_keys/features.h" + +namespace unexportable_keys { + +BASE_FEATURE(kEnableBoundSessionCredentialsSoftwareKeysForManualTesting, + "EnableBoundSessionCredentialsSoftwareKeysForManualTesting", + base::FEATURE_DISABLED_BY_DEFAULT); + +} // namespace unexportable_keys
diff --git a/components/unexportable_keys/features.h b/components/unexportable_keys/features.h new file mode 100644 index 0000000..743ff324 --- /dev/null +++ b/components/unexportable_keys/features.h
@@ -0,0 +1,19 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_UNEXPORTABLE_KEYS_FEATURES_H_ +#define COMPONENTS_UNEXPORTABLE_KEYS_FEATURES_H_ + +#include "base/feature_list.h" + +namespace unexportable_keys { + +// If enabled, DBSC-related code will switch `UnexportableKeyProvider` to a mock +// software-backed implementation. +// This feature flag is expected to never be shipped to end users. +BASE_DECLARE_FEATURE( + kEnableBoundSessionCredentialsSoftwareKeysForManualTesting); + +} // namespace unexportable_keys +#endif // COMPONENTS_UNEXPORTABLE_KEYS_FEATURES_H_
diff --git a/components/unexportable_keys/unexportable_key_task_manager.cc b/components/unexportable_keys/unexportable_key_task_manager.cc index 3e9f967..b8bbb2e 100644 --- a/components/unexportable_keys/unexportable_key_task_manager.cc +++ b/components/unexportable_keys/unexportable_key_task_manager.cc
@@ -19,6 +19,7 @@ #include "components/unexportable_keys/background_long_task_scheduler.h" #include "components/unexportable_keys/background_task_priority.h" #include "components/unexportable_keys/background_task_type.h" +#include "components/unexportable_keys/features.h" #include "components/unexportable_keys/ref_counted_unexportable_signing_key.h" #include "components/unexportable_keys/service_error.h" #include "components/unexportable_keys/unexportable_key_id.h" @@ -93,10 +94,6 @@ // static std::unique_ptr<crypto::UnexportableKeyProvider> UnexportableKeyTaskManager::GetUnexportableKeyProvider() { - static BASE_FEATURE( - kEnableBoundSessionCredentialsSoftwareKeysForManualTesting, - "EnableBoundSessionCredentialsSoftwareKeysForManualTesting", - base::FEATURE_DISABLED_BY_DEFAULT); if (base::FeatureList::IsEnabled( kEnableBoundSessionCredentialsSoftwareKeysForManualTesting)) { return crypto::GetSoftwareUnsecureUnexportableKeyProvider();
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 9064745..dac8285a 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -5979,9 +5979,9 @@ INSTANTIATE_TEST_SUITE_P(, DelegatedInkTest, - testing::ValuesIn(GetRendererTypesSkiaOnly()), + testing::ValuesIn(GetGpuRendererTypes()), testing::PrintToStringParamName()); -// GetRendererTypesSkiaOnly() can return an empty list, e.g. on Fuchsia ARM64. +// GetGpuRendererTypes() can return an empty list, e.g. on Fuchsia ARM64. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DelegatedInkTest); // Test to confirm that predicted points are not drawn if prediction is not @@ -6034,10 +6034,10 @@ INSTANTIATE_TEST_SUITE_P(, DelegatedInkWithPredictionTest, - testing::ValuesIn(GetRendererTypesSkiaOnly()), + testing::ValuesIn(GetGpuRendererTypes()), testing::PrintToStringParamName()); -// GetRendererTypesSkiaOnly() can return an empty list, e.g. on Fuchsia ARM64. +// GetGpuRendererTypes() can return an empty list, e.g. on Fuchsia ARM64. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DelegatedInkWithPredictionTest); // Draw a single trail and erase it, making sure that no bits of trail are left
diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h index b96b656..71ce7727 100644 --- a/components/viz/service/display/skia_output_surface.h +++ b/components/viz/service/display/skia_output_surface.h
@@ -221,6 +221,10 @@ // Enqueue a GPU task to delete the specified shared image. virtual void DestroySharedImage(const gpu::Mailbox& mailbox) = 0; + // Enqueue a GPU task to set specified shared image as `purgeable`. + virtual void SetSharedImagePurgeable(const gpu::Mailbox& mailbox, + bool purgeable) = 0; + virtual bool SupportsBGRA() const = 0; };
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index dcdd2308e..56b436e 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -1090,16 +1090,19 @@ current_frame()->overlay_list.begin(), surface_candidate); } } else { -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_APPLE) - // If there's no primary plane on these platforms it mean's we're delegating - // to the system compositor, and don't need the buffers anymore. If those - // buffers are managed by buffer_queue_, we can tell it to destroy them. - // They'll be recreated when we need them again when GetCurrentBuffer() is - // called. if (buffer_queue_) { + // If there's no primary plane on these platforms it mean's we're + // delegating to the system compositor, and don't need the buffers + // anymore. On LaCrOS the primary plane buffers are immediately destroyed. + // They'll be recreated when we need them again when GetCurrentBuffer() is + // called. On Mac the primary plane buffers are marked as purgeable so the + // OS can decide if they should be destroyed or not. +#if BUILDFLAG(IS_CHROMEOS_LACROS) buffer_queue_->DestroyBuffers(); +#elif BUILDFLAG(IS_APPLE) + buffer_queue_->SetBuffersPurgeable(); +#endif } -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_APPLE) } ScheduleOverlays();
diff --git a/components/viz/service/display_embedder/buffer_queue.cc b/components/viz/service/display_embedder/buffer_queue.cc index bf06870..bd47be74 100644 --- a/components/viz/service/display_embedder/buffer_queue.cc +++ b/components/viz/service/display_embedder/buffer_queue.cc
@@ -81,8 +81,16 @@ available_buffers_.push_back(std::move(displayed_buffer_)); } displayed_buffer_ = std::move(in_flight_buffers_.front()); - in_flight_buffers_.pop_front(); + + if (buffers_can_be_purged_) { + for (auto& buffer : available_buffers_) { + if (SetBufferPurgeable(*buffer, true)) { + // Set a single available buffer to purgeable each swap. + break; + } + } + } } void BufferQueue::SwapBuffersSkipped(const gfx::Rect& damage) { @@ -104,6 +112,12 @@ return true; } + if (buffers_can_be_purged_) { + // If buffers are purgeable wait to recreate until they will be used again. + DestroyBuffers(); + return true; + } + FreeAllBuffers(); AllocateBuffers(number_of_buffers_); @@ -114,6 +128,13 @@ if (buffers_destroyed_) { return; } + + if (buffers_can_be_purged_) { + // If buffers are purgeable wait to recreate until they will be used again. + DestroyBuffers(); + return; + } + FreeAllBuffers(); AllocateBuffers(number_of_buffers_); } @@ -142,6 +163,16 @@ skia_output_surface_->DestroySharedImage(buffer->mailbox); } +bool BufferQueue::SetBufferPurgeable(AllocatedBuffer& buffer, bool purgeable) { + if (buffer.purgeable == purgeable) { + return false; + } + + skia_output_surface_->SetSharedImagePurgeable(buffer.mailbox, purgeable); + buffer.purgeable = true; + return true; +} + void BufferQueue::AllocateBuffers(size_t n) { DCHECK(format_); const SharedImageFormat format = @@ -224,16 +255,31 @@ FreeAllBuffers(); } -void BufferQueue::RecreateBuffersIfDestroyed() { - if (!buffers_destroyed_) { +void BufferQueue::SetBuffersPurgeable() { + if (buffers_can_be_purged_) { return; } - AllocateBuffers(number_of_buffers_); - buffers_destroyed_ = false; - base::TimeDelta elapsed = destroyed_timer_->Elapsed(); - UMA_HISTOGRAM_TIMES("Compositing.BufferQueue.TimeUntilBuffersRecreatedMs", - elapsed); - destroyed_timer_.reset(); + buffers_can_be_purged_ = true; +} + +void BufferQueue::RecreateBuffersIfDestroyed() { + if (buffers_can_be_purged_) { + // Mark buffers as not purgeable. It's possible they were destroyed and + // `available_buffers_` is empty. + buffers_can_be_purged_ = false; + for (auto& buffer : available_buffers_) { + SetBufferPurgeable(*buffer, false); + } + } + + if (buffers_destroyed_) { + buffers_destroyed_ = false; + AllocateBuffers(number_of_buffers_); + base::TimeDelta elapsed = destroyed_timer_->Elapsed(); + UMA_HISTOGRAM_TIMES("Compositing.BufferQueue.TimeUntilBuffersRecreatedMs", + elapsed); + destroyed_timer_.reset(); + } } BufferQueue::AllocatedBuffer::AllocatedBuffer(const gpu::Mailbox& mailbox,
diff --git a/components/viz/service/display_embedder/buffer_queue.h b/components/viz/service/display_embedder/buffer_queue.h index 711393c..c027062 100644 --- a/components/viz/service/display_embedder/buffer_queue.h +++ b/components/viz/service/display_embedder/buffer_queue.h
@@ -110,6 +110,15 @@ // buffers. void DestroyBuffers(); + // Indicates buffer contents can be purged, aka their contents deleted if + // memory is needed. For each completed swap one buffer will be marked + // purgeable. + // + // NOTE: This should only be used when buffers are not currently needed, eg. + // when delegating to system compositor, and if the platform support purgeable + // shared images. + void SetBuffersPurgeable(); + private: friend class BufferQueueTest; friend class BufferQueueMockedSharedImageInterfaceTest; @@ -121,6 +130,7 @@ AllocatedBuffer(const gpu::Mailbox& mailbox, const gfx::Rect& rect); ~AllocatedBuffer(); + bool purgeable = false; gpu::Mailbox mailbox; gfx::Rect damage; // This is the damage for this frame from the previous. }; @@ -132,6 +142,10 @@ // Free |buffer| and destroy its shared image. void FreeBuffer(std::unique_ptr<AllocatedBuffer> buffer); + // Sets `buffer`s shared image as `purgeable` and returns true if the value + // changed. + bool SetBufferPurgeable(AllocatedBuffer& buffer, bool purgeable); + // Unions |damage| to all allocated buffers except |current_buffer_| which // hasn't been displayed yet. void UpdateBufferDamage(const gfx::Rect& damage); @@ -173,6 +187,9 @@ // frames where SwapBuffers() was called without calling GetCurrentBuffer(). base::circular_deque<std::unique_ptr<AllocatedBuffer>> in_flight_buffers_; + // When the buffers are not being used due to delegated compositing. + bool buffers_can_be_purged_ = false; + // Whether the buffers have been destroyed and are not yet recreated. If true, // don't allocate buffers when you normally would. They will be recreated on // demand the next time GetNextBuffer() is called.
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc index a778102..006937d 100644 --- a/components/viz/service/display_embedder/buffer_queue_unittest.cc +++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -12,6 +12,7 @@ #include <string> #include <utility> +#include "base/test/bind.h" #include "build/build_config.h" #include "components/viz/test/fake_skia_output_surface.h" #include "gpu/command_buffer/common/mailbox.h" @@ -626,4 +627,92 @@ EXPECT_FALSE(buffer_queue_->GetLastSwappedBuffer().IsZero()); } +TEST_F(BufferQueueTest, SetPurgeable) { + testing::MockFunction<void(const gpu::Mailbox&, bool)> mock; + skia_output_surface_->SetSharedImagePurgeableCallback( + base::BindLambdaForTesting(mock.AsStdFunction())); + + EXPECT_TRUE(buffer_queue_->Reshape(screen_size, kBufferQueueColorSpace, + kBufferQueueFormat)); + auto mb1 = SendDamagedFrame(small_damage); + auto mb2 = SendDamagedFrame(small_damage); + auto mb3 = SendDamagedFrame(small_damage); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mb3); + + // Queue up `mb1` and `mb2` so they are in flight. `mb3` is still the last + // swapped buffer. + EXPECT_EQ(buffer_queue_->GetCurrentBuffer(), mb1); + buffer_queue_->SwapBuffers(small_damage); + EXPECT_EQ(buffer_queue_->GetCurrentBuffer(), mb2); + buffer_queue_->SwapBuffers(small_damage); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mb3); + + // Set buffers as purgeable. + buffer_queue_->SetBuffersPurgeable(); + + // When the next swap finishes `mb3` is available and gets marked purgeable. + EXPECT_CALL(mock, Call(mb3, true)); + buffer_queue_->SwapBuffersComplete(); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mb1); + + // When the next swap finishes `mb1` is available and gets marked purgeable. + EXPECT_CALL(mock, Call(mb1, true)); + buffer_queue_->SwapBuffersComplete(); + EXPECT_EQ(buffer_queue_->GetLastSwappedBuffer(), mb2); + + // `mb2` is last swapped buffer now and there are no pending swaps. Push an + // empty swap and complete that so `mb2` is available. + EXPECT_CALL(mock, Call(mb2, true)); + buffer_queue_->SwapBuffers(small_damage); + buffer_queue_->SwapBuffersComplete(); + + // The next non-delegated draw will get a primary plane buffer. This will + // cause all three buffers to be marked as not purgeable anymore. + EXPECT_CALL(mock, Call(mb3, false)); + EXPECT_CALL(mock, Call(mb1, false)); + EXPECT_CALL(mock, Call(mb2, false)); + EXPECT_EQ(buffer_queue_->GetCurrentBuffer(), mb3); + + // Reset callback since it points to stack allocated mock. + skia_output_surface_->SetSharedImagePurgeableCallback({}); +} + +TEST_F(BufferQueueTest, SetPurgeableThenReshape) { + testing::MockFunction<void(const gpu::Mailbox&, bool)> mock; + skia_output_surface_->SetSharedImagePurgeableCallback( + base::BindLambdaForTesting(mock.AsStdFunction())); + + // This test will reshape before any buffers can be marked as purgeable. + EXPECT_CALL(mock, Call(testing::_, testing::_)).Times(0); + + EXPECT_TRUE(buffer_queue_->Reshape(screen_size, kBufferQueueColorSpace, + kBufferQueueFormat)); + + // Swap three buffers. First buffer swap completes so there is one displayed + // buffer and two in flight buffers. + buffer_queue_->GetCurrentBuffer(); + buffer_queue_->SwapBuffers(small_damage); + buffer_queue_->GetCurrentBuffer(); + buffer_queue_->SwapBuffers(small_damage); + buffer_queue_->SwapBuffersComplete(); + buffer_queue_->GetCurrentBuffer(); + buffer_queue_->SwapBuffers(small_damage); + EXPECT_FALSE(buffer_queue_->GetLastSwappedBuffer().IsZero()); + + // Set the buffers as purgeable before the next swap buffers complete and then + // immediately reshape. The reshape will cause buffers to be deleted but not + // recreated at the new size until they will be used. + buffer_queue_->SetBuffersPurgeable(); + EXPECT_TRUE(buffer_queue_->Reshape(gfx::Size(1, 1), kBufferQueueColorSpace, + kBufferQueueFormat)); + + // Complete the last two swaps. Since the reshape deleted all the buffers + // they will not be marked as purgeable. + buffer_queue_->SwapBuffersComplete(); + buffer_queue_->SwapBuffersComplete(); + + // Reset callback since it points to stack allocated mock. + skia_output_surface_->SetSharedImagePurgeableCallback({}); +} + } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index 062fd58..2ab8521 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -1731,6 +1731,15 @@ /*need_framebuffer=*/false); } +void SkiaOutputSurfaceImpl::SetSharedImagePurgeable(const gpu::Mailbox& mailbox, + bool purgeable) { + auto task = + base::BindOnce(&SkiaOutputSurfaceImplOnGpu::SetSharedImagePurgeable, + base::Unretained(impl_on_gpu_.get()), mailbox, purgeable); + EnqueueGpuTask(std::move(task), {}, /*make_current=*/false, + /*need_framebuffer=*/false); +} + bool SkiaOutputSurfaceImpl::SupportsBGRA() const { if (graphite_recorder_) { // TODO(crbug.com/1451789): Implement properly for Graphite.
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index ecccf51..dfbc85c7 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -175,6 +175,8 @@ const SkColor4f& color, const gfx::ColorSpace& color_space) override; void DestroySharedImage(const gpu::Mailbox& mailbox) override; + void SetSharedImagePurgeable(const gpu::Mailbox& mailbox, + bool purgeable) override; bool SupportsBGRA() const override; // ExternalUseClient implementation:
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 126d3f4..d9fe792 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -2735,6 +2735,12 @@ solid_color_images_.erase(mailbox); } +void SkiaOutputSurfaceImplOnGpu::SetSharedImagePurgeable( + const gpu::Mailbox& mailbox, + bool purgeable) { + shared_image_factory_->SetSharedImagePurgeable(mailbox, purgeable); +} + gpu::SkiaImageRepresentation* SkiaOutputSurfaceImplOnGpu::GetSkiaRepresentation( gpu::Mailbox mailbox) { auto it = skia_representations_.find(mailbox);
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index 92b11e18..d93b29e 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -281,6 +281,7 @@ const SkColor4f& color, const gfx::ColorSpace& color_space); void DestroySharedImage(gpu::Mailbox mailbox); + void SetSharedImagePurgeable(const gpu::Mailbox& mailbox, bool purgeable); // Called on the viz thread! base::ScopedClosureRunner GetCacheBackBufferCb();
diff --git a/components/viz/test/fake_skia_output_surface.cc b/components/viz/test/fake_skia_output_surface.cc index 04686f64..22beb781 100644 --- a/components/viz/test/fake_skia_output_surface.cc +++ b/components/viz/test/fake_skia_output_surface.cc
@@ -436,6 +436,13 @@ return gpu::Mailbox::GenerateForSharedImage(); } +void FakeSkiaOutputSurface::SetSharedImagePurgeable(const gpu::Mailbox& mailbox, + bool purgeable) { + if (set_purgeable_callback_) { + set_purgeable_callback_.Run(mailbox, purgeable); + } +} + bool FakeSkiaOutputSurface::SupportsBGRA() const { return true; }
diff --git a/components/viz/test/fake_skia_output_surface.h b/components/viz/test/fake_skia_output_surface.h index 566e8a3c..c7bc539 100644 --- a/components/viz/test/fake_skia_output_surface.h +++ b/components/viz/test/fake_skia_output_surface.h
@@ -24,6 +24,9 @@ namespace viz { class FakeSkiaOutputSurface : public SkiaOutputSurface { + using SharedImagePurgeableCallback = + base::RepeatingCallback<void(const gpu::Mailbox&, bool)>; + public: static std::unique_ptr<FakeSkiaOutputSurface> Create3d() { auto provider = TestContextProvider::Create(); @@ -118,6 +121,8 @@ const SkColor4f& color, const gfx::ColorSpace& color_space) override; void DestroySharedImage(const gpu::Mailbox& mailbox) override {} + void SetSharedImagePurgeable(const gpu::Mailbox& mailbox, + bool purgeable) override; bool SupportsBGRA() const override; // ExternalUseClient implementation: @@ -134,6 +139,10 @@ gpu::SharedImageInterface* GetSharedImageInterface(); + void SetSharedImagePurgeableCallback(SharedImagePurgeableCallback callback) { + set_purgeable_callback_ = std::move(callback); + } + // If set true, callbacks triggering will be in a reverse order as SignalQuery // calls. void SetOutOfOrderCallbacks(bool out_of_order_callbacks); @@ -201,6 +210,8 @@ // correctly routed towards gpu main when the platform supports delegated ink. bool delegated_ink_renderer_receiver_arrived_ = false; + SharedImagePurgeableCallback set_purgeable_callback_; + THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<FakeSkiaOutputSurface> weak_ptr_factory_{this};
diff --git a/components/viz/test/test_context_provider.cc b/components/viz/test/test_context_provider.cc index c9362f6..70ff478 100644 --- a/components/viz/test/test_context_provider.cc +++ b/components/viz/test/test_context_provider.cc
@@ -198,12 +198,25 @@ base::StringPiece debug_label, gpu::SurfaceHandle surface_handle, gfx::BufferUsage buffer_usage) { + if (fail_shared_image_creation_with_buffer_usage_) { + return nullptr; + } + // Create a ClientSharedImage with a GMB. auto client_shared_image = CreateSharedImage(format, size, color_space, surface_origin, alpha_type, usage, std::move(debug_label), surface_handle); CHECK(client_shared_image); auto mailbox = client_shared_image->mailbox(); + + if (test_gmb_manager_) { + auto gpu_memory_buffer = test_gmb_manager_->CreateGpuMemoryBuffer( + size, SinglePlaneSharedImageFormatToBufferFormat(format), buffer_usage, + surface_handle, nullptr); + return gpu::ClientSharedImage::CreateForTesting( + mailbox, std::move(gpu_memory_buffer)); + } + auto gmb_handle = CreateGMBHandle(format, size, buffer_usage); return base::MakeRefCounted<gpu::ClientSharedImage>(
diff --git a/components/viz/test/test_context_provider.h b/components/viz/test/test_context_provider.h index 926d7c3..7056c5ae 100644 --- a/components/viz/test/test_context_provider.h +++ b/components/viz/test/test_context_provider.h
@@ -22,6 +22,7 @@ #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/raster_context_provider.h" #include "components/viz/test/test_context_support.h" +#include "components/viz/test/test_gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/gles2_interface_stub.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/common/shared_image_capabilities.h" @@ -161,6 +162,14 @@ const gpu::SharedImageCapabilities& GetCapabilities() override; void SetCapabilities(const gpu::SharedImageCapabilities& caps); + void SetFailSharedImageCreationWithBufferUsage(bool value) { + fail_shared_image_creation_with_buffer_usage_ = value; + } + + void UseTestGMBInSharedImageCreationWithBufferUsage() { + test_gmb_manager_ = std::make_unique<TestGpuMemoryBufferManager>(); + } + private: mutable base::Lock lock_; @@ -171,6 +180,11 @@ base::flat_set<gpu::Mailbox> shared_images_; gpu::SharedImageCapabilities shared_image_capabilities_; + bool fail_shared_image_creation_with_buffer_usage_ = false; + + // If non-null, this will be used to back mappable SharedImages with test + // GpuMemoryBuffers. + std::unique_ptr<TestGpuMemoryBufferManager> test_gmb_manager_; }; class TestContextProvider
diff --git a/components/viz/test/test_types.cc b/components/viz/test/test_types.cc index d2c38cf..521780d 100644 --- a/components/viz/test/test_types.cc +++ b/components/viz/test/test_types.cc
@@ -27,11 +27,11 @@ } } -std::vector<RendererType> GetRendererTypes(bool include_software, - bool skia_only) { +std::vector<RendererType> GetRendererTypes(bool include_software) { std::vector<RendererType> types; - if (include_software && !skia_only) + if (include_software) { types.push_back(RendererType::kSoftware); + } #if BUILDFLAG(ENABLE_GL_BACKEND_TESTS) types.push_back(RendererType::kSkiaGL); #endif // BUILDFLAG(ENABLE_GL_BACKEND_TESTS) @@ -54,15 +54,11 @@ } std::vector<RendererType> GetRendererTypes() { - return GetRendererTypes(true, false); + return GetRendererTypes(true); } std::vector<RendererType> GetGpuRendererTypes() { - return GetRendererTypes(false, false); -} - -std::vector<RendererType> GetRendererTypesSkiaOnly() { - return GetRendererTypes(false, true); + return GetRendererTypes(false); } } // namespace viz
diff --git a/components/viz/test/test_types.h b/components/viz/test/test_types.h index 1bf7f49..948dedc 100644 --- a/components/viz/test/test_types.h +++ b/components/viz/test/test_types.h
@@ -27,9 +27,6 @@ // applicable to the platform. std::vector<RendererType> GetGpuRendererTypes(); -// Returns a list containing all Skia RendererTypes applicable to the platform. -std::vector<RendererType> GetRendererTypesSkiaOnly(); - } // namespace viz #endif // COMPONENTS_VIZ_TEST_TEST_TYPES_H_
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc index d95244e..b2e77fa 100644 --- a/components/webdata/common/web_database_migration_unittest.cc +++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -17,6 +17,7 @@ #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/geo/autofill_country.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autocomplete_table.h" #include "components/autofill/core/browser/webdata/autofill_change.h" #include "components/autofill/core/browser/webdata/autofill_table.h" @@ -27,12 +28,6 @@ #include "sql/statement.h" #include "testing/gtest/include/gtest/gtest.h" -using autofill::AutofillProfile; -using autofill::AutofillTable; -using autofill::CreditCard; -using base::ASCIIToUTF16; -using base::Time; - namespace { // To make the comparison with golden files less whitespace sensitive: @@ -77,12 +72,14 @@ // Load the database via the WebDatabase class and migrate the database to // the current version. void DoMigration() { + autofill::AddressAutofillTable address_autofill_table; autofill::AutocompleteTable autocomplete_table; - AutofillTable autofill_table; + autofill::AutofillTable autofill_table; KeywordTable keyword_table; TokenServiceTable token_service_table; WebDatabase db; + db.AddTable(&address_autofill_table); db.AddTable(&autocomplete_table); db.AddTable(&autofill_table); db.AddTable(&keyword_table); @@ -1058,21 +1055,22 @@ EXPECT_TRUE(connection.DoesTableExist("local_addresses")); EXPECT_TRUE(connection.DoesTableExist("local_addresses_type_tokens")); - // Expect to find the profiles in the local_addresses tables. AutofillTable - // will read from them. - AutofillTable table; + // Expect to find the profiles in the local_addresses tables. + // AddressAutofillTable will read from them. + autofill::AddressAutofillTable table; table.Init(&connection, /*meta_table=*/nullptr); - std::unique_ptr<AutofillProfile> profile = - table.GetAutofillProfile("00000000-0000-0000-0000-000000000000", - AutofillProfile::Source::kLocalOrSyncable); + std::unique_ptr<autofill::AutofillProfile> profile = + table.GetAutofillProfile( + "00000000-0000-0000-0000-000000000000", + autofill::AutofillProfile::Source::kLocalOrSyncable); ASSERT_TRUE(profile); - EXPECT_EQ(profile->modification_date(), Time::FromTimeT(123)); + EXPECT_EQ(profile->modification_date(), base::Time::FromTimeT(123)); EXPECT_EQ(profile->GetRawInfo(autofill::NAME_FULL), u"full name"); EXPECT_EQ(profile->GetRawInfo(autofill::ADDRESS_HOME_ZIP), u"4567"); - EXPECT_TRUE( - table.GetAutofillProfile("00000000-0000-0000-0000-000000000001", - AutofillProfile::Source::kLocalOrSyncable)); + EXPECT_TRUE(table.GetAutofillProfile( + "00000000-0000-0000-0000-000000000001", + autofill::AutofillProfile::Source::kLocalOrSyncable)); } }
diff --git a/components/webdata_services/web_data_service_wrapper.cc b/components/webdata_services/web_data_service_wrapper.cc index 073eb9a..e9dcf1bd 100644 --- a/components/webdata_services/web_data_service_wrapper.cc +++ b/components/webdata_services/web_data_service_wrapper.cc
@@ -13,6 +13,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "build/build_config.h" +#include "components/autofill/core/browser/webdata/addresses/address_autofill_table.h" #include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h" #include "components/autofill/core/browser/webdata/autocomplete_table.h" #include "components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h" @@ -117,6 +118,8 @@ // All tables objects that participate in managing the database must // be added here. + profile_database_->AddTable( + std::make_unique<autofill::AddressAutofillTable>()); profile_database_->AddTable(std::make_unique<autofill::AutocompleteTable>()); profile_database_->AddTable(std::make_unique<autofill::AutofillTable>()); profile_database_->AddTable(std::make_unique<KeywordTable>());
diff --git a/content/browser/back_forward_cache_features_browsertest.cc b/content/browser/back_forward_cache_features_browsertest.cc index 70e4b78..85fd7cc0 100644 --- a/content/browser/back_forward_cache_features_browsertest.cc +++ b/content/browser/back_forward_cache_features_browsertest.cc
@@ -1130,39 +1130,28 @@ ExpectRestored(FROM_HERE); } -// The bool parameter is used for switching -// `kEnableBackForwardCacheForPagesWithMediaDevicesDispatcherHost`. -class BackForwardCacheForPagesWithMediaDevicesDispatcherHostTest - : public BackForwardCacheBrowserTest, - public testing::WithParamInterface<bool> { +// The parameter is used for switching +// `kAllowBFCacheForClosedMediaStreamTrack`. +class BackForwardCacheMediaTest : public BackForwardCacheBrowserTest, + public testing::WithParamInterface<bool> { protected: void SetUpCommandLine(base::CommandLine* command_line) override { - if (IsBFCacheForPagesWithMediaDevicesDispatcherHostEnabled()) { + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { EnableFeatureAndSetParams( - features:: - kEnableBackForwardCacheForPagesWithMediaDevicesDispatcherHost, - "", ""); + blink::features::kAllowBFCacheWhenClosedMediaStreamTrack, "", ""); } else { - DisableFeature( - features:: - kEnableBackForwardCacheForPagesWithMediaDevicesDispatcherHost); + DisableFeature(blink::features::kAllowBFCacheWhenClosedMediaStreamTrack); } BackForwardCacheBrowserTest::SetUpCommandLine(command_line); } - bool IsBFCacheForPagesWithMediaDevicesDispatcherHostEnabled() { - return GetParam(); - } + bool IsAllowBFCacheWhenClosedMediaStreamTrackEnabled() { return GetParam(); } }; -INSTANTIATE_TEST_SUITE_P( - All, - BackForwardCacheForPagesWithMediaDevicesDispatcherHostTest, - testing::Bool()); +INSTANTIATE_TEST_SUITE_P(All, BackForwardCacheMediaTest, testing::Bool()); -IN_PROC_BROWSER_TEST_P( - BackForwardCacheForPagesWithMediaDevicesDispatcherHostTest, - DoesNotCacheIfRecordingAudio) { +IN_PROC_BROWSER_TEST_P(BackForwardCacheMediaTest, + DoesNotCacheIfRecordingAudio) { ASSERT_TRUE(embedded_test_server()->Start()); BackForwardCacheDisabledTester tester; @@ -1183,7 +1172,8 @@ RenderFrameDeletedObserver deleted(current_frame_host()); // 2) Navigate away. - shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title1.html")); + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("b.com", "/title1.html"))); // The page was still recording audio when we navigated away, so it shouldn't // have been cached. @@ -1192,9 +1182,13 @@ // 3) Go back. ASSERT_TRUE(HistoryGoBack(web_contents())); - if (IsBFCacheForPagesWithMediaDevicesDispatcherHostEnabled()) { - ExpectNotRestored({NotRestoredReason::kWasGrantedMediaAccess}, {}, {}, {}, - {}, FROM_HERE); + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // When the flag is enabled, a Media Stream Track that's in the live state + // will block BFCache. + ExpectNotRestored( + {NotRestoredReason::kBlocklistedFeatures}, + {blink::scheduler::WebSchedulerTrackedFeature::kLiveMediaStreamTrack}, + {}, {}, {}, FROM_HERE); } else { // Note that the reason for kWasGrantedMediaAccess occurs after // MediaDevicesDispatcherHost is called, hence, both are reasons for the @@ -1207,9 +1201,8 @@ } } -IN_PROC_BROWSER_TEST_P( - BackForwardCacheForPagesWithMediaDevicesDispatcherHostTest, - DoesNotCacheIfSubframeRecordingAudio) { +IN_PROC_BROWSER_TEST_P(BackForwardCacheMediaTest, + DoesNotCacheIfSubframeRecordingAudio) { ASSERT_TRUE(embedded_test_server()->Start()); BackForwardCacheDisabledTester tester; @@ -1231,7 +1224,8 @@ RenderFrameDeletedObserver deleted(current_frame_host()); // 2) Navigate away. - shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title1.html")); + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("b.com", "/title1.html"))); // The page was still recording audio when we navigated away, so it shouldn't // have been cached. @@ -1240,9 +1234,13 @@ // 3) Go back. ASSERT_TRUE(HistoryGoBack(web_contents())); - if (IsBFCacheForPagesWithMediaDevicesDispatcherHostEnabled()) { - ExpectNotRestored({NotRestoredReason::kWasGrantedMediaAccess}, {}, {}, {}, - {}, FROM_HERE); + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // When the flag is enabled, a Media Stream Track that's in the live state + // blocks BFCache. + ExpectNotRestored( + {NotRestoredReason::kBlocklistedFeatures}, + {blink::scheduler::WebSchedulerTrackedFeature::kLiveMediaStreamTrack}, + {}, {}, {}, FROM_HERE); } else { // Note that the reason for kWasGrantedMediaAccess occurs after // MediaDevicesDispatcherHost is called, hence, both are reasons for the @@ -1256,7 +1254,7 @@ } IN_PROC_BROWSER_TEST_P( - BackForwardCacheForPagesWithMediaDevicesDispatcherHostTest, + BackForwardCacheMediaTest, DoesNotCacheIfMediaDeviceSubscribedButDoesCacheIfFlagEnabled) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -1285,9 +1283,9 @@ // 3) Go back. ASSERT_TRUE(HistoryGoBack(web_contents())); - if (IsBFCacheForPagesWithMediaDevicesDispatcherHostEnabled()) { - // The page should be BFCached when the flag is enabled because - // the only blocker when it's disabled is `kMediaDevicesDispatcherHost`. + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // When the flag is enabled, ended Media Stream Track does not block + // BFCache. ExpectRestored(FROM_HERE); } else { // The page was subscribed to media devices when we navigated away, so it @@ -1304,7 +1302,7 @@ // Checks that the page is not restored from BFCache when it calls // mediaDevice.enumerateDevices() unless the flag is enabled. IN_PROC_BROWSER_TEST_P( - BackForwardCacheForPagesWithMediaDevicesDispatcherHostTest, + BackForwardCacheMediaTest, DoesNotCacheIfDevicesEnumeratedButDoesCacheIfFlagEnabled) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -1323,8 +1321,9 @@ EXPECT_TRUE(NavigateToURL( shell(), embedded_test_server()->GetURL("b.com", "/title1.html"))); - if (IsBFCacheForPagesWithMediaDevicesDispatcherHostEnabled()) { - // 3) Go back. The page should be cached when the flag is enabled. + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // 3) Go back. When the flag is enabled, MediaDevicesDispatcherHost does not + // block BFCache. ASSERT_TRUE(HistoryGoBack(web_contents())); ExpectRestored(FROM_HERE); } else { @@ -1341,13 +1340,12 @@ } // Checks that the page is not restored from BFCache when it calls -// mediaDevice.getDisplayMedia(). -// Since mediaDevice.getDisplayMedia() is not supported in Android, this test +// mediaDevice.getDisplayMedia() and still has live MediaStreamTrack. +// Since mediaDevice.getDisplayMedia() is not supported in Android, the tests // can't run on the OS. #if !BUILDFLAG(IS_ANDROID) -IN_PROC_BROWSER_TEST_P( - BackForwardCacheForPagesWithMediaDevicesDispatcherHostTest, - DoesNotCacheIfDisplayMediaAccessGranted) { +IN_PROC_BROWSER_TEST_P(BackForwardCacheMediaTest, + DoesNotCacheIfDisplayMediaAccessGranted) { ASSERT_TRUE(embedded_test_server()->Start()); // 1) Navigate to an empty page. @@ -1358,26 +1356,78 @@ // Request for video and audio display permission. EXPECT_EQ("success", EvalJs(rfh.get(), R"( - navigator.mediaDevices.getDisplayMedia({audio: true, video: true}) - .then(() => { return "success" }) + new Promise((resolve) => { + navigator.mediaDevices.getDisplayMedia({audio: true, video: true}) + .then(() => { resolve("success"); }) + }); )")); // 2) Navigate away. EXPECT_TRUE(NavigateToURL( shell(), embedded_test_server()->GetURL("b.com", "/title1.html"))); - // The page where display media permission is requested shouldn't be cached. ASSERT_TRUE(rfh.WaitUntilRenderFrameDeleted()); - if (IsBFCacheForPagesWithMediaDevicesDispatcherHostEnabled()) { + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // 3) Go back. When the flag is enabled, a Media Stream Track that's in the + // live state blocks BFCache. + ASSERT_TRUE(HistoryGoBack(web_contents())); + ExpectNotRestored( + {NotRestoredReason::kBlocklistedFeatures}, + {blink::scheduler::WebSchedulerTrackedFeature::kLiveMediaStreamTrack}, + {}, {}, {}, FROM_HERE); + } else { // 3) Go back. ASSERT_TRUE(HistoryGoBack(web_contents())); - ExpectNotRestored({NotRestoredReason::kWasGrantedMediaAccess}, {}, {}, {}, - {}, FROM_HERE); + auto reason = BackForwardCacheDisable::DisabledReason( + BackForwardCacheDisable::DisabledReasonId::kMediaDevicesDispatcherHost); + ExpectNotRestored({NotRestoredReason::kWasGrantedMediaAccess, + NotRestoredReason::kDisableForRenderFrameHostCalled}, + {}, {}, {reason}, {}, FROM_HERE); + } +} + +// Checks that the page is successfully restored from BFCache after stopping the +// media stream track that was caused by getDisplayMedia(). However, the page +// should not be stored in BFCache if the flag is enabled. +IN_PROC_BROWSER_TEST_P( + BackForwardCacheMediaTest, + DoesCacheIfMediaStreamTrackUsingGetDisplayMediaEndedButDoesNotWithoutFlags) { + ASSERT_TRUE(embedded_test_server()->Start()); + + // 1) Navigate to an empty page. + GURL url(embedded_test_server()->GetURL("/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), url)); + + RenderFrameHostWrapper rfh(current_frame_host()); + + // Request for video and audio display permission, and stop it. + EXPECT_EQ("success", EvalJs(rfh.get(), R"( + new Promise((resolve) => { + navigator.mediaDevices.getDisplayMedia({ audio: true }) + .then((mediaStream) => { + mediaStream.getTracks().forEach((track) => track.stop()); + resolve("success"); + }) + .catch((error) => { + resolve("error"); + }); + }); + )")); + + // 2) Navigate away. + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("b.com", "/title1.html"))); + + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // 3) Go back. When flag is enabled, an ended Media Stream Track doesn't + // block BFCache. + ASSERT_TRUE(HistoryGoBack(web_contents())); + ExpectRestored(FROM_HERE); } else { - // 3) Go back. kMediaDevicesDispatcherHost should be one of the blockers for - // BFCache when the flag is disabled. - // Also, kWasGrantedMediaAccess occurs after kMediaDevicesDispatcherHost. + ASSERT_TRUE(rfh.WaitUntilRenderFrameDeleted()); + + // 3) Go back. ASSERT_TRUE(HistoryGoBack(web_contents())); auto reason = BackForwardCacheDisable::DisabledReason( BackForwardCacheDisable::DisabledReasonId::kMediaDevicesDispatcherHost); @@ -4387,6 +4437,8 @@ // TODO(https://crbug.com/1213145): The test is consistently failing on some Mac // bots. +// This test uses Media Stream Track, so the test class is +// `BackForwardCacheMediaTest`. #if BUILDFLAG(IS_MAC) #define MAYBE_NonTrivialRTCPeerConnectionNotCached \ DISABLED_NonTrivialRTCPeerConnectionNotCached @@ -4394,7 +4446,7 @@ #define MAYBE_NonTrivialRTCPeerConnectionNotCached \ NonTrivialRTCPeerConnectionNotCached #endif -IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, +IN_PROC_BROWSER_TEST_P(BackForwardCacheMediaTest, MAYBE_NonTrivialRTCPeerConnectionNotCached) { ASSERT_TRUE(CreateHttpsServer()->Start()); @@ -4459,9 +4511,19 @@ // 3) Go back. ASSERT_TRUE(HistoryGoBack(web_contents())); - ExpectNotRestored({NotRestoredReason::kBlocklistedFeatures}, - {blink::scheduler::WebSchedulerTrackedFeature::kWebRTC}, {}, - {}, {}, FROM_HERE); + + if (IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // When the flag is enabled, a live Media Stream Track blocks BFCache. + ExpectNotRestored( + {NotRestoredReason::kBlocklistedFeatures}, + {blink::scheduler::WebSchedulerTrackedFeature::kWebRTC, + blink::scheduler::WebSchedulerTrackedFeature::kLiveMediaStreamTrack}, + {}, {}, {}, FROM_HERE); + } else { + ExpectNotRestored({NotRestoredReason::kBlocklistedFeatures}, + {blink::scheduler::WebSchedulerTrackedFeature::kWebRTC}, + {}, {}, {}, FROM_HERE); + } } #endif // !BUILDFLAG(IS_ANDROID)
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index 2de2f14..a1d569b 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -1626,6 +1626,8 @@ NOTREACHED_NORETURN(); case WebSchedulerTrackedFeature::kSmartCard: return Page::BackForwardCacheNotRestoredReasonEnum::SmartCard; + case WebSchedulerTrackedFeature::kLiveMediaStreamTrack: + return Page::BackForwardCacheNotRestoredReasonEnum::LiveMediaStreamTrack; } } @@ -1826,6 +1828,7 @@ case WebSchedulerTrackedFeature::kWebTransport: case WebSchedulerTrackedFeature::kIndexedDBEvent: case WebSchedulerTrackedFeature::kSmartCard: + case WebSchedulerTrackedFeature::kLiveMediaStreamTrack: return Page::BackForwardCacheNotRestoredReasonTypeEnum::PageSupportNeeded; case WebSchedulerTrackedFeature::kPortal: case WebSchedulerTrackedFeature::kWebNfc:
diff --git a/content/browser/network/quic_connection_migration_android_browsertest.cc b/content/browser/network/quic_connection_migration_android_browsertest.cc index de3f0c82..e41f087 100644 --- a/content/browser/network/quic_connection_migration_android_browsertest.cc +++ b/content/browser/network/quic_connection_migration_android_browsertest.cc
@@ -90,7 +90,8 @@ "QUIC/Enabled"); command_line->AppendSwitchASCII( switches::kForceFieldTrialParams, - "QUIC.Enabled:migrate_sessions_on_network_change_v2/true"); + "QUIC.Enabled:migrate_sessions_on_network_change_v2/true/" + "retry_without_alt_svc_on_quic_errors/false"); mock_cert_verifier_.SetUpCommandLine(command_line); ASSERT_TRUE(net::QuicSimpleTestServer::Start()); @@ -202,9 +203,11 @@ net::android::SetWifiEnabledForTesting(false); WaitForNetworkChange(); + // The subresource fetch should fail because the server closed the connection + // and retry is disabled. EvalJsResult result = ResolveDelayedResponse(); - EXPECT_TRUE(result.error.empty()) - << "Delayed response got error: '" << result.error << "'"; + EXPECT_FALSE(result.error.empty()); + EXPECT_EQ(histograms.GetTotalSum("Net.QuicProtocolError.RetryStatus"), 0); FetchHistogramsFromChildProcesses(); ASSERT_EQ(histograms.GetBucketCount(
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index cdecc34..4e680d0 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -49,6 +49,7 @@ #include "net/http/http_status_code.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h" #include "third_party/blink/public/mojom/frame/sudden_termination_disabler_type.mojom-shared.h" #if BUILDFLAG(IS_ANDROID) @@ -184,6 +185,7 @@ WebSchedulerTrackedFeature::kIndexedDBEvent, WebSchedulerTrackedFeature::kKeyboardLock, WebSchedulerTrackedFeature::kKeepaliveRequest, + WebSchedulerTrackedFeature::kLiveMediaStreamTrack, WebSchedulerTrackedFeature::kPaymentManager, WebSchedulerTrackedFeature::kPictureInPicture, WebSchedulerTrackedFeature::kPortal, @@ -966,12 +968,14 @@ PopulateStickyReasonsForDocument( BackForwardCacheCanStoreDocumentResult& result, RenderFrameHostImpl* rfh) { - // If the rfh has ever granted media access, prevent it from entering cache. - // TODO(crbug.com/989379): Consider only blocking when there's an active - // media stream. - if (rfh->was_granted_media_access()) { - result.No( - BackForwardCacheMetrics::NotRestoredReason::kWasGrantedMediaAccess); + if (!blink::features::IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + // `kWasGrantedMediaAccess` is no longer a BFCache blocker when the flag is + // enabled. With https://crbug.com/1502395, frames with only "live" Media + // Stream Track will be blocked from BFCache. + if (rfh->was_granted_media_access()) { + result.No( + BackForwardCacheMetrics::NotRestoredReason::kWasGrantedMediaAccess); + } } if (rfh->IsBackForwardCacheDisabled() && !ShouldIgnoreBlocklists()) {
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc index e1420156..edbb0e70 100644 --- a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc +++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -33,6 +33,7 @@ #include "media/capture/mojom/video_capture_types.mojom.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "services/service_manager/public/cpp/interface_provider.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/mediastream/media_devices.h" #include "third_party/blink/public/common/mediastream/media_stream_request.h" #include "url/origin.h" @@ -43,13 +44,6 @@ using blink::mojom::MediaDeviceType; -namespace features { -// When enabled, MediaDevicesDispatcherHost does not block back/forward cache. -BASE_FEATURE(kEnableBackForwardCacheForPagesWithMediaDevicesDispatcherHost, - "EnableBackForwardCacheForPagesWithMediaDevicesDispatcherHost", - base::FEATURE_DISABLED_BY_DEFAULT); -} // namespace features - namespace content { namespace { @@ -101,9 +95,8 @@ if (!render_frame_host) return; - if (!base::FeatureList::IsEnabled( - features:: - kEnableBackForwardCacheForPagesWithMediaDevicesDispatcherHost)) { + if (!blink::features:: + IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { BackForwardCache::DisableForRenderFrameHost( render_frame_host, BackForwardCacheDisable::DisabledReason(
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.h b/content/browser/renderer_host/media/media_devices_dispatcher_host.h index 32b70ed..aefaea82 100644 --- a/content/browser/renderer_host/media/media_devices_dispatcher_host.h +++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.h
@@ -24,11 +24,6 @@ #include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h" #include "url/origin.h" -namespace features { -CONTENT_EXPORT BASE_DECLARE_FEATURE( - kEnableBackForwardCacheForPagesWithMediaDevicesDispatcherHost); -} // namespace features - namespace content { class MediaStreamManager;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index a32f344..a279e78a 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -4517,9 +4517,10 @@ // frame and mouse up is on OOF iframe, the mouse up event is delivered to the // main frame as well to clear cached mouse states including autoscroll // selection state. +// TODO(crbug.com/1512574): This test was detected flaky. IN_PROC_BROWSER_TEST_F( WebContentsImplBrowserTest, - MouseUpInOOPIframeShouldCancelMainFrameAutoscrollSelection) { + DISABLED_MouseUpInOOPIframeShouldCancelMainFrameAutoscrollSelection) { ASSERT_TRUE(embedded_test_server()->Start()); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents());
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 67ef70a..e74c09e 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -442,10 +442,10 @@ # Flaky tests crbug.com/1489477 [ fuchsia fuchsia-board-astro ] conformance/more/conformance/quickCheck* [ Failure ] crbug.com/1489477 [ fuchsia web-engine-shell ] WebglExtension_EXT_float_blend [ Failure ] -crbug.com/1489477 [ fuchsia ] conformance/buffers/buffer-data-array-buffer-delete.html [ Failure ] -crbug.com/1489477 [ fuchsia ] conformance/buffers/element-array-buffer-delete-recreate.html [ Failure ] +crbug.com/1489477 [ fuchsia fuchsia-board-astro ] conformance/buffers/element-array-buffer-delete-recreate.html [ Failure ] crbug.com/1489477 [ fuchsia ] conformance/state/gl-object-get-calls.html [ Failure ] -crbug.com/1489477 [ fuchsia ] conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] +crbug.com/1489477 [ fuchsia fuchsia-board-nelson ] conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] +crbug.com/1489477 [ fuchsia fuchsia-board-sherlock ] conformance/textures/canvas/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] crbug.com/1489477 [ fuchsia ] conformance/textures/canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ Failure ] crbug.com/1489477 [ fuchsia ] conformance/textures/misc/texture-size-limit.html [ Failure ] crbug.com/1489477 [ fuchsia ] conformance/textures/misc/texture-sub-image-cube-maps.html [ Failure ]
diff --git a/gpu/command_buffer/client/client_shared_image.h b/gpu/command_buffer/client/client_shared_image.h index 8116b2a..1da54e7b 100644 --- a/gpu/command_buffer/client/client_shared_image.h +++ b/gpu/command_buffer/client/client_shared_image.h
@@ -106,6 +106,14 @@ Mailbox::GenerateForSharedImage()); } + static scoped_refptr<ClientSharedImage> CreateForTesting( + const Mailbox& mailbox, + std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer) { + auto client_si = base::MakeRefCounted<ClientSharedImage>(mailbox); + client_si->gpu_memory_buffer_ = std::move(gpu_memory_buffer); + return client_si; + } + private: friend class base::RefCountedThreadSafe<ClientSharedImage>; ~ClientSharedImage();
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.cc b/gpu/command_buffer/service/shared_image/shared_image_factory.cc index 976e9f9..7be6010 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
@@ -772,10 +772,23 @@ return true; } +bool SharedImageFactory::SetSharedImagePurgeable(const Mailbox& mailbox, + bool purgeable) { + auto it = shared_images_.find(mailbox); + if (it == shared_images_.end()) { + LOG(ERROR) + << "SetSharedImagePurgeable: Could not find shared image mailbox"; + return false; + } + (*it)->SetPurgeable(purgeable); + return true; +} + void SharedImageFactory::DestroyAllSharedImages(bool have_context) { if (!have_context) { - for (auto& shared_image : shared_images_) + for (auto& shared_image : shared_images_) { shared_image->OnContextLost(); + } } shared_images_.clear(); }
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.h b/gpu/command_buffer/service/shared_image/shared_image_factory.h index f0db175..db63eba 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.h +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.h
@@ -103,6 +103,7 @@ bool UpdateSharedImage(const Mailbox& mailbox, std::unique_ptr<gfx::GpuFence> in_fence); bool DestroySharedImage(const Mailbox& mailbox); + bool SetSharedImagePurgeable(const Mailbox& mailbox, bool purgeable); bool HasImages() const { return !shared_images_.empty(); } void DestroyAllSharedImages(bool have_context);
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation.h b/gpu/command_buffer/service/shared_image/shared_image_representation.h index d3a7d53..1dbf41bf 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_representation.h +++ b/gpu/command_buffer/service/shared_image/shared_image_representation.h
@@ -192,6 +192,7 @@ backing()->Update(std::move(in_fence)); backing()->OnWriteSucceeded(); } + void SetPurgeable(bool purgeable) { backing()->SetPurgeable(purgeable); } bool CopyToGpuMemoryBuffer() { return backing()->CopyToGpuMemoryBuffer(); } void GetGpuMemoryBufferHandleInfo(gfx::GpuMemoryBufferHandle& handle, viz::SharedImageFormat& format,
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 6f0acf2..60c9fca 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -4878,6 +4878,14 @@ <message name="IDS_IOS_TAB_GRID_UNDO_CLOSE_ALL_BUTTON" desc="Title of the button in the tab grid UI that revert the close all action recently taken by the user. [iOS only]"> Undo </message> + <message name="IDS_IOS_TAB_GROUP_CREATION_DATE" desc="Subtitle shown in tab group view to diplay the creation date of the group. [iOS only]"> + Created <ph name="Date"><ex>2023/12/31</ex>$1</ph> + </message> + <message name="IDS_IOS_TAB_GROUP_TABS_NUMBER" desc="Subtitle shown in tab group view to diplay the current number of tab in the group. [iOS only]"> + {count, plural, + =1 {1 Tab} + other {{count} Tabs}} + </message> <message name="IDS_IOS_TAB_PICKUP_BANNER_BUTTON" desc="Infobar button to open a previously opened tab from another device."> Open </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TAB_GROUP_CREATION_DATE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TAB_GROUP_CREATION_DATE.png.sha1 new file mode 100644 index 0000000..9c2001c --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TAB_GROUP_CREATION_DATE.png.sha1
@@ -0,0 +1 @@ +ddd5057fcf8773256caf4edc30212f15c3c11c80 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TAB_GROUP_TABS_NUMBER.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TAB_GROUP_TABS_NUMBER.png.sha1 new file mode 100644 index 0000000..9c2001c --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TAB_GROUP_TABS_NUMBER.png.sha1
@@ -0,0 +1 @@ +ddd5057fcf8773256caf4edc30212f15c3c11c80 \ No newline at end of file
diff --git a/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts b/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts index cdad824..8c8f086 100644 --- a/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts +++ b/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts
@@ -27,8 +27,12 @@ * @private */ function isObservable_(element: HTMLElement): boolean { - return (element instanceof HTMLInputElement) || - (element instanceof HTMLFormElement); + // Ignore passkey fields, which contain the 'webauthn' autofill tag. + const autocomplete_attribute = element.getAttribute('autocomplete'); + const isPasskeyField = autocomplete_attribute?.includes('webauthn'); + return ((element instanceof HTMLInputElement) || + (element instanceof HTMLFormElement)) && + !isPasskeyField; } /*
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 49362b3..c6e2322 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -249,24 +249,6 @@ std::size(kDefaultBrowserGenericConditionsHalfscreenPromo), nullptr}, }; -const FeatureEntry::FeatureParam - kAutofillUseMobileLabelDisambiguationShowAll[] = { - {autofill::features::kAutofillUseMobileLabelDisambiguationParameterName, - autofill::features:: - kAutofillUseMobileLabelDisambiguationParameterShowAll}}; -const FeatureEntry::FeatureParam - kAutofillUseMobileLabelDisambiguationShowOne[] = { - {autofill::features::kAutofillUseMobileLabelDisambiguationParameterName, - autofill::features:: - kAutofillUseMobileLabelDisambiguationParameterShowOne}}; - -const FeatureEntry::FeatureVariation - kAutofillUseMobileLabelDisambiguationVariations[] = { - {"(show all)", kAutofillUseMobileLabelDisambiguationShowAll, - std::size(kAutofillUseMobileLabelDisambiguationShowAll), nullptr}, - {"(show one)", kAutofillUseMobileLabelDisambiguationShowOne, - std::size(kAutofillUseMobileLabelDisambiguationShowOne), nullptr}}; - // Uses int values from SigninPromoViewStyle enum. const FeatureEntry::FeatureParam kDiscoverFeedTopSyncPromoStandard[] = { {kDiscoverFeedTopSyncPromoStyle, "0"}}; @@ -871,14 +853,6 @@ flag_descriptions::kOmniboxInspireMeSignedOutName, flag_descriptions::kOmniboxInspireMeSignedOutDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(omnibox::kZeroSuggestOnNTPForSignedOutUsers)}, - {"autofill-use-mobile-label-disambiguation", - flag_descriptions::kAutofillUseMobileLabelDisambiguationName, - flag_descriptions::kAutofillUseMobileLabelDisambiguationDescription, - flags_ui::kOsIos, - FEATURE_WITH_PARAMS_VALUE_TYPE( - autofill::features::kAutofillUseMobileLabelDisambiguation, - kAutofillUseMobileLabelDisambiguationVariations, - "AutofillUseMobileLabelDisambiguation")}, {"force-startup-signin-promo", flag_descriptions::kForceStartupSigninPromoName, flag_descriptions::kForceStartupSigninPromoDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 26091b04..3d59fb7 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -135,12 +135,6 @@ "When enabled, Chrome Settings link directs to GPay Web rather than " "Payments Center for payment methods management."; -const char kAutofillUseMobileLabelDisambiguationName[] = - "Autofill Uses Mobile Label Disambiguation"; -const char kAutofillUseMobileLabelDisambiguationDescription[] = - "When enabled, Autofill suggestions' labels are displayed using a " - "mobile-friendly format."; - const char kAutofillUseRendererIDsName[] = "Autofill logic uses unqiue renderer IDs"; const char kAutofillUseRendererIDsDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 14d33ef..8068b77 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -117,11 +117,6 @@ extern const char kAutofillUpdateChromeSettingsLinkToGPayWebDescription[]; // Title and description for the flag that controls whether Autofill's -// suggestions' labels are formatting with a mobile-friendly approach. -extern const char kAutofillUseMobileLabelDisambiguationName[]; -extern const char kAutofillUseMobileLabelDisambiguationDescription[]; - -// Title and description for the flag that controls whether Autofill's // logic is using numeric unique renderer IDs instead of string IDs for // form and field elements. extern const char kAutofillUseRendererIDsName[];
diff --git a/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm b/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm index 9a25f17..0cc8d8e 100644 --- a/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm +++ b/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm
@@ -462,9 +462,6 @@ } base::UmaHistogramCounts10000("Memory.Browser.MemoryFootprint.NumOpenTabs", open_tabs_count); - base::UmaHistogramCounts10000( - "Memory.Browser.MemoryFootprint.NumLiveOverscroll", - [OverscrollActionsController instanceCount]); std::move(collect_final_metrics_done_callback_).Run(); }
diff --git a/ios/chrome/browser/settings/model/sync/utils/sync_fake_server_egtest.mm b/ios/chrome/browser/settings/model/sync/utils/sync_fake_server_egtest.mm index 59b76dc..493d5bb 100644 --- a/ios/chrome/browser/settings/model/sync/utils/sync_fake_server_egtest.mm +++ b/ios/chrome/browser/settings/model/sync/utils/sync_fake_server_egtest.mm
@@ -54,6 +54,15 @@ @"Expected Autofill profile to be present"); } +void ClearRelevantData() { + [BookmarkEarlGrey clearBookmarks]; + + [ChromeEarlGrey clearFakeSyncServerData]; + WaitForEntitiesOnFakeServer(0, syncer::AUTOFILL_PROFILE); + WaitForEntitiesOnFakeServer(0, syncer::BOOKMARKS); + WaitForEntitiesOnFakeServer(0, syncer::HISTORY); +} + } // namespace // Hermetic sync tests, which use the fake sync server. @@ -62,29 +71,27 @@ @implementation SyncFakeServerTestCase -- (void)tearDown { ++ (void)setUpForTestCase { + [super setUpForTestCase]; + [BookmarkEarlGrey waitForBookmarkModelsLoaded]; - [BookmarkEarlGrey clearBookmarks]; - [ChromeEarlGrey clearFakeSyncServerData]; - - WaitForEntitiesOnFakeServer(0, syncer::AUTOFILL_PROFILE); - WaitForEntitiesOnFakeServer(0, syncer::BOOKMARKS); - WaitForEntitiesOnFakeServer(0, syncer::HISTORY); - - [super tearDown]; + // Normally there shouldn't be any data (locally or on the fake server) at + // this point, but just in case some other test case didn't clean up after + // itself, clear everything here. + ClearRelevantData(); } - (void)setUp { [super setUp]; GREYAssertTrue(self.testServer->Start(), @"Server did not start."); +} - [ChromeEarlGrey clearFakeSyncServerData]; +- (void)tearDown { + ClearRelevantData(); - WaitForEntitiesOnFakeServer(0, syncer::AUTOFILL_PROFILE); - WaitForEntitiesOnFakeServer(0, syncer::BOOKMARKS); - WaitForEntitiesOnFakeServer(0, syncer::HISTORY); + [super tearDown]; } - (AppLaunchConfiguration)appConfigurationForTestCase {
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm index 15d166d..bc8679ad 100644 --- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm +++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -1673,12 +1673,30 @@ // TODO(crbug.com/779791) : Do not pass `baseViewController` through dispatcher. - (void)showSignin:(ShowSigninCommand*)command baseViewController:(UIViewController*)baseViewController { + // Calling this method when there is a signinCoordinator alive is incorrect + // as there should not be 2 signinCoordinators alive at the same time (note + // that allocating the second one will dealloc the first and this crashes in + // various ways). if (command.skipIfUINotAvaible && (baseViewController.presentedViewController || ![self isTabAvailableToPresentViewController])) { // Make sure the UI is available to present the sign-in view. return; } + if (self.signinCoordinator) { + // As of M121, the CHECK above is known to fire in various cases. The goal + // of the histograms below is to detect the number of incorrect cases and + // for which of the access points they are triggered. + base::UmaHistogramEnumeration( + "Signin.ShowSigninCoordinatorWhenAlreadyPresent.NewAccessPoint", + command.accessPoint, signin_metrics::AccessPoint::ACCESS_POINT_MAX); + base::UmaHistogramEnumeration( + "Signin.ShowSigninCoordinatorWhenAlreadyPresent.OldAccessPoint", + self.signinCoordinator.accessPoint, + signin_metrics::AccessPoint::ACCESS_POINT_MAX); + } + // TODO(crbug.com/1479861): Change this to a CHECK once this invariant is + // correct. DCHECK(!self.signinCoordinator) << "self.signinCoordinator: " << base::SysNSStringToUTF8([self.signinCoordinator description]);
diff --git a/ios/chrome/browser/shared/ui/symbols/symbol_names.h b/ios/chrome/browser/shared/ui/symbols/symbol_names.h index cbf6fab..7c662509 100644 --- a/ios/chrome/browser/shared/ui/symbols/symbol_names.h +++ b/ios/chrome/browser/shared/ui/symbols/symbol_names.h
@@ -198,6 +198,7 @@ extern NSString* const kLockSymbol; extern NSString* const kRulerSymbol; extern NSString* const kLaptopAndIphoneSymbol; +extern NSString* const kNewTabGroupActionSymbol; // Names of the default symbol being non-monochrome by default. When using them, // you probably want to set their color to monochrome.
diff --git a/ios/chrome/browser/shared/ui/symbols/symbol_names.mm b/ios/chrome/browser/shared/ui/symbols/symbol_names.mm index 46727c8..f4ea8f3 100644 --- a/ios/chrome/browser/shared/ui/symbols/symbol_names.mm +++ b/ios/chrome/browser/shared/ui/symbols/symbol_names.mm
@@ -192,6 +192,7 @@ NSString* const kLockSymbol = @"lock"; NSString* const kRulerSymbol = @"ruler"; NSString* const kLaptopAndIphoneSymbol = @"laptopcomputer.and.iphone"; +NSString* const kNewTabGroupActionSymbol = @"plus.square.on.square"; // Names of the default symbol being non-monochrome by default. When using them, // you probably want to set their color to monochrome.
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_with_parental_controls_egtest.mm b/ios/chrome/browser/supervised_user/model/supervised_user_with_parental_controls_egtest.mm index e0b18c1..849dc65 100644 --- a/ios/chrome/browser/supervised_user/model/supervised_user_with_parental_controls_egtest.mm +++ b/ios/chrome/browser/supervised_user/model/supervised_user_with_parental_controls_egtest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "base/test/ios/wait_util.h" #import "components/policy/policy_constants.h" #import "components/supervised_user/core/browser/supervised_user_url_filter.h" #import "components/supervised_user/core/common/features.h" @@ -208,11 +209,17 @@ 1, [ChromeEarlGrey realizedWebStatesCount], @"A single realized web state must exist. The tab reloading filtering" @"behaviour should not force web states to become realized."); - GREYAssertEqual(1, - [SupervisedUserSettingsAppInterface - countSupervisedUserIntersitialsForExistingWebStates], - @"A single interstitial must exist."); - [ChromeEarlGrey waitForMainTabCount:3]; + + // Wait for one interstitial to appear (on the realized tab). + GREYAssert( + base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForPageLoadTimeout, + ^bool { + return + [SupervisedUserSettingsAppInterface + countSupervisedUserIntersitialsForExistingWebStates] == 1; + }), + @"Interstitial did not appear."); // Out of the 3 tabs, only the active one should have recorded metrics for // filtering.
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index e6bb03f7..c27311d 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -193,6 +193,7 @@ "//ios/chrome/browser/ui/sad_tab", "//ios/chrome/browser/ui/sad_tab:coordinator", "//ios/chrome/browser/ui/safe_browsing", + "//ios/chrome/browser/ui/save_to_drive", "//ios/chrome/browser/ui/save_to_photos", "//ios/chrome/browser/ui/send_tab_to_self", "//ios/chrome/browser/ui/settings/autofill",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index d428672..05436287 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -191,6 +191,7 @@ #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator_delegate.h" #import "ios/chrome/browser/ui/sad_tab/sad_tab_coordinator.h" #import "ios/chrome/browser/ui/safe_browsing/safe_browsing_coordinator.h" +#import "ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.h" #import "ios/chrome/browser/ui/save_to_photos/save_to_photos_coordinator.h" #import "ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_coordinator.h" #import "ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_coordinator.h" @@ -472,6 +473,9 @@ // Coordinator for Safe Browsing. @property(nonatomic, strong) SafeBrowsingCoordinator* safeBrowsingCoordinator; +// Coordinator for displaying the Save to Drive UI. +@property(nonatomic, strong) SaveToDriveCoordinator* saveToDriveCoordinator; + // Coordinator for displaying the Save to Photos UI. @property(nonatomic, strong) SaveToPhotosCoordinator* saveToPhotosCoordinator; @@ -658,6 +662,7 @@ - (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion dismissOmnibox:(BOOL)dismissOmnibox { [self stopSaveToPhotos]; + [self hideSaveToDrive]; [self.passKitCoordinator stop]; @@ -2624,11 +2629,20 @@ #pragma mark - SaveToDriveCommands - (void)showSaveToDrive:(ShowSaveToDriveCommand*)command { - // TODO(crbug.com/1495352): Start SaveToDriveCoordinator. + // If the Save to Drive coordinator is not nil, stop it. + [self hideSaveToDrive]; + + _saveToDriveCoordinator = [[SaveToDriveCoordinator alloc] + initWithBaseViewController:self.viewController + browser:self.browser + fileName:command.fileName + fileSize:command.fileSize]; + [_saveToDriveCoordinator start]; } - (void)hideSaveToDrive { - // TODO(crbug.com/1495352): Stop SaveToDriveCoordinator. + [_saveToDriveCoordinator stop]; + _saveToDriveCoordinator = nil; } #pragma mark - SaveToPhotosCommands
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_experimental.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_experimental.mm index 793b7e1..14f03786 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_experimental.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_experimental.mm
@@ -448,6 +448,18 @@ : [super caretRectForPosition:position]; } +- (NSArray<UITextSelectionRect*>*)selectionRectsForRange:(UITextRange*)range { + // Hide the selection UI in pre-edit. UITextField is expected to hide the + // selection UI when `clearsOnInsertion` is YES, but this behavior is not + // working on iOS 17. + if (@available(iOS 17, *)) { + if (self.isPreEditing) { + return nil; + } + } + return [super selectionRectsForRange:range]; +} + #pragma mark - UITextInput - (void)beginFloatingCursorAtPoint:(CGPoint)point {
diff --git a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_egtest.mm b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_egtest.mm index f59267d1..343d4e0 100644 --- a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_egtest.mm +++ b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_egtest.mm
@@ -196,6 +196,13 @@ [ChromeEarlGrey waitForWebStateContainingText:"Login form."]; } +- (void)loadLoginPasskeyPage { + // Loads simple page. It is on localhost so it is considered a secure context. + [ChromeEarlGrey + loadURL:self.testServer->GetURL("/simple_login_form_empty_passkey.html")]; + [ChromeEarlGrey waitForWebStateContainingText:"Login form."]; +} + // Returns the matcher for the edit button from the navigation bar. id<GREYMatcher> NavigationBarEditButton() { return grey_allOf(chrome_test_util::ButtonWithAccessibilityLabelId( @@ -302,6 +309,26 @@ GREYAssert(WaitForKeyboardToAppear(), @"Keyboard didn't appear."); } +// This test verifies that the password bottom sheet does not open when the +// webpage has enabled passkey login. +- (void)testOpenKeyboardOnPasskey { + [PasswordManagerAppInterface + storeCredentialWithUsername:@"user" + password:@"password" + URL:net::NSURLWithGURL(self.testServer->GetURL( + "/simple_login_form_empty_passkey." + "html"))]; + [SigninEarlGreyUI signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1] + enableSync:NO]; + + [self loadLoginPasskeyPage]; + + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElementWithId(kFormPassword)]; + + GREYAssert(WaitForKeyboardToAppear(), @"Keyboard didn't appear."); +} + // This test will allow us to know if we're using a coherent browser state to // open the bottom sheet in incognito mode. - (void)testOpenPasswordBottomSheetUsePasswordIncognito {
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index 95cd602c..2e4dbc9 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -176,6 +176,7 @@ @property(nonatomic, assign) sessions::TabRestoreService* tabRestoreService; // The sync state. @property(nonatomic, assign) SessionsSyncUserState sessionState; +// Mediator in charge of inviting the user to sign-in with a Google account. @property(nonatomic, strong) SigninPromoViewMediator* signinPromoViewMediator; // The browser state used for many operations, derived from the one provided by // `self.browser`. @@ -282,7 +283,9 @@ } if (self.syncService->GetUserSettings()->IsTypeManagedByPolicy( - syncer::UserSelectableType::kTabs)) { + syncer::UserSelectableType::kTabs) || + self.syncService->GetUserSettings()->IsTypeManagedByPolicy( + syncer::UserSelectableType::kHistory)) { // Return YES if the data type is disabled by the SyncTypesListDisabled // policy. return YES;
diff --git a/ios/chrome/browser/ui/save_to_drive/BUILD.gn b/ios/chrome/browser/ui/save_to_drive/BUILD.gn new file mode 100644 index 0000000..7c2d8e4 --- /dev/null +++ b/ios/chrome/browser/ui/save_to_drive/BUILD.gn
@@ -0,0 +1,15 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("save_to_drive") { + sources = [ + "save_to_drive_coordinator.h", + "save_to_drive_coordinator.mm", + ] + deps = [ + "//base", + "//ios/chrome/browser/shared/coordinator/chrome_coordinator", + ] + frameworks = [ "UIKit.framework" ] +}
diff --git a/ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.h b/ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.h new file mode 100644 index 0000000..acc32b7 --- /dev/null +++ b/ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.h
@@ -0,0 +1,23 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SAVE_TO_DRIVE_SAVE_TO_DRIVE_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_SAVE_TO_DRIVE_SAVE_TO_DRIVE_COORDINATOR_H_ + +#import "ios/chrome/browser/shared/coordinator/chrome_coordinator/chrome_coordinator.h" + +@interface SaveToDriveCoordinator : ChromeCoordinator + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + fileName:(NSString*)fileName + fileSize:(int64_t)fileSize + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SAVE_TO_DRIVE_SAVE_TO_DRIVE_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.mm b/ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.mm new file mode 100644 index 0000000..dc4836c8 --- /dev/null +++ b/ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.mm
@@ -0,0 +1,36 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/save_to_drive/save_to_drive_coordinator.h" + +@implementation SaveToDriveCoordinator { + NSString* _fileName; + int64_t _fileSize; + // TODO(crbug.com/1495352): Add an account picker coordinator to let the user + // select the identity with which they wish to save the file to Drive. +} + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + fileName:(NSString*)fileName + fileSize:(int64_t)fileSize { + self = [super initWithBaseViewController:viewController browser:browser]; + if (self) { + _fileName = fileName; + _fileSize = fileSize; + } + return self; +} + +#pragma mark - ChromeCoordinator + +- (void)start { + // TODO(crbug.com/1495352): Start the account picker coordinator. +} + +- (void)stop { + // TODO(crbug.com/1495352): Stop the account picker coordinator. +} + +@end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn index bb9ac7ad..b074eeb 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/BUILD.gn
@@ -33,10 +33,14 @@ ":tab_group_consumer", ":tab_group_mutator", "//base", + "//base:i18n", + "//ios/chrome/app/strings", "//ios/chrome/browser/shared/public/features", + "//ios/chrome/browser/shared/ui/symbols", "//ios/chrome/browser/ui/tab_switcher/tab_grid/grid:grid_ui_constants", "//ios/chrome/common/ui/colors", "//ios/chrome/common/ui/util", + "//ui/base", ] }
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 863acd6..12625a4 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
@@ -5,21 +5,30 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_view_controller.h" #import "base/check.h" +#import "base/i18n/time_formatting.h" +#import "base/strings/sys_string_conversions.h" #import "ios/chrome/browser/shared/public/features/features.h" +#import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_group_mutator.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_groups/tab_groups_commands.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" +#import "ios/chrome/grit/ios_strings.h" +#import "ui/base/l10n/l10n_util_mac.h" namespace { constexpr CGFloat kColoredDotSize = 20; +constexpr CGFloat kDotSeparationSize = 4; constexpr CGFloat kTitleHorizontalMargin = 16; constexpr CGFloat kTitleVerticalMargin = 10; -constexpr CGFloat kLeftMargin = 9; -constexpr CGFloat kFullTitleTopMargin = 24; +constexpr CGFloat kHorizontalMargin = 9; +constexpr CGFloat kPrimaryTitleMargin = 24; constexpr CGFloat kDotTitleSeparationMargin = 8; constexpr CGFloat kBackgroundAlpha = 0.6; +constexpr CGFloat kSubTitleHorizontalPadding = 7; +constexpr CGFloat kThreeDotButtonSize = 19; +constexpr CGFloat kTitleBackgroundCornerRadius = 17; } // namespace @interface TabGroupViewController () <UINavigationBarDelegate> @@ -67,7 +76,26 @@ } [self configureNavigationBar]; - [self configurePrimaryTitle]; + UIView* primaryTitle = [self configuredPrimaryTitle]; + UIView* secondaryTitle = [self configuredSubTitle]; + + [self.view addSubview:primaryTitle]; + [self.view addSubview:secondaryTitle]; + + [NSLayoutConstraint activateConstraints:@[ + [primaryTitle.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor + constant:kHorizontalMargin], + [primaryTitle.topAnchor constraintEqualToAnchor:_navigationBar.bottomAnchor + constant:kPrimaryTitleMargin], + [secondaryTitle.leadingAnchor + constraintEqualToAnchor:self.view.leadingAnchor + constant:kHorizontalMargin], + [secondaryTitle.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor + constant:-kHorizontalMargin], + [secondaryTitle.topAnchor constraintEqualToAnchor:primaryTitle.bottomAnchor + constant:kPrimaryTitleMargin], + ]]; } - (void)didTapPlusButton { @@ -192,13 +220,13 @@ return titleLabel; } -// Configures the full primary title (colored dot and text title). -- (void)configurePrimaryTitle { +// Returns the configured full primary title (colored dot and text title). +- (UIView*)configuredPrimaryTitle { UIView* fullTitleView = [[UIView alloc] initWithFrame:CGRectZero]; fullTitleView.translatesAutoresizingMaskIntoConstraints = NO; fullTitleView.backgroundColor = [[UIColor colorNamed:kSolidWhiteColor] colorWithAlphaComponent:0.1]; - fullTitleView.layer.cornerRadius = 17; + fullTitleView.layer.cornerRadius = kTitleBackgroundCornerRadius; fullTitleView.opaque = NO; UIView* coloredDotView = [self groupColorDotView]; @@ -206,18 +234,12 @@ [fullTitleView addSubview:coloredDotView]; [fullTitleView addSubview:titleView]; - [self.view addSubview:fullTitleView]; - [NSLayoutConstraint activateConstraints:@[ [titleView.leadingAnchor constraintEqualToAnchor:coloredDotView.trailingAnchor constant:kDotTitleSeparationMargin], [coloredDotView.centerYAnchor constraintEqualToAnchor:titleView.centerYAnchor], - [fullTitleView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor - constant:kLeftMargin], - [fullTitleView.topAnchor constraintEqualToAnchor:_navigationBar.bottomAnchor - constant:kFullTitleTopMargin], [coloredDotView.leadingAnchor constraintEqualToAnchor:fullTitleView.leadingAnchor constant:kTitleHorizontalMargin], @@ -229,6 +251,96 @@ [fullTitleView.bottomAnchor constraintEqualToAnchor:titleView.bottomAnchor constant:kTitleVerticalMargin], ]]; + return fullTitleView; +} + +// Returns the string with give the current number of tabs in the group. +- (NSString*)numberOfTabsString { + // TODO(crbug.com/1501837): Configure the string with the real number of + // items. + return l10n_util::GetPluralNSStringF(IDS_IOS_TAB_GROUP_TABS_NUMBER, 1); +} + +// Returns the string which give information about the creation date. +- (NSString*)creationDateString { + NSString* dateString = base::SysUTF16ToNSString( + base::LocalizedTimeFormatWithPattern(_groupCreationDate, "YYYY/MM/dd")); + return l10n_util::GetNSStringF(IDS_IOS_TAB_GROUP_CREATION_DATE, + base::SysNSStringToUTF16(dateString)); +} + +// Returns the configured sub titles view. +- (UIView*)configuredSubTitle { + UIView* subTitleView = [[UIView alloc] initWithFrame:CGRectZero]; + subTitleView.translatesAutoresizingMaskIntoConstraints = NO; + + UITraitCollection* interfaceStyleDarkTraitCollection = [UITraitCollection + traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark]; + UIColor* textColor = [[UIColor colorNamed:kTextSecondaryColor] + resolvedColorWithTraitCollection:interfaceStyleDarkTraitCollection]; + + UILabel* numberOfTabsLabel = [[UILabel alloc] init]; + numberOfTabsLabel.translatesAutoresizingMaskIntoConstraints = NO; + numberOfTabsLabel.textColor = textColor; + numberOfTabsLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + numberOfTabsLabel.text = [self numberOfTabsString]; + + UILabel* creationDateLabel = [[UILabel alloc] init]; + creationDateLabel.translatesAutoresizingMaskIntoConstraints = NO; + creationDateLabel.textColor = textColor; + creationDateLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + creationDateLabel.text = [self creationDateString]; + + UIView* dotSeparation = [[UIView alloc] initWithFrame:CGRectZero]; + dotSeparation.translatesAutoresizingMaskIntoConstraints = NO; + dotSeparation.layer.backgroundColor = textColor.CGColor; + dotSeparation.layer.cornerRadius = kDotSeparationSize / 2; + + // TODO(crbug.com/1501837): Add action to the button. + UIButton* menuButton = [[UIButton alloc] init]; + menuButton.translatesAutoresizingMaskIntoConstraints = NO; + [menuButton + setImage:DefaultSymbolWithPointSize(kMenuSymbol, kThreeDotButtonSize) + forState:UIControlStateNormal]; + menuButton.tintColor = [UIColor colorNamed:kSolidWhiteColor]; + + [subTitleView addSubview:numberOfTabsLabel]; + [subTitleView addSubview:dotSeparation]; + [subTitleView addSubview:creationDateLabel]; + [subTitleView addSubview:menuButton]; + + [NSLayoutConstraint activateConstraints:@[ + [numberOfTabsLabel.leadingAnchor + constraintEqualToAnchor:subTitleView.leadingAnchor + constant:kSubTitleHorizontalPadding], + [numberOfTabsLabel.topAnchor + constraintEqualToAnchor:subTitleView.topAnchor], + [subTitleView.heightAnchor + constraintEqualToAnchor:numberOfTabsLabel.heightAnchor], + [dotSeparation.leadingAnchor + constraintEqualToAnchor:numberOfTabsLabel.trailingAnchor + constant:kDotTitleSeparationMargin], + [dotSeparation.centerYAnchor + constraintEqualToAnchor:numberOfTabsLabel.centerYAnchor], + [dotSeparation.heightAnchor constraintEqualToConstant:kDotSeparationSize], + [dotSeparation.widthAnchor constraintEqualToConstant:kDotSeparationSize], + [creationDateLabel.leadingAnchor + constraintEqualToAnchor:dotSeparation.trailingAnchor + constant:kDotTitleSeparationMargin], + [creationDateLabel.centerYAnchor + constraintEqualToAnchor:numberOfTabsLabel.centerYAnchor], + [menuButton.trailingAnchor + constraintEqualToAnchor:subTitleView.trailingAnchor + constant:-kSubTitleHorizontalPadding], + [menuButton.centerYAnchor + constraintEqualToAnchor:numberOfTabsLabel.centerYAnchor], + [creationDateLabel.trailingAnchor + constraintLessThanOrEqualToAnchor:menuButton.leadingAnchor], + ]]; + + return subTitleView; } @end
diff --git a/ios/chrome/common/ui/promo_style/resources/BUILD.gn b/ios/chrome/common/ui/promo_style/resources/BUILD.gn index 2929c8c..def18a9 100644 --- a/ios/chrome/common/ui/promo_style/resources/BUILD.gn +++ b/ios/chrome/common/ui/promo_style/resources/BUILD.gn
@@ -18,6 +18,7 @@ sources = [ "promo_background_left.imageset/Contents.json", "promo_background_left.imageset/promo_background_left.pdf", + "promo_background_left.imageset/promo_background_left_dark.pdf", ] } @@ -25,5 +26,6 @@ sources = [ "promo_background_right.imageset/Contents.json", "promo_background_right.imageset/promo_background_right.pdf", + "promo_background_right.imageset/promo_background_right_dark.pdf", ] }
diff --git a/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/Contents.json b/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/Contents.json index 7c412807..f2b0c1b 100644 --- a/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/Contents.json +++ b/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/Contents.json
@@ -11,7 +11,7 @@ "value" : "dark" } ], - "filename" : "promo_background_left.pdf", + "filename" : "promo_background_left_dark.pdf", "idiom" : "universal" } ],
diff --git a/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/promo_background_left.pdf b/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/promo_background_left.pdf index a54512f..dd07493d 100644 --- a/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/promo_background_left.pdf +++ b/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/promo_background_left.pdf Binary files differ
diff --git a/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/promo_background_left_dark.pdf b/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/promo_background_left_dark.pdf new file mode 100644 index 0000000..45fc6b8 --- /dev/null +++ b/ios/chrome/common/ui/promo_style/resources/promo_background_left.imageset/promo_background_left_dark.pdf Binary files differ
diff --git a/ios/chrome/common/ui/promo_style/resources/promo_background_right.imageset/Contents.json b/ios/chrome/common/ui/promo_style/resources/promo_background_right.imageset/Contents.json index 69dc7127..c051e06 100644 --- a/ios/chrome/common/ui/promo_style/resources/promo_background_right.imageset/Contents.json +++ b/ios/chrome/common/ui/promo_style/resources/promo_background_right.imageset/Contents.json
@@ -11,7 +11,7 @@ "value" : "dark" } ], - "filename" : "promo_background_right.pdf", + "filename" : "promo_background_right_dark.pdf", "idiom" : "universal" } ],
diff --git a/ios/chrome/common/ui/promo_style/resources/promo_background_right.imageset/promo_background_right_dark.pdf b/ios/chrome/common/ui/promo_style/resources/promo_background_right.imageset/promo_background_right_dark.pdf new file mode 100644 index 0000000..3360bc9 --- /dev/null +++ b/ios/chrome/common/ui/promo_style/resources/promo_background_right.imageset/promo_background_right_dark.pdf Binary files differ
diff --git a/ios/testing/data/http_server_files/simple_login_form_empty_passkey.html b/ios/testing/data/http_server_files/simple_login_form_empty_passkey.html new file mode 100644 index 0000000..d9514cfe --- /dev/null +++ b/ios/testing/data/http_server_files/simple_login_form_empty_passkey.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> + +<html><body> +Login form. +<form name='login_form' id='login_form' action='https://google.com/'> + <input autocomplete='webauthn' type='text' name='username' id='un'><br/> + <input autocomplete='current-password webauthn' type='password' name='password' id='pw'><br/> + <button id='submit_button' value='Submit'>SubForm</button> +</form> +</body></html>
diff --git a/ios/testing/http_server_bundle_data.filelist b/ios/testing/http_server_bundle_data.filelist index f427f09..d7e04b0d 100644 --- a/ios/testing/http_server_bundle_data.filelist +++ b/ios/testing/http_server_bundle_data.filelist
@@ -47,6 +47,7 @@ data/http_server_files/simple_login_form.html data/http_server_files/simple_login_form_empty.html data/http_server_files/simple_login_form_empty_autofocus.html +data/http_server_files/simple_login_form_empty_passkey.html data/http_server_files/simple_signup_form.html data/http_server_files/single_page_wide.pdf data/http_server_files/state_operations.html
diff --git a/ios_internal b/ios_internal index e0a71e9..f94bc05 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit e0a71e95e946c2884c2980332683abf210fd3ffc +Subproject commit f94bc05bf5ee979b36eb2d58b336e469404524c1
diff --git a/media/audio/apple/audio_manager_apple.h b/media/audio/apple/audio_manager_apple.h index 94f251d..9a0c463 100644 --- a/media/audio/apple/audio_manager_apple.h +++ b/media/audio/apple/audio_manager_apple.h
@@ -41,6 +41,10 @@ // Refer main:media/audio/mac/audio_manager_mac.h for more details. virtual bool ShouldDeferStreamStart() const = 0; + // Retrieves the current hardware sample rate associated with a specified + // device. + virtual int HardwareSampleRateForDevice(AudioDeviceID device_id) = 0; + protected: AudioManagerApple(std::unique_ptr<AudioThread> audio_thread, AudioLogFactory* audio_log_factory);
diff --git a/media/audio/ios/audio_manager_ios.cc b/media/audio/ios/audio_manager_ios.cc index 2af0b78d..9d609390 100644 --- a/media/audio/ios/audio_manager_ios.cc +++ b/media/audio/ios/audio_manager_ios.cc
@@ -172,10 +172,6 @@ } // static -double AudioManagerIOS::HardwareSampleRate() { - return AudioSessionManagerIOS::GetInstance().HardwareSampleRate(); -} - double AudioManagerIOS::HardwareIOBufferDuration() { return AudioSessionManagerIOS::GetInstance().HardwareIOBufferDuration(); } @@ -202,6 +198,11 @@ return AudioSessionManagerIOS::GetInstance().IsInputMuted(); } +int AudioManagerIOS::HardwareSampleRateForDevice(AudioDeviceID device_id) { + return static_cast<int>( + AudioSessionManagerIOS::GetInstance().HardwareSampleRate()); +} + bool AudioManagerIOS::IsInputGainSettable() { return AudioSessionManagerIOS::GetInstance().IsInputGainSettable(); }
diff --git a/media/audio/ios/audio_manager_ios.h b/media/audio/ios/audio_manager_ios.h index ae71e7c..01dce9d 100644 --- a/media/audio/ios/audio_manager_ios.h +++ b/media/audio/ios/audio_manager_ios.h
@@ -98,11 +98,14 @@ // Returns the current muting state for the microphone. bool IsInputMuted(AudioDeviceID device_id) override; + // Retrieves the current hardware sample rate associated with a specified + // device. + int HardwareSampleRateForDevice(AudioDeviceID device_id) override; + // Check if delayed start for stream is needed. bool ShouldDeferStreamStart() const override; // Hardware information - double HardwareSampleRate(); double HardwareIOBufferDuration(); double HardwareLatency(bool is_input); long GetDeviceChannels(bool is_input);
diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc index 5b5af3dd..cb1fda2 100644 --- a/media/audio/mac/audio_low_latency_input_mac.cc +++ b/media/audio/mac/audio_low_latency_input_mac.cc
@@ -213,7 +213,7 @@ // The requested sample-rate must match the hardware sample-rate. const int sample_rate = - AudioManagerMac::HardwareSampleRateForDevice(input_device_id_); + manager_->HardwareSampleRateForDevice(input_device_id_); DCHECK_EQ(sample_rate, format_.mSampleRate); log_callback_.Run(base::StrCat( @@ -985,14 +985,6 @@ return noErr; } -int AUAudioInputStream::HardwareSampleRate() { - // Determine the default input device's sample-rate. - AudioDeviceID input_device_id = kAudioObjectUnknown; - AudioManagerMac::GetDefaultInputDevice(&input_device_id); - return static_cast<int>( - AudioManagerMac::HardwareSampleRateForDevice(input_device_id)); -} - base::TimeTicks AUAudioInputStream::GetCaptureTime( const AudioTimeStamp* input_time_stamp) { // Total latency is composed by the dynamic latency and the fixed
diff --git a/media/audio/mac/audio_low_latency_input_mac.h b/media/audio/mac/audio_low_latency_input_mac.h index bb3cb68..5fb98629 100644 --- a/media/audio/mac/audio_low_latency_input_mac.h +++ b/media/audio/mac/audio_low_latency_input_mac.h
@@ -25,7 +25,6 @@ // // - It is recommended to first acquire the native sample rate of the default // input device and then use the same rate when creating this object. -// Use AUAudioInputStream::HardwareSampleRate() to retrieve the sample rate. // - Calling Close() also leads to self destruction. // - The latency consists of two parts: // 1) Hardware latency, which includes Audio Unit latency, audio device @@ -89,9 +88,6 @@ bool IsMuted() override; void SetOutputDeviceForAec(const std::string& output_device_id) override; - // Returns the current hardware sample rate for the default input device. - static int HardwareSampleRate(); - // Returns true if the audio unit is active/running. // The result is based on the kAudioOutputUnitProperty_IsRunning property // which exists for output units.
diff --git a/media/audio/mac/audio_low_latency_input_mac_unittest.cc b/media/audio/mac/audio_low_latency_input_mac_unittest.cc index b4ceb0b..f8a5a70 100644 --- a/media/audio/mac/audio_low_latency_input_mac_unittest.cc +++ b/media/audio/mac/audio_low_latency_input_mac_unittest.cc
@@ -139,11 +139,19 @@ #endif } + int HardwareSampleRateForDefaultInputDevice() { + // Determine the default input device's sample-rate. + AudioDeviceID input_device_id = kAudioObjectUnknown; + AudioManagerMac::GetDefaultInputDevice(&input_device_id); + auto* manager = static_cast<AudioManagerApple*>(audio_manager_.get()); + return manager->HardwareSampleRateForDevice(input_device_id); + } + // Convenience method which creates a default AudioInputStream object using // a 10ms frame size and a sample rate which is set to the hardware sample // rate. AudioInputStream* CreateDefaultAudioInputStream() { - int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); + int fs = HardwareSampleRateForDefaultInputDevice(); int samples_per_packet = fs / 100; AudioInputStream* ais = audio_manager_->MakeAudioInputStream( AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, @@ -159,7 +167,7 @@ // specified channel layout. AudioInputStream* CreateAudioInputStream( ChannelLayoutConfig channel_layout_config) { - int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); + int fs = HardwareSampleRateForDefaultInputDevice(); int samples_per_packet = fs / 100; AudioInputStream* ais = audio_manager_->MakeAudioInputStream( AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, @@ -289,7 +297,7 @@ ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable()); const char* file_name = "out_stereo_10sec.pcm"; - int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); + int fs = HardwareSampleRateForDefaultInputDevice(); AudioInputStream* ais = CreateDefaultAudioInputStream(); EXPECT_EQ(ais->Open(), AudioInputStream::OpenOutcome::kSuccess);
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc index cfbd2f1..7f07999 100644 --- a/media/audio/mac/audio_manager_mac.cc +++ b/media/audio/mac/audio_manager_mac.cc
@@ -652,27 +652,6 @@ } // static -int AudioManagerMac::HardwareSampleRateForDevice(AudioDeviceID device_id) { - DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); - Float64 nominal_sample_rate; - UInt32 info_size = sizeof(nominal_sample_rate); - - static const AudioObjectPropertyAddress kNominalSampleRateAddress = { - kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMain}; - OSStatus result = - AudioObjectGetPropertyData(device_id, &kNominalSampleRateAddress, 0, 0, - &info_size, &nominal_sample_rate); - if (result != noErr) { - OSSTATUS_DLOG(WARNING, result) - << "Could not get default sample rate for device: " << device_id - << ", returing fallback sample rate " << kFallbackSampleRate; - return kFallbackSampleRate; - } - - return static_cast<int>(nominal_sample_rate); -} - void AudioManagerMac::GetAudioInputDeviceNames( media::AudioDeviceNames* device_names) { DCHECK(device_names->empty()); @@ -1464,6 +1443,27 @@ return result == noErr && muted != 0; } +int AudioManagerMac::HardwareSampleRateForDevice(AudioDeviceID device_id) { + DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); + Float64 nominal_sample_rate; + UInt32 info_size = sizeof(nominal_sample_rate); + + static const AudioObjectPropertyAddress kNominalSampleRateAddress = { + kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMain}; + OSStatus result = + AudioObjectGetPropertyData(device_id, &kNominalSampleRateAddress, 0, 0, + &info_size, &nominal_sample_rate); + if (result != noErr) { + OSSTATUS_DLOG(WARNING, result) + << "Could not get default sample rate for device: " << device_id + << ", returing fallback sample rate " << kFallbackSampleRate; + return kFallbackSampleRate; + } + + return static_cast<int>(nominal_sample_rate); +} + // static AudioDeviceID AudioManagerMac::FindFirstOutputSubdevice( AudioDeviceID aggregate_device_id) {
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h index 8761484..1183932 100644 --- a/media/audio/mac/audio_manager_mac.h +++ b/media/audio/mac/audio_manager_mac.h
@@ -118,7 +118,10 @@ // Returns the current muting state for the microphone. bool IsInputMuted(AudioDeviceID device_id) override; - static int HardwareSampleRateForDevice(AudioDeviceID device_id); + // Retrieves the current hardware sample rate associated with a specified + // device. + int HardwareSampleRateForDevice(AudioDeviceID device_id) override; + static bool GetDefaultInputDevice(AudioDeviceID* input_device); static bool GetDefaultOutputDevice(AudioDeviceID* output_device); static AudioDeviceID GetAudioDeviceIdByUId(bool is_input,
diff --git a/testing/libfuzzer/fuzzing_browsertests.md b/testing/libfuzzer/fuzzing_browsertests.md index 3bdce35..c898d972 100644 --- a/testing/libfuzzer/fuzzing_browsertests.md +++ b/testing/libfuzzer/fuzzing_browsertests.md
@@ -22,7 +22,7 @@ # Writing an in process fuzz case * Use the template `chrome/test/fuzzing/in_process_fuzzer.gni` -* Provide a source code file which inherits from `InProcessFuzzTest`. This +* Provide a source code file which inherits from `InProcessFuzzer`. This must override the `Fuzz` method. You'll find that your base class inherits from the full browser test infrastructure, so you can do anything you'd do in a normal Chrome browser test.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index eff7cc9b..f90261559 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1276,6 +1276,28 @@ ] } ], + "AutofillEnableCacheForRegexMatching": [ + { + "platforms": [ + "android", + "android_webview", + "chromeos", + "chromeos_lacros", + "ios", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillEnableCacheForRegexMatching" + ] + } + ] + } + ], "AutofillEnableCardArtAndCardProductName": [ { "platforms": [ @@ -2633,29 +2655,6 @@ ] } ], - "BlinkSchedulerPrioritizeNavigationIPCs": [ - { - "platforms": [ - "android", - "android_weblayer", - "android_webview", - "chromeos", - "chromeos_lacros", - "fuchsia", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "BlinkSchedulerPrioritizeNavigationIPCs" - ] - } - ] - } - ], "BlockMidiByDefault": [ { "platforms": [ @@ -10127,21 +10126,6 @@ ] } ], - "LanguagePacksBasePack": [ - { - "platforms": [ - "chromeos" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "HandwritingLibraryDlc" - ] - } - ] - } - ], "LauncherGameSearchStudy": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index 40f4de8..d704273 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 40f4de8fa1ff252fd57552a6a1d5cf4067f83883 +Subproject commit d704273d78967f286c300d445bdc0eb9f43b2389
diff --git a/third_party/beto-core/BUILD.gn b/third_party/beto-core/BUILD.gn index 960942f2..fe8724a7 100644 --- a/third_party/beto-core/BUILD.gn +++ b/third_party/beto-core/BUILD.gn
@@ -4,21 +4,124 @@ assert(is_chromeos, "beto-core is used by Nearby Presence which is CrOS only") -import("//build/rust/cargo_crate.gni") import("//build/rust/rust_static_library.gni") import("//build/rust/rust_unit_test.gni") import("//build/rust/rust_unit_tests_group.gni") import("//testing/test.gni") -executable("ldt_c_sample") { - sources = [ "src/nearby/presence/ldt_np_c_sample/main.c" ] - include_dirs = [ "src/nearby/presence/ldt_np_adv_ffi/include" ] - deps = [ ":ldt_np_adv_ffi" ] +test("np_cpp_tests") { + sources = [ + "src/nearby/presence/np_cpp_ffi/shared/shared_test_util.cc", + "src/nearby/presence/np_cpp_ffi/tests/byte_buffer_tests.cc", + "src/nearby/presence/np_cpp_ffi/tests/credential_book_tests.cc", + "src/nearby/presence/np_cpp_ffi/tests/credential_slab_tests.cc", + "src/nearby/presence/np_cpp_ffi/tests/deserialize_result_tests.cc", + "src/nearby/presence/np_cpp_ffi/tests/deserialize_v0_tests.cc", + "src/nearby/presence/np_cpp_ffi/tests/deserialize_v1_tests.cc", + "src/nearby/presence/np_cpp_ffi/tests/np_cpp_test.cc", + "src/nearby/presence/np_cpp_ffi/tests/np_cpp_test.h", + ] + include_dirs = [ + "src/nearby/presence/np_cpp_ffi/include", + "src/nearby/presence/np_c_ffi/include/cpp", + "src/nearby/presence/np_cpp_ffi/shared", + ] + deps = [ + ":nearby_protocol", + "//base/test:run_all_unittests", + "//testing/gtest", + ] } -cargo_crate("np_adv") { - build_native_rust_unit_tests = false - crate_type = "rlib" +executable("np_rust_sample") { + sources = [ "src/nearby/presence/np_cpp_ffi/sample/main.cc" ] + include_dirs = [ + "src/nearby/presence/np_cpp_ffi/include", + "src/nearby/presence/np_c_ffi/include/cpp", + ] + deps = [ ":nearby_protocol" ] +} + +source_set("nearby_protocol") { + sources = [ "src/nearby/presence/np_cpp_ffi/nearby_protocol.cc" ] + public = [ + "src/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_types.h", + "src/nearby/presence/np_cpp_ffi/include/nearby_protocol.h", + ] + include_dirs = [ "src/nearby/presence/np_c_ffi/include/cpp" ] + public_deps = [ "//third_party/abseil-cpp:absl" ] + deps = [ ":np_c_ffi" ] +} + +rust_static_library("np_c_ffi") { + crate_root = "src/nearby/presence/np_c_ffi/src/lib.rs" + sources = [ + "src/nearby/presence/np_c_ffi/src/credentials.rs", + "src/nearby/presence/np_c_ffi/src/deserialize/mod.rs", + "src/nearby/presence/np_c_ffi/src/deserialize/v0.rs", + "src/nearby/presence/np_c_ffi/src/deserialize/v1.rs", + "src/nearby/presence/np_c_ffi/src/lib.rs", + ] + deps = [ + ":lock_adapter", + ":np_ffi_core", + ] + features = [ "boringssl" ] + allow_unsafe = true +} + +rust_static_library("np_ffi_core") { + crate_root = "src/nearby/presence/np_ffi_core/src/lib.rs" + sources = [ + "src/nearby/presence/np_ffi_core/src/common.rs", + "src/nearby/presence/np_ffi_core/src/credentials.rs", + "src/nearby/presence/np_ffi_core/src/deserialize/mod.rs", + "src/nearby/presence/np_ffi_core/src/deserialize/v0.rs", + "src/nearby/presence/np_ffi_core/src/deserialize/v1.rs", + "src/nearby/presence/np_ffi_core/src/lib.rs", + "src/nearby/presence/np_ffi_core/src/utils.rs", + ] + deps = [ + ":array_view", + ":crypto_provider", + ":crypto_provider_default", + ":handle_map", + ":ldt_np_adv", + ":lock_adapter", + ":np_adv", + ":np_hkdf", + "//third_party/rust/lazy_static/v1:lib", + ] + features = [ "boringssl" ] +} + +rust_static_library("handle_map") { + build_native_rust_unit_tests = true + crate_root = "src/nearby/util/handle_map/src/lib.rs" + sources = [ + "src/nearby/util/handle_map/src/declare_handle_map.rs", + "src/nearby/util/handle_map/src/guard.rs", + "src/nearby/util/handle_map/src/lib.rs", + "src/nearby/util/handle_map/src/shard.rs", + "src/nearby/util/handle_map/src/tests.rs", + ] + deps = [ ":lock_adapter" ] +} + +rust_static_library("lock_adapter") { + build_native_rust_unit_tests = true + crate_root = "src/nearby/util/lock_adapter/src/lib.rs" + sources = [ + "src/nearby/util/lock_adapter/src/lib.rs", + "src/nearby/util/lock_adapter/src/spin.rs", + "src/nearby/util/lock_adapter/src/std.rs", + ] + features = [ "std" ] +} + +rust_static_library("np_adv") { + build_native_rust_unit_tests = true + crate_root = "src/nearby/presence/np_adv/src/lib.rs" sources = [ "src/nearby/presence/np_adv/src/array_vec.rs", @@ -85,11 +188,48 @@ "//third_party/rust/strum_macros/v0_25:lib", "//third_party/rust/tinyvec/v1:lib", ] + test_deps = [ + ":crypto_provider_default", + ":rand_ext", + ":test_helper", + "//third_party/rust/anyhow/v1:lib", + "//third_party/rust/hex/v0_4:lib", + "//third_party/rust/rand/v0_8:lib", + "//third_party/rust/serde_json/v1:lib", + ] + features = [ "alloc" ] } -cargo_crate("np_ed25519") { - crate_type = "rlib" - build_native_rust_unit_tests = false +rust_unit_test("np_adv_examples_v0") { + crate_root = "src/nearby/presence/np_adv/tests/examples_v0.rs" + sources = [ "src/nearby/presence/np_adv/tests/examples_v0.rs" ] + deps = [ + ":crypto_provider", + ":crypto_provider_default", + ":ldt_np_adv", + ":np_adv", + ":np_hkdf", + "//third_party/rust/serde/v1:lib", + "//third_party/rust/serde_json/v1:lib", + ] +} + +rust_unit_test("np_adv_examples_v1") { + crate_root = "src/nearby/presence/np_adv/tests/examples_v1.rs" + sources = [ "src/nearby/presence/np_adv/tests/examples_v1.rs" ] + deps = [ + ":crypto_provider", + ":crypto_provider_default", + ":ldt_np_adv", + ":np_adv", + ":np_ed25519", + ":np_hkdf", + "//third_party/rust/serde/v1:lib", + "//third_party/rust/serde_json/v1:lib", + ] +} + +rust_static_library("np_ed25519") { crate_root = "src/nearby/presence/np_ed25519/src/lib.rs" sources = [ "src/nearby/presence/np_ed25519/src/lib.rs" ] deps = [ @@ -98,14 +238,20 @@ ":sink", "//third_party/rust/tinyvec/v1:lib", ] + features = [ "std" ] } -cargo_crate("sink") { - crate_type = "rlib" - build_native_rust_unit_tests = false +rust_static_library("sink") { crate_root = "src/nearby/presence/sink/src/lib.rs" sources = [ "src/nearby/presence/sink/src/lib.rs" ] deps = [ "//third_party/rust/tinyvec/v1:lib" ] + features = [ "std" ] +} + +executable("ldt_c_sample") { + sources = [ "src/nearby/presence/ldt_np_c_sample/main.c" ] + include_dirs = [ "src/nearby/presence/ldt_np_adv_ffi/include" ] + deps = [ ":ldt_np_adv_ffi" ] } test("ldt_ffi_tests") { @@ -140,9 +286,9 @@ ] } -cargo_crate("crypto_provider_boringssl") { +rust_static_library("crypto_provider_boringssl") { build_native_rust_unit_tests = true - crate_type = "rlib" + crate_root = "src/nearby/crypto/crypto_provider_boringssl/src/lib.rs" sources = [ "src/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm.rs", @@ -164,12 +310,10 @@ ":crypto_provider_stubs", "//third_party/boringssl:bssl_crypto", ] - dev_deps = [ ":crypto_provider_test" ] + test_deps = [ ":crypto_provider_test" ] } -cargo_crate("crypto_provider") { - build_native_rust_unit_tests = false - crate_type = "rlib" +rust_static_library("crypto_provider") { crate_root = "src/nearby/crypto/crypto_provider/src/lib.rs" sources = [ "src/nearby/crypto/crypto_provider/src/aead.rs", @@ -193,10 +337,8 @@ deps = [ "//third_party/rust/tinyvec/v1:lib" ] } -cargo_crate("crypto_provider_test") { - build_native_rust_unit_tests = false +rust_static_library("crypto_provider_test") { testonly = true - crate_type = "rlib" crate_root = "src/nearby/crypto/crypto_provider_test/src/lib.rs" sources = [ "src/nearby/crypto/crypto_provider_test/src/lib.rs" ] deps = [ @@ -212,18 +354,13 @@ ] } -cargo_crate("crypto_provider_stubs") { - build_native_rust_unit_tests = false - crate_type = "rlib" +rust_static_library("crypto_provider_stubs") { crate_root = "src/nearby/crypto/crypto_provider_stubs/src/lib.rs" sources = [ "src/nearby/crypto/crypto_provider_stubs/src/lib.rs" ] deps = [ ":crypto_provider" ] } -cargo_crate("crypto_provider_default") { - testonly = true - build_native_rust_unit_tests = false - crate_type = "rlib" +rust_static_library("crypto_provider_default") { crate_root = "src/nearby/crypto/crypto_provider_default/src/lib.rs" sources = [ "src/nearby/crypto/crypto_provider_default/src/lib.rs" ] edition = "2021" @@ -235,8 +372,7 @@ features = [ "boringssl" ] } -cargo_crate("ldt_np_adv") { - crate_type = "rlib" +rust_static_library("ldt_np_adv") { build_native_rust_unit_tests = true crate_root = "src/nearby/presence/ldt_np_adv/src/lib.rs" sources = [ "src/nearby/presence/ldt_np_adv/src/lib.rs" ] @@ -248,7 +384,7 @@ ":np_hkdf", ":xts_aes", ] - dev_deps = [ + test_deps = [ ":crypto_provider_default", ":rand_ext", ":test_helper", @@ -259,9 +395,7 @@ ] } -cargo_crate("ldt") { - crate_type = "rlib" - build_native_rust_unit_tests = false +rust_static_library("ldt") { crate_root = "src/nearby/presence/ldt/src/lib.rs" sources = [ "src/nearby/presence/ldt/src/lib.rs" ] deps = [ @@ -322,31 +456,24 @@ ] } -cargo_crate("ldt_tbc") { - crate_type = "rlib" - build_native_rust_unit_tests = false +rust_static_library("ldt_tbc") { crate_root = "src/nearby/presence/ldt_tbc/src/lib.rs" sources = [ "src/nearby/presence/ldt_tbc/src/lib.rs" ] deps = [ ":crypto_provider" ] } -cargo_crate("array_view") { - crate_type = "rlib" +rust_static_library("array_view") { build_native_rust_unit_tests = true crate_root = "src/nearby/presence/array_view/src/lib.rs" sources = [ "src/nearby/presence/array_view/src/lib.rs" ] } -cargo_crate("array_ref") { - crate_type = "rlib" - build_native_rust_unit_tests = false +rust_static_library("array_ref") { crate_root = "src/nearby/presence/array_ref/src/lib.rs" sources = [ "src/nearby/presence/array_ref/src/lib.rs" ] } -cargo_crate("np_hkdf") { - crate_type = "rlib" - build_native_rust_unit_tests = false +rust_static_library("np_hkdf") { crate_root = "src/nearby/presence/np_hkdf/src/lib.rs" sources = [ "src/nearby/presence/np_hkdf/src/lib.rs", @@ -375,8 +502,7 @@ ] } -cargo_crate("xts_aes") { - crate_type = "rlib" +rust_static_library("xts_aes") { build_native_rust_unit_tests = true crate_root = "src/nearby/presence/xts_aes/src/lib.rs" sources = [ "src/nearby/presence/xts_aes/src/lib.rs" ] @@ -385,7 +511,7 @@ ":crypto_provider", ":ldt_tbc", ] - dev_deps = [ + test_deps = [ ":test_helper", "//third_party/rust/hex/v0_4:lib", ] @@ -419,11 +545,8 @@ ] } -# rust test targets -cargo_crate("test_helper") { +rust_static_library("test_helper") { testonly = true - build_native_rust_unit_tests = false - crate_type = "rlib" crate_root = "src/nearby/presence/test_helper/src/lib.rs" sources = [ "src/nearby/presence/test_helper/src/lib.rs" ] edition = "2021" @@ -434,11 +557,8 @@ ] } -# rust test targets -cargo_crate("rand_ext") { +rust_static_library("rand_ext") { testonly = true - build_native_rust_unit_tests = false - crate_type = "rlib" crate_root = "src/nearby/presence/rand_ext/src/lib.rs" sources = [ "src/nearby/presence/rand_ext/src/lib.rs" ] edition = "2021"
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index fcb7e4f..11cfff4 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -54,6 +54,12 @@ "AdInterestGroupAPIRestrictedPolicyByDefault", base::FEATURE_DISABLED_BY_DEFAULT); +// Make MediaDevicesDispatcherHost and ended MediaStreamTrack not block BFCache. +// See https://chrbug.com/1502395 for more details. +BASE_FEATURE(kAllowBFCacheWhenClosedMediaStreamTrack, + "AllowBFCacheWhenClosedMediaStreamTrack", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kComputePressureRateObfuscationMitigation, "ComputePressureRateObfuscationMitigation", base::FEATURE_ENABLED_BY_DEFAULT); @@ -2271,6 +2277,11 @@ return base::FeatureList::IsEnabled(blink::features::kAllowURNsInIframes); } +bool IsAllowBFCacheWhenClosedMediaStreamTrackEnabled() { + return base::FeatureList::IsEnabled( + blink::features::kAllowBFCacheWhenClosedMediaStreamTrack); +} + bool IsFencedFramesEnabled() { return base::FeatureList::IsEnabled(blink::features::kFencedFrames); }
diff --git a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc index 8fb17f0..d80a45af 100644 --- a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc +++ b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
@@ -134,6 +134,8 @@ return {"WebSerial", "Serial port open"}; case WebSchedulerTrackedFeature::kSmartCard: return {"SmartCard", "SmartCardContext used"}; + case WebSchedulerTrackedFeature::kLiveMediaStreamTrack: + return {"LiveMediaStreamTrack", "page has live MediaStreamTrack"}; } return {}; }
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 4df0611..1a6905f 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -51,6 +51,9 @@ kAdInterestGroupAPIRestrictedPolicyByDefault); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( + kAllowBFCacheWhenClosedMediaStreamTrack); + +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( kAlignFontDisplayAutoTimeoutWithLCPGoal); BLINK_COMMON_EXPORT extern const base::FeatureParam<int> kAlignFontDisplayAutoTimeoutWithLCPGoalTimeoutParam; @@ -147,7 +150,6 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( kBackForwardCacheDWCOnJavaScriptExecution); - BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheWithKeepaliveRequest); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBackgroundResourceFetch); @@ -398,7 +400,6 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<int> kDeprecateUnloadBucket; BLINK_COMMON_EXPORT extern const base::FeatureParam<std::string> kDeprecateUnloadAllowlist; - // This feature (EventTimingReportAllEarlyEntriesOnPaintedPresentation) is // having an effect only when EventTimingMatchPresentationIndex is turned on. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( @@ -1468,6 +1469,8 @@ // Helper functions for querying feature status. Please declare any features or // constants for features in the section above. +BLINK_COMMON_EXPORT bool IsAllowBFCacheWhenClosedMediaStreamTrackEnabled(); + BLINK_COMMON_EXPORT int GetMaxUnthrottledTimeoutNestingLevel(); // Checks both of kAllowPageWithIDBConnectionInBFCache and
diff --git a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h index 8936826..1d3a82a 100644 --- a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h +++ b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
@@ -147,13 +147,14 @@ // See comments for `kWebTransportSticky`. kWebSocketSticky = 63, kWebRTCSticky = 64, - kSmartCard = 65, + // There is a "live" MediaStreamTrack. + kLiveMediaStreamTrack = 66, // Please keep in sync with WebSchedulerTrackedFeature in // tools/metrics/histograms/enums.xml. These values should not be renumbered. - kMaxValue = kSmartCard, + kMaxValue = kLiveMediaStreamTrack, }; using WebSchedulerTrackedFeatures =
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index ff76494..447c534 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -8903,6 +8903,7 @@ WebTransportSticky WebSocketSticky SmartCard + LiveMediaStreamTrack # Disabled for RenderFrameHost reasons # See content/browser/renderer_host/back_forward_cache_disable.h for explanations. ContentSecurityHandler
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc index e497771..fd81b966 100644 --- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -296,8 +296,6 @@ // Use the global proxy as window wrapper object. V8DOMWrapper::SetNativeInfo(GetIsolate(), global_proxy, wrapper_type_info, window); - // Mark the handle to be traced by Oilpan, since the global proxy has a - // reference to the DOMWindow. CHECK(global_proxy_ == window->AssociateWithWrapper(GetIsolate(), world_, wrapper_type_info, global_proxy));
diff --git a/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc index 59439de..3caa238f 100644 --- a/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc
@@ -133,6 +133,8 @@ // The global proxy object. Note this is not the global object. v8::Local<v8::Object> global_proxy = global_proxy_.Get(GetIsolate()); + V8DOMWrapper::SetNativeInfo(GetIsolate(), global_proxy, wrapper_type_info, + window); CHECK(global_proxy == window->AssociateWithWrapper(GetIsolate(), world_, wrapper_type_info, global_proxy));
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc index 38942bc..a308d63 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.cc
@@ -27,8 +27,10 @@ #include <memory> +#include "base/check_op.h" #include "base/functional/callback_helpers.h" #include "build/build_config.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h" #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" @@ -416,6 +418,7 @@ setReadyState(MediaStreamSource::kReadyStateEnded); feature_handle_for_scheduler_.reset(); + feature_handle_for_scheduler_on_live_media_stream_track_.reset(); UserMediaClient* user_media_client = UserMediaClient::From(To<LocalDOMWindow>(execution_context)); if (user_media_client) { @@ -857,6 +860,8 @@ } PropagateTrackEnded(); feature_handle_for_scheduler_.reset(); + feature_handle_for_scheduler_on_live_media_stream_track_.reset(); + break; } SendLogMessage(String::Format("%s()", __func__)); @@ -1062,9 +1067,18 @@ } void MediaStreamTrackImpl::EnsureFeatureHandleForScheduler() { + // The two handlers must be in sync. + if (features::IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + CHECK_EQ(!!feature_handle_for_scheduler_, + !!feature_handle_for_scheduler_on_live_media_stream_track_); + } else { + CHECK(!feature_handle_for_scheduler_on_live_media_stream_track_); + } + if (feature_handle_for_scheduler_) { return; } + LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(GetExecutionContext()); // Ideally we'd use To<LocalDOMWindow>, but in unittests the ExecutionContext // may not be a LocalDOMWindow. @@ -1080,6 +1094,12 @@ SchedulingPolicy::Feature::kWebRTC, {SchedulingPolicy::DisableAggressiveThrottling(), SchedulingPolicy::DisableAlignWakeUps()}); + if (features::IsAllowBFCacheWhenClosedMediaStreamTrackEnabled()) { + feature_handle_for_scheduler_on_live_media_stream_track_ = + GetExecutionContext()->GetScheduler()->RegisterFeature( + SchedulingPolicy::Feature::kLiveMediaStreamTrack, + {SchedulingPolicy::DisableBackForwardCache()}); + } } void MediaStreamTrackImpl::AddObserver(MediaStreamTrack::Observer* observer) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h index b6ebe5c..fa8c3c2 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track_impl.h
@@ -201,6 +201,17 @@ FrameScheduler::SchedulingAffectingFeatureHandle feature_handle_for_scheduler_; + // This handle notifies the scheduler about a live media stream track + // for the purpose of disabling/enabling BFCache. When there is a live stream + // track, the page should not be BFCached. + // TODO(crbug.com/1502395): Currently we intentionally use this handler for + // BFCache although its behavior is almost the same as the one above. The one + // above uses the WebRTC feature even though it's not necessarily related to + // Web RTC. Discuss with those who own the handler and merge the two handlers + // into one. + FrameScheduler::SchedulingAffectingFeatureHandle + feature_handle_for_scheduler_on_live_media_stream_track_; + MediaStreamSource::ReadyState ready_state_; HeapHashSet<Member<MediaStream>> registered_media_streams_; bool is_iterating_registered_media_streams_ = false;
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 4dabeb70..be9e4211 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
@@ -45,6 +45,7 @@ MLOperand* BuildArgMinMax( V8TestingScope& scope, MLGraphBuilder* builder, + ArgMinMaxKind kind, const MLOperand* input, const MLArgMinMaxOptions* options = MLArgMinMaxOptions::Create());
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test_mojo.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test_mojo.cc index 6f8d480..ecc370a5 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test_mojo.cc +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test_mojo.cc
@@ -5059,6 +5059,192 @@ } } +struct ArgMinMaxTester { + OperandInfoBlink input; + absl::optional<Vector<uint32_t>> axes; + absl::optional<bool> keep_dimensions; + absl::optional<bool> select_last_index; + OperandInfoMojo expected_input; + OperandInfoMojo expected_output; + Vector<uint32_t> expected_axes; + bool expected_keep_dimensions; + bool expected_select_last_index; + + void Test(MLGraphTestMojo& helper, + V8TestingScope& scope, + MLGraphBuilder* builder) { + Test(helper, scope, builder, ArgMinMaxKind::kArgMin); + Test(helper, scope, builder, ArgMinMaxKind::kArgMax); + } + + void Test(MLGraphTestMojo& helper, + V8TestingScope& scope, + MLGraphBuilder* builder, + ArgMinMaxKind kind) { + // Build the graph. + auto* input_operand = + BuildInput(builder, "input", input.dimensions, input.data_type, + scope.GetExceptionState()); + auto* options = MLArgMinMaxOptions::Create(); + if (axes.has_value()) { + options->setAxes(axes.value()); + } + if (keep_dimensions.has_value()) { + options->setKeepDimensions(keep_dimensions.value()); + } + if (select_last_index.has_value()) { + options->setSelectLastIndex(select_last_index.value()); + } + auto* output_operand = + BuildArgMinMax(scope, builder, kind, input_operand, options); + auto [graph, build_exception] = + helper.BuildGraph(scope, builder, {{"output", output_operand}}); + ASSERT_NE(graph, nullptr); + + 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_arg_min_max()); + auto& argminmax = operation->get_arg_min_max(); + + blink_mojom::ArgMinMax::Kind mojom_kind; + switch (kind) { + case ArgMinMaxKind::kArgMin: + mojom_kind = blink_mojom::ArgMinMax::Kind::kMin; + break; + case ArgMinMaxKind::kArgMax: + mojom_kind = blink_mojom::ArgMinMax::Kind::kMax; + break; + } + EXPECT_EQ(argminmax->kind, mojom_kind); + // Validate the axes of ArgMinMax operation. + EXPECT_EQ(argminmax->axes, expected_axes); + // Validate the keep_dimensions of ArgMinMax operation. + EXPECT_EQ(argminmax->keep_dimensions, expected_keep_dimensions); + // Validate the select_last_index of ArgMinMax operation. + EXPECT_EQ(argminmax->select_last_index, expected_select_last_index); + + // Validate the input operand. + EXPECT_EQ(graph_info->input_operands.size(), 1u); + auto input_operand_id = graph_info->input_operands[0]; + EXPECT_EQ(argminmax->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_input.data_type); + EXPECT_EQ(input_operand_iter->value->dimensions, expected_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(argminmax->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_output.data_type); + EXPECT_EQ(output_operand_iter->value->dimensions, + expected_output.dimensions); + } +}; + +TEST_P(MLGraphTestMojo, ArgMinMaxTest) { + V8TestingScope scope; + // Bind fake WebNN Context in the service for testing. + ScopedWebNNServiceBinder scoped_setup_binder(*this, scope); + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + webnn::features::kWebMachineLearningNeuralNetwork); + auto* options = MLContextOptions::Create(); + // Create WebNN Context with GPU device type. + options->setDeviceType(V8MLDeviceType::Enum::kGpu); + auto* builder = CreateGraphBuilder(scope, options); + ASSERT_NE(builder, nullptr); + { + // Test argMinMax with default options. + ArgMinMaxTester{ + .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .expected_input = {.data_type = + blink_mojom::Operand::DataType::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .expected_output = {.data_type = blink_mojom::Operand::DataType::kInt64, + .dimensions = {}}, + .expected_axes = {0, 1, 2, 3}, + .expected_keep_dimensions = false, + .expected_select_last_index = false} + .Test(*this, scope, builder); + } + { + // Test argMinMax with axes = {}. + ArgMinMaxTester{ + .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .axes = Vector<uint32_t>{}, + .expected_input = {.data_type = + blink_mojom::Operand::DataType::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .expected_output = {.data_type = blink_mojom::Operand::DataType::kInt64, + .dimensions = {1, 2, 3, 4}}, + .expected_axes = {}, + .expected_keep_dimensions = false, + .expected_select_last_index = false} + .Test(*this, scope, builder); + } + { + // Test argMinMax with axes = {1}. + ArgMinMaxTester{ + .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .axes = Vector<uint32_t>{1}, + .expected_input = {.data_type = + blink_mojom::Operand::DataType::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .expected_output = {.data_type = blink_mojom::Operand::DataType::kInt64, + .dimensions = {1, 3, 4}}, + .expected_axes = {1}, + .expected_keep_dimensions = false, + .expected_select_last_index = false} + .Test(*this, scope, builder); + } + { + // Test argMinMax with axes = {1, 3} and keepDimensions = true. + ArgMinMaxTester{ + .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .axes = Vector<uint32_t>{1, 3}, + .keep_dimensions = true, + .expected_input = {.data_type = + blink_mojom::Operand::DataType::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .expected_output = {.data_type = blink_mojom::Operand::DataType::kInt64, + .dimensions = {1, 1, 3, 1}}, + .expected_axes = {1, 3}, + .expected_keep_dimensions = true, + .expected_select_last_index = false} + .Test(*this, scope, builder); + } + { + // Test argMinMax with axes = {1, 3}, keepDimensions = true and and + // selectLastIndex = true. + ArgMinMaxTester{ + .input = {.data_type = V8MLOperandDataType::Enum::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .axes = Vector<uint32_t>{1, 3}, + .keep_dimensions = true, + .select_last_index = true, + .expected_input = {.data_type = + blink_mojom::Operand::DataType::kFloat32, + .dimensions = {1, 2, 3, 4}}, + .expected_output = {.data_type = blink_mojom::Operand::DataType::kInt64, + .dimensions = {1, 1, 3, 1}}, + .expected_axes = {1, 3}, + .expected_keep_dimensions = true, + .expected_select_last_index = true} + .Test(*this, scope, builder); + } +} + TEST_P(MLGraphTestMojo, WebNNGraphComputeTest) { V8TestingScope scope; // Bind fake WebNN Context in the service for testing.
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_type_converter.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_type_converter.cc index e0707905..2bb226e 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_type_converter.cc +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_type_converter.cc
@@ -256,7 +256,7 @@ static_cast<const blink::MLArgMinMaxOptions*>(arg_min_max->Options()); CHECK(options); const auto input_rank = arg_min_max->Inputs()[0]->Dimensions().size(); - const auto axes = options->axes(); + const auto axes = options->getAxesOr(CreateAllAxes(input_rank)); CHECK_LE(axes.size(), input_rank); arg_min_max_mojo->axes = axes; arg_min_max_mojo->keep_dimensions = options->keepDimensions();
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index cbc474a..17f9801 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -49,10 +49,8 @@ #include "components/viz/common/resources/transferable_resource.h" #include "gpu/command_buffer/client/client_shared_image.h" #include "gpu/command_buffer/client/context_support.h" -#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/common/capabilities.h" -#include "gpu/command_buffer/common/gpu_memory_buffer_support.h" #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/config/gpu_driver_bug_workaround_type.h" #include "gpu/config/gpu_feature_info.h" @@ -827,7 +825,6 @@ SkAlphaType alpha_type, GLenum texture_target, GLuint texture_id, - std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer, bool is_overlay_candidate, gpu::Mailbox mailbox) : owning_thread_ref(base::PlatformThread::CurrentRef()), @@ -838,7 +835,6 @@ alpha_type(alpha_type), texture_target(texture_target), texture_id(texture_id), - gpu_memory_buffer(std::move(gpu_memory_buffer)), is_overlay_candidate(is_overlay_candidate), mailbox(mailbox) {} @@ -873,7 +869,6 @@ } sii->DestroySharedImage(receive_sync_token, mailbox); - gpu_memory_buffer.reset(); gl->DeleteTextures(1u, &texture_id); } @@ -1893,15 +1888,13 @@ state_restorer_->SetTextureBindingDirty(); gpu::SharedImageInterface* sii = ContextProvider()->SharedImageInterface(); - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager = - Platform::Current()->GetGpuMemoryBufferManager(); gpu::Mailbox back_buffer_mailbox; // Set only when using swap chains. gpu::Mailbox front_buffer_mailbox; GLenum texture_target = GL_TEXTURE_2D; GLuint texture_id = 0; - std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; + bool created_mappable_si = false; uint32_t usage = gpu::SHARED_IMAGE_USAGE_GLES2_READ | gpu::SHARED_IMAGE_USAGE_GLES2_WRITE | gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT | @@ -1973,28 +1966,23 @@ viz::SinglePlaneSharedImageFormatToBufferFormat( color_buffer_format_), ContextProvider()->GetCapabilities())) { - gpu_memory_buffer = gpu_memory_buffer_manager->CreateGpuMemoryBuffer( - size, - viz::SinglePlaneSharedImageFormatToBufferFormat( - color_buffer_format_), - buffer_usage, gpu::kNullSurfaceHandle, nullptr); - if (gpu_memory_buffer) { - auto client_shared_image = sii->CreateSharedImage( - color_buffer_format_, size, color_space_, origin, - back_buffer_alpha_type, usage | additional_usage_flags, - "WebGLDrawingBuffer", gpu_memory_buffer->CloneHandle()); + auto client_shared_image = sii->CreateSharedImage( + color_buffer_format_, size, color_space_, origin, + back_buffer_alpha_type, usage | additional_usage_flags, + "WebGLDrawingBuffer", gpu::kNullSurfaceHandle, buffer_usage); + if (client_shared_image) { + created_mappable_si = true; #if BUILDFLAG(IS_MAC) // Ensure that the backing IOSurface has its color space set to be the // same as that of the just-created SharedImage (the former is used by // CoreAnimation, while the latter is used by viz). // TODO(crbug.com/924198): Explore moving to a CreateSharedImage() // codepath that sets the color space of the IOSurface on the service - // side and eliminating the usage of GMB here altogether. Will require - // resolving issues with low-latency canvas tests that caused prior - // attempts to be reverted (crbug.com/1346737). - gpu_memory_buffer->SetColorSpace(color_space_); + // side and eliminating the usage of MappableSI here altogether. Will + // require resolving issues with low-latency canvas tests that caused + // prior attempts to be reverted (crbug.com/1346737). + client_shared_image->SetColorSpaceOnNativeBuffer(color_space_); #endif - CHECK(client_shared_image); back_buffer_mailbox = client_shared_image->mailbox(); #if BUILDFLAG(IS_MAC) // A CHROMIUM_image backed texture requires a specialized set of @@ -2005,9 +1993,9 @@ } } - // Create a normal SharedImage if GpuMemoryBuffer is not needed or the + // Create a normal SharedImage if Mappable SharedImage is not needed or the // allocation above failed. - if (!gpu_memory_buffer) { + if (!created_mappable_si) { // We want to set the correct SkAlphaType on the new shared image but in // the case of ShouldUseChromiumImage() we instead keep this buffer // premultiplied, draw to |premultiplied_alpha_false_mailbox_|, and @@ -2049,7 +2037,7 @@ front_buffer_mailbox.name); front_color_buffer_ = base::MakeRefCounted<ColorBuffer>( weak_factory_.GetWeakPtr(), size, color_space_, color_buffer_format_, - back_buffer_alpha_type, texture_target, texture_id, nullptr, + back_buffer_alpha_type, texture_target, texture_id, /*is_overlay_candidate=*/true, front_buffer_mailbox); } @@ -2077,12 +2065,12 @@ texture_target, 0, 0); gl_->DeleteFramebuffers(1, &fbo); } - const bool is_overlay_candidate = !!gpu_memory_buffer || using_swap_chain_; + const bool is_overlay_candidate = created_mappable_si || using_swap_chain_; return base::MakeRefCounted<ColorBuffer>( weak_factory_.GetWeakPtr(), size, color_space_, color_buffer_format_, - back_buffer_alpha_type, texture_target, texture_id, - std::move(gpu_memory_buffer), is_overlay_candidate, back_buffer_mailbox); + back_buffer_alpha_type, texture_target, texture_id, is_overlay_candidate, + back_buffer_mailbox); } void DrawingBuffer::AttachColorBufferToReadFramebuffer() { @@ -2165,8 +2153,7 @@ bool DrawingBuffer::ShouldUseChromiumImage() { return RuntimeEnabledFeatures::WebGLImageChromiumEnabled() && - chromium_image_usage_ == kAllowChromiumImage && - Platform::Current()->GetGpuMemoryBufferManager(); + chromium_image_usage_ == kAllowChromiumImage; } } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h index 93ac96a..f504d97 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -67,10 +67,6 @@ class Layer; } -namespace gfx { -class GpuMemoryBuffer; -} - namespace gpu { namespace gles2 { class GLES2Interface; @@ -428,7 +424,6 @@ SkAlphaType alpha_type, GLenum texture_target, GLuint texture_id, - std::unique_ptr<gfx::GpuMemoryBuffer>, bool is_overlay_candidate, gpu::Mailbox mailbox); ColorBuffer(const ColorBuffer&) = delete; @@ -449,7 +444,6 @@ const SkAlphaType alpha_type; const GLenum texture_target; const GLuint texture_id; - std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; const bool is_overlay_candidate; // The mailbox used to send this buffer to the compositor.
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc index def4774..d343f44 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
@@ -43,7 +43,6 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/graphics/canvas_color_params.h" #include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h" -#include "third_party/blink/renderer/platform/graphics/test/gpu_memory_buffer_test_platform.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "ui/gl/gpu_preference.h" #include "v8/include/v8.h" @@ -352,13 +351,18 @@ protected: void SetUp() override { - platform_ = std::make_unique< - ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform>>(); - gfx::Size initial_size(kInitialWidth, kInitialHeight); auto gl = std::make_unique<GLES2InterfaceForTests>(); auto provider = std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl)); + + // DrawingBuffer requests MappableSharedImages with usage SCANOUT, whereas + // TestSII by default creates backing SharedMemory GMBs that don't support + // this usage. Configure the TestSII to instead use test GMBs that have + // relaxed usage validation. + auto* sii = static_cast<viz::TestSharedImageInterface*>( + provider->SharedImageInterface()); + sii->UseTestGMBInSharedImageCreationWithBufferUsage(); GLES2InterfaceForTests* gl_ = static_cast<GLES2InterfaceForTests*>(provider->ContextGL()); EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1); @@ -372,13 +376,7 @@ testing::Mock::VerifyAndClearExpectations(gl_); } - void TearDown() override { - platform_.reset(); - } - GLuint image_id0_; - std::unique_ptr<ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform>> - platform_; }; TEST_F(DrawingBufferImageChromiumTest, VerifyResizingReallocatesImages) { @@ -512,9 +510,6 @@ TEST_F(DrawingBufferImageChromiumTest, AllocationFailure) { GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests(); - viz::TestGpuMemoryBufferManager* gmb_manager = - static_cast<viz::TestGpuMemoryBufferManager*>( - Platform::Current()->GetGpuMemoryBufferManager()); viz::TestSharedImageInterface* sii = drawing_buffer_->SharedImageInterfaceForTests(); @@ -538,10 +533,10 @@ testing::Mock::VerifyAndClearExpectations(gl_); VerifyStateWasRestored(); - // Force GpuMemoryBuffer creation failure. Request another resource. It should + // Force MappableSI creation failure. Request another resource. It should // still be provided, but this time with allowOverlay = false. EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1); - gmb_manager->SetFailOnCreate(true); + sii->SetFailSharedImageCreationWithBufferUsage(true); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource2, &release_callback2)); @@ -551,10 +546,10 @@ EXPECT_TRUE(sii->CheckSharedImageExists(mailbox2)); VerifyStateWasRestored(); - // Check that if GpuMemoryBuffer allocation starts working again, resources + // Check that if MappableSI creation starts working again, resources // are correctly created with allowOverlay = true. EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1); - gmb_manager->SetFailOnCreate(false); + sii->SetFailSharedImageCreationWithBufferUsage(false); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3, &release_callback3));
diff --git a/third_party/blink/renderer/platform/graphics/image_to_buffer_copier.cc b/third_party/blink/renderer/platform/graphics/image_to_buffer_copier.cc index 3414f9d..99b9a75 100644 --- a/third_party/blink/renderer/platform/graphics/image_to_buffer_copier.cc +++ b/third_party/blink/renderer/platform/graphics/image_to_buffer_copier.cc
@@ -35,13 +35,14 @@ dest_image_size_ = size; + // We copy the contents of the source image into the destination SharedImage + // via GL, followed by giving out the destination SharedImage's native + // buffer handle to eventually be read by the display compositor. dest_shared_image_ = sii_->CreateSharedImage( viz::SinglePlaneFormat::kRGBA_8888, size, gfx::ColorSpace(), kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, - gpu::SHARED_IMAGE_USAGE_GLES2_READ | - gpu::SHARED_IMAGE_USAGE_GLES2_WRITE, - "ImageToBufferCopier", gpu::kNullSurfaceHandle, - gfx::BufferUsage::SCANOUT); + gpu::SHARED_IMAGE_USAGE_GLES2_WRITE, "ImageToBufferCopier", + gpu::kNullSurfaceHandle, gfx::BufferUsage::SCANOUT); CHECK(dest_shared_image_); gl_->WaitSyncTokenCHROMIUM(sii_->GenUnverifiedSyncToken().GetConstData()); }
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator.cc b/third_party/blink/renderer/platform/text/text_break_iterator.cc index 6e5766cf..55bcf81f 100644 --- a/third_party/blink/renderer/platform/text/text_break_iterator.cc +++ b/third_party/blink/renderer/platform/text/text_break_iterator.cc
@@ -293,53 +293,6 @@ return ch > kAsciiLineBreakTableLastChar && ch != kNoBreakSpaceCharacter; } -template <typename CharacterType> -struct LazyLineBreakIterator::Context { - STACK_ALLOCATED(); - - public: - struct ContextChar { - STACK_ALLOCATED(); - - public: - ContextChar() = default; - explicit ContextChar(UChar ch) : ch(ch), is_space(IsBreakableSpace(ch)) {} - - UChar ch = 0; - bool is_space = false; - }; - - Context(const CharacterType* str, int len, unsigned start_offset, int index) { - CHECK_GE(index, 0); - DCHECK_GE(static_cast<unsigned>(index), start_offset); - CHECK_LE(index, len); - if (index > 0) { - last = ContextChar(str[index - 1]); - if (index > 1) { - last_last_ch = str[index - 2]; - } - } - } - - bool Fetch(const CharacterType* str, int len, int index) { - if (UNLIKELY(index >= len)) { - return false; - } - current = ContextChar(str[index]); - return true; - } - - void Advance(int& index) { - ++index; - last_last_ch = last.ch; - last = current; - } - - ContextChar current; - ContextChar last; - CharacterType last_last_ch; -}; - template <typename CharacterType, LineBreakType lineBreakType, BreakSpaceType break_space> @@ -347,60 +300,57 @@ int pos, const CharacterType* str, int len) const { - Context<CharacterType> context(str, len, start_offset_, pos); + CHECK_GE(pos, 0); + DCHECK_GE(static_cast<unsigned>(pos), start_offset_); + CHECK_LE(pos, len); int next_break = -1; + UChar last_last_ch = pos > 1 ? str[pos - 2] : 0; + UChar last_ch = pos > 0 ? str[pos - 1] : 0; + bool is_last_space = IsBreakableSpace(last_ch); ULineBreak last_line_break; - if (lineBreakType == LineBreakType::kBreakAll) { - last_line_break = - LineBreakPropertyValue(context.last_last_ch, context.last.ch); - } - for (int i = pos; context.Fetch(str, len, i); context.Advance(i)) { + if (lineBreakType == LineBreakType::kBreakAll) + last_line_break = LineBreakPropertyValue(last_last_ch, last_ch); + CharacterType ch; + bool is_space; + for (int i = pos; i < len; + i++, last_last_ch = last_ch, last_ch = ch, is_last_space = is_space) { + ch = str[i]; + + is_space = IsBreakableSpace(ch); switch (break_space) { case BreakSpaceType::kAfterSpaceRun: - if (context.current.is_space) { + if (is_space) continue; - } - if (context.last.is_space) { + if (is_last_space) return i; - } break; case BreakSpaceType::kAfterEverySpace: - if (context.last.is_space || - IsOtherSpaceSeparator<CharacterType>(context.last.ch)) { + if (is_last_space || IsOtherSpaceSeparator<CharacterType>(last_ch)) return i; - } - if ((context.current.is_space || - IsOtherSpaceSeparator<CharacterType>(context.current.ch)) && - i + 1 < len) { + if ((is_space || IsOtherSpaceSeparator<CharacterType>(ch)) && + i + 1 < len) return i + 1; - } break; } - if (ShouldBreakAfter(context.last_last_ch, context.last.ch, - context.current.ch)) { + if (ShouldBreakAfter(last_last_ch, last_ch, ch)) return i; - } - if (lineBreakType == LineBreakType::kBreakAll && - !U16_IS_LEAD(context.current.ch)) { - ULineBreak line_break = - LineBreakPropertyValue(context.last.ch, context.current.ch); + if (lineBreakType == LineBreakType::kBreakAll && !U16_IS_LEAD(ch)) { + ULineBreak line_break = LineBreakPropertyValue(last_ch, ch); if (ShouldBreakAfterBreakAll(last_line_break, line_break)) - return i > pos && U16_IS_TRAIL(context.current.ch) ? i - 1 : i; + return i > pos && U16_IS_TRAIL(ch) ? i - 1 : i; if (line_break != U_LB_COMBINING_MARK) last_line_break = line_break; } if (lineBreakType == LineBreakType::kKeepAll && - ShouldKeepAfterKeepAll(context.last_last_ch, context.last.ch, - context.current.ch)) { + ShouldKeepAfterKeepAll(last_last_ch, last_ch, ch)) { // word-break:keep-all prevents breaks between East Asian ideographic. continue; } - if (NeedsLineBreakIterator(context.current.ch) || - NeedsLineBreakIterator(context.last.ch)) { + if (NeedsLineBreakIterator(ch) || NeedsLineBreakIterator(last_ch)) { if (next_break < i) { // Don't break if positioned at start of primary context. if (i) { @@ -426,9 +376,8 @@ } } } - if (i == next_break && !context.last.is_space) { + if (i == next_break && !is_last_space) return i; - } } }
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator.h b/third_party/blink/renderer/platform/text/text_break_iterator.h index d10dfa4..bb00bdb 100644 --- a/third_party/blink/renderer/platform/text/text_break_iterator.h +++ b/third_party/blink/renderer/platform/text/text_break_iterator.h
@@ -227,9 +227,6 @@ private: FRIEND_TEST_ALL_PREFIXES(TextBreakIteratorTest, Strictness); - template <typename CharacterType> - struct Context; - const AtomicString& LocaleWithKeyword() const; void InvalidateLocaleWithKeyword();
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials index 5f14a2a..69967dc 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials +++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -109,7 +109,6 @@ crbug.com/626703 external/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-3.html [ Timeout ] crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-zero-intersection-area.html [ Timeout ] crbug.com/626703 external/wpt/html/browsers/windows/clear-window-name.https.html [ Timeout ] -crbug.com/626703 external/wpt/custom-elements/form-associated/ElementInternals-target-element-is-held-strongly.html [ Timeout ] crbug.com/626703 external/wpt/custom-elements/throw-on-dynamic-markup-insertion-counter-construct-xml-parser.xhtml [ Crash ] crbug.com/626703 external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] crbug.com/626703 external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index 1890226..2a64eb5 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -736,7 +736,10 @@ crbug.com/874695 [ Mac12 ] virtual/threaded/http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.js [ Slow ] crbug.com/874695 [ Release Win ] virtual/threaded/http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.js [ Slow ] crbug.com/1494075 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow-desktop.html [ Slow ] -crbug.com/1494075 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Slow ] +crbug.com/1494075 [ Debug Mac13 ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Slow ] +crbug.com/1494075 [ Linux ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Slow ] +crbug.com/1494075 [ Mac Release ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Slow ] +crbug.com/1494075 [ Release Win ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Slow ] crbug.com/1494075 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-out-slow.html [ Slow ] crbug.com/871139 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow-desktop.html [ Slow ] crbug.com/871139 [ Linux ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 825dfca..bdff7d0 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -418,7 +418,6 @@ crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=select-boundary&left-white-space=nowrap&right-white-space=pre-wrap [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=select-boundary&left-white-space=pre&right-white-space=normal [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=select-boundary&left-white-space=pre&right-white-space=nowrap [ Failure ] -crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=select-boundary&left-white-space=pre&right-white-space=pre-line [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=select-boundary&left-white-space=pre&right-white-space=pre-wrap [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=select-boundary&left-white-space=pre-line&right-white-space=normal [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=select-boundary&left-white-space=pre-line&right-white-space=pre-wrap [ Failure ] @@ -550,6 +549,11 @@ crbug.com/1370460 [ Mac ] external/wpt/svg/text/reftests/lang-attribute.svg [ Failure ] crbug.com/1370460 [ Mac ] external/wpt/svg/text/reftests/xml-lang-attribute.svg [ Failure ] +# Temporarily disabled to unblock https://crrev.com/c/5131015 +crbug.com/1512108 http/tests/devtools/console/console-functions.js [ Failure Pass ] +crbug.com/1512108 http/tests/devtools/console/console-tainted-globals.js [ Failure Pass ] +crbug.com/1512108 http/tests/devtools/sources/debugger/properties-special.js [ Failure Pass ] + # WPT backgrounds and borders tests. Note that there are many more in NeverFixTests # that should be investigated (see crbug.com/780700) crbug.com/492187 external/wpt/css/CSS2/backgrounds/background-intrinsic-004.xht [ Failure ] @@ -574,9 +578,6 @@ crbug.com/882975 [ Win10.20h2 ] virtual/threaded/fast/events/pinch/gesture-pinch-zoom-prevent-in-handler.html [ Failure Pass ] crbug.com/882975 [ Win10.20h2 ] virtual/threaded/fast/events/pinch/scroll-visual-viewport-send-boundary-events.html [ Failure Pass ] -# Temporarily disabled to unblock https://crrev.com/c/5126051 -crbug.com/798498 http/tests/devtools/copy-network-request.js [ Failure Pass ] - crbug.com/898394 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 ] @@ -2610,7 +2611,6 @@ crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justify-tabs-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justify-tabs-003.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justify-tabs-004.html [ Failure ] -crbug.com/626703 external/wpt/xhr/send-authentication-basic.htm [ Failure ] crbug.com/626703 external/wpt/service-workers/service-worker/controlled-dedicatedworker-postMessage.https.html [ Failure Timeout ] crbug.com/626703 external/wpt/service-workers/service-worker/controlled-iframe-postMessage.https.html [ Failure Timeout ] crbug.com/626703 external/wpt/fetch/metadata/generated/worker-dedicated-constructor.sub.html [ Failure ] @@ -2629,6 +2629,8 @@ crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html* [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 virtual/webnn-service-enabled/external/wpt/webnn/gpu/arg_min_max.https.any.html [ Skip Timeout ] +crbug.com/626703 virtual/webnn-service-enabled/external/wpt/webnn/gpu/arg_min_max.https.any.worker.html [ Crash ] crbug.com/626703 [ Mac13 ] virtual/threaded/external/wpt/long-animation-frame/tentative/loaf-source-location-redirect.html [ Skip Timeout ] crbug.com/626703 external/wpt/css/css-page/page-orientation-on-landscape-001-print.html [ Failure ] crbug.com/626703 external/wpt/css/css-page/page-orientation-on-portrait-001-print.html [ Failure ] @@ -2697,7 +2699,6 @@ crbug.com/626703 [ Mac12 ] external/wpt/css/css-masking/animations/clip-path-interpolation-002.html [ Timeout ] crbug.com/626703 [ Mac12 ] external/wpt/editing/other/join-pre-and-other-block.html?method=backspace&block=div [ Timeout ] crbug.com/626703 [ Mac12 ] external/wpt/performance-timeline/back-forward-cache-restoration.tentative.html [ Timeout ] -crbug.com/626703 [ Mac12 ] virtual/keepalive-in-browser-migration/external/wpt/fetch/api/response/response-clone.any.sharedworker.html [ Timeout ] crbug.com/626703 [ Mac12 ] virtual/pna-navigations-warning/external/wpt/fetch/private-network-access/shared-worker-fetch.tentative.https.window.html [ Timeout ] crbug.com/626703 [ Mac12 ] virtual/prefetch-no-vary-search/external/wpt/speculation-rules/prefetch/no-vary-search/prefetch-single-with-hint.https.html?3-3 [ Timeout ] crbug.com/626703 [ Mac12 ] virtual/prefetch-reusable/external/wpt/speculation-rules/prefetch/no-vary-search/prefetch-single-with-hint.https.html?27-27 [ Timeout ] @@ -4849,7 +4850,6 @@ crbug.com/1454939 fast/events/touch/gesture/focus-selectionchange-on-tap.html [ Failure Pass ] crbug.com/1455239 http/tests/security/drag-drop-different-origin.html [ Failure Pass ] -crbug.com/1455579 virtual/disable-device-id-pointer-event/fast/events/pointerevents/device-id/get-device-id-from-pointer-event.html [ Failure Pass ] crbug.com/1456442 virtual/compositor-threaded-percent-based-scrolling/fast/events/wheel/wheel-latched-scroll-node-removed.html [ Failure Pass Timeout ] # Green Mac11 Test @@ -6515,7 +6515,6 @@ # Flaky test crbug.com/1454689 http/tests/inspector-protocol/tracing/cpu-profiling.js [ Failure Pass ] -crbug.com/1455245 virtual/fedcm-multi-idp/external/wpt/credential-management/fedcm-multi-idp/abort-multiple-gets-through-first-idp.https.html [ Pass Timeout ] crbug.com/1455245 virtual/fedcm-multi-idp/external/wpt/credential-management/fedcm-multi-idp/get-before-and-after-onload.https.html [ Failure Pass Timeout ] crbug.com/1455245 virtual/fedcm-multi-idp/external/wpt/credential-management/fedcm-multi-idp/get-before-and-during-onload.https.html [ Pass Timeout ] crbug.com/1455245 virtual/fedcm-multi-idp/external/wpt/credential-management/fedcm-multi-idp/get-before-onload-and-during-dom-content-loaded.https.html [ Pass Timeout ] @@ -6869,7 +6868,9 @@ crbug.com/1510005 [ Linux ] virtual/scalefactor200/external/wpt/css/filter-effects/backdrop-filter-svg.html [ Crash Failure Pass Timeout ] # TODO(crbug.com/1511492): Re-enable these tests. -crbug.com/1511492 [ Linux ] external/wpt/event-timing/first-input-interactionid-tap.html [ Crash Failure Timeout ] +crbug.com/1511492 [ Linux ] external/wpt/event-timing/first-input-interactionid-tap.html [ Crash Failure Pass Timeout ] +crbug.com/1511492 [ Linux ] external/wpt/event-timing/interactionid-tap.html [ Crash Failure Pass Timeout ] +crbug.com/1511492 [ Linux ] external/wpt/pointerevents/pointerevent_contextmenu_is_a_pointerevent.html?touch [ Crash Failure Pass Timeout ] crbug.com/1511492 [ Linux ] external/wpt/event-timing/external/wpt/event-timing/interactionid-tap.html [ Crash Failure Timeout ] # TODO(crbug.com/1496375): Re-enable these tests.
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 58965ae39..8c2d209e 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -395334,6 +395334,14 @@ "3f87fc8042d2b3de1bf13d64333ba08cdfdabb3b", [] ], + "arg_min_max.https.any-expected.txt": [ + "6fcce59d82c31dc4b67915add69a3c5d2a2ccfbd", + [] + ], + "arg_min_max.https.any.worker-expected.txt": [ + "7f086a50092bb70e348758d75df9ee8668b111d7", + [] + ], "batch_normalization.https.any-expected.txt": [ "7369d8f44cb7cbe82d7242ea94726a2dc080ae15", [] @@ -395500,6 +395508,14 @@ "0a12871cebab50b0e826674107ff503e6ede5347", [] ], + "arg_max.json": [ + "9af47a95894223eb39d4f73f81f5b9c9a4112bff", + [] + ], + "arg_min.json": [ + "dc0b5cdfd1a6bc822bce05f3ba014bb119f3e679", + [] + ], "average_pool2d.json": [ "802e0d764621707c0b00d6a05627d0c1eeba9233", [] @@ -395746,7 +395762,7 @@ ] }, "utils.js": [ - "c3b10a7020182f1765cdd7890410766334bc6055", + "0e2687ec22bac4a4dea3dbe938f9fc386a0a6a4e", [] ] }, @@ -643821,6 +643837,13 @@ {} ] ], + "viewport-scrollbars-cause-resize-in-iframe.html": [ + "ce9ec3276886b5786ffe1309251469e92f29e1a9", + [ + null, + {} + ] + ], "viewport-scrollbars-cause-resize.html": [ "086e8d92b087afe8aea2fbc91c1f96dd7d328e72", [ @@ -659697,6 +659720,57 @@ ] }, "webnn": { + "arg_min_max.https.any.js": [ + "cff1d6a955ce31fbecde084f8407a8f53bf6b889", + [ + "webnn/arg_min_max.https.any.html", + { + "script_metadata": [ + [ + "title", + "test WebNN API argMin/Max operations" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "script", + "./resources/utils.js" + ], + [ + "timeout", + "long" + ] + ], + "timeout": "long" + } + ], + [ + "webnn/arg_min_max.https.any.worker.html", + { + "script_metadata": [ + [ + "title", + "test WebNN API argMin/Max operations" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "script", + "./resources/utils.js" + ], + [ + "timeout", + "long" + ] + ], + "timeout": "long" + } + ] + ], "batch_normalization.https.any.js": [ "15e66a8bc06b2e73c19f910c765428b89b3f3b3d", [ @@ -660259,6 +660333,57 @@ ] ], "gpu": { + "arg_min_max.https.any.js": [ + "76092ea92e6931f64f24f068341fe7335fd58259", + [ + "webnn/gpu/arg_min_max.https.any.html", + { + "script_metadata": [ + [ + "title", + "test WebNN API argMin/Max operations" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "script", + "../resources/utils.js" + ], + [ + "timeout", + "long" + ] + ], + "timeout": "long" + } + ], + [ + "webnn/gpu/arg_min_max.https.any.worker.html", + { + "script_metadata": [ + [ + "title", + "test WebNN API argMin/Max operations" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "script", + "../resources/utils.js" + ], + [ + "timeout", + "long" + ] + ], + "timeout": "long" + } + ] + ], "batch_normalization.https.any.js": [ "90b6def636d1090dc0fe19368fbb5ac38d0133cd", [
diff --git a/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any-expected.txt b/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any-expected.txt new file mode 100644 index 0000000..6fcce59d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any-expected.txt
@@ -0,0 +1,83 @@ +This is a testharness.js-based test. +[FAIL] argMin float32 1D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 2D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 3D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 5D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[2] / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[] / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 4D tensor all options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 0D scalar options.axes=[] / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMin float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 1D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 2D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 3D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 5D tensor default options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[2] / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[] / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 4D tensor all options / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 0D scalar options.axes=[] / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +[FAIL] argMax float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true / async + promise_test: Unhandled rejection with value: object "NotSupportedError: The operand data type (int64) is not supported." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any.js new file mode 100644 index 0000000..cff1d6a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any.js
@@ -0,0 +1,10 @@ +// META: title=test WebNN API argMin/Max operations +// META: global=window,dedicatedworker +// META: script=./resources/utils.js +// META: timeout=long + +'use strict'; + +// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-argminmax + +testWebNNOperation(['argMin', 'argMax'], buildOperationWithSingleInput); \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any.worker-expected.txt new file mode 100644 index 0000000..7f086a5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webnn/arg_min_max.https.any.worker-expected.txt
@@ -0,0 +1,164 @@ +This is a testharness.js-based test. +Found 80 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] argMin float32 1D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 2D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 3D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 5D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[2] / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[] / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.keepDimensions=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.keepDimensions=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.selectLastIndex=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.selectLastIndex=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.keepDimensions=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 4D tensor all options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 0D scalar options.axes=[] / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 1D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 2D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 3D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 5D tensor default options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[2] / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[] / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.keepDimensions=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.keepDimensions=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.selectLastIndex=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.selectLastIndex=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.keepDimensions=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 4D tensor all options / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 0D scalar options.axes=[] / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMax float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true / sync + Failed to execute 'buildSync' on 'MLGraphBuilder': The operand data type (int64) is not supported. +[FAIL] argMin float32 1D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 2D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 3D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 5D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[2] / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[] / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 4D tensor all options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 0D scalar options.axes=[] / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMin float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 1D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 2D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 3D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 5D tensor default options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[2] / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[] / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.keepDimensions=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 4D tensor all options / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 0D scalar options.axes=[] / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +[FAIL] argMax float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true / async + promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/webnn/gpu/arg_min_max.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/gpu/arg_min_max.https.any.js new file mode 100644 index 0000000..76092ea9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webnn/gpu/arg_min_max.https.any.js
@@ -0,0 +1,10 @@ +// META: title=test WebNN API argMin/Max operations +// META: global=window,dedicatedworker +// META: script=../resources/utils.js +// META: timeout=long + +'use strict'; + +// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-argminmax + +testWebNNOperation(['argMin', 'argMax'], buildOperationWithSingleInput, 'gpu'); \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webnn/resources/test_data/arg_max.json b/third_party/blink/web_tests/external/wpt/webnn/resources/test_data/arg_max.json new file mode 100644 index 0000000..9af47a9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webnn/resources/test_data/arg_max.json
@@ -0,0 +1,919 @@ +{ + "tests": [ + { + "name": "argMax float32 1D tensor default options", + "inputs": { + "input": { + "shape": [24], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 2D tensor default options", + "inputs": { + "input": { + "shape": [4, 6], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 3D tensor default options", + "inputs": { + "input": { + "shape": [2, 3, 4], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor default options", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 5D tensor default options", + "inputs": { + "input": { + "shape": [2, 1, 4, 1, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[2]", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [2] + }, + "expected": { + "name": "output", + "shape": [2, 1, 3], + "data": [ + 1, + 2, + 2, + 1, + 2, + 2 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[]", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [] + }, + "expected": { + "name": "output", + "shape": [2, 1, 4, 3], + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.keepDimensions=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "keepDimensions": true + }, + "expected": { + "name": "output", + "shape": [1, 1, 1, 1], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.keepDimensions=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "keepDimensions": true + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.selectLastIndex=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 20 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.selectLastIndex=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 3 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[0, 2] options.keepDimensions=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [0, 2], + "keepDimensions": false + }, + "expected": { + "name": "output", + "shape": [1, 3], + "data": [ + 1, + 2, + 2 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0, 1], + "keepDimensions": true + }, + "expected": { + "name": "output", + "shape": [1, 1, 4, 1], + "data": [ + 2, + 0, + 2, + 1 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [0, 2], + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [1, 3], + "data": [ + 1, + 2, + 2 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [0, 2], + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [1, 3], + "data": [ + 5, + 6, + 6 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0, 1], + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [4], + "data": [ + 2, + 0, + 2, + 1 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0, 1], + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [4], + "data": [ + 5, + 3, + 5, + 4 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 4D tensor all options", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955, + -51.0936194154457, + -6.5397018645619625, + 73.81338015899149, + 88.46114630531724, + -5.294266751122791, + -79.20668057325759, + -41.70176598864654, + 73.81338015899149, + 88.46114630531724, + -84.939998758247, + -61.488942502520906, + -98.33874402761955 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0], + "keepDimensions": true, + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [1, 1, 4, 1], + "data": [ + 2, + 0, + 2, + 1 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 0D scalar options.axes=[]", + "inputs": { + "input": { + "shape": [], + "data": [ + -51.0936194154457 + ], + "type": "float32" + } + }, + "options": { + "axes": [] + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 0 + ], + "type": "int64" + } + }, + { + "name": "argMax float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true", + "inputs": { + "input": { + "shape": [], + "data": [ + -51.0936194154457 + ], + "type": "float32" + } + }, + "options": { + "axes": [], + "keepDimensions": true, + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 0 + ], + "type": "int64" + } + } + ] +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webnn/resources/test_data/arg_min.json b/third_party/blink/web_tests/external/wpt/webnn/resources/test_data/arg_min.json new file mode 100644 index 0000000..dc0b5cd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webnn/resources/test_data/arg_min.json
@@ -0,0 +1,919 @@ +{ + "tests": [ + { + "name": "argMin float32 1D tensor default options", + "inputs": { + "input": { + "shape": [24], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 2D tensor default options", + "inputs": { + "input": { + "shape": [4, 6], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 3D tensor default options", + "inputs": { + "input": { + "shape": [2, 3, 4], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor default options", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 5D tensor default options", + "inputs": { + "input": { + "shape": [2, 1, 4, 1, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[2]", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [2] + }, + "expected": { + "name": "output", + "shape": [2, 1, 3], + "data": [ + 2, + 2, + 0, + 0, + 0, + 0 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[]", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [] + }, + "expected": { + "name": "output", + "shape": [2, 1, 4, 3], + "data": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.keepDimensions=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "keepDimensions": true + }, + "expected": { + "name": "output", + "shape": [1, 1, 1, 1], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.keepDimensions=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "keepDimensions": true + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.selectLastIndex=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 19 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.selectLastIndex=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 7 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[0, 2] options.keepDimensions=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [0, 2], + "keepDimensions": false + }, + "expected": { + "name": "output", + "shape": [1, 3], + "data": [ + 2, + 2, + 4 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[3, 0, 1] options.keepDimensions=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0, 1], + "keepDimensions": true + }, + "expected": { + "name": "output", + "shape": [1, 1, 4, 1], + "data": [ + 4, + 0, + 1, + 1 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [0, 2], + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [1, 3], + "data": [ + 2, + 2, + 4 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[0, 2] options.selectLastIndex=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [0, 2], + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [1, 3], + "data": [ + 6, + 6, + 4 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=false", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0, 1], + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [4], + "data": [ + 4, + 0, + 1, + 1 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor options.axes=[3, 0, 1] options.selectLastIndex=true", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0, 1], + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [4], + "data": [ + 4, + 0, + 4, + 1 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 4D tensor all options", + "inputs": { + "input": { + "shape": [2, 1, 4, 3], + "data": [ + 3.830124090690262, + -24.986487937638074, + 5.299982630691289, + -48.5486590218902, + 40.30886781808215, + 60.184293919409726, + -82.78385618759043, + -96.50904103637833, + 71.87028201591897, + 38.866394268784035, + -39.143725517854435, + 31.444366685561903, + -82.78385618759043, + -96.50904103637833, + -25.53388886326502, + -16.142265850469343, + 66.63677406472371, + 82.5119815304117, + -82.78385618759043, + -96.50904103637833, + 39.7687246127592, + 42.15040238450999, + 82.66863662444459, + 85.4526923278379 + ], + "type": "float32" + } + }, + "options": { + "axes": [3, 0], + "keepDimensions": true, + "selectLastIndex": false + }, + "expected": { + "name": "output", + "shape": [1, 1, 4, 1], + "data": [ + 4, + 0, + 1, + 1 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 0D scalar options.axes=[]", + "inputs": { + "input": { + "shape": [], + "data": [ + 3.830124090690262 + ], + "type": "float32" + } + }, + "options": { + "axes": [] + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 0 + ], + "type": "int64" + } + }, + { + "name": "argMin float32 0D scalar options.axes=[] no effect by both keepDimensions and selectLastIndex being true", + "inputs": { + "input": { + "shape": [], + "data": [ + 3.830124090690262 + ], + "type": "float32" + } + }, + "options": { + "axes": [], + "keepDimensions": true, + "selectLastIndex": true + }, + "expected": { + "name": "output", + "shape": [], + "data": [ + 0 + ], + "type": "int64" + } + } + ] +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js b/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js index c3b10a7..0e2687ec 100644 --- a/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js +++ b/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js
@@ -12,6 +12,7 @@ uint32: Uint32Array, int8: Int8Array, uint8: Uint8Array, + int64: BigInt64Array, }; const getTypedArrayData = (type, data) => { @@ -22,6 +23,11 @@ for (let i = 0; i < data.length; i++) { outData[i] = toHalf(data[i]); } + } else if (type === 'int64') { + outData = new TypedArrayDict[type](data.length); + for (let i = 0; i < data.length; i++) { + outData[i] = BigInt(data[i]); + } } else { outData = new TypedArrayDict[type](data); } @@ -280,6 +286,8 @@ // Refer to precision metrics on https://github.com/webmachinelearning/webnn/issues/265#issuecomment-1256242643 const PrecisionMetrics = { + argMax: {ULP: {int64: 0}}, + argMin: {ULP: {int64: 0}}, batchNormalization: {ULP: {float32: 6, float16: 6}}, clamp: {ULP: {float32: 0, float16: 0}}, concat: {ULP: {float32: 0, float16: 0}}, @@ -428,6 +436,9 @@ actualBitwise = actual[i]; // convert expected data of Float16 to Uint16 expectedBitwise = toHalf(expected[i]); + } else if (dataType === 'int64') { + actualBitwise = actual[i]; + expectedBitwise = BigInt(expected[i]); } distance = actualBitwise - expectedBitwise; distance = distance >= 0 ? distance : -distance;
diff --git a/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt b/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt index 0bac7b0..e92460e45 100644 --- a/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/caretPositionFromPoint-with-transformation-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/caretPositionFromPoint-with-transformation-expected.txt deleted file mode 100644 index ed6d508..0000000 --- a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/caretPositionFromPoint-with-transformation-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: frameDoc.caretPositionFromPoint is not a function -[TIMEOUT] iframe's with equal content should report the same caret offset - Test timed out -Harness: the test ran to completion.
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index 42bf9b8..6a94fae 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit 42bf9b85713027338720203624f1ee98d0982a89 +Subproject commit 6a94fae344833b2e4c170955c9b10fa3a40c5550
diff --git a/third_party/cros-components/src b/third_party/cros-components/src index 075d293..f448b44 160000 --- a/third_party/cros-components/src +++ b/third_party/cros-components/src
@@ -1 +1 @@ -Subproject commit 075d293d1a98cce55cdb88185239126eb64f6d55 +Subproject commit f448b44c03202bdb5fb1305216d4723724d5288b
diff --git a/third_party/dawn b/third_party/dawn index 673e8b4..0b6ca39 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit 673e8b4639e3e19b97380992f2a82bc4442d9643 +Subproject commit 0b6ca39d38735c9177dc8f7291dad5314fed3b11
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index 2854d42..457fec8b 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit 2854d4287a81c0a177ea4d6fa64737f1b9640614 +Subproject commit 457fec8b5b9ff390f9e7a8e64f8a886d97cbe1f9
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 0a48a3b..c67fdad 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 0a48a3bd9f916f605f225b4e7e2760380d0a9cc9 +Subproject commit c67fdadcd104ba82740a25feed4fec2931b5f6f3
diff --git a/third_party/pdfium b/third_party/pdfium index b2d4f11..57e284b 160000 --- a/third_party/pdfium +++ b/third_party/pdfium
@@ -1 +1 @@ -Subproject commit b2d4f1104c43ccd42df2e48902ae857f0d5a188a +Subproject commit 57e284ba20215dfa5cdbf732b4e158c544323d86
diff --git a/third_party/skia b/third_party/skia index e40b61c..276075b 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit e40b61c3dfefe6a5ac8f200b0041148d5108cfa0 +Subproject commit 276075b975675ba92d907dd64247937b7b73245e
diff --git a/third_party/webrtc b/third_party/webrtc index 57b0664..acdc89d6 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 57b06646bee860edb996c9c9f4ea6372a12a9536 +Subproject commit acdc89d65328911b4e98afe0757028eca162cbb3
diff --git a/third_party/zlib/trees.c b/third_party/zlib/trees.c index 5ca23e9..3813527 100644 --- a/third_party/zlib/trees.c +++ b/third_party/zlib/trees.c
@@ -938,7 +938,8 @@ /* Check for no overlay of pending_buf on needed symbols */ #ifdef LIT_MEM - Assert(s->pending < (s->lit_bufsize << 1) + sx, "pendingBuf overflow"); + Assert(s->pending < (s->lit_bufsize << 1) + (sx << 1), + "pendingBuf overflow"); #else Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); #endif
diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc index 57ee6fd..7790665 100644 --- a/tools/android/forwarder2/host_forwarder_main.cc +++ b/tools/android/forwarder2/host_forwarder_main.cc
@@ -35,7 +35,7 @@ namespace { const char kLogFilePath[] = "/tmp/host_forwarder_log"; -const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon"; +const char kDefaultDaemonIdentifier[] = "chrome_host_forwarder_daemon"; const int kBufSize = 256; @@ -188,11 +188,11 @@ const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); std::string adb_path = "adb"; bool kill_server = false; + std::string serial_id = cmd_line.HasSwitch("serial-id") ? + cmd_line.GetSwitchValueASCII("serial-id") : std::string(); base::Pickle pickle; - pickle.WriteString( - cmd_line.HasSwitch("serial-id") ? - cmd_line.GetSwitchValueASCII("serial-id") : std::string()); + pickle.WriteString(serial_id); const std::vector<std::string> args = cmd_line.GetArgs(); if (cmd_line.HasSwitch("kill-server")) { @@ -221,10 +221,15 @@ if (kill_server && args.size() > 0) ExitWithUsage(); + std::string daemon_identifier = kDefaultDaemonIdentifier; + if (!serial_id.empty()) { + daemon_identifier += "_" + serial_id; + } + ClientDelegate client_delegate(pickle); ServerDelegate daemon_delegate(adb_path); Daemon daemon( - kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, + kLogFilePath, daemon_identifier, &client_delegate, &daemon_delegate, &GetExitNotifierFD); if (kill_server)
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index b14d5b56..401cb8b 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -6093,6 +6093,40 @@ </description> </action> +<action name="ChromeOS.AppInstallDialog.AppLaunched"> + <owner>dominicschulz@google.com</owner> + <owner>cros-web-apps-infra-team@google.com</owner> + <description> + Recorded when the user requested a previously installed app to be launched + in the CrOS App Install dialog. + </description> +</action> + +<action name="ChromeOS.AppInstallDialog.Cancelled"> + <owner>dominicschulz@google.com</owner> + <owner>cros-web-apps-infra-team@google.com</owner> + <description> + Recorded when the user closed an installation dialog without installing. + </description> +</action> + +<action name="ChromeOS.AppInstallDialog.Installed"> + <owner>dominicschulz@google.com</owner> + <owner>cros-web-apps-infra-team@google.com</owner> + <description> + Recorded when the user requested an app to be installed in the CrOS App + Install dialog. + </description> +</action> + +<action name="ChromeOS.AppInstallDialog.Shown"> + <owner>dominicschulz@google.com</owner> + <owner>cros-web-apps-infra-team@google.com</owner> + <description> + Recorded when the CrOS App Install dialog was opened by the user. + </description> +</action> + <action name="ChromeOS.Settings.InputMethod.Autocorrect.Open"> <owner>zacpartridge@chromium.org</owner> <owner>essential-inputs-team@google.com</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a934214..39d884a4 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -28552,8 +28552,6 @@ <int value="-2133276662" label="EduCoexistenceConsentLog:disabled"/> <int value="-2132591642" label="enable-input-view"/> <int value="-2132161378" label="SendTabToSelfHistory:disabled"/> - <int value="-2131746498" - label="AutofillUseImprovedLabelDisambiguation:enabled"/> <int value="-2130982324" label="DesktopPWAsWebBundles:disabled"/> <int value="-2129940395" label="WebAssemblySimd:disabled"/> <int value="-2129781123" label="RequestDesktopSiteZoom:enabled"/> @@ -30825,6 +30823,8 @@ <int value="-1093135462" label="DesktopPWAsAttentionBadgingCrOS:disabled"/> <int value="-1092514142" label="JourneysKeywordFiltering:disabled"/> <int value="-1092211161" label="BluetoothWbsDogfood:disabled"/> + <int value="-1092165602" + label="EnableBoundSessionCredentialsSoftwareKeysForManualTesting:enabled"/> <int value="-1090001589" label="WebViewRestrictSensitiveContent:enabled"/> <int value="-1089665395" label="HTMLParamElementUrlSupport:enabled"/> <int value="-1088804127" label="DuetTabStripIntegrationAndroid:disabled"/> @@ -32276,6 +32276,8 @@ <int value="-400098787" label="QuietNotificationPrompts:enabled"/> <int value="-399614193" label="EnableSuggestedDriveFiles:enabled"/> <int value="-399333540" label="FiltersInRecents:disabled"/> + <int value="-399166855" + label="enable-bound-session-credentials-software-keys-for-manual-testing:enabled"/> <int value="-398922143" label="IframeOneGoogleBar:enabled"/> <int value="-398623652" label="CCTTargetTranslateLanguage:enabled"/> <int value="-398325847" label="HelpAppCrosComponents:enabled"/> @@ -33465,7 +33467,6 @@ <int value="160524775" label="PDFTwoUpView:disabled"/> <int value="160838658" label="SmartDimModelV3:enabled"/> <int value="161008398" label="NearbyKeepAliveFix:disabled"/> - <int value="161409456" label="AutofillUseMobileLabelDisambiguation:disabled"/> <int value="161694478" label="OmniboxNewAnswerLayout:enabled"/> <int value="161706692" label="ContextualPageActionPriceTracking:disabled"/> <int value="165429419" label="DrawNativeEdgeToEdge:disabled"/> @@ -34343,6 +34344,8 @@ <int value="578894559" label="IPH_Snooze:enabled"/> <int value="580288865" label="ClipboardMaximumAge:disabled"/> <int value="580546202" label="WindowSplitting:disabled"/> + <int value="580915599" + label="EnableBoundSessionCredentialsSoftwareKeysForManualTesting:disabled"/> <int value="581118445" label="enable-eol-notification"/> <int value="581355159" label="ContentSuggestionsCategoryRanker:disabled"/> <int value="582187448" label="DontPrefetchLibraries:enabled"/> @@ -35236,8 +35239,6 @@ <int value="1006280999" label="CrOSLateBootArcVmmSwap:enabled"/> <int value="1006608931" label="ArcEnableUnifiedAudioFocus:disabled"/> <int value="1007444341" label="enable-prefixed-encrypted-media"/> - <int value="1008677979" - label="AutofillUseImprovedLabelDisambiguation:disabled"/> <int value="1009252543" label="BlinkExtension:disabled"/> <int value="1009437086" label="AutofillEnableOfferNotification:disabled"/> <int value="1009596554" label="PWAsDefaultOfflinePage:enabled"/> @@ -35569,7 +35570,6 @@ <int value="1169418814" label="ManualFallbacksFilling:enabled"/> <int value="1170030686" label="BookmarkBottomSheet:enabled"/> <int value="1170632919" label="DrawNativeEdgeToEdge:enabled"/> - <int value="1173244409" label="AutofillUseMobileLabelDisambiguation:enabled"/> <int value="1174088940" label="enable-wasm"/> <int value="1175660959" label="AutofillEnableCardArtImage:enabled"/> <int value="1176183341" label="SearchHistoryLink:enabled"/> @@ -36125,6 +36125,8 @@ <int value="1429923065" label="enable-media-internals:enabled"/> <int value="1430924529" label="TranslateIntent:enabled"/> <int value="1431050645" label="PayWithGoogleV1:disabled"/> + <int value="1431148950" + label="enable-bound-session-credentials-software-keys-for-manual-testing:disabled"/> <int value="1431934725" label="OmniboxAutocompleteTitles:disabled"/> <int value="1432263468" label="SpeculationRulesPrefetchProxy:disabled"/> <int value="1433706192" label="FileSystemObserver:disabled"/>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index 2132e9a4..16f6d81e 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -3791,19 +3791,6 @@ </summary> </histogram> -<histogram name="Autofill.ProfileSuggestionsMadeWithFormatter" - enum="BooleanCreated" expires_after="2024-12-12"> - <owner>battre@chromium.org</owner> - <owner>src/components/autofill/OWNERS</owner> - <summary> - This metric is recorded when the autofill-use-improved-label-disambiguation - experiment is enabled and profile suggestions are available. This metric - measures how often suggestions were created with and without a formatter. - Warning: this histogram was expired from 2020-09-30 to 2022-04-07; data may - be missing. - </summary> -</histogram> - <histogram name="Autofill.ProfileTokenQuality.ObservationCountBeforeSubmission.PerProfile" units="Observations" expires_after="M125">
diff --git a/tools/metrics/histograms/metadata/chromeos/enums.xml b/tools/metrics/histograms/metadata/chromeos/enums.xml index 4e90f891..9bc92f8 100644 --- a/tools/metrics/histograms/metadata/chromeos/enums.xml +++ b/tools/metrics/histograms/metadata/chromeos/enums.xml
@@ -855,6 +855,12 @@ <int value="5" label="FailedToDownloadToFile"/> </enum> +<enum name="GeolocationAccessLevel"> + <int value="0" label="Blocked for all"/> + <int value="1" label="Allowed"/> + <int value="2" label="Only allowed for system services"/> +</enum> + <enum name="HardwareVerifierQualificationStatus"> <summary> List of the possible qualification status of a component. This is defined in
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml index 97faee1..68a6302c 100644 --- a/tools/metrics/histograms/metadata/chromeos/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -2031,6 +2031,24 @@ </summary> </histogram> +<histogram name="ChromeOS.PrivacyHub.Geolocation.AccessLevelChanged.{Source}" + enum="GeolocationAccessLevel" expires_after="2024-06-01"> + <owner>zauri@google.com</owner> + <owner>chromeos-privacyhub@google.com</owner> + <summary> + Records system geolocation permission change originated from the {Source}. + </summary> + <token key="Source"> + <variant name="GeolocationDialog" + summary="geolocation dialogs. These dialogs are surfaced in the + affected system services, like Automatic Time Zone"/> + <variant name="LocationPermissionNotification" + summary="ChromeOS system notification"/> + <variant name="SystemSettings" + summary="ChromeOS system settings > Location access subpage"/> + </token> +</histogram> + <histogram name="ChromeOS.PrivacyHub.LearnMorePage.Opened" enum="PrivacyHubLearnMoreSensor" expires_after="2024-05-19"> <owner>cschlosser@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/media/enums.xml b/tools/metrics/histograms/metadata/media/enums.xml index c3b1a67..831749a2 100644 --- a/tools/metrics/histograms/metadata/media/enums.xml +++ b/tools/metrics/histograms/metadata/media/enums.xml
@@ -1239,12 +1239,6 @@ <int value="2" label="MediaStream"/> </enum> -<enum name="MediaNotificationClickSource"> - <int value="0" label="Media"/> - <int value="1" label="Presentation"/> - <int value="2" label="MediaFling"/> -</enum> - <enum name="MediaNotificationDisplayPage"> <int value="0" label="Unknown"/> <int value="1" label="Quick settings media view"/>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index 0cc9af9..4cd87c0 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -4242,15 +4242,6 @@ </summary> </histogram> -<histogram name="Media.Notification.Click" enum="MediaNotificationClickSource" - expires_after="2020-06-07"> - <owner>mlamouri@chromium.org</owner> - <owner>media-dev-uma@chromium.org</owner> - <summary> - The type of media notification the user clicked to go back to Chrome. - </summary> -</histogram> - <histogram name="Media.Notification.Count" units="count" expires_after="2024-06-02"> <owner>yrw@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml index caccd1b..1d659c7 100644 --- a/tools/metrics/histograms/metadata/memory/histograms.xml +++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -290,21 +290,6 @@ </summary> </histogram> -<histogram name="Memory.Browser.MemoryFootprint.NumLiveOverscroll" units="tabs" - expires_after="2021-09-12"> - <owner>ajuma@chromium.org</owner> - <owner>rkgibson@google.com</owner> - <summary> - Investigation into crbug.com/1102494 shows that OverscrollActionsController - is allocating thousands of objects in it's -initWithScrollView:. This is - likely because thousands of OverscrollActionsControllers are being - initialized. The theory is that there are users that have many many tabs, - causing many OverscrollActionsControllers to be allocated. This histogram - tests that theory by logging how many live OverscrollActionsControllers - there are. This is recorded every time histograms are uploaded. - </summary> -</histogram> - <histogram name="Memory.Browser.MemoryFootprint.NumOpenTabs" units="tabs" expires_after="2024-04-28"> <owner>ajuma@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/net/enums.xml b/tools/metrics/histograms/metadata/net/enums.xml index f4c89be..f58bf02 100644 --- a/tools/metrics/histograms/metadata/net/enums.xml +++ b/tools/metrics/histograms/metadata/net/enums.xml
@@ -124,6 +124,19 @@ <int value="5" label="HTTP_NETWORK_TRANSACTION"/> </enum> +<enum name="CacheAccessStatus"> + <int value="0" label="Hit"> + Recorded when cache entry was found and produced a classification. + </int> + <int value="1" label="Not found"> + Recorded when cache entry was not found. + </int> + <int value="2" label="Outdated"> + Recorded when cache entry was found but did not produce a classification, + because it was outdated. + </int> +</enum> + <enum name="CertificateChangeNotificationType"> <int value="0" label="Trust"/> <int value="1" label="Client Cert"/>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml index 91c8a3b..96cee27 100644 --- a/tools/metrics/histograms/metadata/net/histograms.xml +++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -1723,16 +1723,6 @@ </summary> </histogram> -<histogram name="Net.ErrorPageCounts.SuggestionClicked" - enum="NetErrorOfflineSuggestionType" expires_after="2021-12-19"> - <owner>sclittle@chromium.org</owner> - <owner>offline-dev@chromium.org</owner> - <summary> - Counts of the type of offline content suggestions clicked on the network - error page. Reported upon click. - </summary> -</histogram> - <histogram name="Net.ErrorPageCounts.SuggestionPresented" enum="NetErrorOfflineSuggestionType" expires_after="2021-12-05"> <owner>sclittle@chromium.org</owner> @@ -4699,6 +4689,17 @@ </summary> </histogram> +<histogram name="Net.SafeSearch.CacheHit" enum="CacheAccessStatus" + expires_after="2024-04-28"> + <owner>tju@google.com</owner> + <owner>chrome-kids-eng@google.com</owner> + <summary> + Records if a URL classification in safe_search_api::URLChecker was provided + from the cache or not. In the latter case, it distinguishes between true + cache misses and cache hits which were unfit for classification. + </summary> +</histogram> + <histogram name="Net.SharedDictionaryManagerOnDisk.DictionarySizeKB" units="KB" expires_after="2024-03-03"> <owner>horo@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml index 9ab33d3..347b924 100644 --- a/tools/metrics/histograms/metadata/settings/histograms.xml +++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -497,7 +497,7 @@ </histogram> <histogram name="Settings.SafetyCheck.NotificationsModuleEntryPointShown" - enum="BooleanVisible" expires_after="2023-12-21"> + enum="BooleanVisible" expires_after="2024-06-01"> <owner>sideyilmaz@chromium.org</owner> <owner>msramek@chromium.org</owner> <owner>hkamila@chromium.org</owner> @@ -593,7 +593,7 @@ <histogram name="Settings.SafetyCheck.UnusedSitePermissionsRegrantDays{SourceUI}.All" - units="days" expires_after="2023-12-21"> + units="days" expires_after="2024-06-01"> <owner>sideyilmaz@chromium.org</owner> <owner>tov@chromium.org</owner> <owner>msramek@chromium.org</owner> @@ -612,7 +612,7 @@ <histogram name="Settings.SafetyCheck.UnusedSitePermissionsRegrantDays{SourceUI}.{PermissionType}" - units="days" expires_after="2023-12-21"> + units="days" expires_after="2024-06-01"> <owner>sideyilmaz@chromium.org</owner> <owner>tov@chromium.org</owner> <owner>msramek@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml index dd110110..70b366f 100644 --- a/tools/metrics/histograms/metadata/signin/histograms.xml +++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -1498,6 +1498,24 @@ </summary> </histogram> +<histogram + name="Signin.ShowSigninCoordinatorWhenAlreadyPresent.{View}AccessPoint" + enum="SigninAccessPoint" expires_after="2024-12-01"> + <owner>arthurmilchior@chromium.org</owner> + <owner>chrome-signin-team@google.com</owner> + <owner>msarda@chromium.org</owner> + <owner>jlebel@chromium.org</owner> + <summary> + This histogram is recorded when two sign-in views are being opened at the + same time. This indicates the access point which triggered the {View} to be + opened. + </summary> + <token key="View"> + <variant name="New" summary="second"/> + <variant name="Old" summary="first"/> + </token> +</histogram> + <histogram name="Signin.SignIn.Completed" enum="SigninAccessPoint" expires_after="2024-04-28"> <owner>bsazonov@chromium.org</owner>
diff --git a/tools/rust/build_rust.py b/tools/rust/build_rust.py index c727853..77f562d 100755 --- a/tools/rust/build_rust.py +++ b/tools/rust/build_rust.py
@@ -763,6 +763,11 @@ GitCherryPick(RUST_SRC_DIR, 'https://github.com/rust-lang/rust.git', '46a801559127441675f2341bd1d684809a47def1') + # TODO: Remove once + # https://github.com/rust-lang/rust/pull/118941 has been merged. + GitCherryPick(RUST_SRC_DIR, 'https://github.com/rust-lang/rust.git', + '0a285e8de7eec36e1de68c83764d23f2522a4274') + path = FetchBetaPackage('cargo', checkout_revision) if sys.platform == 'win32': cargo_bin = os.path.join(path, 'cargo', 'bin', 'cargo.exe')
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index b6cb4fe..fbf8b09 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -355,7 +355,7 @@ slot="jelly" id="pinned-toggle-jelly" command="#toggle-pinned" - aria-labelledby="pinned-toggle-label"> + aria-label="$i18n{OFFLINE_COLUMN_LABEL}"> </cros-switch> <cr-toggle slot="old"
diff --git a/ui/ozone/platform/headless/headless_window.cc b/ui/ozone/platform/headless/headless_window.cc index ba5852b..df7fdfd 100644 --- a/ui/ozone/platform/headless/headless_window.cc +++ b/ui/ozone/platform/headless/headless_window.cc
@@ -92,8 +92,15 @@ UpdateWindowState(PlatformWindowState::kNormal); } #if BUILDFLAG(IS_CHROMEOS_LACROS) - delegate_->OnFullscreenModeChanged(); -#endif + // Setting kImmersive when it's fullscreen on headless window since the + // immersive fullscreen is default for fullscreen on Lacros. + delegate_->OnFullscreenTypeChanged( + window_state_ == PlatformWindowState::kFullScreen + ? PlatformFullscreenType::kImmersive + : PlatformFullscreenType::kNone, + fullscreen ? PlatformFullscreenType::kImmersive + : PlatformFullscreenType::kNone); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) } void HeadlessWindow::Maximize() {
diff --git a/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h index 63f185d..735a218 100644 --- a/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h +++ b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h
@@ -84,10 +84,6 @@ // Sets a native window's immersive mode. virtual void SetUseImmersiveMode(bool immersive) = 0; - // Whether the shell supports top level immersive status. The deprecated - // immersive status used to be set on the surface level. - virtual bool SupportsTopLevelImmersiveStatus() const = 0; - // Sets the top inset (header) height which is reserved or occupied by the top // window frame. virtual void SetTopInset(int height) = 0;
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc index 33b5727..ea8d63ab 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -558,17 +558,17 @@ fullscreen_display_id_ = display::kInvalidDisplayId; #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (shell_toplevel_ && shell_toplevel()->SupportsTopLevelImmersiveStatus() && - is_immersive_fullscreen_ != window_states.is_immersive_fullscreen) { - is_immersive_fullscreen_ = window_states.is_immersive_fullscreen; - delegate()->OnImmersiveModeChanged(is_immersive_fullscreen_); - } - - if (is_fullscreen_ != window_states.is_fullscreen) { - is_fullscreen_ = window_states.is_fullscreen; + CHECK(!window_states.is_immersive_fullscreen || window_states.is_fullscreen); + PlatformFullscreenType fullscreen_type = + window_states.is_immersive_fullscreen + ? PlatformFullscreenType::kImmersive + : (window_states.is_fullscreen ? PlatformFullscreenType::kPlain + : PlatformFullscreenType::kNone); + if (fullscreen_type_ != fullscreen_type) { // The fullscreen state change has finished and we we need to inform the // browser/app that the transition is done. - delegate()->OnFullscreenModeChanged(); + delegate()->OnFullscreenTypeChanged(fullscreen_type_, fullscreen_type); + fullscreen_type_ = fullscreen_type; } #endif @@ -822,21 +822,13 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) void WaylandToplevelWindow::SetImmersiveFullscreenStatus(bool status) { - auto* zaura_surface = GetZAuraSurface(); - if (shell_toplevel_ && shell_toplevel_->SupportsTopLevelImmersiveStatus()) { + if (shell_toplevel_) { shell_toplevel_->SetUseImmersiveMode(status); - } else if (zaura_surface && - zaura_surface->SetFullscreenMode( - status ? ZAURA_SURFACE_FULLSCREEN_MODE_IMMERSIVE - : ZAURA_SURFACE_FULLSCREEN_MODE_PLAIN)) { - // TODO(ffred): the deprecated immersive mode flow used to transition - // immediately after sending the request to exo. This is needed to - // maintain backwards compatibility. Remove once we have rolled past the - // supported skew. - delegate()->OnImmersiveModeChanged(status); } else { - // TODO(https://crbug.com/1113900): Implement AuraShell support for - // non-browser windows and replace this if-else clause by a DCHECK. + // TODO(elkurin): Investigate whether we can deprecate this clause. This + // pass is used by some tests which do not set shell properly and ideally we + // would like to fix those tests. After those fixes, remove this clause or + // replace it by CHECK. NOTIMPLEMENTED_LOG_ONCE(); // TODO(https://crbug.com/1113900): With Lacros, the state change gets // completed asynchronously (see removal of notification call in @@ -844,7 +836,10 @@ // application now. This needs also be properly addressed with the // immersive mode change inside the immersive mode handling by calling // this delegate - or `BrowserView::FullscreenStateChanged()` directly. - delegate()->OnFullscreenModeChanged(); + auto new_type = status ? PlatformFullscreenType::kImmersive + : PlatformFullscreenType::kPlain; + delegate()->OnFullscreenTypeChanged(fullscreen_type_, new_type); + fullscreen_type_ = new_type; } } @@ -1016,7 +1011,18 @@ void WaylandToplevelWindow::DumpState(std::ostream& out) const { WaylandWindow::DumpState(out); #if BUILDFLAG(IS_CHROMEOS_LACROS) - out << ", is_immersive_fullscreen=" << ToBoolString(is_immersive_fullscreen_); + out << ", fullscreen_type="; + switch (fullscreen_type_) { + case PlatformFullscreenType::kNone: + out << "not fullscreen"; + break; + case PlatformFullscreenType::kPlain: + out << "plain fullscreen"; + break; + case PlatformFullscreenType::kImmersive: + out << "immersive fullscreen"; + break; + } #endif out << ", title=" << window_title_ << ", is_active=" << ToBoolString(is_active_)
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h index 2455bca7..2e0a395 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -267,11 +267,9 @@ bool is_active_ = false; #if BUILDFLAG(IS_CHROMEOS_LACROS) - bool is_immersive_fullscreen_ = false; - - // This is used to detect fullscreen state changes from the Aura side + // This is used to detect fullscreen type changes from the Aura side // to inform Lacros clients from the asynchronous task completion. - bool is_fullscreen_ = false; + PlatformFullscreenType fullscreen_type_ = PlatformFullscreenType::kNone; // Unique ID for this window. May be shared over non-Wayland IPC transports // (e.g. mojo) to identify the window.
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc index dfae20e..92d79ed 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -1186,7 +1186,10 @@ // Now, set to fullscreen. #if BUILDFLAG(IS_CHROMEOS_LACROS) - EXPECT_CALL(delegate_, OnFullscreenModeChanged()).Times(1); + EXPECT_CALL(delegate_, + OnFullscreenTypeChanged(PlatformFullscreenType::kNone, + PlatformFullscreenType::kPlain)) + .Times(1); #endif EXPECT_CALL(delegate_, OnWindowStateChanged(_, Eq(PlatformWindowState::kFullScreen))) @@ -1203,7 +1206,9 @@ // Unfullscreen #if BUILDFLAG(IS_CHROMEOS_LACROS) - EXPECT_CALL(delegate_, OnFullscreenModeChanged()).Times(1); + EXPECT_CALL(delegate_, OnFullscreenTypeChanged(PlatformFullscreenType::kPlain, + PlatformFullscreenType::kNone)) + .Times(1); #endif EXPECT_CALL(delegate_, OnWindowStateChanged(_, Eq(PlatformWindowState::kNormal))) @@ -1240,7 +1245,10 @@ AdvanceFrameToCurrent(window_.get(), delegate_); #if BUILDFLAG(IS_CHROMEOS_LACROS) - EXPECT_CALL(delegate_, OnFullscreenModeChanged()).Times(1); + EXPECT_CALL(delegate_, + OnFullscreenTypeChanged(PlatformFullscreenType::kNone, + PlatformFullscreenType::kPlain)) + .Times(1); #endif EXPECT_CALL(delegate_, OnWindowStateChanged(_, Eq(PlatformWindowState::kFullScreen))) @@ -1257,7 +1265,9 @@ // Restore #if BUILDFLAG(IS_CHROMEOS_LACROS) - EXPECT_CALL(delegate_, OnFullscreenModeChanged()).Times(1); + EXPECT_CALL(delegate_, OnFullscreenTypeChanged(PlatformFullscreenType::kPlain, + PlatformFullscreenType::kNone)) + .Times(1); #endif EXPECT_CALL(delegate_, OnWindowStateChanged(_, Eq(PlatformWindowState::kNormal))) @@ -4219,7 +4229,10 @@ auto toplevel = CreateWaylandWindowWithParams( PlatformWindowType::kWindow, gfx::Rect(10, 10, 200, 200), &delegate_2); - EXPECT_CALL(delegate_2, OnImmersiveModeChanged(true)).Times(1); + EXPECT_CALL(delegate_2, + OnFullscreenTypeChanged(PlatformFullscreenType::kNone, + PlatformFullscreenType::kImmersive)) + .Times(1); toplevel->HandleAuraToplevelConfigure(0, 0, 0, 0, {.is_maximized = false, .is_fullscreen = true, @@ -4248,7 +4261,10 @@ .is_activated = true}); toplevel->HandleSurfaceConfigure(++serial); - EXPECT_CALL(delegate_2, OnImmersiveModeChanged(false)).Times(1); + EXPECT_CALL(delegate_2, + OnFullscreenTypeChanged(PlatformFullscreenType::kImmersive, + PlatformFullscreenType::kNone)) + .Times(1); toplevel->HandleAuraToplevelConfigure(0, 0, 0, 0, {.is_maximized = false, .is_fullscreen = false,
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc index 814a86c..642abc2 100644 --- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc
@@ -195,16 +195,9 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) void XDGToplevelWrapperImpl::SetUseImmersiveMode(bool immersive) { - if (SupportsTopLevelImmersiveStatus()) { - auto mode = immersive ? ZAURA_TOPLEVEL_FULLSCREEN_MODE_IMMERSIVE - : ZAURA_TOPLEVEL_FULLSCREEN_MODE_PLAIN; - zaura_toplevel_set_fullscreen_mode(aura_toplevel_.get(), mode); - } -} - -bool XDGToplevelWrapperImpl::SupportsTopLevelImmersiveStatus() const { - return aura_toplevel_ && zaura_toplevel_get_version(aura_toplevel_.get()) >= - ZAURA_TOPLEVEL_SET_FULLSCREEN_MODE_SINCE_VERSION; + auto mode = immersive ? ZAURA_TOPLEVEL_FULLSCREEN_MODE_IMMERSIVE + : ZAURA_TOPLEVEL_FULLSCREEN_MODE_PLAIN; + zaura_toplevel_set_fullscreen_mode(aura_toplevel_.get(), mode); } void XDGToplevelWrapperImpl::SetTopInset(int height) {
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h index 854ebc9..47604d47 100644 --- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
@@ -41,7 +41,6 @@ void UnSetFullscreen() override; #if BUILDFLAG(IS_CHROMEOS_LACROS) void SetUseImmersiveMode(bool immersive) override; - bool SupportsTopLevelImmersiveStatus() const override; void SetTopInset(int height) override; void SetShadowCornersRadii(const gfx::RoundedCornersF& radii) override; #endif
diff --git a/ui/ozone/test/mock_platform_window_delegate.h b/ui/ozone/test/mock_platform_window_delegate.h index e63156d..18db812 100644 --- a/ui/ozone/test/mock_platform_window_delegate.h +++ b/ui/ozone/test/mock_platform_window_delegate.h
@@ -35,8 +35,12 @@ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) MOCK_METHOD1(OnWindowTiledStateChanged, void(WindowTiledEdges new_tiled_edges)); - MOCK_METHOD0(OnFullscreenModeChanged, void()); #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) + MOCK_METHOD2(OnFullscreenTypeChanged, + void(PlatformFullscreenType old_type, + PlatformFullscreenType new_type)); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) MOCK_METHOD0(OnLostCapture, void()); MOCK_METHOD1(OnAcceleratedWidgetAvailable, void(gfx::AcceleratedWidget widget)); @@ -49,7 +53,6 @@ MOCK_METHOD0(GetOwnedWindowAnchorAndRectInDIP, absl::optional<OwnedWindowAnchor>()); MOCK_METHOD0(OnMouseEnter, void()); - MOCK_METHOD1(OnImmersiveModeChanged, void(bool immersive)); MOCK_METHOD1(OnOverviewModeChanged, void(bool overview)); MOCK_METHOD2(OnRotateFocus, bool(PlatformWindowDelegate::RotateDirection, bool));
diff --git a/ui/platform_window/platform_window_delegate.cc b/ui/platform_window/platform_window_delegate.cc index 6ce982e8..b94be90e 100644 --- a/ui/platform_window/platform_window_delegate.cc +++ b/ui/platform_window/platform_window_delegate.cc
@@ -42,7 +42,9 @@ #endif #if BUILDFLAG(IS_CHROMEOS_LACROS) -void PlatformWindowDelegate::OnFullscreenModeChanged() {} +void PlatformWindowDelegate::OnFullscreenTypeChanged( + PlatformFullscreenType old_type, + PlatformFullscreenType new_type) {} #endif absl::optional<gfx::Size> PlatformWindowDelegate::GetMinimumSizeForWindow() {
diff --git a/ui/platform_window/platform_window_delegate.h b/ui/platform_window/platform_window_delegate.h index fa43b7c..42f0e2a 100644 --- a/ui/platform_window/platform_window_delegate.h +++ b/ui/platform_window/platform_window_delegate.h
@@ -45,6 +45,24 @@ kFloated, }; +#if BUILDFLAG(IS_CHROMEOS_LACROS) +enum class PlatformFullscreenType { + // kNone represents a non-fullscreen state. This should be set for most cases + // except for the window state is `kFullscreen`. + kNone, + + // kPlain represents a fullscreen mode without immersive feature. This + // corresponds to fullscreen + non-immersive mode. The window state must be + // 'kFullscreen`. This state is also used by the locked fullscreen or pinned + // mode in other words. + kPlain, + + // kImmersive represents a immersive fullscreen mode. This corresponds to + // fullscreen + immersive mode. The window state must be `kFullscreen`. + kImmersive, +}; +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + enum class PlatformWindowOcclusionState { kUnknown, kVisible, @@ -140,17 +158,13 @@ #endif #if BUILDFLAG(IS_CHROMEOS_LACROS) - // Notifies delegate that the pending fullscreen operation has been completed. - virtual void OnFullscreenModeChanged(); -#endif - -#if BUILDFLAG(IS_CHROMEOS_LACROS) // TODO(ffred): We should just add kImmersiveFullscreen as a state. However, // that will require more refactoring in other places to understand that // kImmersiveFullscreen is a fullscreen status. - // Sets the immersive mode for the window. This will only have an effect on - // ChromeOS platforms. - virtual void OnImmersiveModeChanged(bool immersive) {} + // + // Notifies that fullscreen type has changed. + virtual void OnFullscreenTypeChanged(PlatformFullscreenType old_type, + PlatformFullscreenType new_type); // Lets the window know that ChromeOS overview mode has changed. virtual void OnOverviewModeChanged(bool in_overview) {}
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.cc index e31ee7c..5028a156 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.cc
@@ -74,6 +74,10 @@ void OnTouchEvent(ui::TouchEvent* event) override { event->SetHandled(); } }; +bool IsImmersive(ui::PlatformFullscreenType type) { + return type == ui::PlatformFullscreenType::kImmersive; +} + } // namespace namespace views { @@ -128,6 +132,7 @@ DestroyNonClientEventFilter(); DesktopWindowTreeHostPlatform::OnClosed(); } + void DesktopWindowTreeHostLacros::OnWindowStateChanged( ui::PlatformWindowState old_window_show_state, ui::PlatformWindowState new_window_show_state) { @@ -138,10 +143,15 @@ ToChromeosWindowStateType(new_window_show_state)); } -void DesktopWindowTreeHostLacros::OnImmersiveModeChanged(bool enabled) { +void DesktopWindowTreeHostLacros::OnFullscreenTypeChanged( + ui::PlatformFullscreenType old_type, + ui::PlatformFullscreenType new_type) { // Keep in sync with ImmersiveFullscreenController::Enable for widget. See // comment there for details. - GetContentWindow()->SetProperty(chromeos::kImmersiveIsActive, enabled); + if (IsImmersive(old_type) != IsImmersive(new_type)) { + GetContentWindow()->SetProperty(chromeos::kImmersiveIsActive, + IsImmersive(new_type)); + } } void DesktopWindowTreeHostLacros::OnOverviewModeChanged(bool in_overview) {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h index 88ed9243..be6d51d 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h
@@ -64,7 +64,8 @@ void OnWindowStateChanged( ui::PlatformWindowState old_window_show_state, ui::PlatformWindowState new_window_show_state) override; - void OnImmersiveModeChanged(bool enabled) override; + void OnFullscreenTypeChanged(ui::PlatformFullscreenType old_type, + ui::PlatformFullscreenType new_type) override; void OnOverviewModeChanged(bool in_overview) override; void OnTooltipShownOnServer(const std::u16string& text, const gfx::Rect& bounds) override;